metrics

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Jan 2, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package metrics provides Prometheus-based monitoring and metrics collection functionality for Go applications.

The metrics package is designed to provide a standardized observability approach with dual HTTP endpoints for system-level and application-level metrics, full control over metric definitions, and integration with the Fx dependency injection framework for easy incorporation into Aleph Alpha services.

Architecture

This package follows the "accept interfaces, return structs" design pattern:

  • MetricsCollector interface: Defines the contract for metrics operations
  • Metrics struct: Concrete implementation of the MetricsCollector interface
  • NewMetrics constructor: Returns *Metrics (concrete type)
  • FX module: Provides both *Metrics and MetricsCollector interface for dependency injection

Dual Endpoint Design

The package provides two separate Prometheus endpoints:

1. System Metrics Endpoint (default: :9090)

  • Go runtime metrics (goroutines, memory, GC stats)
  • Process metrics (CPU, file descriptors, memory)
  • Build info metrics
  • Automatically registered, no user action required

2. Application Metrics Endpoint (default: :9091)

  • User-defined custom metrics only
  • Full control over metric names, types, and labels
  • No default metrics - clean slate for application observability

This separation allows:

  • Different scrape configurations (e.g., system metrics every 15s, app metrics every 5s)
  • Different access controls (e.g., system metrics internal-only)
  • Cleaner organization and cardinality management

Core Features

  • Two configurable /metrics endpoints for Prometheus scraping
  • Integration with go.uber.org/fx for automatic lifecycle management
  • Support for all Prometheus metric types (Counter, Gauge, Histogram, Summary)
  • User-defined metrics with custom labels
  • Automatic service label wrapping for multi-service observability
  • Graceful startup and shutdown via Fx lifecycle hooks

Direct Usage (Without FX)

For simple applications or tests, create metrics directly:

import "github.com/Aleph-Alpha/std/v1/metrics"

// Create metrics servers (returns concrete *Metrics)
cfg := metrics.Config{
	SystemMetricsAddress:      ":9090",
	ApplicationMetricsAddress: ":9091",
	ServiceName:               "search-store",
}

m := metrics.NewMetrics(cfg)

// Start both servers
go m.SystemServer.ListenAndServe()
go m.ApplicationServer.ListenAndServe()

// Create custom application metrics
requestCounter := m.CreateCounter(
	"http_requests_total",
	"Total HTTP requests",
	[]string{"method", "status"},
)
requestCounter.WithLabelValues("GET", "200").Inc()

// Access metrics:
// - System: http://localhost:9090/metrics
// - Application: http://localhost:9091/metrics

FX Module Integration

For production applications using Uber's fx, use the FXModule which provides both the concrete type and interface:

import (
	"go.uber.org/fx"
	"github.com/Aleph-Alpha/std/v1/metrics"
	"github.com/Aleph-Alpha/std/v1/logger"
)

app := fx.New(
	logger.FXModule, // Optional: provides std logger
	metrics.FXModule, // Provides *Metrics and MetricsCollector interface
	fx.Provide(func() metrics.Config {
		return metrics.Config{
			SystemMetricsAddress:      ":9090",
			ApplicationMetricsAddress: ":9091",
			ServiceName:               "search-store",
		}
	}),
	fx.Invoke(func(m metrics.MetricsCollector) {
		// Define application metrics
		counter := m.CreateCounter(
			"requests_processed",
			"Total processed requests",
			[]string{"status"},
		)
		counter.WithLabelValues("success").Inc()
	}),
)
app.Run()

Type Aliases in Consumer Code

To simplify your code and make it metrics-agnostic, use type aliases:

package myapp

import stdMetrics "github.com/Aleph-Alpha/std/v1/metrics"

// Use type alias to reference std's interface
type MetricsCollector = stdMetrics.MetricsCollector

// Now use MetricsCollector throughout your codebase
func MyFunction(metrics MetricsCollector) {
	counter := metrics.CreateCounter("my_counter", "My counter", []string{"label"})
	counter.WithLabelValues("value").Inc()
}

This eliminates the need for adapters and allows you to switch implementations by only changing the alias definition.

Configuration

The metrics servers can be configured via environment variables:

METRICS_SYSTEM_ADDRESS=:9090          # System metrics endpoint address
METRICS_APPLICATION_ADDRESS=:9091     # Application metrics endpoint address
METRICS_SERVICE_NAME=search-store     # Adds service label to all metrics

