1 // Package metrics provides a framework for application instrumentation. It's 2 // primarily designed to help you get started with good and robust 3 // instrumentation, and to help you migrate from a less-capable system like 4 // Graphite to a more-capable system like Prometheus. If your organization has 5 // already standardized on an instrumentation system like Prometheus, and has no 6 // plans to change, it may make sense to use that system's instrumentation 7 // library directly. 8 // 9 // This package provides three core metric abstractions (Counter, Gauge, and 10 // Histogram) and implementations for almost all common instrumentation 11 // backends. Each metric has an observation method (Add, Set, or Observe, 12 // respectively) used to record values, and a With method to "scope" the 13 // observation by various parameters. For example, you might have a Histogram to 14 // record request durations, parameterized by the method that's being called. 15 // 16 // var requestDuration metrics.Histogram 17 // // ... 18 // requestDuration.With("method", "MyMethod").Observe(time.Since(begin)) 19 // 20 // This allows a single high-level metrics object (requestDuration) to work with 21 // many code paths somewhat dynamically. The concept of With is fully supported 22 // in some backends like Prometheus, and not supported in other backends like 23 // Graphite. So, With may be a no-op, depending on the concrete implementation 24 // you choose. Please check the implementation to know for sure. For 25 // implementations that don't provide With, it's necessary to fully parameterize 26 // each metric in the metric name, e.g. 27 // 28 // // Statsd 29 // c := statsd.NewCounter("request_duration_MyMethod_200") 30 // c.Add(1) 31 // 32 // // Prometheus 33 // c := prometheus.NewCounter(stdprometheus.CounterOpts{ 34 // Name: "request_duration", 35 // ... 36 // }, []string{"method", "status_code"}) 37 // c.With("method", "MyMethod", "status_code", strconv.Itoa(code)).Add(1) 38 // 39 // Usage 40 // 41 // Metrics are dependencies, and should be passed to the components that need 42 // them in the same way you'd construct and pass a database handle, or reference 43 // to another component. Metrics should *not* be created in the global scope. 44 // Instead, instantiate metrics in your func main, using whichever concrete 45 // implementation is appropriate for your organization. 46 // 47 // latency := prometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ 48 // Namespace: "myteam", 49 // Subsystem: "foosvc", 50 // Name: "request_latency_seconds", 51 // Help: "Incoming request latency in seconds.", 52 // }, []string{"method", "status_code"}) 53 // 54 // Write your components to take the metrics they will use as parameters to 55 // their constructors. Use the interface types, not the concrete types. That is, 56 // 57 // // NewAPI takes metrics.Histogram, not *prometheus.Summary 58 // func NewAPI(s Store, logger log.Logger, latency metrics.Histogram) *API { 59 // // ... 60 // } 61 // 62 // func (a *API) ServeFoo(w http.ResponseWriter, r *http.Request) { 63 // begin := time.Now() 64 // // ... 65 // a.latency.Observe(time.Since(begin).Seconds()) 66 // } 67 // 68 // Finally, pass the metrics as dependencies when building your object graph. 69 // This should happen in func main, not in the global scope. 70 // 71 // api := NewAPI(store, logger, latency) 72 // http.ListenAndServe("/", api) 73 // 74 // Note that metrics are "write-only" interfaces. 75 // 76 // Implementation details 77 // 78 // All metrics are safe for concurrent use. Considerable design influence has 79 // been taken from https://github.com/codahale/metrics and 80 // https://prometheus.io. 81 // 82 // Each telemetry system has different semantics for label values, push vs. 83 // pull, support for histograms, etc. These properties influence the design of 84 // their respective packages. This table attempts to summarize the key points of 85 // distinction. 86 // 87 // SYSTEM DIM COUNTERS GAUGES HISTOGRAMS 88 // dogstatsd n batch, push-aggregate batch, push-aggregate native, batch, push-each 89 // statsd 1 batch, push-aggregate batch, push-aggregate native, batch, push-each 90 // graphite 1 batch, push-aggregate batch, push-aggregate synthetic, batch, push-aggregate 91 // expvar 1 atomic atomic synthetic, batch, in-place expose 92 // influx n custom custom custom 93 // prometheus n native native native 94 // pcp 1 native native native 95 // cloudwatch n batch push-aggregate batch push-aggregate synthetic, batch, push-aggregate 96 // 97 package metrics 98