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  }