github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/mongo/mongometrics/txnmetrics.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package mongometrics
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/mgo/v3/txn"
    10  	"github.com/prometheus/client_golang/prometheus"
    11  )
    12  
    13  const (
    14  	databaseLabel   = "database"
    15  	collectionLabel = "collection"
    16  	optypeLabel     = "optype"
    17  	failedLabel     = "failed"
    18  )
    19  
    20  var (
    21  	jujuMgoTxnLabelNames = []string{
    22  		databaseLabel,
    23  		collectionLabel,
    24  		optypeLabel,
    25  		failedLabel,
    26  	}
    27  )
    28  
    29  // TxnCollector is a prometheus.Collector that collects metrics about
    30  // mgo/txn operations.
    31  type TxnCollector struct {
    32  	txnOpsTotalCounter *prometheus.CounterVec
    33  	txnRetries         prometheus.Histogram
    34  	txnDurations       prometheus.Histogram
    35  }
    36  
    37  // NewTxnCollector returns a new TxnCollector.
    38  func NewTxnCollector() *TxnCollector {
    39  	return &TxnCollector{
    40  		txnOpsTotalCounter: prometheus.NewCounterVec(
    41  			prometheus.CounterOpts{
    42  				Namespace: "juju",
    43  				Name:      "mgo_txn_ops_total",
    44  				Help:      "Total number of mgo/txn ops executed.",
    45  			},
    46  			jujuMgoTxnLabelNames,
    47  		),
    48  		txnRetries: prometheus.NewHistogram(
    49  			prometheus.HistogramOpts{
    50  				Namespace: "juju",
    51  				Name:      "mgo_txn_retries",
    52  				Help:      "Number of attempts to complete a transaction",
    53  				Buckets:   prometheus.LinearBuckets(0, 1, 50),
    54  			},
    55  		),
    56  		txnDurations: prometheus.NewHistogram(
    57  			prometheus.HistogramOpts{
    58  				Namespace: "juju",
    59  				Name:      "mgo_txn_durations",
    60  				Help:      "Time (ms) taken to complete a transaction",
    61  				Buckets:   prometheus.LinearBuckets(0, 2, 50),
    62  			},
    63  		),
    64  	}
    65  }
    66  
    67  // AfterRunTransaction is called when a mgo/txn transaction has run.
    68  func (c *TxnCollector) AfterRunTransaction(dbName, modelUUID string, attempt int, duration time.Duration, ops []txn.Op, err error) {
    69  	for _, op := range ops {
    70  		c.updateMetrics(dbName, attempt, duration, op, err)
    71  	}
    72  }
    73  
    74  func (c *TxnCollector) updateMetrics(dbName string, attempt int, duration time.Duration, op txn.Op, err error) {
    75  	var failed string
    76  	if err != nil {
    77  		failed = "failed"
    78  	}
    79  	var optype string
    80  	switch {
    81  	case op.Insert != nil:
    82  		optype = "insert"
    83  	case op.Update != nil:
    84  		optype = "update"
    85  	case op.Remove:
    86  		optype = "remove"
    87  	default:
    88  		optype = "assert"
    89  	}
    90  	c.txnOpsTotalCounter.With(prometheus.Labels{
    91  		databaseLabel:   dbName,
    92  		collectionLabel: op.C,
    93  		optypeLabel:     optype,
    94  		failedLabel:     failed,
    95  	}).Inc()
    96  	c.txnRetries.Observe(float64(attempt))
    97  	c.txnDurations.Observe(float64(duration / time.Millisecond))
    98  }
    99  
   100  // Describe is part of the prometheus.Collector interface.
   101  func (c *TxnCollector) Describe(ch chan<- *prometheus.Desc) {
   102  	c.txnOpsTotalCounter.Describe(ch)
   103  	c.txnRetries.Describe(ch)
   104  	c.txnDurations.Describe(ch)
   105  }
   106  
   107  // Collect is part of the prometheus.Collector interface.
   108  func (c *TxnCollector) Collect(ch chan<- prometheus.Metric) {
   109  	c.txnOpsTotalCounter.Collect(ch)
   110  	c.txnRetries.Collect(ch)
   111  	c.txnDurations.Collect(ch)
   112  }