expfmt

package
v0.67.3 Latest Latest
Warning

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

Go to latest
Published: Nov 14, 2025 License: Apache-2.0 Imports: 19 Imported by: 3,860

Documentation

Overview

Package expfmt contains tools for reading and writing Prometheus metrics.

Index

Constants

View Source
const (
	TextVersion   = "0.0.4"
	ProtoType     = `application/vnd.google.protobuf`
	ProtoProtocol = `io.prometheus.client.MetricFamily`
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead.
	ProtoFmt        = ProtoType + "; proto=" + ProtoProtocol + ";"
	OpenMetricsType = `application/openmetrics-text`
	//nolint:revive // Allow for underscores.
	OpenMetricsVersion_0_0_1 = "0.0.1"
	//nolint:revive // Allow for underscores.
	OpenMetricsVersion_1_0_0 = "1.0.0"

	// The Content-Type values for the different wire protocols. Do not do direct
	// comparisons to these constants, instead use the comparison functions.
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeUnknown) instead.
	FmtUnknown Format = `<unknown>`
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeTextPlain) instead.
	FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoDelim) instead.
	FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoText) instead.
	FmtProtoText Format = ProtoFmt + ` encoding=text`
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead.
	FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead.
	//nolint:revive // Allow for underscores.
	FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
	// Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead.
	//nolint:revive // Allow for underscores.
	FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
)

Constants to assemble the Content-Type values for the different wire protocols. The Content-Type strings here are all for the legacy exposition formats, where valid characters for metric names and label names are limited. Support for arbitrary UTF-8 characters in those names is already partially implemented in this module (see model.ValidationScheme), but to actually use it on the wire, new content-type strings will have to be agreed upon and added here.

Variables

This section is empty.

Functions

func ExtractSamples

func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error)

ExtractSamples builds a slice of samples from the provided metric families. If an error occurs during sample extraction, it continues to extract from the remaining metric families. The returned error is the last error that has occurred.

func FinalizeOpenMetrics added in v0.9.0

func FinalizeOpenMetrics(w io.Writer) (written int, err error)

FinalizeOpenMetrics writes the final `# EOF\n` line required by OpenMetrics.

func MetricFamilyToOpenMetrics added in v0.9.0

func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...EncoderOption) (written int, err error)

MetricFamilyToOpenMetrics converts a MetricFamily proto message into the OpenMetrics text format and writes the resulting lines to 'out'. It returns the number of bytes written and any error encountered. The output will have the same order as the input, no further sorting is performed. Furthermore, this function assumes the input is already sanitized and does not perform any sanity checks. If the input contains duplicate metrics or invalid metric or label names, the conversion will result in invalid text format output.

If metric names conform to the legacy validation pattern, they will be placed outside the brackets in the traditional way, like `foo{}`. If the metric name fails the legacy validation check, it will be placed quoted inside the brackets: `{"foo"}`. As stated above, the input is assumed to be santized and no error will be thrown in this case.

Similar to metric names, if label names conform to the legacy validation pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label name fails the legacy validation check, it will be quoted: `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and no error will be thrown in this case.

This function fulfills the type 'expfmt.encoder'.

Note that OpenMetrics requires a final `# EOF` line. Since this function acts on individual metric families, it is the responsibility of the caller to append this line to 'out' once all metric families have been written. Conveniently, this can be done by calling FinalizeOpenMetrics.

