From e931587bf8f356522bb9c05ee04df36330334080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gy=C3=B6rgy=20Krajcsovits?= Date: Tue, 8 Oct 2024 10:12:25 +0200 Subject: [PATCH] Factor out label compare and store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: György Krajcsovits --- model/textparse/nhcbparse.go | 80 ++++++++++++++++++------------- model/textparse/nhcbparse_test.go | 43 ++++++++++++++++- 2 files changed, 89 insertions(+), 34 deletions(-) diff --git a/model/textparse/nhcbparse.go b/model/textparse/nhcbparse.go index d71f7c604..9069937f1 100644 --- a/model/textparse/nhcbparse.go +++ b/model/textparse/nhcbparse.go @@ -70,9 +70,6 @@ type NHCBParser struct { tempNHCB convertnhcb.TempHistogram isCollationInProgress bool - // Remembers the last native histogram name so we can ignore - // conversions to NHCB when the name is the same. - lastNativeHistLabels labels.Labels // Remembers the last base histogram metric name (assuming it's // a classic histogram) so we can tell if the next float series // is part of the same classic histogram. @@ -159,34 +156,7 @@ func (p *NHCBParser) Next() (Entry, error) { p.metricString = p.parser.Metric(&p.lset) p.ct = p.parser.CreatedTimestamp() // Check the label set to see if we can continue or need to emit the NHCB. - shouldInsertNHCB := false - if len(p.lastBaseHistLabels) > 0 { - InnerCompare: - for _, l := range p.lset { - if l.Name == labels.MetricName { - baseName := convertnhcb.GetHistogramMetricBaseName(l.Value) - if baseName != p.lastBaseHistLabels.Get(labels.MetricName) { - p.storeBaseLabels() - shouldInsertNHCB = true - break InnerCompare - } - continue InnerCompare - } - if l.Name == labels.BucketLabel { - // Ignore. - continue InnerCompare - } - if l.Value != p.lastBaseHistLabels.Get(l.Name) { - // Different label value. - p.storeBaseLabels() - shouldInsertNHCB = true - break InnerCompare - } - } - } else { - p.storeBaseLabels() - } - if shouldInsertNHCB && p.processNHCB() { + if p.compareLabels() && p.processNHCB() { p.entry = et return EntryHistogram, nil } @@ -198,7 +168,6 @@ func (p *NHCBParser) Next() (Entry, error) { p.bytes, p.ts, p.h, p.fh = p.parser.Histogram() p.metricString = p.parser.Metric(&p.lset) p.ct = p.parser.CreatedTimestamp() - p.lastNativeHistLabels.CopyFrom(p.lset) case EntryType: p.bName, p.typ = p.parser.Type() } @@ -209,6 +178,53 @@ func (p *NHCBParser) Next() (Entry, error) { return et, err } +// Return true if labels have changed and we should emit the NHCB. +// Update the stored labels if the labels have changed. +func (p *NHCBParser) compareLabels() bool { + // Collection not in progress. + if p.lastBaseHistLabels.IsEmpty() { + if p.typ == model.MetricTypeHistogram { + p.storeBaseLabels() + } + return false + } + if p.typ != model.MetricTypeHistogram { + // Different metric type, emit the NHCB. + p.lastBaseHistLabels = labels.EmptyLabels() + return true + } + + // Compare the labels. + for _, l := range p.lset { + if l.Name == labels.MetricName { + baseName := convertnhcb.GetHistogramMetricBaseName(l.Value) + if baseName != p.lastBaseHistLabels.Get(labels.MetricName) { + if p.typ == model.MetricTypeHistogram { + p.storeBaseLabels() + } else { + p.lastBaseHistLabels = labels.EmptyLabels() + } + return true + } + continue + } + if l.Name == labels.BucketLabel { + // Ignore. + continue + } + if l.Value != p.lastBaseHistLabels.Get(l.Name) { + // Different label value. + if p.typ == model.MetricTypeHistogram { + p.storeBaseLabels() + } else { + p.lastBaseHistLabels = labels.EmptyLabels() + } + return true + } + } + return false +} + // Save the label set of the classic histogram without suffix and bucket `le` label. func (p *NHCBParser) storeBaseLabels() { builder := labels.Builder{} diff --git a/model/textparse/nhcbparse_test.go b/model/textparse/nhcbparse_test.go index 2df3fd101..28fb90fcd 100644 --- a/model/textparse/nhcbparse_test.go +++ b/model/textparse/nhcbparse_test.go @@ -282,14 +282,14 @@ foobar{quantile="0.99"} 150.1` v: 17, lset: labels.FromStrings("__name__", "foo_total"), t: int64p(1520879607789), - // TODO(krajorama) e:es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, + //es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, ct: int64p(1520872607123), }, { m: `foo_total{a="b"}`, v: 17.0, lset: labels.FromStrings("__name__", "foo_total", "a", "b"), t: int64p(1520879607789), - // TODO(krajorama) e:es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, + //es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, ct: int64p(1520872607123), }, { m: "bar", @@ -500,3 +500,42 @@ something_created{a="b"} 1520430002 got := testParse(t, p) requireEntries(t, exp, got) } + +func TestNhcbParserExemplarOnOpenMetricsParser(t *testing.T) { + // The input is taken originally from TestOpenMetricsParse, with additional tests for the NHCBParser. + + input := `# HELP foo Counter with and without labels to certify CT is parsed for both cases +# TYPE foo counter +foo_total 17.0 1520879607.789 # {id="counter-test"} 5 +foo_created 1520872607.123 +# EOF +` + exp := []parsedEntry{ + { + m: "foo", + help: "Counter with and without labels to certify CT is parsed for both cases", + }, { + m: "foo", + typ: model.MetricTypeCounter, + }, { + m: "foo_total", + v: 17, + lset: labels.FromStrings("__name__", "foo_total"), + t: int64p(1520879607789), + //es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, + ct: int64p(1520872607123), + // }, { + // m: `foo_total{a="b"}`, + // v: 17.0, + // lset: labels.FromStrings("__name__", "foo_total", "a", "b"), + // t: int64p(1520879607789), + // es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, + // ct: int64p(1520872607123), + }, + } + + p := NewOpenMetricsParser([]byte(input), labels.NewSymbolTable(), WithOMParserCTSeriesSkipped()) + p = NewNHCBParser(p, false) + got := testParse(t, p) + requireEntries(t, exp, got) +}