metrics

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Jun 4, 2026 License: GPL-2.0, GPL-3.0 Imports: 11 Imported by: 0

README

metrics

CI Go Reference

Hand-rolled Prometheus text-format exposition library for Go

A lightweight, zero-dependency metrics library that exposes counters, gauges, labeled counters, histograms, and more in Prometheus text format. Standard library only.

Install

Go: go get github.com/cplieger/metrics@latest

Usage

package main

import (
	"net/http"
	"github.com/cplieger/metrics"
)

func main() {
	r := metrics.NewRegistry("myapp")
	reqs := metrics.NewLabeledCounter("myapp_http_requests_total", "Total HTTP requests", []string{"method", "status"})
	dur := metrics.NewHistogram("myapp_http_duration_seconds", "Request latency", metrics.WithBuckets([]float64{0.01, 0.05, 0.1, 0.5, 1, 5}))
	r.RegisterLabeledCounter(reqs)
	r.RegisterHistogram(dur)

	reqs.Inc("GET", "200")

	timer := metrics.NewTimer(dur)
	// ... do work ...
	timer.ObserveDuration()

	http.Handle("/metrics", r.Handler())
	http.ListenAndServe(":9090", nil)
}

API

Constants & Variables
  • DefaultBuckets []float64 — default histogram bucket boundaries (0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0)
  • OpenMetricsContentType string — OpenMetrics content type (application/openmetrics-text; version=1.0.0; charset=utf-8)
Counters
  • NewCounter(name, help) *Counter — monotonic counter with Inc(), Add(n int64)
  • NewLabeledCounter(name, help, labels) *LabeledCounter — per-label-combination counter with Inc(vals...)
Gauges
  • NewGauge(name, help) *Gauge — float64 gauge with Set(float64), Add(float64), Sub(float64), Inc(), Dec(), Get()
  • NewLabeledGauge(name, help, labels) *LabeledGauge — per-label gauge with Set(float64, vals...)
Histograms
  • NewHistogram(name, help, opts ...Option) *Histogram — histogram with Observe(seconds); uses DefaultBuckets unless WithBuckets is provided
  • NewLabeledHistogram(name, help, labels, opts ...Option) *LabeledHistogram — labeled histogram with Observe(seconds, vals...)
  • WithBuckets([]float64) Option — sets custom bucket boundaries
  • FormatBound(float64) string — formats a bucket boundary for Prometheus output
  • type Option func(*histogramCfg) — functional option for histogram configuration
Timer
  • NewTimer(h *Histogram) *Timer — starts a timer; call ObserveDuration() to record elapsed time
Registry
  • NewRegistry(prefix) *Registry — collects metrics; Handler() returns http.HandlerFunc
  • RegisterCounter, RegisterGauge, RegisterLabeledCounter, RegisterLabeledGauge, RegisterHistogram, RegisterLabeledHistogram
  • EnableImageMetrics() — enables image metric output in handlers
  • OpenMetricsHandler() — returns handler serving OpenMetrics text format (1.0.0)
  • NegotiateHandler() — returns handler with content negotiation (OpenMetrics if Accept header requests it, otherwise Prometheus text)
Image Metrics
  • SetImageMetrics([]ImageMetric) — set per-image gauge data
Process Metrics (emitted automatically)
  • process_goroutines, process_heap_bytes, process_gc_pause_seconds_total, process_uptime_seconds
  • process_start_time_seconds, process_cpu_seconds_total (Linux), process_resident_memory_bytes (Linux)
  • process_open_fds, process_max_fds (Linux)
Low-level Writers
  • WriteCounter, WriteGauge, WriteLabeledCounter, WriteLabeledGauge, WriteHistogram, WriteLabeledHistogram, WriteImageMetrics, WriteProcessMetrics

Spec Conformance

This library emits valid Prometheus text exposition format (version 0.0.4):

  • Label values are escaped per spec: only \, ", and \n are escaped (as \\, \", \n)
  • HELP text escapes \ and \n only
  • Metric and label names are validated at creation time ([a-zA-Z_:][a-zA-Z0-9_:]* for metrics, [a-zA-Z_][a-zA-Z0-9_]* for labels)
  • Label arity is enforced (panics on mismatch)
  • Histograms always include +Inf bucket equal to _count
OpenMetrics Text Format

Full support for OpenMetrics text exposition format 1.0.0 (the CNCF-standard successor to Prometheus format):

  • Content-Type: application/openmetrics-text; version=1.0.0; charset=utf-8
  • Exposition ends with mandatory # EOF line
  • TYPE metadata appears before HELP (per spec ordering)
  • Counter samples use _total suffix
  • Gauge values rendered as floats (e.g., 42.0)
  • Content negotiation via NegotiateHandler() (responds to Accept header)
  • Direct access via OpenMetricsHandler()

Unsupported by Design (SKIP List)

The following features are intentionally not implemented:

Feature Reason
Summary metric type Prometheus best practices recommend histograms; complex windowed-quantile implementation for no consumer benefit
Exemplars (OpenMetrics) Niche; requires tracing integration and adds complexity for a feature most scrapers ignore
Push / remote-write All consumers are pull-based
Protobuf exposition format Text format is default in Prometheus 3.0; protobuf requires code generation
Native histograms (exponential buckets) Requires protobuf format; large specialized implementation
Unregister / dynamic metric lifecycle All consumers have static metric sets
Float64 counter Integer counters are sufficient for all consumers
Gzip response compression Use standard HTTP middleware
Gauge.SetToCurrentTime() Trivial one-liner users can write themselves

License

GPL-3.0 — see LICENSE.

Documentation

Overview

Package metrics provides a hand-rolled Prometheus text-format exposition library. It requires only the Go standard library.

Both Prometheus text format (0.0.4) and OpenMetrics text format (1.0.0) are supported. Use Handler() for Prometheus format, OpenMetricsHandler() for OpenMetrics, or NegotiateHandler() for automatic content negotiation based on the Accept header.

Unsupported by design (SKIP list):

  • Summary metric type: Prometheus best practices recommend histograms
  • Exemplars (OpenMetrics): niche; requires tracing integration
  • Push / remote-write: all consumers are pull-based
  • Protobuf exposition format: text format is default in Prometheus 3.0
  • Native histograms (exponential buckets): requires protobuf format
  • Unregister / dynamic metric lifecycle: all consumers have static metric sets
  • Float64 counter: integer counters are sufficient
  • Gzip response compression: use standard HTTP middleware
  • Gauge.SetToCurrentTime(): trivial one-liner
Example
package main

import (
	"net/http"

	"github.com/cplieger/metrics"
)

func main() {
	r := metrics.NewRegistry("myapp")
	reqs := metrics.NewLabeledCounter("myapp_http_requests_total", "Total HTTP requests", []string{"method", "status"})
	dur := metrics.NewHistogram("myapp_http_duration_seconds", "Request latency", metrics.WithBuckets([]float64{0.01, 0.05, 0.1, 0.5, 1, 5}))
	r.RegisterLabeledCounter(reqs)
	r.RegisterHistogram(dur)

	reqs.Inc("GET", "200")

	timer := metrics.NewTimer(dur)
	_ = timer
	timer.ObserveDuration()

	http.Handle("/metrics", r.Handler())
}

Index

Examples

Constants

View Source
const OpenMetricsContentType = "application/openmetrics-text; version=1.0.0; charset=utf-8"

OpenMetricsContentType is the content type per the OpenMetrics specification.

Variables

View Source
var DefaultBuckets = []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0}

DefaultBuckets are the default histogram bucket boundaries (HTTP latency).

Functions

func FormatBound

func FormatBound(v float64) string

FormatBound formats a bucket boundary for Prometheus output.

func WriteCounter

func WriteCounter(b *strings.Builder, c *Counter)

WriteCounter writes a counter in Prometheus text format.

func WriteGauge

func WriteGauge(b *strings.Builder, g *Gauge)

WriteGauge writes a gauge in Prometheus text format.

func WriteHistogram

func WriteHistogram(b *strings.Builder, h *Histogram)

WriteHistogram writes a histogram in Prometheus text format.

func WriteLabeledCounter

func WriteLabeledCounter(b *strings.Builder, lc *LabeledCounter)

WriteLabeledCounter writes a labeled counter in Prometheus text format.

func WriteLabeledGauge

func WriteLabeledGauge(b *strings.Builder, lg *LabeledGauge)

WriteLabeledGauge writes a labeled gauge in Prometheus text format.

func WriteLabeledHistogram

func WriteLabeledHistogram(b *strings.Builder, lh *LabeledHistogram)

WriteLabeledHistogram writes all child histograms in Prometheus text format.

func WriteProcessMetrics

func WriteProcessMetrics(b *strings.Builder, startTime time.Time)

WriteProcessMetrics writes Go runtime and standard process metrics.

Types

type Counter

type Counter struct {
	// contains filtered or unexported fields
}

Counter is a monotonically increasing counter.

func NewCounter

func NewCounter(name, help string) *Counter

NewCounter creates a named counter.

func (*Counter) Add

func (c *Counter) Add(n int64)

Add increments the counter by n. Panics if n < 0.

func (*Counter) Inc

func (c *Counter) Inc()

Inc increments the counter by 1.

type Gauge

type Gauge struct {
	// contains filtered or unexported fields
}

Gauge is a value that can go up and down (float64).

func NewGauge

func NewGauge(name, help string) *Gauge

NewGauge creates a named gauge.

func (*Gauge) Add

func (g *Gauge) Add(delta float64)

Add adds a float64 delta to the gauge.

func (*Gauge) Dec

func (g *Gauge) Dec()

Dec decrements the gauge by 1.

func (*Gauge) Get

func (g *Gauge) Get() float64

Get returns the current gauge value.

func (*Gauge) Inc

func (g *Gauge) Inc()

Inc increments the gauge by 1.

