chore: make deps

This commit is contained in:
2025-11-11 14:18:57 +01:00
parent db7c4042d0
commit 45af67d22d
590 changed files with 22837 additions and 16387 deletions

View File

@ -220,7 +220,7 @@ func extractSamples(f *dto.MetricFamily, o *DecodeOptions) (model.Vector, error)
return extractSummary(o, f), nil
case dto.MetricType_UNTYPED:
return extractUntyped(o, f), nil
case dto.MetricType_HISTOGRAM:
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
return extractHistogram(o, f), nil
}
return nil, fmt.Errorf("expfmt.extractSamples: unknown metric family type %v", f.GetType())
@ -403,9 +403,13 @@ func extractHistogram(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
infSeen = true
}
v := q.GetCumulativeCountFloat()
if v <= 0 {
v = float64(q.GetCumulativeCount())
}
samples = append(samples, &model.Sample{
Metric: model.Metric(lset),
Value: model.SampleValue(q.GetCumulativeCount()),
Value: model.SampleValue(v),
Timestamp: timestamp,
})
}
@ -428,9 +432,13 @@ func extractHistogram(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
}
lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
v := m.Histogram.GetSampleCountFloat()
if v <= 0 {
v = float64(m.Histogram.GetSampleCount())
}
count := &model.Sample{
Metric: model.Metric(lset),
Value: model.SampleValue(m.Histogram.GetSampleCount()),
Value: model.SampleValue(v),
Timestamp: timestamp,
}
samples = append(samples, count)

View File

@ -160,38 +160,38 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
n, err = w.WriteString("# HELP ")
written += n
if err != nil {
return
return written, err
}
n, err = writeName(w, compliantName)
written += n
if err != nil {
return
return written, err
}
err = w.WriteByte(' ')
written++
if err != nil {
return
return written, err
}
n, err = writeEscapedString(w, *in.Help, true)
written += n
if err != nil {
return
return written, err
}
err = w.WriteByte('\n')
written++
if err != nil {
return
return written, err
}
}
n, err = w.WriteString("# TYPE ")
written += n
if err != nil {
return
return written, err
}
n, err = writeName(w, compliantName)
written += n
if err != nil {
return
return written, err
}
switch metricType {
case dto.MetricType_COUNTER:
@ -208,39 +208,41 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
n, err = w.WriteString(" unknown\n")
case dto.MetricType_HISTOGRAM:
n, err = w.WriteString(" histogram\n")
case dto.MetricType_GAUGE_HISTOGRAM:
n, err = w.WriteString(" gaugehistogram\n")
default:
return written, fmt.Errorf("unknown metric type %s", metricType.String())
}
written += n
if err != nil {
return
return written, err
}
if toOM.withUnit && in.Unit != nil {
n, err = w.WriteString("# UNIT ")
written += n
if err != nil {
return
return written, err
}
n, err = writeName(w, compliantName)
written += n
if err != nil {
return
return written, err
}
err = w.WriteByte(' ')
written++
if err != nil {
return
return written, err
}
n, err = writeEscapedString(w, *in.Unit, true)
written += n
if err != nil {
return
return written, err
}
err = w.WriteByte('\n')
written++
if err != nil {
return
return written, err
}
}
@ -304,7 +306,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
)
written += n
if err != nil {
return
return written, err
}
}
n, err = writeOpenMetricsSample(
@ -314,7 +316,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
)
written += n
if err != nil {
return
return written, err
}
n, err = writeOpenMetricsSample(
w, compliantName, "_count", metric, "", 0,
@ -325,7 +327,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
createdTsBytesWritten, err = writeOpenMetricsCreated(w, compliantName, "", metric, "", 0, metric.Summary.GetCreatedTimestamp())
n += createdTsBytesWritten
}
case dto.MetricType_HISTOGRAM:
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
if metric.Histogram == nil {
return written, fmt.Errorf(
"expected histogram in metric %s %s", compliantName, metric,
@ -333,6 +335,12 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
}
infSeen := false
for _, b := range metric.Histogram.Bucket {
if b.GetCumulativeCountFloat() > 0 {
return written, fmt.Errorf(
"OpenMetrics v1.0 does not support float histogram %s %s",
compliantName, metric,
)
}
n, err = writeOpenMetricsSample(
w, compliantName, "_bucket", metric,
model.BucketLabel, b.GetUpperBound(),
@ -341,7 +349,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
)
written += n
if err != nil {
return
return written, err
}
if math.IsInf(b.GetUpperBound(), +1) {
infSeen = true
@ -354,9 +362,12 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
0, metric.Histogram.GetSampleCount(), true,
nil,
)
// We do not check for a float sample count here
// because we will check for it below (and error
// out if needed).
written += n
if err != nil {
return
return written, err
}
}
n, err = writeOpenMetricsSample(
@ -366,7 +377,13 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
)
written += n
if err != nil {
return
return written, err
}
if metric.Histogram.GetSampleCountFloat() > 0 {
return written, fmt.Errorf(
"OpenMetrics v1.0 does not support float histogram %s %s",
compliantName, metric,
)
}
n, err = writeOpenMetricsSample(
w, compliantName, "_count", metric, "", 0,
@ -384,10 +401,10 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
}
written += n
if err != nil {
return
return written, err
}
}
return
return written, err
}
// FinalizeOpenMetrics writes the final `# EOF\n` line required by OpenMetrics.

