github.com/wfusion/gofusion@v1.1.14/common/infra/asynq/x/metrics/metrics.go (about) 1 // Package metrics provides implementations of prometheus.Collector to collect Asynq queue metrics. 2 package metrics 3 4 import ( 5 "fmt" 6 "log" 7 8 "github.com/prometheus/client_golang/prometheus" 9 10 "github.com/wfusion/gofusion/common/infra/asynq" 11 ) 12 13 // Namespace used in fully-qualified metrics names. 14 const namespace = "asynq" 15 16 // QueueMetricsCollector gathers queue metrics. 17 // It implements prometheus.Collector interface. 18 // 19 // All metrics exported from this collector have prefix "asynq". 20 type QueueMetricsCollector struct { 21 inspector *asynq.Inspector 22 } 23 24 // collectQueueInfo gathers QueueInfo of all queues. 25 // Since this operation is expensive, it must be called once per collection. 26 func (qmc *QueueMetricsCollector) collectQueueInfo() ([]*asynq.QueueInfo, error) { 27 qnames, err := qmc.inspector.Queues() 28 if err != nil { 29 return nil, fmt.Errorf("failed to get queue names: %v", err) 30 } 31 infos := make([]*asynq.QueueInfo, len(qnames)) 32 for i, qname := range qnames { 33 qinfo, err := qmc.inspector.GetQueueInfo(qname) 34 if err != nil { 35 return nil, fmt.Errorf("failed to get queue info: %v", err) 36 } 37 infos[i] = qinfo 38 } 39 return infos, nil 40 } 41 42 // Descriptors used by QueueMetricsCollector 43 var ( 44 tasksQueuedDesc = prometheus.NewDesc( 45 prometheus.BuildFQName(namespace, "", "tasks_enqueued_total"), 46 "Number of tasks enqueued; broken down by queue and state.", 47 []string{"queue", "state"}, nil, 48 ) 49 50 queueSizeDesc = prometheus.NewDesc( 51 prometheus.BuildFQName(namespace, "", "queue_size"), 52 "Number of tasks in a queue", 53 []string{"queue"}, nil, 54 ) 55 56 queueLatencyDesc = prometheus.NewDesc( 57 prometheus.BuildFQName(namespace, "", "queue_latency_seconds"), 58 "Number of seconds the oldest pending task is waiting in pending state to be processed.", 59 []string{"queue"}, nil, 60 ) 61 62 queueMemUsgDesc = prometheus.NewDesc( 63 prometheus.BuildFQName(namespace, "", "queue_memory_usage_approx_bytes"), 64 "Number of memory used by a given queue (approximated number by sampling).", 65 []string{"queue"}, nil, 66 ) 67 68 tasksProcessedTotalDesc = prometheus.NewDesc( 69 prometheus.BuildFQName(namespace, "", "tasks_processed_total"), 70 "Number of tasks processed (both succeeded and failed); broken down by queue", 71 []string{"queue"}, nil, 72 ) 73 74 tasksFailedTotalDesc = prometheus.NewDesc( 75 prometheus.BuildFQName(namespace, "", "tasks_failed_total"), 76 "Number of tasks failed; broken down by queue", 77 []string{"queue"}, nil, 78 ) 79 80 pausedQueues = prometheus.NewDesc( 81 prometheus.BuildFQName(namespace, "", "queue_paused_total"), 82 "Number of queues paused", 83 []string{"queue"}, nil, 84 ) 85 ) 86 87 func (qmc *QueueMetricsCollector) Describe(ch chan<- *prometheus.Desc) { 88 prometheus.DescribeByCollect(qmc, ch) 89 } 90 91 func (qmc *QueueMetricsCollector) Collect(ch chan<- prometheus.Metric) { 92 queueInfos, err := qmc.collectQueueInfo() 93 if err != nil { 94 log.Printf("Failed to collect metrics data: %v", err) 95 } 96 for _, info := range queueInfos { 97 ch <- prometheus.MustNewConstMetric( 98 tasksQueuedDesc, 99 prometheus.GaugeValue, 100 float64(info.Active), 101 info.Queue, 102 "active", 103 ) 104 ch <- prometheus.MustNewConstMetric( 105 tasksQueuedDesc, 106 prometheus.GaugeValue, 107 float64(info.Pending), 108 info.Queue, 109 "pending", 110 ) 111 ch <- prometheus.MustNewConstMetric( 112 tasksQueuedDesc, 113 prometheus.GaugeValue, 114 float64(info.Scheduled), 115 info.Queue, 116 "scheduled", 117 ) 118 ch <- prometheus.MustNewConstMetric( 119 tasksQueuedDesc, 120 prometheus.GaugeValue, 121 float64(info.Retry), 122 info.Queue, 123 "retry", 124 ) 125 ch <- prometheus.MustNewConstMetric( 126 tasksQueuedDesc, 127 prometheus.GaugeValue, 128 float64(info.Archived), 129 info.Queue, 130 "archived", 131 ) 132 ch <- prometheus.MustNewConstMetric( 133 tasksQueuedDesc, 134 prometheus.GaugeValue, 135 float64(info.Completed), 136 info.Queue, 137 "completed", 138 ) 139 140 ch <- prometheus.MustNewConstMetric( 141 queueSizeDesc, 142 prometheus.GaugeValue, 143 float64(info.Size), 144 info.Queue, 145 ) 146 147 ch <- prometheus.MustNewConstMetric( 148 queueLatencyDesc, 149 prometheus.GaugeValue, 150 info.Latency.Seconds(), 151 info.Queue, 152 ) 153 154 ch <- prometheus.MustNewConstMetric( 155 queueMemUsgDesc, 156 prometheus.GaugeValue, 157 float64(info.MemoryUsage), 158 info.Queue, 159 ) 160 161 ch <- prometheus.MustNewConstMetric( 162 tasksProcessedTotalDesc, 163 prometheus.CounterValue, 164 float64(info.ProcessedTotal), 165 info.Queue, 166 ) 167 168 ch <- prometheus.MustNewConstMetric( 169 tasksFailedTotalDesc, 170 prometheus.CounterValue, 171 float64(info.FailedTotal), 172 info.Queue, 173 ) 174 175 pausedValue := 0 // zero to indicate "not paused" 176 if info.Paused { 177 pausedValue = 1 178 } 179 ch <- prometheus.MustNewConstMetric( 180 pausedQueues, 181 prometheus.GaugeValue, 182 float64(pausedValue), 183 info.Queue, 184 ) 185 } 186 } 187 188 // NewQueueMetricsCollector returns a collector that exports metrics about Asynq queues. 189 func NewQueueMetricsCollector(inspector *asynq.Inspector) *QueueMetricsCollector { 190 return &QueueMetricsCollector{inspector: inspector} 191 }