fxmetrics

package
v0.0.0-...-edc4474 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: Apache-2.0 Imports: 26 Imported by: 2

README

Metrics Module

This module provides prometheus metrics support.

This package provides 3 modules:

  • A regular module that exposes a standard prometheus endpoint for use in long running daemons
  • An OTLP module which uses the prometheus sdk to define metrics, but pushes them out over OTLP rather than the standard prometheus http endpoint
  • A push module that pushes metrics into push gateway, for use with jobs

Because client code only interacts with the *prometheus.Registry, they can be swapped out transparently.

The following metric collectors are registered by default:

Additional custom metrics can of course be registered.

Regular Module

Components

The module lazily provides the following components:

  • A *prometheus.Registry
  • GrpcServerInterceptors that count all incoming requests by method and status
  • GrpcClientInterceptors that count all requests made with the client by method and status
  • HttpMiddleware that count all incoming requests by method and status

It starts an additional webserver exposing the prometheus endpoint.

OTLP Module

Components

The module lazily provides the following components:

  • A *prometheus.Registry
  • A metric.MeterProvider (allows you to define metrics with the otel sdk)
  • GrpcServerInterceptors that count all incoming requests by method and status
  • GrpcClientInterceptors that count all requests made with the client by method and status
  • HttpMiddleware that count all incoming requests by method and status

It adds hooks to push the metrics when the system stops and at regular intervals during runtime.

Configuration

The module provides the following configuration options:

  • GrpcClient: A grpc client config, see the docs in the fxgrpc package for details
  • Histograms: A bool which enables support for histograms in the grpc middleware (will most likely be removed)
  • ProcessName: A string used as a prefix inside the process collector to prevent clashes
  • PushInterval: The frequency at which metrics are pushed during runtime
  • Enabled: Disables the pushing of metrics completely

Push Module

Components

The module lazily provides the following components:

  • A *prometheus.Registry
  • GrpcServerInterceptors that count all incoming requests by method and status
  • GrpcClientInterceptors that count all requests made with the client by method and status
  • HttpMiddleware that count all incoming requests by method and status

It adds hooks to push the metrics when the system stops and at regular intervals during runtime.

Configuration
  • InsecureConnection: Disables TLS when connecting to the endpoint
  • CertFile: Path to a pem encoded client certificate
  • KeyFile: Path to the pem encoded key of the client certificate
  • RootCAFile: Path to a pem encoded bundle of CA certificates used to validate the server
  • Endpoint: The http endpoint of the push gateway
  • Histograms: A bool which enables support for histograms in the grpc middleware (will most likely be removed)
  • ProcessName: A string used as a prefix inside the process collector to prevent clashes
  • JobName: The name of the job in pushgateway
  • GroupingLabels: A map of label name & values Pushgateway keeps a copy of each metric for each value of the set of grouping label keys
  • PushInterval: The frequency at which metrics are pushed during runtime. When 0 metrics are only pushed when the system stops

Documentation

Overview

package fxmetrics provides a convenient way to expose prometheus metrics.

Example
package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"

	sconfig "github.com/exoscale/stelling/config"
	"github.com/exoscale/stelling/fxmetrics"
	"github.com/prometheus/client_golang/prometheus"
	"go.uber.org/fx"
	"go.uber.org/fx/fxevent"
	"go.uber.org/zap"
)

type Config struct {
	fxmetrics.Metrics
}

func main() {
	conf := &Config{}
	args := []string{"metrics-test"}
	if err := sconfig.Load(conf, args); err != nil {
		panic(err)
	}
	opts := fx.Options(
		// Suppressing fx logs to ensure deterministic output
		fx.WithLogger(func() fxevent.Logger { return fxevent.NopLogger }),
		fxmetrics.NewModule(conf),
		fx.Provide(
			zap.NewNop,
			provideMetrics,
		),
		fx.Invoke(registerMetrics),
		fx.Invoke(run),
	)
	if err := fx.ValidateApp(opts); err != nil {
		panic(err)
	}

	fx.New(opts).Run()

}

func provideMetrics() prometheus.Collector {
	counter := prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "app",
		Subsystem: "component",
		Name:      "example_total",
		Help:      "Total number of times run was called",
	}, []string{})
	// Metrics are provisioned lazily, by reading it here we ensure it's present
	counter.GetMetricWithLabelValues() //nolint:errcheck
	return counter
}

func registerMetrics(metric prometheus.Collector, reg *prometheus.Registry) error {
	return reg.Register(metric)
}

