metrics

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package metrics owns the caller's Prometheus instrumentation: the registry (with the standard process/runtime collectors), the HTTP request metrics observed by the middleware layer, and the background scheduler tick metrics recorded through the TickRecorder port. It is the only platform package that imports the Prometheus client directly; consumers (middleware, schedulers, the composition root) work through the types defined here so the instrumentation backend stays swappable behind one seam.

Every metric constructor here takes its namespace from the caller (see NewHTTPMetrics, NewPromTickRecorder) so more than one application can share this package on a common scrape target without their metric names colliding. This package defines no domain-specific metrics (e.g. calendar sync) — those stay in the consuming application, built on the same registry.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Handler

func Handler(reg *prometheus.Registry) http.Handler

Handler returns the HTTP scrape handler for reg, keeping the promhttp dependency inside this package so the composition root never imports the Prometheus client directly. The Registry option makes the handler report scrape errors (e.g. a collector failing mid-gather) as metrics on the same registry instead of failing silently. It panics when reg is nil (matching the platform convention of failing loudly at construction for required dependencies).

func NewRegistry

func NewRegistry() *prometheus.Registry

NewRegistry returns a fresh Prometheus registry pre-populated with the standard collectors: Go runtime metrics (goroutines, GC, memory), process metrics (CPU, RSS, fds), and build info (Go version, module version). A dedicated registry is used instead of prometheus.DefaultRegisterer so the exposed metric set is explicit and tests can build isolated registries without cross-test collisions.

Types

type HTTPMetrics

type HTTPMetrics struct {
	// RequestsTotal counts completed requests, labelled by method, matched
	// route pattern, and final status code (numeric string, e.g. "200").
	RequestsTotal *prometheus.CounterVec
	// RequestDuration observes request latency in seconds, labelled by method
	// and matched route pattern. Status is intentionally omitted to bound the
	// histogram's series count (each series carries a full bucket set).
	RequestDuration *prometheus.HistogramVec
	// RequestsInFlight gauges the number of requests currently being served.
	RequestsInFlight prometheus.Gauge
}

HTTPMetrics bundles the per-request HTTP metrics recorded by the Metrics middleware. The fields are exported so the middleware can record values and tests can assert on them with prometheus/testutil, but construction always goes through NewHTTPMetrics so every instance is registered.

func NewHTTPMetrics

func NewHTTPMetrics(reg prometheus.Registerer, namespace string) *HTTPMetrics

NewHTTPMetrics constructs the HTTP request metrics and registers them on reg, with every metric name prefixed by namespace (the fully-qualified name is "<namespace>_<Name>" — see prometheus.CounterOpts's own Namespace field) so more than one application can share a scrape target without their HTTP metrics colliding.

It panics when reg is nil or namespace is empty (matching the platform convention of failing loudly at construction for required dependencies — an empty namespace would silently emit unprefixed metric names that collide across apps on a shared scrape target) and when a metric with the same name is already registered, so a double-wired registry surfaces at boot rather than as silently shared counters.

type NopTickRecorder

type NopTickRecorder struct{}

NopTickRecorder is a no-op TickRecorder for tests and optional wiring where tick instrumentation is irrelevant.

func (NopTickRecorder) ObserveTick

ObserveTick discards the observation.

type PromTickRecorder

type PromTickRecorder struct {
	// TicksTotal counts completed scheduler cycles, labelled by scheduler name
	// and result ("success" or "error").
	TicksTotal *prometheus.CounterVec
	// TickDuration observes cycle duration in seconds, labelled by scheduler
	// name. Result is intentionally omitted to bound the histogram's series
	// count (each series carries a full bucket set).
	TickDuration *prometheus.HistogramVec
	// LastSuccess gauges the Unix timestamp of each scheduler's most recent
	// successful cycle; a failing cycle leaves it untouched, so a stale value
	// signals a scheduler that has stopped succeeding.
	LastSuccess *prometheus.GaugeVec
	// contains filtered or unexported fields
}

PromTickRecorder is the Prometheus-backed TickRecorder. The fields are exported so tests can assert on them with prometheus/testutil, but construction always goes through NewPromTickRecorder so every instance is registered.

func NewPromTickRecorder

func NewPromTickRecorder(reg prometheus.Registerer, namespace string, known []SchedulerName) *PromTickRecorder

NewPromTickRecorder constructs the scheduler tick metrics and registers them on reg, with every metric name prefixed by namespace (see NewHTTPMetrics for the namespacing mechanics) so more than one application can share a scrape target without their scheduler metrics colliding.

known is the caller's allowlist of canonical scheduler names; ObserveTick collapses any name outside it to the fixed "other" label so a misbehaving caller cannot mint unbounded series. An empty or nil known means every name collapses to "other" — a caller who forgets this argument sees a blank-looking scheduler dashboard rather than an unbounded label, which is the point.

It panics when reg is nil or namespace is empty (matching the platform convention of failing loudly at construction for required dependencies), when known contains the reserved SchedulerName("other") — that would let a legitimate scheduler share the collapsed-fallback series with every truly unknown name, defeating the point of the allowlist — and when a metric with the same name is already registered, so a double-wired registry surfaces at boot rather than as silently shared counters.

func (*PromTickRecorder) ObserveTick

func (r *PromTickRecorder) ObserveTick(name SchedulerName, d time.Duration, err error)

ObserveTick records one completed cycle: it increments the tick counter with the outcome derived from err, observes the cycle duration, and — on success only — moves the scheduler's last-success timestamp to now, so a failing scheduler's staleness is visible. A name outside r's known allowlist is collapsed to the fixed "other" label value so a misbehaving caller cannot mint unbounded series.

type SchedulerName

type SchedulerName string

SchedulerName identifies a background scheduler in the tick metrics' scheduler label. It is a distinct type (not a bare string) so callers must deliberately mint a value rather than accidentally passing arbitrary text; combined with PromTickRecorder collapsing names outside its constructor's allowlist to "other", the label's cardinality stays bounded even against misuse.

type TickRecorder

type TickRecorder interface {
	ObserveTick(name SchedulerName, d time.Duration, err error)
}

TickRecorder is the minimal port (ISP) a background scheduler records one completed poll cycle through: how long the cycle took and whether it failed. name should be one of the caller's own canonical scheduler names so the label set stays bounded; implementations collapse anything outside their known allowlist to a fixed fallback value. Implementations must be safe for concurrent use — a caller may run each scheduler in its own goroutine.

Jump to

Keyboard shortcuts

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