Set an address to empty string ("") to disable that endpoint:

cfg := metrics.Config{
	SystemMetricsAddress:      "",      // Disable system metrics
	ApplicationMetricsAddress: ":9091", // Only application metrics
	ServiceName:               "search-store",
}

Metric Types and Usage Examples

## 1. Counter - Cumulative metrics that only increase

Use counters for tracking totals (requests, errors, bytes processed):

requestCounter := m.CreateCounter(
	"http_requests_total",
	"Total number of HTTP requests",
	[]string{"method", "status", "endpoint"},
)

// In your HTTP handler:
requestCounter.WithLabelValues("GET", "200", "/api/search").Inc()
requestCounter.WithLabelValues("POST", "500", "/api/index").Inc()

## 2. Gauge - Values that can go up or down

Use gauges for current state (active connections, queue depth, temperature):

activeConnections := m.CreateGauge(
	"active_database_connections",
	"Number of active database connections",
	[]string{"pool"},
)

// Track connection pool size
activeConnections.WithLabelValues("postgres").Set(25)
activeConnections.WithLabelValues("postgres").Inc()  // Add 1
activeConnections.WithLabelValues("postgres").Dec()  // Subtract 1
activeConnections.WithLabelValues("postgres").Add(5) // Add 5

## 3. Histogram - Distribution tracking with quantiles

Use histograms for latency, request sizes, or any value distribution:

requestDuration := m.CreateHistogram(
	"http_request_duration_seconds",
	"HTTP request duration in seconds",
	[]string{"method", "endpoint"},
	[]float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}, // buckets
)

// In your HTTP handler:
start := time.Now()
// ... handle request ...
duration := time.Since(start).Seconds()
requestDuration.WithLabelValues("GET", "/api/search").Observe(duration)

Prometheus will automatically calculate:

  • Quantiles (p50, p95, p99)
  • Count of observations
  • Sum of all observed values

## 4. Summary - Client-side streaming quantiles

Use summaries when you need precise quantile calculations on the client side:

apiLatency := m.CreateSummary(
	"api_request_latency_seconds",
	"API request latency in seconds",
	[]string{"endpoint"},
	map[float64]float64{
		0.5:  0.05,  // 50th percentile (median) with 5% error
		0.9:  0.01,  // 90th percentile with 1% error
		0.99: 0.001, // 99th percentile with 0.1% error
	},
)

// In your API handler:
start := time.Now()
// ... process request ...
apiLatency.WithLabelValues("/api/search").Observe(time.Since(start).Seconds())

Complete HTTP Middleware Example

Here's a complete example of HTTP request instrumentation:

package main

import (
	"net/http"
	"time"

	"go.uber.org/fx"
	"github.com/Aleph-Alpha/std/v1/metrics"
	"github.com/Aleph-Alpha/std/v1/logger"
)

type HTTPMetrics struct {
	RequestsTotal   metrics.Counter
	RequestDuration metrics.Histogram
	RequestSize     metrics.Histogram
	ResponseSize    metrics.Histogram
	ActiveRequests  metrics.Gauge
}

func NewHTTPMetrics(m metrics.MetricsCollector) *HTTPMetrics {
	return &HTTPMetrics{
		RequestsTotal: m.CreateCounter(
			"http_requests_total",
			"Total number of HTTP requests",
			[]string{"method", "endpoint", "status"},
		),
		RequestDuration: m.CreateHistogram(
			"http_request_duration_seconds",
			"HTTP request duration in seconds",
			[]string{"method", "endpoint"},
			[]float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
		),
		RequestSize: m.CreateHistogram(
			"http_request_size_bytes",
			"HTTP request size in bytes",
			[]string{"method", "endpoint"},
			exponentialBuckets(100, 10, 8), // 100, 1000, 10000, ...
		),
		ResponseSize: m.CreateHistogram(
			"http_response_size_bytes",
			"HTTP response size in bytes",
			[]string{"method", "endpoint"},
			exponentialBuckets(100, 10, 8),
		),
		ActiveRequests: m.CreateGauge(
			"http_requests_active",
			"Number of active HTTP requests",
			[]string{"method", "endpoint"},
		),
	}
}

