mirror of
https://github.com/prometheus/prometheus
synced 2024-12-26 00:23:18 +00:00
textparse: Fix endless loop #12731
PR #12557 introduced the possibility of parsing multiple exemplars per native histograms. It did so by requiring the `Exemplar` method of the parser to be called repeatedly until it returns false. However, the protobuf parser code wasn't correctly updated for the old case of a single exemplar for a classic bucket (if actually parsed as a classic bucket) and a single exemplar on a counter. In those cases, the method would return `true` forever, yielding the same exemplar again and again, leading to an endless loop. With this fix, the state is now tracked and the single exemplar is only returned once. Signed-off-by: beorn7 <beorn@grafana.com>
This commit is contained in:
parent
3d9a830f2f
commit
65ccf4460a
@ -56,6 +56,10 @@ type ProtobufParser struct {
|
||||
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 classic histogram.
|
||||
|
||||
// exemplarReturned is set to true each time an exemplar has been
|
||||
// returned, and set back to false upon each Next() call.
|
||||
exemplarReturned bool
|
||||
|
||||
// state is marked by the entry we are processing. EntryInvalid implies
|
||||
// that we have to decode the next MetricFamily.
|
||||
state Entry
|
||||
@ -295,6 +299,10 @@ func (p *ProtobufParser) Metric(l *labels.Labels) string {
|
||||
// histogram, the legacy bucket section is still used for exemplars. To ingest
|
||||
// all exemplars, call the Exemplar method repeatedly until it returns false.
|
||||
func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
|
||||
if p.exemplarReturned && p.state == EntrySeries {
|
||||
// We only ever return one exemplar per (non-native-histogram) series.
|
||||
return false
|
||||
}
|
||||
m := p.mf.GetMetric()[p.metricPos]
|
||||
var exProto *dto.Exemplar
|
||||
switch p.mf.GetType() {
|
||||
@ -335,6 +343,7 @@ func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
|
||||
}
|
||||
p.builder.Sort()
|
||||
ex.Labels = p.builder.Labels()
|
||||
p.exemplarReturned = true
|
||||
return true
|
||||
}
|
||||
|
||||
@ -342,6 +351,7 @@ func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
|
||||
// text format parser). It returns (EntryInvalid, io.EOF) if no samples were
|
||||
// read.
|
||||
func (p *ProtobufParser) Next() (Entry, error) {
|
||||
p.exemplarReturned = false
|
||||
switch p.state {
|
||||
case EntryInvalid:
|
||||
p.metricPos = 0
|
||||
|
Loading…
Reference in New Issue
Block a user