func run(lc fx.Lifecycle, sd fx.Shutdowner) {
	lc.Append(fx.Hook{
		OnStart: func(ctx context.Context) error {
			go func() {
				// By default the metrics server binds to 0.0.0.0:9091
				resp, err := http.DefaultClient.Get("http://localhost:9091/metrics") //nolint:noctx
				if err != nil {
					panic(err)
				}
				fmt.Println("Response code for GET http://localhost:9091/metrics", resp.StatusCode)
				body := resp.Body
				metrics, err := io.ReadAll(body)
				if err != nil {
					panic(err)
				}
				hasMetric := bytes.Contains(metrics, []byte("app_component_example_total 0"))
				fmt.Println("Payload contains the custom metric", hasMetric)
				defer body.Close()
				sd.Shutdown() //nolint:errcheck
			}()
			return nil
		},
	})
}
Output:
Response code for GET http://localhost:9091/metrics 200
Payload contains the custom metric true

Index

Examples

Constants

View Source
const GrpcInterceptorWeight = 60

Variables

This section is empty.

Functions

func GetCertReloaderConfig

func GetCertReloaderConfig(conf PushMetricsConfig) *reloader.CertReloaderConfig

func InitializeGrpcServerMetrics

func InitializeGrpcServerMetrics(metrics *grpc_prometheus.ServerMetrics, server reflection.ServiceInfoProvider)

func InvokeOtlpMeterProvider

func InvokeOtlpMeterProvider(lc fx.Lifecycle, mp metric.MeterProvider)

InvokeOtlpMeterProvider can be embedded in a system to ensure the metric.MeterProvider is created

func NewMetricsHandlers

func NewMetricsHandlers(p RegisterParams) http.Handler

func NewModule

func NewModule(conf MetricsConfig) fx.Option

NewModule Exposes prometheus metrics.

func NewOtlpMeterProvider

func NewOtlpMeterProvider(lc fx.Lifecycle, conf OtlpMetricsConfig, reg *prometheus.Registry, logger *zap.Logger) (metric.MeterProvider, error)

func NewOtlpModule

func NewOtlpModule(conf OtlpMetricsConfig) fx.Option

func NewPrometheusRegistry

func NewPrometheusRegistry(conf MetricsConfig) (*prometheus.Registry, error)

func NewPushModule

func NewPushModule(conf PushMetricsConfig) fx.Option

func NewVersionCollector

func NewVersionCollector() prometheus.GaugeFunc

NewVersionCollector returns a collector collecting a single metric "go_version_info" with the constant value of 1 and 2 labels "revision" and "revision_timestamp". Their values can be set at link time. `go build -ldflags="-X 'github.com/exoscale/stelling/fxmetrics.revision=v1.0.0'"` `go build -ldflags="-X 'github.com/exoscale/stelling/fxmetrics.revisionTimestamp=2024-06-18T14:28:57Z'"` If not set at link time, the labels will contain the values of "vcs.revision" and "vcs.time" from the BuildInfo.Settings map. If neither way returns an output, the value will be set to "unknown".

func ProvideMetricsPusher

func ProvideMetricsPusher(lc fx.Lifecycle, conf PushMetricsConfig, reloader *reloader.CertReloader, logger *zap.Logger) (*push.Pusher, error)

func RegisterPushMetrics

func RegisterPushMetrics(reg *prometheus.Registry, pusher *push.Pusher)

Types

type GrpcClientInterceptorParams

type GrpcClientInterceptorParams struct {
	fx.In

	Conf         MetricsConfig
	Reg          *prometheus.Registry
	HistogramOps []grpc_prometheus.HistogramOption `optional:"true"`
}

type GrpcClientInterceptorsResult

type GrpcClientInterceptorsResult struct {
	fx.Out

	*fxgrpc.UnaryClientInterceptor  `group:"unary_client_interceptor"`
	*fxgrpc.StreamClientInterceptor `group:"stream_client_interceptor"`
}

type GrpcServerInterceptorParams

type GrpcServerInterceptorParams struct {
	fx.In

	Conf         MetricsConfig
	Reg          *prometheus.Registry
	HistogramOps []grpc_prometheus.HistogramOption `optional:"true"`
}

type GrpcServerInterceptorsResult

type GrpcServerInterceptorsResult struct {
	fx.Out

	*fxgrpc.UnaryServerInterceptor  `group:"unary_server_interceptor"`
	*fxgrpc.StreamServerInterceptor `group:"stream_server_interceptor"`
	*grpc_prometheus.ServerMetrics
}

type HttpMetrics

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

func NewHttpMetrics

func NewHttpMetrics() *HttpMetrics

func (*HttpMetrics) Collect

func (m *HttpMetrics) Collect(ch chan<- prometheus.Metric)

Collect is called by the Prometheus registry when collecting metrics. The implementation sends each collected metric via the provided channel and returns once the last metric has been sent.

func (*HttpMetrics) Describe

func (m *HttpMetrics) Describe(ch chan<- *prometheus.Desc)