func (hm *HTTPMetrics) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		endpoint := r.URL.Path
		method := r.Method

		// Track active requests
		hm.ActiveRequests.WithLabelValues(method, endpoint).Inc()
		defer hm.ActiveRequests.WithLabelValues(method, endpoint).Dec()

		// Track request size
		if r.ContentLength > 0 {
			hm.RequestSize.WithLabelValues(method, endpoint).Observe(float64(r.ContentLength))
		}

		// Capture response
		wrw := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
		next.ServeHTTP(wrw, r)

		// Record metrics
		duration := time.Since(start).Seconds()
		status := fmt.Sprintf("%d", wrw.statusCode)

		hm.RequestsTotal.WithLabelValues(method, endpoint, status).Inc()
		hm.RequestDuration.WithLabelValues(method, endpoint).Observe(duration)
		hm.ResponseSize.WithLabelValues(method, endpoint).Observe(float64(wrw.bytesWritten))
	})
}

type responseWriter struct {
	http.ResponseWriter
	statusCode   int
	bytesWritten int
}

func (rw *responseWriter) WriteHeader(code int) {
	rw.statusCode = code
	rw.ResponseWriter.WriteHeader(code)
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	n, err := rw.ResponseWriter.Write(b)
	rw.bytesWritten += n
	return n, err
}

func main() {
	app := fx.New(
		logger.FXModule,
		metrics.FXModule,
		fx.Provide(
			func() metrics.Config {
				return metrics.Config{
					SystemMetricsAddress:      ":9090",
					ApplicationMetricsAddress: ":9091",
					ServiceName:               "api-gateway",
				}
			},
			NewHTTPMetrics,
		),
		fx.Invoke(func(hm *HTTPMetrics) {
			// Your HTTP server setup with middleware
			mux := http.NewServeMux()
			mux.HandleFunc("/api/search", handleSearch)

			server := &http.Server{
				Addr:    ":8080",
				Handler: hm.Middleware(mux),
			}

			go server.ListenAndServe()
		}),
	)
	app.Run()
}

Database Metrics Example

Track database operations with detailed labels:

type DBMetrics struct {
	QueriesTotal    metrics.Counter
	QueryDuration   metrics.Histogram
	ActiveConns     metrics.Gauge
	QueryErrors     metrics.Counter
}

func NewDBMetrics(m metrics.MetricsCollector) *DBMetrics {
	return &DBMetrics{
		QueriesTotal: m.CreateCounter(
			"db_queries_total",
			"Total number of database queries",
			[]string{"operation", "table"},
		),
		QueryDuration: m.CreateHistogram(
			"db_query_duration_seconds",
			"Database query duration in seconds",
			[]string{"operation", "table"},
			[]float64{.001, .005, .01, .025, .05, .1, .25, .5, 1, 2.5},
		),
		ActiveConns: m.CreateGauge(
			"db_connections_active",
			"Number of active database connections",
			[]string{"pool"},
		),
		QueryErrors: m.CreateCounter(
			"db_query_errors_total",
			"Total number of database query errors",
			[]string{"operation", "table", "error_type"},
		),
	}
}

// Usage in database layer:
func (db *Database) Query(ctx context.Context, query string) error {
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		db.metrics.QueryDuration.WithLabelValues("select", "documents").Observe(duration)
	}()

	db.metrics.QueriesTotal.WithLabelValues("select", "documents").Inc()

	err := db.conn.QueryContext(ctx, query)
	if err != nil {
		db.metrics.QueryErrors.WithLabelValues("select", "documents", "timeout").Inc()
		return err
	}

	return nil
}

Business Metrics Example

Track application-specific business metrics:

type BusinessMetrics struct {
	DocumentsIndexed    metrics.Counter
	SearchesPerformed   metrics.Counter
	ActiveUsers         metrics.Gauge
	DocumentProcessTime metrics.Histogram
	CacheHits           metrics.Counter
}