View File

@ -108,38 +108,38 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
n, err = w.WriteString("# HELP ")
written += n
if err != nil {
return
return written, err
}
n, err = writeName(w, name)
written += n
if err != nil {
return
return written, err
}
err = w.WriteByte(' ')
written++
if err != nil {
return
return written, err
}
n, err = writeEscapedString(w, *in.Help, false)
written += n
if err != nil {
return
return written, err
}
err = w.WriteByte('\n')
written++
if err != nil {
return
return written, err
}
}
n, err = w.WriteString("# TYPE ")
written += n
if err != nil {
return
return written, err
}
n, err = writeName(w, name)
written += n
if err != nil {
return
return written, err
}
metricType := in.GetType()
switch metricType {
@ -151,14 +151,17 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
n, err = w.WriteString(" summary\n")
case dto.MetricType_UNTYPED:
n, err = w.WriteString(" untyped\n")
case dto.MetricType_HISTOGRAM:
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
// The classic Prometheus text format has no notion of a gauge
// histogram. We render a gauge histogram in the same way as a
// regular histogram.
n, err = w.WriteString(" histogram\n")
default:
return written, fmt.Errorf("unknown metric type %s", metricType.String())
}
written += n
if err != nil {
return
return written, err
}
// Finally the samples, one line for each.
@ -208,7 +211,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
)
written += n
if err != nil {
return
return written, err
}
}
n, err = writeSample(
@ -217,13 +220,13 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
)
written += n
if err != nil {
return
return written, err
}
n, err = writeSample(
w, name, "_count", metric, "", 0,
float64(metric.Summary.GetSampleCount()),
)
case dto.MetricType_HISTOGRAM:
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
if metric.Histogram == nil {
return written, fmt.Errorf(
"expected histogram in metric %s %s", name, metric,
@ -231,28 +234,36 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
}
infSeen := false
for _, b := range metric.Histogram.Bucket {
v := b.GetCumulativeCountFloat()
if v == 0 {
v = float64(b.GetCumulativeCount())
}
n, err = writeSample(
w, name, "_bucket", metric,
model.BucketLabel, b.GetUpperBound(),
float64(b.GetCumulativeCount()),
v,
)
written += n
if err != nil {
return
return written, err
}
if math.IsInf(b.GetUpperBound(), +1) {
infSeen = true
}
}
if !infSeen {
v := metric.Histogram.GetSampleCountFloat()
if v == 0 {
v = float64(metric.Histogram.GetSampleCount())
}
n, err = writeSample(
w, name, "_bucket", metric,
model.BucketLabel, math.Inf(+1),
float64(metric.Histogram.GetSampleCount()),
v,
)
written += n
if err != nil {
return
return written, err
}
}
n, err = writeSample(
@ -261,12 +272,13 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
)
written += n
if err != nil {
return
return written, err
}
n, err = writeSample(
w, name, "_count", metric, "", 0,
float64(metric.Histogram.GetSampleCount()),
)
v := metric.Histogram.GetSampleCountFloat()
if v == 0 {
v = float64(metric.Histogram.GetSampleCount())
}
n, err = writeSample(w, name, "_count", metric, "", 0, v)
default:
return written, fmt.Errorf(
"unexpected type in metric %s %s", name, metric,
@ -274,10 +286,10 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e
}
written += n
if err != nil {
return
return written, err
}
}
return
return written, err
}
// writeSample writes a single sample in text format to w, given the metric

