diff options
| author | 2024-08-19 10:13:46 +0000 | |
|---|---|---|
| committer | 2024-08-19 10:13:46 +0000 | |
| commit | 6ff8376d96f094daacf62decf2ee7ff602c2d531 (patch) | |
| tree | 0b0ad45951ef1aae841384fd550e01b44f4cba76 /vendor/github.com/prometheus/common/expfmt | |
| parent | [bugfix] permit unspecified orientation data (#3205) (diff) | |
| download | gotosocial-6ff8376d96f094daacf62decf2ee7ff602c2d531.tar.xz | |
[chore]: Bump github.com/prometheus/client_golang from 1.19.1 to 1.20.0 (#3210)
Diffstat (limited to 'vendor/github.com/prometheus/common/expfmt')
4 files changed, 199 insertions, 44 deletions
| diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go index b2b89b017..25cfaa216 100644 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ b/vendor/github.com/prometheus/common/expfmt/decode.go @@ -75,14 +75,14 @@ func ResponseFormat(h http.Header) Format {  func NewDecoder(r io.Reader, format Format) Decoder {  	switch format.FormatType() {  	case TypeProtoDelim: -		return &protoDecoder{r: r} +		return &protoDecoder{r: bufio.NewReader(r)}  	}  	return &textDecoder{r: r}  }  // protoDecoder implements the Decoder interface for protocol buffers.  type protoDecoder struct { -	r io.Reader +	r protodelim.Reader  }  // Decode implements the Decoder interface. @@ -90,7 +90,7 @@ func (d *protoDecoder) Decode(v *dto.MetricFamily) error {  	opts := protodelim.UnmarshalOptions{  		MaxSize: -1,  	} -	if err := opts.UnmarshalFrom(bufio.NewReader(d.r), v); err != nil { +	if err := opts.UnmarshalFrom(d.r, v); err != nil {  		return err  	}  	if !model.IsValidMetricName(model.LabelValue(v.GetName())) { diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go index 8fd806184..ff5ef7a9d 100644 --- a/vendor/github.com/prometheus/common/expfmt/encode.go +++ b/vendor/github.com/prometheus/common/expfmt/encode.go @@ -21,9 +21,10 @@ import (  	"google.golang.org/protobuf/encoding/protodelim"  	"google.golang.org/protobuf/encoding/prototext" -	"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"  	"github.com/prometheus/common/model" +	"github.com/munnerz/goautoneg" +  	dto "github.com/prometheus/client_model/go"  ) @@ -139,7 +140,13 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {  // interface is kept for backwards compatibility.  // In cases where the Format does not allow for UTF-8 names, the global  // NameEscapingScheme will be applied. -func NewEncoder(w io.Writer, format Format) Encoder { +// +// 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. +func NewEncoder(w io.Writer, format Format, options ...EncoderOption) Encoder {  	escapingScheme := format.ToEscapingScheme()  	switch format.FormatType() { @@ -178,7 +185,7 @@ func NewEncoder(w io.Writer, format Format) Encoder {  	case TypeOpenMetrics:  		return encoderCloser{  			encode: func(v *dto.MetricFamily) error { -				_, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme)) +				_, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme), options...)  				return err  			},  			close: func() error { diff --git a/vendor/github.com/prometheus/common/expfmt/expfmt.go b/vendor/github.com/prometheus/common/expfmt/expfmt.go index 6fc9555e3..051b38cd1 100644 --- a/vendor/github.com/prometheus/common/expfmt/expfmt.go +++ b/vendor/github.com/prometheus/common/expfmt/expfmt.go @@ -15,6 +15,7 @@  package expfmt  import ( +	"fmt"  	"strings"  	"github.com/prometheus/common/model" @@ -63,7 +64,7 @@ const (  type FormatType int  const ( -	TypeUnknown = iota +	TypeUnknown FormatType = iota  	TypeProtoCompact  	TypeProtoDelim  	TypeProtoText @@ -73,7 +74,8 @@ const (  // NewFormat generates a new Format from the type provided. Mostly used for  // tests, most Formats should be generated as part of content negotiation in -// encode.go. +// encode.go. If a type has more than one version, the latest version will be +// returned.  func NewFormat(t FormatType) Format {  	switch t {  	case TypeProtoCompact: @@ -91,13 +93,21 @@ func NewFormat(t FormatType) Format {  	}  } +// NewOpenMetricsFormat generates a new OpenMetrics format matching the +// specified version number. +func NewOpenMetricsFormat(version string) (Format, error) { +	if version == OpenMetricsVersion_0_0_1 { +		return fmtOpenMetrics_0_0_1, nil +	} +	if version == OpenMetricsVersion_1_0_0 { +		return fmtOpenMetrics_1_0_0, nil +	} +	return fmtUnknown, fmt.Errorf("unknown open metrics version string") +} +  // FormatType deduces an overall FormatType for the given format.  func (f Format) FormatType() FormatType {  	toks := strings.Split(string(f), ";") -	if len(toks) < 2 { -		return TypeUnknown -	} -  	params := make(map[string]string)  	for i, t := range toks {  		if i == 0 { diff --git a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go index 5622578ed..353c5e93f 100644 --- a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go +++ b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go @@ -22,11 +22,47 @@ import (  	"strconv"  	"strings" +	"google.golang.org/protobuf/types/known/timestamppb" +  	"github.com/prometheus/common/model"  	dto "github.com/prometheus/client_model/go"  ) +type encoderOption struct { +	withCreatedLines bool +	withUnit         bool +} + +type EncoderOption func(*encoderOption) + +// WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder +// to include _created lines (See +// https://github.com/OpenObservability/OpenMetrics/blob/main/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 WithCreatedLines() EncoderOption { +	return func(t *encoderOption) { +		t.withCreatedLines = true +	} +} + +// WithUnit is an EncoderOption enabling a set unit to be written to the output +// and to be added to the metric name, if it's not there already, as a suffix. +// Without opting in this way, the unit will not be added to the metric name and, +// on top of that, the unit will not be passed onto the output, even if it +// were declared in the *dto.MetricFamily struct, i.e. even if in.Unit !=nil. +func WithUnit() EncoderOption { +	return func(t *encoderOption) { +		t.withUnit = true +	} +} +  // 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 @@ -59,20 +95,34 @@ import (  // 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` and `# HELP` -//     line. A counter with a missing `_total` suffix is not an error. However, +//     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.  // -//   - No support for the following (optional) features: `# UNIT` line, `_created` -//     line, info type, stateset type, gaugehistogram type. +//   - 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/OpenObservability/OpenMetrics/blob/main/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 MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int, err error) { +func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...EncoderOption) (written int, err error) { +	toOM := encoderOption{} +	for _, option := range options { +		option(&toOM) +	} +  	name := in.GetName()  	if name == "" {  		return 0, fmt.Errorf("MetricFamily has no name: %s", in) @@ -95,12 +145,15 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  	}  	var ( -		n          int -		metricType = in.GetType() -		shortName  = name +		n             int +		metricType    = in.GetType() +		compliantName = name  	) -	if metricType == dto.MetricType_COUNTER && strings.HasSuffix(shortName, "_total") { -		shortName = name[:len(name)-6] +	if metricType == dto.MetricType_COUNTER && strings.HasSuffix(compliantName, "_total") { +		compliantName = name[:len(name)-6] +	} +	if toOM.withUnit && in.Unit != nil && !strings.HasSuffix(compliantName, fmt.Sprintf("_%s", *in.Unit)) { +		compliantName = compliantName + fmt.Sprintf("_%s", *in.Unit)  	}  	// Comments, first HELP, then TYPE. @@ -110,7 +163,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  		if err != nil {  			return  		} -		n, err = writeName(w, shortName) +		n, err = writeName(w, compliantName)  		written += n  		if err != nil {  			return @@ -136,7 +189,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  	if err != nil {  		return  	} -	n, err = writeName(w, shortName) +	n, err = writeName(w, compliantName)  	written += n  	if err != nil {  		return @@ -163,55 +216,89 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  	if err != nil {  		return  	} +	if toOM.withUnit && in.Unit != nil { +		n, err = w.WriteString("# UNIT ") +		written += n +		if err != nil { +			return +		} +		n, err = writeName(w, compliantName) +		written += n +		if err != nil { +			return +		} + +		err = w.WriteByte(' ') +		written++ +		if err != nil { +			return +		} +		n, err = writeEscapedString(w, *in.Unit, true) +		written += n +		if err != nil { +			return +		} +		err = w.WriteByte('\n') +		written++ +		if err != nil { +			return +		} +	} + +	var createdTsBytesWritten int  	// Finally the samples, one line for each. +	if metricType == dto.MetricType_COUNTER && strings.HasSuffix(name, "_total") { +		compliantName = compliantName + "_total" +	}  	for _, metric := range in.Metric {  		switch metricType {  		case dto.MetricType_COUNTER:  			if metric.Counter == nil {  				return written, fmt.Errorf( -					"expected counter in metric %s %s", name, metric, +					"expected counter in metric %s %s", compliantName, metric,  				)  			} -			// Note that we have ensured above that either the name -			// ends on `_total` or that the rendered type is -			// `unknown`. Therefore, no `_total` must be added here.  			n, err = writeOpenMetricsSample( -				w, name, "", metric, "", 0, +				w, compliantName, "", metric, "", 0,  				metric.Counter.GetValue(), 0, false,  				metric.Counter.Exemplar,  			) +			if toOM.withCreatedLines && metric.Counter.CreatedTimestamp != nil { +				createdTsBytesWritten, err = writeOpenMetricsCreated(w, compliantName, "_total", metric, "", 0, metric.Counter.GetCreatedTimestamp()) +				n += createdTsBytesWritten +			}  		case dto.MetricType_GAUGE:  			if metric.Gauge == nil {  				return written, fmt.Errorf( -					"expected gauge in metric %s %s", name, metric, +					"expected gauge in metric %s %s", compliantName, metric,  				)  			}  			n, err = writeOpenMetricsSample( -				w, name, "", metric, "", 0, +				w, compliantName, "", metric, "", 0,  				metric.Gauge.GetValue(), 0, false,  				nil,  			)  		case dto.MetricType_UNTYPED:  			if metric.Untyped == nil {  				return written, fmt.Errorf( -					"expected untyped in metric %s %s", name, metric, +					"expected untyped in metric %s %s", compliantName, metric,  				)  			}  			n, err = writeOpenMetricsSample( -				w, name, "", metric, "", 0, +				w, compliantName, "", metric, "", 0,  				metric.Untyped.GetValue(), 0, false,  				nil,  			)  		case dto.MetricType_SUMMARY:  			if metric.Summary == nil {  				return written, fmt.Errorf( -					"expected summary in metric %s %s", name, metric, +					"expected summary in metric %s %s", compliantName, metric,  				)  			}  			for _, q := range metric.Summary.Quantile {  				n, err = writeOpenMetricsSample( -					w, name, "", metric, +					w, compliantName, "", metric,  					model.QuantileLabel, q.GetQuantile(),  					q.GetValue(), 0, false,  					nil, @@ -222,7 +309,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  				}  			}  			n, err = writeOpenMetricsSample( -				w, name, "_sum", metric, "", 0, +				w, compliantName, "_sum", metric, "", 0,  				metric.Summary.GetSampleSum(), 0, false,  				nil,  			) @@ -231,20 +318,24 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  				return  			}  			n, err = writeOpenMetricsSample( -				w, name, "_count", metric, "", 0, +				w, compliantName, "_count", metric, "", 0,  				0, metric.Summary.GetSampleCount(), true,  				nil,  			) +			if toOM.withCreatedLines && metric.Summary.CreatedTimestamp != nil { +				createdTsBytesWritten, err = writeOpenMetricsCreated(w, compliantName, "", metric, "", 0, metric.Summary.GetCreatedTimestamp()) +				n += createdTsBytesWritten +			}  		case dto.MetricType_HISTOGRAM:  			if metric.Histogram == nil {  				return written, fmt.Errorf( -					"expected histogram in metric %s %s", name, metric, +					"expected histogram in metric %s %s", compliantName, metric,  				)  			}  			infSeen := false  			for _, b := range metric.Histogram.Bucket {  				n, err = writeOpenMetricsSample( -					w, name, "_bucket", metric, +					w, compliantName, "_bucket", metric,  					model.BucketLabel, b.GetUpperBound(),  					0, b.GetCumulativeCount(), true,  					b.Exemplar, @@ -259,7 +350,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  			}  			if !infSeen {  				n, err = writeOpenMetricsSample( -					w, name, "_bucket", metric, +					w, compliantName, "_bucket", metric,  					model.BucketLabel, math.Inf(+1),  					0, metric.Histogram.GetSampleCount(), true,  					nil, @@ -270,7 +361,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  				}  			}  			n, err = writeOpenMetricsSample( -				w, name, "_sum", metric, "", 0, +				w, compliantName, "_sum", metric, "", 0,  				metric.Histogram.GetSampleSum(), 0, false,  				nil,  			) @@ -279,13 +370,17 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int  				return  			}  			n, err = writeOpenMetricsSample( -				w, name, "_count", metric, "", 0, +				w, compliantName, "_count", metric, "", 0,  				0, metric.Histogram.GetSampleCount(), true,  				nil,  			) +			if toOM.withCreatedLines && metric.Histogram.CreatedTimestamp != nil { +				createdTsBytesWritten, err = writeOpenMetricsCreated(w, compliantName, "", metric, "", 0, metric.Histogram.GetCreatedTimestamp()) +				n += createdTsBytesWritten +			}  		default:  			return written, fmt.Errorf( -				"unexpected type in metric %s %s", name, metric, +				"unexpected type in metric %s %s", compliantName, metric,  			)  		}  		written += n @@ -350,7 +445,7 @@ func writeOpenMetricsSample(  			return written, err  		}  	} -	if exemplar != nil { +	if exemplar != nil && len(exemplar.Label) > 0 {  		n, err = writeExemplar(w, exemplar)  		written += n  		if err != nil { @@ -473,6 +568,49 @@ func writeOpenMetricsNameAndLabelPairs(  	return written, nil  } +// writeOpenMetricsCreated writes the created timestamp for a single time series +// following OpenMetrics text format to w, given the metric name, the metric proto +// message itself, optionally a suffix to be removed, e.g. '_total' for counters, +// an additional label name with a float64 value (use empty string as label name if +// not required) and the timestamp that represents the created timestamp. +// The function returns the number of bytes written and any error encountered. +func writeOpenMetricsCreated(w enhancedWriter, +	name, suffixToTrim string, metric *dto.Metric, +	additionalLabelName string, additionalLabelValue float64, +	createdTimestamp *timestamppb.Timestamp, +) (int, error) { +	written := 0 +	n, err := writeOpenMetricsNameAndLabelPairs( +		w, strings.TrimSuffix(name, suffixToTrim)+"_created", metric.Label, additionalLabelName, additionalLabelValue, +	) +	written += n +	if err != nil { +		return written, err +	} + +	err = w.WriteByte(' ') +	written++ +	if err != nil { +		return written, err +	} + +	// TODO(beorn7): Format this directly from components of ts to +	// avoid overflow/underflow and precision issues of the float +	// conversion. +	n, err = writeOpenMetricsFloat(w, float64(createdTimestamp.AsTime().UnixNano())/1e9) +	written += n +	if err != nil { +		return written, err +	} + +	err = w.WriteByte('\n') +	written++ +	if err != nil { +		return written, err +	} +	return written, nil +} +  // writeExemplar writes the provided exemplar in OpenMetrics format to w. The  // function returns the number of bytes written and any error encountered.  func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) { | 