func NewBusinessMetrics(m metrics.MetricsCollector) *BusinessMetrics {
	return &BusinessMetrics{
		DocumentsIndexed: m.CreateCounter(
			"documents_indexed_total",
			"Total number of documents indexed",
			[]string{"type", "status"},
		),
		SearchesPerformed: m.CreateCounter(
			"searches_performed_total",
			"Total number of search queries performed",
			[]string{"type", "result_count_bucket"},
		),
		ActiveUsers: m.CreateGauge(
			"active_users",
			"Number of currently active users",
			[]string{"tier"},
		),
		DocumentProcessTime: m.CreateHistogram(
			"document_processing_seconds",
			"Time to process a document",
			[]string{"type", "stage"},
			[]float64{.1, .5, 1, 2, 5, 10, 30, 60},
		),
		CacheHits: m.CreateCounter(
			"cache_operations_total",
			"Total cache operations",
			[]string{"cache", "operation", "result"},
		),
	}
}

Performance Considerations

1. Label Cardinality:

  • Keep label values bounded (avoid user IDs, request IDs, timestamps)
  • High cardinality can cause memory issues
  • Good: []string{"method", "status"} with ~10 combinations
  • Bad: []string{"user_id"} with millions of users

2. Metric Updates:

  • All Prometheus metric operations are thread-safe
  • Prefer gauges over counters when values can decrease
  • Use histograms for latency tracking (more efficient than summaries)

3. Histogram vs Summary:

  • Histograms: Server-side quantile calculation, aggregatable across instances
  • Summaries: Client-side quantile calculation, NOT aggregatable
  • Prefer histograms unless you need precise quantiles per instance

Thread Safety

All methods on the Metrics struct and all Prometheus collectors are safe for concurrent use by multiple goroutines. No additional synchronization is needed.

Observability

Exposed metrics can be scraped by Prometheus and visualized in Grafana or any compatible monitoring system. Example Prometheus scrape config:

scrape_configs:
  - job_name: 'system-metrics'
    static_configs:
      - targets: ['localhost:9090']
    scrape_interval: 15s

  - job_name: 'application-metrics'
    static_configs:
      - targets: ['localhost:9091']
    scrape_interval: 5s

Testing

For unit tests, you can create a metrics instance without starting the servers:

func TestMyFunction(t *testing.T) {
	cfg := metrics.Config{
		SystemMetricsAddress:      "",      // Disable
		ApplicationMetricsAddress: ":0",    // Random port
		ServiceName:               "test",
	}
	m := metrics.NewMetrics(cfg)

	counter := m.CreateCounter("test_counter", "Test counter", []string{"label"})
	counter.WithLabelValues("test").Inc()

	// Verify metrics using prometheus/testutil
	// ...
}

Index

Constants

View Source
const (
	DefaultSystemMetricsAddress      = ":9090"
	DefaultApplicationMetricsAddress = ":9091"
)

Default addresses for metrics servers if none is specified.

Variables

FXModule defines the Fx module for the metrics package. This module integrates two separate Prometheus metrics servers into an Fx-based application by providing the Metrics factory and registering lifecycle hooks for both servers.

The module provides: 1. *Metrics (concrete type) for direct use 2. MetricsCollector interface for dependency injection 3. Lifecycle management for both system and application metrics HTTP servers

System Metrics Endpoint (default: :9090):

  • Go runtime metrics (goroutines, memory, GC)
  • Process metrics (CPU, file descriptors)
  • Build info metrics

Application Metrics Endpoint (default: :9091):

  • User-defined custom metrics created via CreateCounter, CreateGauge, etc.

Usage:

app := fx.New(
    metrics.FXModule,
    fx.Provide(func() metrics.Config {
        return metrics.Config{
            SystemMetricsAddress:      ":9090",
            ApplicationMetricsAddress: ":9091",
            ServiceName:               "search-store",
        }
    }),
    fx.Invoke(func(m metrics.MetricsCollector) {
        // Create custom metrics
        counter := m.CreateCounter("requests_total", "Total requests", []string{"endpoint"})
        counter.WithLabelValues("/api/search").Inc()
    }),
)

Dependencies required by this module: - A metrics.Config instance must be available in the dependency injection container - A logger.LoggerClient instance is optional but recommended for startup/shutdown logs

Functions

func Ptr added in v0.12.0

func Ptr(s string) *string

Ptr returns a pointer to the given string value. Helper function for disabling endpoints in configuration.

Example:

cfg := metrics.Config{
    SystemMetricsAddress: metrics.Ptr(""),     // Explicitly disable
    ApplicationMetricsAddress: nil,            // Use default
    ServiceName: "my-service",
}

func RegisterMetricsLifecycle

func RegisterMetricsLifecycle(lc fx.Lifecycle, m *Metrics, log *logger.LoggerClient)

