# package metrics

`package metrics` provides a set of uniform interfaces for service instrumentation.
It has
 [counters](http://prometheus.io/docs/concepts/metric_types/#counter),
 [gauges](http://prometheus.io/docs/concepts/metric_types/#gauge), and
 [histograms](http://prometheus.io/docs/concepts/metric_types/#histogram),
and provides adapters to popular metrics packages, like
 [expvar](https://golang.org/pkg/expvar),
 [StatsD](https://github.com/etsy/statsd), and
 [Prometheus](https://prometheus.io).

## Rationale

Code instrumentation is absolutely essential to achieve
 [observability](https://speakerdeck.com/mattheath/observability-in-micro-service-architectures)
 into a distributed system.
Metrics and instrumentation tools have coalesced around a few well-defined idioms.
`package metrics` provides a common, minimal interface those idioms for service authors.

## Usage

A simple counter, exported via expvar.

```go
import (
	"github.com/go-kit/kit/metrics"
	"github.com/go-kit/kit/metrics/expvar"
)

func main() {
	var myCount metrics.Counter
	myCount = expvar.NewCounter("my_count")
	myCount.Add(1)
}
```

A histogram for request duration,
 exported via a Prometheus summary with dynamically-computed quantiles.

```go
import (
	"time"

	stdprometheus "github.com/prometheus/client_golang/prometheus"

	"github.com/go-kit/kit/metrics"
	"github.com/go-kit/kit/metrics/prometheus"
)

func main() {
	var dur metrics.Histogram = prometheus.NewSummary(stdprometheus.SummaryOpts{
		Namespace: "myservice",
		Subsystem: "api",
		Name:     "request_duration_seconds",
		Help:     "Total time spent serving requests.",
	}, []string{})
	// ...
}

func handleRequest(dur metrics.Histogram) {
	defer func(begin time.Time) { dur.Observe(time.Since(begin).Seconds()) }(time.Now())
	// handle request
}
```

A gauge for the number of goroutines currently running, exported via StatsD.

```go
import (
	"net"
	"os"
	"runtime"
	"time"

	"github.com/go-kit/kit/metrics"
	"github.com/go-kit/kit/metrics/statsd"
)

func main() {
	statsd := statsd.New("foo_svc.", log.NewNopLogger())
	report := time.NewTicker(5 * time.Second)
	defer report.Stop()
	go statsd.SendLoop(report.C, "tcp", "statsd.internal:8125")
	goroutines := statsd.NewGauge("goroutine_count")
	go exportGoroutines(goroutines)
	// ...
}

func exportGoroutines(g metrics.Gauge) {
	for range time.Tick(time.Second) {
		g.Set(float64(runtime.NumGoroutine()))
	}
}
```