Describe sends the super-set of all possible descriptors of metrics collected by this Collector to the provided channel and returns once the last descriptor has been sent.

type HttpMiddlewareResult

type HttpMiddlewareResult struct {
	fx.Out

	Middleware *fxhttp.Middleware `group:"http_middleware"`
}

func NewHttpMiddleware

func NewHttpMiddleware(reg *prometheus.Registry) (HttpMiddlewareResult, error)

type Metrics

type Metrics struct {
	fxhttp.Server

	// indicates whether Prometheus grpc middleware exports Histograms or not
	Histograms bool `default:"false"`
	// ProcessName is used as a prefix for certain metrics that can clash
	ProcessName string
}

func (*Metrics) ApplyDefaults

func (m *Metrics) ApplyDefaults()

func (*Metrics) MarshalLogObject

func (m *Metrics) MarshalLogObject(enc zapcore.ObjectEncoder) error

func (*Metrics) MetricsConfig

func (m *Metrics) MetricsConfig() *Metrics

type MetricsConfig

type MetricsConfig interface {
	MetricsConfig() *Metrics
}

type OtlpMetrics

type OtlpMetrics struct {
	// Enabled allows otlp metrics support to be toggled on and off
	Enabled bool
	// PushInterval is the frequency with which metrics are pushed
	PushInterval time.Duration `default:"15s"`
	// indicates whether Prometheus grpc middleware exports Histograms or not
	Histograms bool `default:"false"`
	// ProcessName is used as a prefix for certain metrics that can clash
	ProcessName string

	// GrpcClient is the client used to talk to the collector
	GrpcClient fxgrpc.Client `validate:"required_with=Enabled,omitempty"`
}

func (*OtlpMetrics) MarshalLogObject

func (m *OtlpMetrics) MarshalLogObject(enc zapcore.ObjectEncoder) error

func (*OtlpMetrics) MetricsConfig

func (om *OtlpMetrics) MetricsConfig() *Metrics

func (*OtlpMetrics) OtlpMetricsConfig

func (om *OtlpMetrics) OtlpMetricsConfig() *OtlpMetrics

type OtlpMetricsConfig

type OtlpMetricsConfig interface {
	OtlpMetricsConfig() *OtlpMetrics
	MetricsConfig() *Metrics
}

type PushMetrics

type PushMetrics struct {
	// InsecureConnection indicates whether TLS needs to be disabled when connecting to PushGateway
	InsecureConnection bool
	// CertFile is the path to the pem encoded TLS certificate
	CertFile string `validate:"omitempty,file"`
	// KeyFile is the path to the pem encoded private key of the TLS certificate
	KeyFile string `validate:"required_with=CertFile,omitempty,file"`
	// RootCAFile is the path to a pem encoded CA cert bundle used to validate server connections
	RootCAFile string `validate:"omitempty,file"`
	// indicates whether Prometheus grpc middleware exports Histograms or not
	Histograms bool `default:"false"`
	// ProcessName is used as a prefix for certain metrics that can clash
	ProcessName string
	// Endpoint is the URL on which the prometheus pushgateway can be reached
	Endpoint string `validate:"omitempty,url"`
	// JobName is the name of the job in PushGateway
	JobName string `validate:"required_with=Endpoint"`
	// GroupingLabelKey is the label on which PushGateway groups metrics
	// (ie: you can keep a copy of each metric for each value of the GroupingLabelKey)
	// Deprecated: Use GroupingLabels
	GroupingLabelKey string ``
	// The value for this instance of the GroupingLabel (see GroupingLabelKey)
	// Deprecated: Use GroupingLabels
	GroupingLabelValue string `validate:"required_with=GroupingLabelKey"`

	// GroupingLabels are labels on which PushGateway groups metrics
	GroupingLabels map[string]string `validate:"excluded_with=GroupingLabelKey"`

	// PushInterval is the frequency with which metrics are pushed
	// If the PushInterval is set to 0, metrics will only be pushed when the system stops
	PushInterval time.Duration `default:"15s"`
	// ExtraLabels will add each key as a label with the corresponding value in all produced metrics
	ExtraLabels map[string]string
}

func (*PushMetrics) MarshalLogObject

func (m *PushMetrics) MarshalLogObject(enc zapcore.ObjectEncoder) error

func (*PushMetrics) MetricsConfig

func (m *PushMetrics) MetricsConfig() *Metrics

func (*PushMetrics) PushMetricsConfig

func (m *PushMetrics) PushMetricsConfig() *PushMetrics

type PushMetricsConfig

type PushMetricsConfig interface {
	PushMetricsConfig() *PushMetrics
	MetricsConfig() *Metrics
}

type RegisterParams

type RegisterParams struct {
	fx.In

	Reg *prometheus.Registry
}

Jump to

Keyboard shortcuts

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