RegisterMetricsLifecycle manages the startup and shutdown lifecycle of both Prometheus metrics HTTP servers (system and application).

Parameters:

  • lc: The Fx lifecycle controller
  • m: The Metrics instance containing both HTTP servers
  • log: The logger instance for structured lifecycle logging (optional)

The lifecycle hook:

  • OnStart: Launches both metrics servers in background goroutines
  • OnStop: Gracefully shuts down both servers

This ensures that both metrics endpoints are available for scraping during the application's lifetime and shut down cleanly when the application stops.

Note: This function is automatically invoked by the FXModule and does not need to be called directly in application code.

Types

type Config

type Config struct {
	// SystemMetricsAddress determines the network address where the system
	// metrics HTTP server listens. This endpoint exposes Go runtime,
	// process, and build info metrics.
	//
	// Example values:
	//   - ":9090"   → Listen on all interfaces, port 9090
	//   - "127.0.0.1:9090" → Listen only on localhost, port 9090
	//   - nil (or omitted) → Use default ":9090"
	//
	// To disable the system metrics endpoint, use an empty string pointer:
	//   SystemMetricsAddress: ptr(""),
	//
	// This setting can be configured via:
	//   - YAML configuration with the "system_metrics_address" key
	//   - Environment variable METRICS_SYSTEM_ADDRESS
	//
	// Default: ":9090"
	SystemMetricsAddress *string `yaml:"system_metrics_address" envconfig:"METRICS_SYSTEM_ADDRESS"`

	// ApplicationMetricsAddress determines the network address where the
	// application metrics HTTP server listens. This endpoint exposes
	// user-defined custom metrics created via CreateCounter, CreateGauge, etc.
	//
	// Example values:
	//   - ":9091"   → Listen on all interfaces, port 9091
	//   - "127.0.0.1:9091" → Listen only on localhost, port 9091
	//   - nil (or omitted) → Use default ":9091"
	//
	// To disable the application metrics endpoint, use an empty string pointer:
	//   ApplicationMetricsAddress: ptr(""),
	//
	// This setting can be configured via:
	//   - YAML configuration with the "application_metrics_address" key
	//   - Environment variable METRICS_APPLICATION_ADDRESS
	//
	// Default: ":9091"
	ApplicationMetricsAddress *string `yaml:"application_metrics_address" envconfig:"METRICS_APPLICATION_ADDRESS"`

	// ServiceName identifies the service exposing metrics.
	// This is used as a common label in all metrics to help
	// distinguish metrics between services in multi-tenant deployments.
	//
	// Example:
	//   ServiceName: "document-index"
	//   → metrics include label service="document-index"
	//
	// This setting can be configured via:
	//   - YAML configuration with the "service_name" key
	//   - Environment variable METRICS_SERVICE_NAME
	ServiceName string `yaml:"service_name" envconfig:"METRICS_SERVICE_NAME"`
}

Config defines the configuration structure for the Prometheus metrics servers. It contains settings that control how metrics are exposed and collected.

The package provides two separate metrics endpoints: 1. System Metrics Endpoint (default: :9090): Exposes Go runtime, process, and build info metrics 2. Application Metrics Endpoint (default: :9091): Exposes user-defined application-specific metrics

type Counter added in v0.12.0

type Counter interface {
	// WithLabelValues returns the Counter for the given label values.
	// The number of label values must match the number of labels defined
	// when the counter was created.
	WithLabelValues(lvs ...string) Counter

	// Inc increments the counter by 1.
	Inc()

	// Add adds the given value to the counter. The value must be >= 0.
	Add(val float64)
}

Counter represents a cumulative metric that only increases. It is used to track totals such as request counts, errors, or bytes processed.

This interface abstracts the underlying Prometheus CounterVec implementation.

type Gauge added in v0.12.0

type Gauge interface {
	// WithLabelValues returns the Gauge for the given label values.
	// The number of label values must match the number of labels defined
	// when the gauge was created.
	WithLabelValues(lvs ...string) Gauge

	// Set sets the gauge to an arbitrary value.
	Set(val float64)

	// Inc increments the gauge by 1.
	Inc()

	// Dec decrements the gauge by 1.
	Dec()

	// Add adds the given value to the gauge. The value can be negative.
	Add(val float64)

	// Sub subtracts the given value from the gauge. The value can be negative.
	Sub(val float64)

	// SetToCurrentTime sets the gauge to the current Unix timestamp in seconds.
	SetToCurrentTime()
}

