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.
A reporter emitting while a request is in flight also takes a MetadataLabels, built from the configured header-to-name pairs, and carries those labels on its collectors. Values are read from the request's incoming metadata at each emit rather than resolved once and carried along, because the proxy forwards over a socket that context values do not cross while metadata does.
Index ¶
- Variables
- func WithFixedLabels(r prometheus.Registerer, labels map[string]string) prometheus.Registerer
- type Factory
- func (f *Factory) ForSubsystem(subsys string) *Factory
- func (f *Factory) NewCounter(opts prometheus.CounterOpts, labelNames []string) *prometheus.CounterVec
- func (f *Factory) NewGauge(opts prometheus.GaugeOpts) prometheus.Gauge
- func (f *Factory) NewHistogram(opts prometheus.HistogramOpts, labelNames []string) *prometheus.HistogramVec
- type MetadataLabels
- type MetricsParams
Constants ¶
This section is empty.
Variables ¶
var Module = fx.Options( fx.Provide(func(p MetricsParams) *Factory { return New( p.Config.Metrics.Namespace, promauto.With(WithFixedLabels(p.Registerer, p.Config.Metrics.Labels.Fixed)), ) }), fx.Invoke(func(p MetricsParams) error { if p.Config.Metrics.HostPort == "" { 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.Config.Metrics.HostPort, Handler: mux, ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 10 * time.Second, } log := p.Logger.With( tag.Component("metrics"), tag.String("addr", p.Config.Metrics.HostPort), ) 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 the injected config names. Any configured fixed labels are stamped onto the Factory's registerer rather than onto each collector, so every collector declared through it carries them and the runtime's own go_* and process_* series, which register directly, do not. 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 ¶
func WithFixedLabels ¶ added in v0.7.0
func WithFixedLabels(r prometheus.Registerer, labels map[string]string) prometheus.Registerer
WithFixedLabels returns r with labels stamped onto every collector registered through it, so a constant an operator configures once reaches every series the proxy publishes rather than only the ones emitted while serving a request. It returns r unchanged when there are none, so a deployment configuring no fixed labels registers exactly what it did before.
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 ¶
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 ¶
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 MetadataLabels ¶ added in v0.7.0
type MetadataLabels struct {
// contains filtered or unexported fields
}
MetadataLabels is the ordered set of inbound metadata headers reported as extra labels on request-scoped collectors. The zero MetadataLabels carries none, which is what a deployment that configures none runs, so a reporter holding one keeps its label set and its emit path exactly as they were.
func NewMetadataLabels ¶ added in v0.7.0
func NewMetadataLabels(cfg []config.MetricLabel) MetadataLabels
NewMetadataLabels builds the ordered labels for cfg. Headers are lowercased here because gRPC canonicalizes metadata keys while a config preserves whatever case its author wrote; names keep their case, which Prometheus distinguishes.
func (MetadataLabels) AppendValues ¶ added in v0.7.0
func (l MetadataLabels) AppendValues(ctx context.Context, dst []string) []string
AppendValues appends this request's label values to dst in MetadataLabels.Names order and returns the extended slice, so a caller resolves them once and appends them to more than one label list. It returns dst untouched when none are configured, without reading ctx.
func (MetadataLabels) Len ¶ added in v0.7.0
func (l MetadataLabels) Len() int
Len is the number of extra labels, and zero for a MetadataLabels carrying none.
func (MetadataLabels) Names ¶ added in v0.7.0
func (l MetadataLabels) Names() []string
Names returns the extra label names in configured order, for appending to a collector's own label names at construction. The result is a copy.
type MetricsParams ¶
type MetricsParams struct {
fx.In
Lifecycle fx.Lifecycle
Shutdowner fx.Shutdowner
Config *config.Config
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. Config supplies the listen address and the Prometheus prefix through its Metrics block. 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.