Back to Encore

Metrics

docs/go/observability/metrics.md

1.56.93.6 KB
Original Source

Encore provides built-in support for defining custom metrics in your Go applications. Once defined, metrics are automatically collected and displayed in the Encore Cloud Dashboard, and can be exported to third-party observability services.

See the Platform metrics documentation for information about integrations with third-party services like Grafana Cloud and Datadog.

Defining custom metrics

Define custom metrics by importing the encore.dev/metrics package and creating a new metric using one of the metrics.NewCounter or metrics.NewGauge functions.

For example, to count the number of orders processed:

go
import "encore.dev/metrics"

var OrdersProcessed = metrics.NewCounter[uint64]("orders_processed", metrics.CounterConfig{})

func process(order *Order) {
    // ...
    OrdersProcessed.Increment()
}

Metric types

Encore currently supports two metric types: counters and gauges.

Counters measure the count of something. A counter's value must always increase, never decrease. (Note that the value gets reset to 0 when the application restarts.) Typical use cases include counting the number of requests, the amount of data processed, and so on.

Gauges measure the current value of something. Unlike counters, a gauge's value can fluctuate up and down. Typical use cases include measuring CPU usage, the number of active instances running of a process, and so on.

For information about their respective APIs, see the API documentation for Counter and Gauge.

Counter example

go
import "encore.dev/metrics"

var RequestsReceived = metrics.NewCounter[uint64]("requests_received", metrics.CounterConfig{})

func handleRequest() {
    RequestsReceived.Increment()
    // ... handle request
}

Gauge example

go
import "encore.dev/metrics"

var ActiveConnections = metrics.NewGauge[int64]("active_connections", metrics.GaugeConfig{})

func onConnect() {
    ActiveConnections.Add(1)
}

func onDisconnect() {
    ActiveConnections.Add(-1)
}

Defining labels

Encore's metrics package provides a type-safe way of attaching labels to metrics. To define labels, create a struct type representing the labels and then use metrics.NewCounterGroup or metrics.NewGaugeGroup.

The Labels type must be a named struct, where each field corresponds to a single label. Each field must be of type string, int, or bool.

Counter with labels

go
import "encore.dev/metrics"

type Labels struct {
    Success bool
}

var OrdersProcessed = metrics.NewCounterGroup[Labels, uint64]("orders_processed", metrics.CounterConfig{})

func process(order *Order) {
    var success bool
    // ... populate success with true/false ...
    OrdersProcessed.With(Labels{Success: success}).Increment()
}

Gauge with labels

go
import "encore.dev/metrics"

type ConnectionLabels struct {
    Region string
}

var ActiveConnections = metrics.NewGaugeGroup[ConnectionLabels, int64]("active_connections", metrics.GaugeConfig{})

func onConnect(region string) {
    ActiveConnections.With(ConnectionLabels{Region: region}).Add(1)
}
<Callout type="important">

Each combination of label values creates a unique time series tracked in memory and stored by the monitoring system. Using numerous labels can lead to a combinatorial explosion, causing high cloud expenses and degraded performance.

As a general rule, limit the unique time series to tens or hundreds at most, rather than thousands.

</Callout>