Gauge represents a metric that can arbitrarily go up and down. It is used for values like active connections, temperature, or queue depth.

This interface abstracts the underlying Prometheus GaugeVec implementation.

type Histogram added in v0.12.0

type Histogram interface {
	// WithLabelValues returns the Histogram (Observer) for the given label values.
	// The number of label values must match the number of labels defined
	// when the histogram was created.
	WithLabelValues(lvs ...string) Observer

	// Observe adds a single observation to the histogram.
	Observe(val float64)
}

Histogram tracks the distribution of observations (e.g., request durations or response sizes). Histograms calculate quantiles, counts, and sums on the server side.

This interface abstracts the underlying Prometheus HistogramVec implementation.

type Metrics

type Metrics struct {
	// SystemServer defines the HTTP server for the /metrics endpoint exposing
	// Go runtime, process, and build info metrics.
	// Endpoint: SystemMetricsAddress (default: :9090)
	SystemServer *http.Server

	// ApplicationServer defines the HTTP server for the /metrics endpoint exposing
	// user-defined application metrics.
	// Endpoint: ApplicationMetricsAddress (default: :9091)
	ApplicationServer *http.Server

	// SystemRegistry is the Prometheus registry for system-level metrics
	// (Go runtime, process collectors, build info).
	SystemRegistry *prometheus.Registry

	// ApplicationRegistry is the Prometheus registry for user-defined metrics.
	// All metrics created via CreateCounter, CreateGauge, CreateHistogram, CreateSummary
	// are registered here.
	ApplicationRegistry *prometheus.Registry
	// contains filtered or unexported fields
}

Metrics encapsulates two separate Prometheus registries and HTTP servers: 1. System metrics (Go runtime, process, build info) - exposed on SystemServer 2. Application metrics (user-defined custom metrics) - exposed on ApplicationServer

This separation allows different scrape configurations and access controls for system-level vs application-level observability.

func NewMetrics

func NewMetrics(cfg Config) *Metrics

NewMetrics initializes and returns a new instance of the Metrics struct. It sets up two separate Prometheus registries and HTTP servers:

1. System Metrics Endpoint (default: :9090):

  • Go runtime metrics (goroutines, GC stats, heap usage)
  • Process metrics (CPU time, memory, file descriptors)
  • Build info metrics

2. Application Metrics Endpoint (default: :9091):

  • User-defined metrics created via CreateCounter, CreateGauge, etc.
  • No default metrics - fully controlled by the application

Parameters:

  • cfg: Configuration for the metrics servers, including addresses and service name

Returns:

  • *Metrics: A configured Metrics instance ready for lifecycle management and Fx module integration

Both registries automatically wrap all metrics with a constant `service` label for easier aggregation and filtering in multi-service environments.

Example:

cfg := metrics.Config{
    SystemMetricsAddress:      ":9090",
    ApplicationMetricsAddress: ":9091",
    ServiceName:               "document-index",
}
metricsInstance := metrics.NewMetrics(cfg)
go metricsInstance.SystemServer.ListenAndServe()
go metricsInstance.ApplicationServer.ListenAndServe()

Access metrics at:

func (*Metrics) CreateCounter

func (m *Metrics) CreateCounter(name, help string, labels []string) Counter

CreateCounter creates a new counter metric and registers it to the application metrics registry.

Counters are cumulative metrics that only increase (e.g., total requests, errors).

Example:

counter := m.CreateCounter("http_requests_total", "Total HTTP requests", []string{"method", "status"})
counter.WithLabelValues("GET", "200").Inc()
counter.WithLabelValues("POST", "500").Inc()

func (*Metrics) CreateGauge

func (m *Metrics) CreateGauge(name, help string, labels []string) Gauge

CreateGauge creates a new gauge metric and registers it to the application metrics registry.

Gauges represent values that can go up or down (e.g., active connections, temperature, queue depth).

Example:

gauge := m.CreateGauge("active_connections", "Number of active connections", []string{"pool"})
gauge.WithLabelValues("postgres").Set(42)
gauge.WithLabelValues("postgres").Inc()
gauge.WithLabelValues("postgres").Dec()