The output should be fully OpenMetrics compliant. However, there are a few missing features and peculiarities to avoid complications when switching from Prometheus to OpenMetrics or vice versa:

  • Counters are expected to have the `_total` suffix in their metric name. In the output, the suffix will be truncated from the `# TYPE`, `# HELP` and `# UNIT` lines. A counter with a missing `_total` suffix is not an error. However, its type will be set to `unknown` in that case to avoid invalid OpenMetrics output.

  • According to the OM specs, the `# UNIT` line is optional, but if populated, the unit has to be present in the metric name as its suffix: (see https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#unit). However, in order to accommodate any potential scenario where such a change in the metric name is not desirable, the users are here given the choice of either explicitly opt in, in case they wish for the unit to be included in the output AND in the metric name as a suffix (see the description of the WithUnit function above), or not to opt in, in case they don't want for any of that to happen.

  • No support for the following (optional) features: info type, stateset type, gaugehistogram type.

  • The size of exemplar labels is not checked (i.e. it's possible to create exemplars that are larger than allowed by the OpenMetrics specification).

  • The value of Counters is not checked. (OpenMetrics doesn't allow counters with a `NaN` value.)

func MetricFamilyToText

func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err error)

MetricFamilyToText converts a MetricFamily proto message into text format and writes the resulting lines to 'out'. It returns the number of bytes written and any error encountered. The output will have the same order as the input, no further sorting is performed. Furthermore, this function assumes the input is already sanitized and does not perform any sanity checks. If the input contains duplicate metrics or invalid metric or label names, the conversion will result in invalid text format output.

If metric names conform to the legacy validation pattern, they will be placed outside the brackets in the traditional way, like `foo{}`. If the metric name fails the legacy validation check, it will be placed quoted inside the brackets: `{"foo"}`. As stated above, the input is assumed to be santized and no error will be thrown in this case.

Similar to metric names, if label names conform to the legacy validation pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label name fails the legacy validation check, it will be quoted: `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and no error will be thrown in this case.

This method fulfills the type 'prometheus.encoder'.

Types

type Closer added in v0.9.0

type Closer interface {
	Close() error
}

Closer is implemented by Encoders that need to be closed to finalize encoding. (For example, OpenMetrics needs a final `# EOF` line.)

Note that all Encoder implementations returned from this package implement Closer, too, even if the Close call is a no-op. This happens in preparation for adding a Close method to the Encoder interface directly in a (mildly breaking) release in the future.

type DecodeOptions

type DecodeOptions struct {
	// Timestamp is added to each value from the stream that has no explicit timestamp set.
	Timestamp model.Time
}

DecodeOptions contains options used by the Decoder and in sample extraction.

type Decoder

type Decoder interface {
	Decode(*dto.MetricFamily) error
}

Decoder types decode an input stream into metric families.

func NewDecoder

func NewDecoder(r io.Reader, format Format) Decoder

NewDecoder returns a new decoder based on the given input format. Metric names are validated based on the provided Format -- if the format requires escaping, raditional Prometheues validity checking is used. Otherwise, names are checked for UTF-8 validity. Supported formats include delimited protobuf and Prometheus text format. For historical reasons, this decoder fallbacks to classic text decoding for any other format. This decoder does not fully support OpenMetrics although it may often succeed due to the similarities between the formats. This decoder may not support the latest features of Prometheus text format and is not intended for high-performance applications. See: https://github.com/prometheus/common/issues/812

type Encoder

type Encoder interface {
	Encode(*dto.MetricFamily) error
}

Encoder types encode metric families into an underlying wire protocol.

func NewEncoder

func NewEncoder(w io.Writer, format Format, options ...EncoderOption) Encoder

NewEncoder returns a new encoder based on content type negotiation. All Encoder implementations returned by NewEncoder also implement Closer, and callers should always call the Close method. It is currently only required for FmtOpenMetrics, but a future (breaking) release will add the Close method to the Encoder interface directly. The current version of the Encoder interface is kept for backwards compatibility. In cases where the Format does not allow for UTF-8 names, the global NameEscapingScheme will be applied.

NewEncoder can be called with additional options to customize the OpenMetrics text output. For example: NewEncoder(w, FmtOpenMetrics_1_0_0, WithCreatedLines())

Extra options are ignored for all other formats.

type EncoderOption added in v0.49.0

type EncoderOption func(*encoderOption)

func WithCreatedLines added in v0.49.0

func WithCreatedLines() EncoderOption

WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder to include _created lines (See https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#counter-1). Created timestamps can improve the accuracy of series reset detection, but come with a bandwidth cost.

At the time of writing, created timestamp ingestion is still experimental in Prometheus and need to be enabled with the feature-flag `--feature-flag=created-timestamp-zero-ingestion`, and breaking changes are still possible. Therefore, it is recommended to use this feature with caution.

func