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  }