func (*Metrics) CreateHistogram

func (m *Metrics) CreateHistogram(name, help string, labels []string, buckets []float64) Histogram

CreateHistogram creates a new histogram metric and registers it to the application metrics registry.

Histograms track distributions of values (e.g., request latencies) and automatically calculate quantiles and counts.

Example:

hist := m.CreateHistogram(
    "request_duration_seconds",
    "Request duration in seconds",
    []string{"endpoint"},
    []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
)
hist.WithLabelValues("/api/search").Observe(0.25)

func (*Metrics) CreateSummary added in v0.12.0

func (m *Metrics) CreateSummary(name, help string, labels []string, objectives map[float64]float64) Summary

CreateSummary creates a new summary metric and registers it to the application metrics registry.

Summaries calculate streaming quantiles on the client side. Objectives define the quantile ranks and their allowed error.

Example:

summary := m.CreateSummary(
    "api_latency_seconds",
    "API request latency in seconds",
    []string{"endpoint"},
    map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
)
summary.WithLabelValues("/api/search").Observe(0.25)

type MetricsCollector added in v0.12.0

type MetricsCollector interface {
	// CreateCounter creates a new counter metric and registers it to the
	// application metrics registry.
	//
	// Counters are cumulative metrics that only increase over time (e.g., total requests).
	// Use WithLabelValues to set specific label values before incrementing.
	//
	// Example:
	//   counter := m.CreateCounter("http_requests_total", "Total HTTP requests", []string{"method", "status"})
	//   counter.WithLabelValues("GET", "200").Inc()
	CreateCounter(name, help string, labels []string) Counter

	// CreateHistogram creates a new histogram metric and registers it to the
	// application metrics registry.
	//
	// Histograms track distributions of values (e.g., request durations) and automatically
	// calculate quantiles and counts across configurable buckets.
	//
	// Example:
	//   hist := m.CreateHistogram("request_duration_seconds", "Request duration", []string{"endpoint"}, []float64{.01, .05, .1, .5, 1, 5})
	//   hist.WithLabelValues("/api/search").Observe(0.25)
	CreateHistogram(name, help string, labels []string, buckets []float64) Histogram

	// CreateGauge creates a new gauge metric and registers it to the
	// application metrics registry.
	//
	// Gauges represent values that can go up or down (e.g., active connections, temperature).
	// Use Set, Inc, Dec, Add, or Sub to modify gauge values.
	//
	// Example:
	//   gauge := m.CreateGauge("active_connections", "Number of active connections", []string{"pool"})
	//   gauge.WithLabelValues("postgres").Set(42)
	CreateGauge(name, help string, labels []string) Gauge

	// CreateSummary creates a new summary metric and registers it to the
	// application metrics registry.
	//
	// Summaries are similar to histograms but calculate streaming quantiles on the client side.
	// Objectives define the quantile ranks (e.g., 0.5 for median, 0.99 for 99th percentile).
	//
	// Example:
	//   summary := m.CreateSummary("api_latency_seconds", "API latency", []string{"endpoint"}, map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001})
	//   summary.WithLabelValues("/api/search").Observe(0.25)
	CreateSummary(name, help string, labels []string, objectives map[float64]float64) Summary
}

MetricsCollector provides an interface for collecting and exposing application metrics. It abstracts metric operations with support for counters, histograms, gauges, and summaries.

This interface is implemented by the concrete *Metrics type and does not expose any Prometheus-specific types, allowing for potential alternative implementations or testing mocks.

All metrics created through this interface are registered to the application metrics registry and exposed via the application metrics endpoint (default: :9091).

type Observer added in v0.12.0

type Observer interface {
	// Observe adds a single observation to the metric.
	Observe(val float64)
}

Observer is a common interface for metrics that observe values (Histogram and Summary).

type Summary added in v0.12.0

type Summary interface {
	// WithLabelValues returns the Summary (Observer) for the given label values.
	// The number of label values must match the number of labels defined
	// when the summary was created.
	WithLabelValues(lvs ...string) Observer

	// Observe adds a single observation to the summary.
	Observe(val float64)
}

Summary calculates streaming quantiles of observed values on the client side. Unlike histograms, summaries cannot be aggregated across multiple instances.

This interface abstracts the underlying Prometheus SummaryVec implementation.

Jump to

Keyboard shortcuts

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