appmetrics

package
v0.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2023 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package appmetrics creates and registers metrics structs.

Applications that report metrics often want to define those metrics in a common type or package so they are easy to use in other parts of the application. The appmetrics package provides a way to easily define, initialize, and register these shared metric structs.

A metrics struct contains one or more fields of a supported metric interface type that have the "metric" tag giving the metric's name in a registry. The metric types and the registry are defined by the go-metrics package.

For global metrics, this struct is often exported as a field:

// in the app's "metrics" package
type Metrics struct {
	Errors        metrics.Counter `metric:"errors"`
	ActiveWorkers metrics.Gauge   `metric:"active_workers"`
}

var M *Metrics

func init() {
	M = appmetrics.New()
	appmetrics.Register(metrics.DefaultRegistry, M)
}

// in a different package
metrics.M.Errors.Inc(1)
metrics.M.ActiveWorkers.Update(len(workers))
Example
package main

import (
	"fmt"

	"github.com/rcrowley/go-metrics"
)

type Metrics struct {
	Counter       metrics.Counter         `metric:"counter"`
	TaggedCounter Tagged[metrics.Counter] `metric:"counter.tagged"`

	Gauge           metrics.Gauge   `metric:"gauge"`
	FunctionalGauge FunctionalGauge `metric:"gauge.functional"`

	calls int64
}

func (m *Metrics) ComputeFunctionalGauge() int64 {
	m.calls++
	return m.calls
}

func main() {
	// Initialize a Metrics struct
	m := New[Metrics]()

	// Register it with a registry
	Register(metrics.DefaultRegistry, m)

	// Report metrics
	m.Counter.Inc(5)
	m.TaggedCounter.Tag("foo").Inc(1)
	m.TaggedCounter.Tag("bar").Inc(1)
	m.Gauge.Update(42)

	// Read metrics from the registry
	metrics.Each(func(name string, m any) {
		switch m := m.(type) {
		case metrics.Counter:
			fmt.Printf("%s: %d\n", name, m.Count())
		case metrics.Gauge:
			fmt.Printf("%s: %d\n", name, m.Value())
		}
	})

}
Output:

counter: 5
counter.tagged: 0
counter.tagged[foo]: 1
counter.tagged[bar]: 1
gauge: 42
gauge.functional: 1

Index

Examples

Constants

View Source
const (
	MetricTag       = "metric"
	MetricSampleTag = "metric-sample"
)
View Source
const (
	DefaultReservoirSize = 1028
	DefaultExpDecayAlpha = 0.015
)

DefaultReservoirSize and DefaultExpDecayAlpha are the values used for histogram sampling when the "metric-sample" tag is not present. They create an exponentially-decaying sample with the same behavior as UNIX load averages.

View Source
const (
	GaugeFunctionPrefix = "Compute"
)

Variables

This section is empty.

Functions

func MetricNames

func MetricNames[M any](m *M) []string

MetricNames returns the names of the metrics in the struct m. See New for an explanation of how this package identifies metric fields. MetricNames panics if the struct contains invalid metric definitions.

func New

func New[M any]() *M

New creates a new metrics struct. The type M must be a struct and should have one or more fields that have the "metric" tag. New allocates a new struct and populates all of the tagged metric fields.

The metric tag gives the name of the associated metric in the registry. Every field with this tag must be one of the supported metric interface types:

For example, this struct defines two metrics, a counter and a gauge:

type M struct {
	APIResponses metrics.Counter `metric:"api.responses"`
	Workers	     metrics.Gauge   `metric:"workers"`
}

New panics if any aspect of the struct definition is invalid. New does not register the metrics with a registry. Call Register with the new struct to make the metrics available to emitters and other clients.

By default, each metric registers as the static name given in the "metric" tag. You can define metrics with dynamic names by using the Tagged interface; see that type for more details.

If the metric is a histogram or a timer, the field may also set the "metric-sample" tag. This tag defines the sample type for the metric's histogram. The tag value is a comma-separated list of the sample type and the sample's parameters. The supported types are:

  • "uniform": optionally accepts an integer for the reservoir size
  • "expdecay": optionally accepts an integer for the reservoir size and a float for the alpha value; you must set both or neither value

