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
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.
16 // var requestDuration metrics.Histogram
18 // requestDuration.With("method", "MyMethod").Observe(time.Since(begin))
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.
29 // c := statsd.NewCounter("request_duration_MyMethod_200")
33 // c := prometheus.NewCounter(stdprometheus.CounterOpts{
34 // Name: "request_duration",
36 // }, []string{"method", "status_code"})
37 // c.With("method", "MyMethod", "status_code", strconv.Itoa(code)).Add(1)
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.
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"})
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,
57 // // NewAPI takes metrics.Histogram, not *prometheus.Summary
58 // func NewAPI(s Store, logger log.Logger, latency metrics.Histogram) *API {
62 // func (a *API) ServeFoo(w http.ResponseWriter, r *http.Request) {
63 // begin := time.Now()
65 // a.latency.Observe(time.Since(begin).Seconds())
68 // Finally, pass the metrics as dependencies when building your object graph.
69 // This should happen in func main, not in the global scope.
71 // api := NewAPI(store, logger, latency)
72 // http.ListenAndServe("/", api)
74 // Note that metrics are "write-only" interfaces.
76 // Implementation details
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.
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
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