metrics

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package metrics wires Prometheus metrics into the proxy. Its fx Module provides a namespaced Factory bound to the injected Prometheus registry and serves that registry at /metrics over HTTP, binding the server to the fx application lifecycle. Consumers inject the Factory, optionally scoping it to a subsystem with Factory.ForSubsystem, to declare their collectors.

Index

Constants

This section is empty.

Variables

View Source
var (
	// AddrTag annotates the host:port the metrics HTTP server listens on,
	// supplied to fx as the named value "metricsAddr".
	AddrTag = fx.ResultTags(`name:"metricsAddr"`)

	// NamespaceTag annotates the Prometheus namespace prefixed onto every
	// collector, supplied to fx as the named value "metricsNamespace".
	NamespaceTag = fx.ResultTags(`name:"metricsNamespace"`)
)
View Source
var Module = fx.Options(
	fx.Provide(func(p MetricsParams) *Factory {
		return New(p.Namespace, promauto.With(p.Registerer))
	}),
	fx.Invoke(func(p MetricsParams) error {
		if p.Addr == "" {
			return errors.New("metrics addr not set")
		}

		mux := http.NewServeMux()
		mux.Handle("/metrics", promhttp.HandlerFor(p.Gatherer, promhttp.HandlerOpts{
			Registry: p.Registerer,
		}))

		svr := &http.Server{
			Addr:              p.Addr,
			Handler:           mux,
			ReadHeaderTimeout: 5 * time.Second,
			ReadTimeout:       10 * time.Second,
		}

		log := p.Logger.With(
			tag.Component("metrics"),
			tag.String("addr", p.Addr),
		)

		p.Lifecycle.Append(fx.Hook{
			OnStart: func(context.Context) error {
				go func() {
					defer func() { _ = svr.Close() }()

					log.Info("Starting metrics server")
					if err := svr.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
						log.Error("Failed to run metrics server", tag.Error(err))
						_ = p.Shutdowner.Shutdown(fx.ExitCode(1))
					}
				}()

				return nil
			},
			OnStop: func(ctx context.Context) error {
				log.Info("Shutting down metrics server")
				if err := svr.Shutdown(ctx); err != nil && !errors.Is(err, http.ErrServerClosed) {
					return err
				}

				return nil
			},
		})

		return nil
	}),
)

Module provides a namespaced Factory bound to the injected Prometheus registry and serves the registry at /metrics on the address named "metricsAddr". Consumers inject the Factory to declare their collectors, which auto-register under the configured namespace, and should pre-resolve labeled handles once at setup rather than per request to keep the emit path lock-free and allocation-free.

The HTTP server is bound to the fx lifecycle: it starts in a background goroutine on OnStart and shuts down gracefully on OnStop. If the server stops for any reason other than a clean shutdown, the whole app is brought down with a non-zero exit code.

Functions

This section is empty.

Types

type Factory

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

Factory binds a Prometheus namespace (and optionally a subsystem) to a promauto.Factory so callers create collectors that are automatically namespaced and registered, without each call site repeating the prefix. It is the dependency other packages inject to declare their own metrics.

func New

func New(ns string, factory promauto.Factory) *Factory

New returns a Factory that prefixes ns onto every collector it creates, using factory to build and register them with the underlying registry.

func (*Factory) ForSubsystem

func (f *Factory) ForSubsystem(subsys string) *Factory

ForSubsystem returns a copy of the Factory scoped to subsys, so collectors it creates are named namespace_subsys_<name>. The receiver is left unchanged, so one namespace-level Factory can spawn independent per-subsystem factories.

func (*Factory) NewCounter

func (f *Factory) NewCounter(opts prometheus.CounterOpts, labelNames []string) *prometheus.CounterVec

NewCounter creates and registers a CounterVec. It forces the bound namespace (and subsystem, when set) onto opts, overriding any the caller set, so every counter shares the same prefix. labelNames are the counter's variable label dimensions.

func (*Factory) NewGauge

func (f *Factory) NewGauge(opts prometheus.GaugeOpts) prometheus.Gauge

NewGauge creates and registers a label-less Gauge. It forces the bound namespace (and subsystem, when set) onto opts, overriding any the caller set, so every gauge shares the same prefix.

func (*Factory) NewHistogram

func (f *Factory) NewHistogram(opts prometheus.HistogramOpts, labelNames []string) *prometheus.HistogramVec

NewHistogram creates and registers a HistogramVec. It forces the bound namespace (and subsystem, when set) onto opts, overriding any the caller set, so every histogram shares the same prefix. labelNames are the histogram's variable label dimensions.

type MetricsParams

type MetricsParams struct {
	fx.In
	Lifecycle  fx.Lifecycle
	Shutdowner fx.Shutdowner

	Addr      string `name:"metricsAddr"`
	Namespace string `name:"metricsNamespace"`
	Logger    logger.Logger

	Gatherer   prometheus.Gatherer
	Registerer prometheus.Registerer
}

MetricsParams holds the fx-injected dependencies needed to run the metrics HTTP server and build the namespaced Factory. Addr is the named "metricsAddr" listen address and Namespace is the named "metricsNamespace" Prometheus prefix. Registerer is where collectors register and Gatherer is what the /metrics handler scrapes; supplying both lets callers (and tests) choose between the package-global registry and an isolated one.

Jump to

Keyboard shortcuts

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