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 }