func (*Gauge) Set

func (g *Gauge) Set(v float64)

Set sets the gauge to an arbitrary float64 value.

func (*Gauge) Sub

func (g *Gauge) Sub(delta float64)

Sub subtracts a float64 delta from the gauge.

type Histogram

type Histogram struct {
	// contains filtered or unexported fields
}

Histogram tracks a distribution using cumulative buckets and atomic CAS for sum.

func NewHistogram

func NewHistogram(name, help string, opts ...Option) *Histogram

NewHistogram creates a histogram with the given name and help text. By default it uses DefaultBuckets; use WithBuckets to override.

func (*Histogram) Observe

func (h *Histogram) Observe(seconds float64)

Observe records a value in the histogram.

type LabeledCounter

type LabeledCounter struct {
	// contains filtered or unexported fields
}

LabeledCounter tracks counts per label combination.

func NewLabeledCounter

func NewLabeledCounter(name, help string, labels []string) *LabeledCounter

NewLabeledCounter creates a labeled counter with the given label names.

func (*LabeledCounter) Inc

func (lc *LabeledCounter) Inc(labelVals ...string)

Inc increments the counter for the given label values.

type LabeledGauge

type LabeledGauge struct {
	// contains filtered or unexported fields
}

LabeledGauge tracks gauges per label combination.

func NewLabeledGauge

func NewLabeledGauge(name, help string, labels []string) *LabeledGauge

NewLabeledGauge creates a labeled gauge.

func (*LabeledGauge) Delete

func (lg *LabeledGauge) Delete(labelVals ...string)

Delete removes a single label combination from the gauge. It panics if the number of label values does not match the label count.

func (*LabeledGauge) Reset

func (lg *LabeledGauge) Reset()

Reset removes all label combinations from the gauge.

func (*LabeledGauge) Set

func (lg *LabeledGauge) Set(v float64, labelVals ...string)

Set sets the gauge for the given label values.

type LabeledHistogram

type LabeledHistogram struct {
	// contains filtered or unexported fields
}

LabeledHistogram tracks histograms per label combination.

func NewLabeledHistogram

func NewLabeledHistogram(name, help string, labels []string, opts ...Option) *LabeledHistogram

NewLabeledHistogram creates a labeled histogram with the given name, help, and label names. By default it uses DefaultBuckets; use WithBuckets to override.

func (*LabeledHistogram) Observe

func (lh *LabeledHistogram) Observe(seconds float64, labelVals ...string)

Observe records a value for the given label values.

type Option

type Option func(*histogramCfg)

Option configures optional histogram parameters.

func WithBuckets

func WithBuckets(buckets []float64) Option

WithBuckets returns an Option that sets custom bucket boundaries for a histogram.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry holds a collection of metrics to be served.

func NewRegistry

func NewRegistry(prefix string) *Registry

NewRegistry creates a new metrics registry.

func (*Registry) Handler

func (r *Registry) Handler() http.HandlerFunc

Handler returns an HTTP handler serving Prometheus text format.

func (*Registry) NegotiateHandler

func (r *Registry) NegotiateHandler() http.HandlerFunc

NegotiateHandler returns an HTTP handler that performs content negotiation. If the client sends an Accept header preferring OpenMetrics, it responds in OpenMetrics text format; otherwise it falls back to Prometheus text format 0.0.4.

func (*Registry) OpenMetricsHandler

func (r *Registry) OpenMetricsHandler() http.HandlerFunc

OpenMetricsHandler returns an HTTP handler that always serves OpenMetrics text format.

func (*Registry) RegisterCounter

func (r *Registry) RegisterCounter(c *Counter)

RegisterCounter adds a counter to the registry.

func (*Registry) RegisterGauge

func (r *Registry) RegisterGauge(g *Gauge)

RegisterGauge adds a gauge to the registry.

func (*Registry) RegisterHistogram

func (r *Registry) RegisterHistogram(h *Histogram)

RegisterHistogram adds a histogram to the registry.

func (*Registry) RegisterLabeledCounter

func (r *Registry) RegisterLabeledCounter(lc *LabeledCounter)

RegisterLabeledCounter adds a labeled counter to the registry.

func (*Registry) RegisterLabeledGauge

func (r *Registry) RegisterLabeledGauge(lg *LabeledGauge)

RegisterLabeledGauge adds a labeled gauge to the registry.

func (*Registry) RegisterLabeledHistogram

func (r *Registry) RegisterLabeledHistogram(lh *LabeledHistogram)

RegisterLabeledHistogram adds a labeled histogram to the registry.

type Timer

type Timer struct {
	// contains filtered or unexported fields
}

Timer measures elapsed time and reports to a Histogram.

func NewTimer

func NewTimer(h *Histogram) *Timer

NewTimer starts a timer that will observe into the given histogram.

func (*Timer) ObserveDuration

func (t *Timer) ObserveDuration() time.Duration

ObserveDuration records the elapsed time since the timer was created.

Jump to

Keyboard shortcuts

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