Disable CT handling and enable exemplar handling

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
This commit is contained in:
György Krajcsovits 2024-10-09 11:08:08 +02:00
parent e931587bf8
commit 7fccf1e6be
3 changed files with 92 additions and 89 deletions

View file

@ -38,7 +38,6 @@ type NHCBParser struct {
// For Series and Histogram.
bytes []byte
ts *int64
ct *int64
value float64
h *histogram.Histogram
fh *histogram.FloatHistogram
@ -58,16 +57,16 @@ type NHCBParser struct {
bytesNHCB []byte
hNHCB *histogram.Histogram
fhNHCB *histogram.FloatHistogram
ctNHCB *int64
lsetNHCB labels.Labels
exemplars []exemplar.Exemplar
metricStringNHCB string
// Collates values from the classic histogram series to build
// the converted histogram later.
tempLsetNHCB labels.Labels
tempCtNHCB *int64
tempCtNHCBbacking int64
tempNHCB convertnhcb.TempHistogram
tempExemplars []exemplar.Exemplar
tempExemplarCount int
isCollationInProgress bool
// Remembers the last base histogram metric name (assuming it's
@ -81,6 +80,7 @@ func NewNHCBParser(p Parser, keepClassicHistograms bool) Parser {
parser: p,
keepClassicHistograms: keepClassicHistograms,
tempNHCB: convertnhcb.NewTempHistogram(),
tempExemplars: make([]exemplar.Exemplar, 0, 1),
}
}
@ -121,14 +121,19 @@ func (p *NHCBParser) Metric(l *labels.Labels) string {
}
func (p *NHCBParser) Exemplar(ex *exemplar.Exemplar) bool {
if p.justInsertedNHCB {
if len(p.exemplars) == 0 {
return false
}
*ex = p.exemplars[0]
p.exemplars = p.exemplars[1:]
return true
}
return p.parser.Exemplar(ex)
}
func (p *NHCBParser) CreatedTimestamp() *int64 {
if p.justInsertedNHCB {
return p.ctNHCB
}
return p.ct
return nil
}
func (p *NHCBParser) Next() (Entry, error) {
@ -154,7 +159,6 @@ func (p *NHCBParser) Next() (Entry, error) {
case EntrySeries:
p.bytes, p.ts, p.value = p.parser.Series()
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.
if p.compareLabels() && p.processNHCB() {
p.entry = et
@ -167,7 +171,6 @@ func (p *NHCBParser) Next() (Entry, error) {
case EntryHistogram:
p.bytes, p.ts, p.h, p.fh = p.parser.Histogram()
p.metricString = p.parser.Metric(&p.lset)
p.ct = p.parser.CreatedTimestamp()
case EntryType:
p.bName, p.typ = p.parser.Type()
}
@ -255,10 +258,6 @@ func (p *NHCBParser) handleClassicHistogramSeries(lset labels.Labels) bool {
if convertnhcb.GetHistogramMetricBaseName(mName) != string(p.bName) {
return false
}
if p.ct != nil {
p.tempCtNHCBbacking = *p.ct
p.tempCtNHCB = &p.tempCtNHCBbacking
}
switch {
case strings.HasSuffix(mName, "_bucket") && lset.Has(labels.BucketLabel):
le, err := strconv.ParseFloat(lset.Get(labels.BucketLabel), 64)
@ -285,9 +284,36 @@ func (p *NHCBParser) handleClassicHistogramSeries(lset labels.Labels) bool {
func (p *NHCBParser) processClassicHistogramSeries(lset labels.Labels, suffix string, updateHist func(*convertnhcb.TempHistogram)) {
p.isCollationInProgress = true
p.tempLsetNHCB = convertnhcb.GetHistogramMetricBase(lset, suffix)
p.storeExemplars()
updateHist(&p.tempNHCB)
}
func (p *NHCBParser) storeExemplars() {
for ex := p.nextExemplarPtr(); p.parser.Exemplar(ex); ex = p.nextExemplarPtr() {
p.tempExemplarCount++
}
}
func (p *NHCBParser) nextExemplarPtr() *exemplar.Exemplar {
switch {
case p.tempExemplarCount == len(p.tempExemplars)-1:
// Reuse the previously allocated exemplar, it was not filled up.
case len(p.tempExemplars) == cap(p.tempExemplars):
// Let the runtime grow the slice.
p.tempExemplars = append(p.tempExemplars, exemplar.Exemplar{})
default:
// Take the next element into use.
p.tempExemplars = p.tempExemplars[:len(p.tempExemplars)+1]
}
return &p.tempExemplars[len(p.tempExemplars)-1]
}
func (p *NHCBParser) swapExemplars() {
p.exemplars = p.tempExemplars[:p.tempExemplarCount]
p.tempExemplars = p.tempExemplars[:0]
p.tempExemplarCount = 0
}
// processNHCB converts the collated classic histogram series to NHCB and caches the info
// to be returned to callers.
func (p *NHCBParser) processNHCB() bool {
@ -314,12 +340,11 @@ func (p *NHCBParser) processNHCB() bool {
p.hNHCB = nil
p.fhNHCB = fh
}
p.ctNHCB = p.tempCtNHCB
p.metricStringNHCB = p.tempLsetNHCB.Get(labels.MetricName) + strings.ReplaceAll(p.tempLsetNHCB.DropMetricName().String(), ", ", ",")
p.bytesNHCB = []byte(p.metricStringNHCB)
p.lsetNHCB = p.tempLsetNHCB
p.swapExemplars()
p.tempNHCB = convertnhcb.NewTempHistogram()
p.tempCtNHCB = nil
p.isCollationInProgress = false
p.justInsertedNHCB = true
return true

View file

@ -207,7 +207,10 @@ foobar{quantile="0.99"} 150.1`
// Custom values are empty as we do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "hhh"),
// TODO(krajorama) e: []*exemplar.Exemplar{{Labels: labels.FromStrings("id", "histogram-bucket-test"), Value: 4}},
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("id", "histogram-bucket-test"), Value: 4},
{Labels: labels.FromStrings("id", "histogram-count-test"), Value: 4},
},
}, {
m: "ggh",
typ: model.MetricTypeGaugeHistogram,
@ -228,7 +231,7 @@ foobar{quantile="0.99"} 150.1`
m: `smr_seconds_count`,
v: 2,
lset: labels.FromStrings("__name__", "smr_seconds_count"),
// TODO(krajorama) e:es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "summary-count-test"), Value: 1, HasTs: true, Ts: 123321}},
es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "summary-count-test"), Value: 1, HasTs: true, Ts: 123321}},
}, {
m: `smr_seconds_sum`,
v: 42,
@ -282,15 +285,15 @@ foobar{quantile="0.99"} 150.1`
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),
es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}},
// TODO(krajorama): 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),
es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}},
// TODO(krajorama): ct: int64p(1520872607123),
}, {
m: "bar",
help: "Summary with CT at the end, making sure we find CT even if it's multiple lines a far",
@ -301,22 +304,22 @@ foobar{quantile="0.99"} 150.1`
m: "bar_count",
v: 17.0,
lset: labels.FromStrings("__name__", "bar_count"),
ct: int64p(1520872608124),
// TODO(krajorama): ct: int64p(1520872608124),
}, {
m: "bar_sum",
v: 324789.3,
lset: labels.FromStrings("__name__", "bar_sum"),
ct: int64p(1520872608124),
// TODO(krajorama): ct: int64p(1520872608124),
}, {
m: `bar{quantile="0.95"}`,
v: 123.7,
lset: labels.FromStrings("__name__", "bar", "quantile", "0.95"),
ct: int64p(1520872608124),
// TODO(krajorama): ct: int64p(1520872608124),
}, {
m: `bar{quantile="0.99"}`,
v: 150.0,
lset: labels.FromStrings("__name__", "bar", "quantile", "0.99"),
ct: int64p(1520872608124),
// TODO(krajorama): ct: int64p(1520872608124),
}, {
m: "baz",
help: "Histogram with the same objective as above's summary",
@ -334,7 +337,7 @@ foobar{quantile="0.99"} 150.1`
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "baz"),
ct: int64p(1520872609125),
// TODO(krajorama): ct: int64p(1520872609125),
}, {
m: "fizz_created",
help: "Gauge which shouldn't be parsed as CT",
@ -362,7 +365,7 @@ foobar{quantile="0.99"} 150.1`
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "something"),
ct: int64p(1520430001000),
// TODO(krajorama): ct: int64p(1520430001000),
}, {
m: `something{a="b"}`,
shs: &histogram.Histogram{
@ -374,7 +377,7 @@ foobar{quantile="0.99"} 150.1`
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "something", "a", "b"),
ct: int64p(1520430002000),
// TODO(krajorama): ct: int64p(1520430002000),
}, {
m: "yum",
help: "Summary with _created between sum and quantiles",
@ -385,22 +388,22 @@ foobar{quantile="0.99"} 150.1`
m: `yum_count`,
v: 20,
lset: labels.FromStrings("__name__", "yum_count"),
ct: int64p(1520430003000),
// TODO(krajorama): ct: int64p(1520430003000),
}, {
m: `yum_sum`,
v: 324789.5,
lset: labels.FromStrings("__name__", "yum_sum"),
ct: int64p(1520430003000),
// TODO(krajorama): ct: int64p(1520430003000),
}, {
m: `yum{quantile="0.95"}`,
v: 123.7,
lset: labels.FromStrings("__name__", "yum", "quantile", "0.95"),
ct: int64p(1520430003000),
// TODO(krajorama): ct: int64p(1520430003000),
}, {
m: `yum{quantile="0.99"}`,
v: 150.0,
lset: labels.FromStrings("__name__", "yum", "quantile", "0.99"),
ct: int64p(1520430003000),
// TODO(krajorama): ct: int64p(1520430003000),
}, {
m: "foobar",
help: "Summary with _created as the first line",
@ -411,22 +414,22 @@ foobar{quantile="0.99"} 150.1`
m: `foobar_count`,
v: 21,
lset: labels.FromStrings("__name__", "foobar_count"),
ct: int64p(1520430004000),
// TODO(krajorama): ct: int64p(1520430004000),
}, {
m: `foobar_sum`,
v: 324789.6,
lset: labels.FromStrings("__name__", "foobar_sum"),
ct: int64p(1520430004000),
// TODO(krajorama): ct: int64p(1520430004000),
}, {
m: `foobar{quantile="0.95"}`,
v: 123.8,
lset: labels.FromStrings("__name__", "foobar", "quantile", "0.95"),
ct: int64p(1520430004000),
// TODO(krajorama): ct: int64p(1520430004000),
}, {
m: `foobar{quantile="0.99"}`,
v: 150.1,
lset: labels.FromStrings("__name__", "foobar", "quantile", "0.99"),
ct: int64p(1520430004000),
// TODO(krajorama): ct: int64p(1520430004000),
}, {
m: "metric",
help: "foo\x00bar",
@ -450,14 +453,14 @@ func TestNhcbParserMultiHOnOpenMetricsParser(t *testing.T) {
# TYPE something histogram
something_count 18
something_sum 324789.4
something_created 1520430001
something_bucket{le="0.0"} 1
something_bucket{le="+Inf"} 18
something_bucket{le="0.0"} 1 # {id="something-test"} -2.0
something_bucket{le="1.0"} 16 # {id="something-test"} 0.5
something_bucket{le="+Inf"} 18 # {id="something-test"} 8
something_count{a="b"} 9
something_sum{a="b"} 42123.0
something_bucket{a="b",le="0.0"} 8
something_bucket{a="b",le="+Inf"} 9
something_created{a="b"} 1520430002
something_bucket{a="b",le="0.0"} 8 # {id="something-test"} 0.0 123.321
something_bucket{a="b",le="1.0"} 8
something_bucket{a="b",le="+Inf"} 9 # {id="something-test"} 2e100 123.000
# EOF
`
@ -474,63 +477,33 @@ something_created{a="b"} 1520430002
Schema: -53, // Custom buckets.
Count: 18,
Sum: 324789.4,
PositiveSpans: []histogram.Span{{Offset: 0, Length: 2}},
PositiveBuckets: []int64{1, 16},
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
PositiveSpans: []histogram.Span{{Offset: 0, Length: 3}},
PositiveBuckets: []int64{1, 14, -13},
CustomValues: []float64{0.0, 1.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "something"),
ct: int64p(1520430001000),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("id", "something-test"), Value: -2.0},
{Labels: labels.FromStrings("id", "something-test"), Value: 0.5},
{Labels: labels.FromStrings("id", "something-test"), Value: 8.0},
},
// TODO(krajorama): ct: int64p(1520430001000),
}, {
m: `something{a="b"}`,
shs: &histogram.Histogram{
Schema: -53, // Custom buckets.
Count: 9,
Sum: 42123.0,
PositiveSpans: []histogram.Span{{Offset: 0, Length: 2}},
PositiveSpans: []histogram.Span{{Offset: 0, Length: 1}, {Offset: 1, Length: 1}},
PositiveBuckets: []int64{8, -7},
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
CustomValues: []float64{0.0, 1.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "something", "a", "b"),
ct: int64p(1520430002000),
},
}
p := NewOpenMetricsParser([]byte(input), labels.NewSymbolTable(), WithOMParserCTSeriesSkipped())
p = NewNHCBParser(p, false)
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),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("id", "something-test"), Value: 0.0, HasTs: true, Ts: 123321},
{Labels: labels.FromStrings("id", "something-test"), Value: 2e100, HasTs: true, Ts: 123000},
},
// TODO(krajorama): ct: int64p(1520430002000),
},
}

View file

@ -178,6 +178,11 @@ func (m *Manager) reload() {
level.Error(m.logger).Log("msg", "error reloading target set", "err", "invalid config id:"+setName)
continue
}
if scrapeConfig.ConvertClassicHistograms && m.opts.EnableCreatedTimestampZeroIngestion {
// TODO(krajorama): lift this limitation
level.Error(m.logger).Log("msg", "error reloading target set", "err", "cannot convert classic histograms to native histograms with custom buckets and ingest created timestamp zero samples at the same time")
continue
}
m.metrics.targetScrapePools.Inc()
sp, err := newScrapePool(scrapeConfig, m.append, m.offsetSeed, log.With(m.logger, "scrape_pool", setName), m.buffers, m.opts, m.metrics)
if err != nil {