View File

@ -48,8 +48,10 @@ func (e ParseError) Error() string {
return fmt.Sprintf("text format parsing error in line %d: %s", e.Line, e.Msg)
}
// TextParser is used to parse the simple and flat text-based exchange format. Its
// zero value is ready to use.
// TextParser is used to parse the simple and flat text-based exchange format.
//
// TextParser instances must be created with NewTextParser, the zero value of
// TextParser is invalid.
type TextParser struct {
metricFamiliesByName map[string]*dto.MetricFamily
buf *bufio.Reader // Where the parsed input is read through.
@ -129,9 +131,44 @@ func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricF
if p.err != nil && errors.Is(p.err, io.EOF) {
p.parseError("unexpected end of input stream")
}
for _, histogramMetric := range p.histograms {
normalizeHistogram(histogramMetric.GetHistogram())
}
return p.metricFamiliesByName, p.err
}
// normalizeHistogram makes sure that all the buckets and the count in each
// histogram is either completely float or completely integer.
func normalizeHistogram(histogram *dto.Histogram) {
if histogram == nil {
return
}
anyFloats := false
if histogram.GetSampleCountFloat() != 0 {
anyFloats = true
} else {
for _, b := range histogram.GetBucket() {
if b.GetCumulativeCountFloat() != 0 {
anyFloats = true
break
}
}
}
if !anyFloats {
return
}
if histogram.GetSampleCountFloat() == 0 {
histogram.SampleCountFloat = proto.Float64(float64(histogram.GetSampleCount()))
histogram.SampleCount = nil
}
for _, b := range histogram.GetBucket() {
if b.GetCumulativeCountFloat() == 0 {
b.CumulativeCountFloat = proto.Float64(float64(b.GetCumulativeCount()))
b.CumulativeCount = nil
}
}
}
func (p *TextParser) reset(in io.Reader) {
p.metricFamiliesByName = map[string]*dto.MetricFamily{}
p.currentLabelPairs = nil
@ -281,7 +318,9 @@ func (p *TextParser) readingLabels() stateFn {
// Summaries/histograms are special. We have to reset the
// currentLabels map, currentQuantile and currentBucket before starting to
// read labels.
if p.currentMF.GetType() == dto.MetricType_SUMMARY || p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
if p.currentMF.GetType() == dto.MetricType_SUMMARY ||
p.currentMF.GetType() == dto.MetricType_HISTOGRAM ||
p.currentMF.GetType() == dto.MetricType_GAUGE_HISTOGRAM {
p.currentLabels = map[string]string{}
p.currentLabels[string(model.MetricNameLabel)] = p.currentMF.GetName()
p.currentQuantile = math.NaN()
@ -374,7 +413,9 @@ func (p *TextParser) startLabelName() stateFn {
// Special summary/histogram treatment. Don't add 'quantile' and 'le'
// labels to 'real' labels.
if (p.currentMF.GetType() != dto.MetricType_SUMMARY || p.currentLabelPair.GetName() != model.QuantileLabel) &&
(p.currentMF.GetType() != dto.MetricType_HISTOGRAM || p.currentLabelPair.GetName() != model.BucketLabel) {
((p.currentMF.GetType() != dto.MetricType_HISTOGRAM &&
p.currentMF.GetType() != dto.MetricType_GAUGE_HISTOGRAM) ||
p.currentLabelPair.GetName() != model.BucketLabel) {
p.currentLabelPairs = append(p.currentLabelPairs, p.currentLabelPair)
}
// Check for duplicate label names.
@ -425,7 +466,7 @@ func (p *TextParser) startLabelValue() stateFn {
}
}
// Similar special treatment of histograms.
if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
if p.currentMF.GetType() == dto.MetricType_HISTOGRAM || p.currentMF.GetType() == dto.MetricType_GAUGE_HISTOGRAM {
if p.currentLabelPair.GetName() == model.BucketLabel {
if p.currentBucket, p.err = parseFloat(p.currentLabelPair.GetValue()); p.err != nil {
// Create a more helpful error message.
@ -476,7 +517,7 @@ func (p *TextParser) readingValue() stateFn {
p.summaries[signature] = p.currentMetric
p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
}
case dto.MetricType_HISTOGRAM:
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
signature := model.LabelsToSignature(p.currentLabels)
if histogram := p.histograms[signature]; histogram != nil {
p.currentMetric = histogram
@ -522,24 +563,38 @@ func (p *TextParser) readingValue() stateFn {
},
)
}
case dto.MetricType_HISTOGRAM:
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
// *sigh*
if p.currentMetric.Histogram == nil {
p.currentMetric.Histogram = &dto.Histogram{}
}
switch {
case p.currentIsHistogramCount:
p.currentMetric.Histogram.SampleCount = proto.Uint64(uint64(value))
if uintValue := uint64(value); value == float64(uintValue) {
p.currentMetric.Histogram.SampleCount = proto.Uint64(uintValue)
} else {
if value < 0 {
p.parseError(fmt.Sprintf("negative count for histogram %q", p.currentMF.GetName()))
return nil
}
p.currentMetric.Histogram.SampleCountFloat = proto.Float64(value)
}
case p.currentIsHistogramSum:
p.currentMetric.Histogram.SampleSum = proto.Float64(value)
case !math.IsNaN(p.currentBucket):
p.currentMetric.Histogram.Bucket = append(
p.currentMetric.Histogram.Bucket,
&dto.Bucket{
UpperBound: proto.Float64(p.currentBucket),
CumulativeCount: proto.Uint64(uint64(value)),
},
)
b := &dto.Bucket{
UpperBound: proto.Float64(p.currentBucket),
}
if uintValue := uint64(value); value == float64(uintValue) {
b.CumulativeCount = proto.Uint64(uintValue)
} else {
if value < 0 {
p.parseError(fmt.Sprintf("negative bucket population for histogram %q", p.currentMF.GetName()))
return nil
}
b.CumulativeCountFloat = proto.Float64(value)
}
p.currentMetric.Histogram.Bucket = append(p.currentMetric.Histogram.Bucket, b)
}
default:
p.err = fmt.Errorf("unexpected type for metric name %q", p.currentMF.GetName())
@ -602,10 +657,18 @@ func (p *TextParser) readingType() stateFn {
if p.readTokenUntilNewline(false); p.err != nil {
return nil // Unexpected end of input.
}
metricType, ok := dto.MetricType_value[strings.ToUpper(p.currentToken.String())]
typ := strings.ToUpper(p.currentToken.String()) // Tolerate any combination of upper and lower case.
metricType, ok := dto.MetricType_value[typ] // Tolerate "gauge_histogram" (not originally part of the text format).
if !ok {
p.parseError(fmt.Sprintf("unknown metric type %q", p.currentToken.String()))
return nil
// We also want to tolerate "gaugehistogram" to mark a gauge
// histogram, because that string is used in OpenMetrics. Note,
// however, that gauge histograms do not officially exist in the
// classic text format.
if typ != "GAUGEHISTOGRAM" {
p.parseError(fmt.Sprintf("unknown metric type %q", p.currentToken.String()))
return nil
}
metricType = int32(dto.MetricType_GAUGE_HISTOGRAM)
}
p.currentMF.Type = dto.MetricType(metricType).Enum()
return p.startOfLine
@ -855,7 +918,8 @@ func (p *TextParser) setOrCreateCurrentMF() {
}
histogramName := histogramMetricName(name)
if p.currentMF = p.metricFamiliesByName[histogramName]; p.currentMF != nil {
if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
if p.currentMF.GetType() == dto.MetricType_HISTOGRAM ||
p.currentMF.GetType() == dto.MetricType_GAUGE_HISTOGRAM {
if isCount(name) {
p.currentIsHistogramCount = true
}