expfmt

package
v0.0.96 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package expfmt provides a fast, allocation-light encoder for the Prometheus text exposition format.

It exists for promxy's /federate endpoint (issue #784). The upstream federation handler builds a full dto.MetricFamily tree per request and hands it to github.com/prometheus/common/expfmt, whose text encoder (since common v0.65 / the Prometheus 3.x UTF-8 name support) re-validates every metric and label name on encode. Together that dominates federation CPU and allocations. promxy already has the data as labels.Labels (it just decoded a downstream response), so it can stream the exposition format directly, skipping the dto tree.

The output is byte-for-byte identical to common/expfmt for the subset federation emits: UNTYPED float samples. In particular, name handling (legacy-valid names written bare, otherwise quoted with the metric name moved inside the braces), label-value escaping, and float/timestamp formatting all match common/expfmt exactly, including UTF-8 names. This is verified by byte-equivalence tests against common/expfmt.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MetricFamilyToText

func MetricFamilyToText(out io.Writer, mf *dto.MetricFamily) error

MetricFamilyToText encodes an UNTYPED metric family to the text format, byte-for-byte compatible with common/expfmt for that type. It exists mainly as a testing/benchmarking surface that shares the exact primitives the federation Encoder uses; the federation handler uses Encoder directly.

Types

type Encoder

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

Encoder streams federation output (UNTYPED float samples) directly from labels.Labels, without building a dto.MetricFamily. Samples must be supplied grouped by metric name (sorted), matching upstream federation which emits one "# TYPE <name> untyped" line per metric family.

scheme is the name-escaping scheme negotiated from the scrape request's Accept header (model.EscapingScheme), applied to every metric and label name exactly as common/expfmt's encoder does via model.EscapeMetricFamily. For the default (UnderscoreEscaping) and legacy-valid names this is allocation-free.

func NewEncoder

func NewEncoder(w io.Writer, scheme model.EscapingScheme) *Encoder

func (*Encoder) Flush

func (e *Encoder) Flush() error

Flush flushes any buffered output to the underlying writer.

func (*Encoder) WriteFloatSample

func (e *Encoder) WriteFloatSample(name string, lbls labels.Labels, external []labels.Label, v float64, t int64)

WriteFloatSample writes one untyped sample.

  • name is the metric name (the value of the __name__ label).
  • lbls is the full label set of the series; the __name__ label and any empty-valued labels are skipped (matching upstream federation).
  • external are additional labels (e.g. external_labels) to attach, in the order given, but only when not already present in lbls. Pass them pre-sorted by name to match upstream byte ordering.

A "# TYPE <name> untyped" line is emitted whenever name changes from the previous call, so callers must group samples by name.

Jump to

Keyboard shortcuts

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