For example:

type M struct {
	DownloadSize    metrics.Histogram `metric:"download.size" metric-sample:"uniform,100"`
	DownloadLatency metrics.Time      `metric:"download.latency" metric-sample:"expdecay,1028,0.015"`
}

See rcrowley/go-metrics for an explanation of the differences between sample types.

If the tag is not set, the histogram uses an exponentially decaying sample with DefaultReservoirSize and DefaultExpDecayAlpha. These values are also used when the reservoir size and alpha are not specified.

Metric fields can also be one of the functional metric interface types:

A functional metrics execute a function each time a client requests its value. Each functional metric must have a corresponding exported method or function field that is the field name with the "Compute" prefix. For example:

type M struct {
	QueueLength FunctionalGauge		   `metric:"queue_length"`
	Temperature FunctionalGaugeFloat64 `metric:"temperature"`

	ComputeQueueLength func() int64
}

func (m *M) ComputeTemperature() float64 {
	return getCurrentTemperature()
}

New panics if a functional metric is missing its compute function or if the function has the wrong type. At this time, functional metrics do not support tagging.

func Register

func Register[M any](r metrics.Registry, m *M)

Register registers all of the metrics in the struct m with the registry. See New for an explanation of how this package identifies metric fields. Register panics if the struct contains invalid metric definitions.

Register skips any metric with a name that already exist in the registry, even if the existing metric has a different type.

func Unregister

func Unregister[M any](r metrics.Registry, m *M)

Unregister unregisters all of the metrics in the struct m from the registry. See New for an explanation of how this package identifies metric fields. Unregister panics if the struct contains invalid metric definitions.

Unregistering is generally not required, but is necessary to free meter and timer metrics if they are otherwise unreferenced.

Types

type FunctionalGauge

type FunctionalGauge interface {
	Snapshot() metrics.Gauge
	Value() int64
}

FunctionalGauge is a metrics.Gauge that computes its value by calling a function.

A FunctionalGauge cannot be used as a Tagged metric.

type FunctionalGaugeFloat64

type FunctionalGaugeFloat64 interface {
	Snapshot() metrics.GaugeFloat64
	Value() float64
}

FunctionalGaugeFloat64 is a metrics.GaugeFloat64 that computes its value by calling a function.

A FunctionalGaugeFloat64 cannot be used as a Tagged metric.

type Tagged

type Tagged[M any] interface {
	// Tag returns an instance of the metric that reports with the given tags.
	// Tags may be either plain values or key-value pairs separated by a colon.
	// Tag trims whitespace from each tag and ignores any empty tags.
	Tag(tags ...string) M
}

Tagged is a metric with dynamic tags. The type M must be one of the supported metric types. Tags are strings that can either be plain values or key-value pairs where the key and value are separated by a colon.

While Tagged metrics can be used directly, it's helpful to wrap them in a function that accepts the expected tag values using the correct types. For example:

struct M {
	Responses Tagged[metrics.Counter] `metric:"responses"`
}

func (m *M) ResponsesByTypeAndStatus(typ string, status int) metrics.Counter {
	return m.Responses.Tag("type:" + type, "status:" + strconv.Itoa(stats))
}

Tags are added as a suffix to the base metric name: the tags are joined by commas, then surrounded by square brackets. Using the previous example, the full metric names might be:

  • "responses[type:api,status:200]"
  • "responses[type:file,status:404]"

Note that each unique combination of tags produces a separate metric in the registry. For this reason avoid tags that can take many values, like IDs.

Directories

Path Synopsis
emitter
datadog
Package datadog defines configuration and functions for emitting metrics to Datadog using the DogStatd protocol.
Package datadog defines configuration and functions for emitting metrics to Datadog using the DogStatd protocol.
prometheus
Package prometheus defines configuration and functions for emitting metrics to Prometheus.
Package prometheus defines configuration and functions for emitting metrics to Prometheus.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL