github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/core/cache/metrics.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package cache 5 6 import ( 7 "github.com/juju/loggo" 8 "github.com/prometheus/client_golang/prometheus" 9 ) 10 11 const ( 12 metricsNamespace = "juju_cache" 13 14 statusLabel = "status" 15 lifeLabel = "life" 16 disabledLabel = "disabled" 17 deletedLabel = "deleted" 18 controllerAccessLabel = "controller_access" 19 domainLabel = "domain" 20 agentStatusLabel = "agent_status" 21 machineStatusLabel = "machine_status" 22 ) 23 24 var ( 25 machineLabelNames = []string{ 26 agentStatusLabel, 27 lifeLabel, 28 machineStatusLabel, 29 } 30 31 modelLabelNames = []string{ 32 lifeLabel, 33 statusLabel, 34 } 35 36 userLabelNames = []string{ 37 controllerAccessLabel, 38 deletedLabel, 39 disabledLabel, 40 domainLabel, 41 } 42 43 logger = loggo.GetLogger("juju.core.cache") 44 ) 45 46 // ControllerGauges holds the prometheus gauges for ever increasing 47 // values used by the controller. 48 type ControllerGauges struct { 49 ModelConfigReads prometheus.Gauge 50 ModelHashCacheHit prometheus.Gauge 51 ModelHashCacheMiss prometheus.Gauge 52 } 53 54 func createControllerGauges() *ControllerGauges { 55 return &ControllerGauges{ 56 ModelConfigReads: prometheus.NewGauge( 57 prometheus.GaugeOpts{ 58 Namespace: metricsNamespace, 59 Name: "model_config_reads", 60 Help: "The number of times the model config is read.", 61 }, 62 ), 63 ModelHashCacheHit: prometheus.NewGauge( 64 prometheus.GaugeOpts{ 65 Namespace: metricsNamespace, 66 Name: "model_hash_cache_hit", 67 Help: "The number of times the model config change hash was determined using the cached value.", 68 }, 69 ), 70 ModelHashCacheMiss: prometheus.NewGauge( 71 prometheus.GaugeOpts{ 72 Namespace: metricsNamespace, 73 Name: "model_hash_cache_miss", 74 Help: "The number of times the model config change hash was generated.", 75 }, 76 ), 77 } 78 } 79 80 // Collect is part of the prometheus.Collector interface. 81 func (c *ControllerGauges) Collect(ch chan<- prometheus.Metric) { 82 c.ModelConfigReads.Collect(ch) 83 c.ModelHashCacheHit.Collect(ch) 84 c.ModelHashCacheMiss.Collect(ch) 85 } 86 87 // Collector is a prometheus.Collector that collects metrics about 88 // the Juju global state. 89 type Collector struct { 90 controller *Controller 91 92 scrapeDuration prometheus.Gauge 93 scrapeErrors prometheus.Gauge 94 95 models *prometheus.GaugeVec 96 machines *prometheus.GaugeVec 97 users *prometheus.GaugeVec 98 } 99 100 // NewMetricsCollector returns a new Collector. 101 func NewMetricsCollector(controller *Controller) *Collector { 102 return &Collector{ 103 controller: controller, 104 scrapeDuration: prometheus.NewGauge( 105 prometheus.GaugeOpts{ 106 Namespace: metricsNamespace, 107 Name: "scrape_duration_seconds", 108 Help: "Amount of time taken to collect state metrics.", 109 }, 110 ), 111 scrapeErrors: prometheus.NewGauge( 112 prometheus.GaugeOpts{ 113 Namespace: metricsNamespace, 114 Name: "scrape_errors", 115 Help: "Number of errors observed while collecting state metrics.", 116 }, 117 ), 118 119 models: prometheus.NewGaugeVec( 120 prometheus.GaugeOpts{ 121 Namespace: metricsNamespace, 122 Name: "models", 123 Help: "Number of models in the controller.", 124 }, 125 modelLabelNames, 126 ), 127 machines: prometheus.NewGaugeVec( 128 prometheus.GaugeOpts{ 129 Namespace: metricsNamespace, 130 Name: "machines", 131 Help: "Number of machines managed by the controller.", 132 }, 133 machineLabelNames, 134 ), 135 users: prometheus.NewGaugeVec( 136 prometheus.GaugeOpts{ 137 Namespace: metricsNamespace, 138 Name: "users", 139 Help: "Number of local users in the controller.", 140 }, 141 userLabelNames, 142 ), 143 } 144 } 145 146 // Describe is part of the prometheus.Collector interface. 147 func (c *Collector) Describe(ch chan<- *prometheus.Desc) { 148 c.machines.Describe(ch) 149 c.models.Describe(ch) 150 c.users.Describe(ch) 151 152 c.scrapeErrors.Describe(ch) 153 c.scrapeDuration.Describe(ch) 154 } 155 156 // Collect is part of the prometheus.Collector interface. 157 func (c *Collector) Collect(ch chan<- prometheus.Metric) { 158 timer := prometheus.NewTimer(prometheus.ObserverFunc(c.scrapeDuration.Set)) 159 defer c.scrapeDuration.Collect(ch) 160 defer timer.ObserveDuration() 161 c.scrapeErrors.Set(0) 162 defer c.scrapeErrors.Collect(ch) 163 164 c.machines.Reset() 165 c.models.Reset() 166 c.users.Reset() 167 168 c.updateMetrics() 169 170 c.controller.metrics.Collect(ch) 171 c.machines.Collect(ch) 172 c.models.Collect(ch) 173 c.users.Collect(ch) 174 } 175 176 func (c *Collector) updateMetrics() { 177 logger.Tracef("updating cache metrics") 178 defer logger.Tracef("updated cache metrics") 179 180 modelUUIDs := c.controller.ModelUUIDs() 181 for _, m := range modelUUIDs { 182 c.updateModelMetrics(m) 183 } 184 185 // TODO: add user metrics. 186 } 187 188 func (c *Collector) updateModelMetrics(modelUUID string) { 189 model, err := c.controller.Model(modelUUID) 190 if err != nil { 191 logger.Debugf("error getting model: %v", err) 192 return 193 } 194 195 // TODO: add machines, applications and units. 196 197 c.models.With(prometheus.Labels{ 198 lifeLabel: string(model.details.Life), 199 statusLabel: string(model.details.Status.Status), 200 }).Inc() 201 }