histograms: Fix bug #12552

The problem was the following:

When trying to parse native histograms and classic histograms in
parallel, the parser would first parse the histogram proto messages as
a native histogram and then parse the same message again, but now as a
classic histogram. Afterwards, it would forget that it was dealing
with a metric family that contains native histograms and would parse
the rest of the metric family as classic histograms only. The fix is
to check again after being done with a classic histogram.

Signed-off-by: beorn7 <beorn@grafana.com>
This commit is contained in:
beorn7 2023-07-12 18:42:02 +02:00
parent 1c3bd04bea
commit da047c6857

View file

@ -54,7 +54,7 @@ type ProtobufParser struct {
// quantiles/buckets. // quantiles/buckets.
fieldPos int fieldPos int
fieldsDone bool // true if no more fields of a Summary or (legacy) Histogram to be processed. fieldsDone bool // true if no more fields of a Summary or (legacy) Histogram to be processed.
redoClassic bool // true after parsing a native histogram if we need to parse it again as a classit histogram. redoClassic bool // true after parsing a native histogram if we need to parse it again as a classic histogram.
// state is marked by the entry we are processing. EntryInvalid implies // state is marked by the entry we are processing. EntryInvalid implies
// that we have to decode the next MetricFamily. // that we have to decode the next MetricFamily.
@ -411,6 +411,14 @@ func (p *ProtobufParser) Next() (Entry, error) {
p.metricPos++ p.metricPos++
p.fieldPos = -2 p.fieldPos = -2
p.fieldsDone = false p.fieldsDone = false
// If this is a metric family containing native
// histograms, we have to switch back to native
// histograms after parsing a classic histogram.
if p.state == EntrySeries &&
(t == dto.MetricType_HISTOGRAM || t == dto.MetricType_GAUGE_HISTOGRAM) &&
isNativeHistogram(p.mf.GetMetric()[0].GetHistogram()) {
p.state = EntryHistogram
}
} }
if p.metricPos >= len(p.mf.GetMetric()) { if p.metricPos >= len(p.mf.GetMetric()) {
p.state = EntryInvalid p.state = EntryInvalid