mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-11 13:57:36 -08:00
Prometheus support parse exemplars from native histogram (#13488)
scrape: support parsing exemplars from native histogram --------- Signed-off-by: Ziqi Zhao <zhaoziqi9146@gmail.com> Signed-off-by: Björn Rabenstein <github@rabenste.in> Co-authored-by: Björn Rabenstein <github@rabenste.in>
This commit is contained in:
parent
ff6c83269c
commit
a93859a52f
|
@ -56,6 +56,8 @@ type ProtobufParser struct {
|
||||||
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 classic histogram.
|
redoClassic bool // true after parsing a native histogram if we need to parse it again as a classic histogram.
|
||||||
|
// exemplarPos is the position within the exemplars slice of a native histogram.
|
||||||
|
exemplarPos int
|
||||||
|
|
||||||
// exemplarReturned is set to true each time an exemplar has been
|
// exemplarReturned is set to true each time an exemplar has been
|
||||||
// returned, and set back to false upon each Next() call.
|
// returned, and set back to false upon each Next() call.
|
||||||
|
@ -304,8 +306,9 @@ func (p *ProtobufParser) Metric(l *labels.Labels) string {
|
||||||
|
|
||||||
// Exemplar writes the exemplar of the current sample into the passed
|
// Exemplar writes the exemplar of the current sample into the passed
|
||||||
// exemplar. It returns if an exemplar exists or not. In case of a native
|
// exemplar. It returns if an exemplar exists or not. In case of a native
|
||||||
// histogram, the legacy bucket section is still used for exemplars. To ingest
|
// histogram, the exemplars in the native histogram will be returned.
|
||||||
// all exemplars, call the Exemplar method repeatedly until it returns false.
|
// If this field is empty, the classic 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 {
|
func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
|
||||||
if p.exemplarReturned && p.state == EntrySeries {
|
if p.exemplarReturned && p.state == EntrySeries {
|
||||||
// We only ever return one exemplar per (non-native-histogram) series.
|
// We only ever return one exemplar per (non-native-histogram) series.
|
||||||
|
@ -317,28 +320,42 @@ func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
|
||||||
case dto.MetricType_COUNTER:
|
case dto.MetricType_COUNTER:
|
||||||
exProto = m.GetCounter().GetExemplar()
|
exProto = m.GetCounter().GetExemplar()
|
||||||
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
|
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
|
||||||
bb := m.GetHistogram().GetBucket()
|
|
||||||
isClassic := p.state == EntrySeries
|
isClassic := p.state == EntrySeries
|
||||||
if p.fieldPos < 0 {
|
if !isClassic && len(m.GetHistogram().GetExemplars()) > 0 {
|
||||||
if isClassic {
|
exs := m.GetHistogram().GetExemplars()
|
||||||
return false // At _count or _sum.
|
for p.exemplarPos < len(exs) {
|
||||||
|
exProto = exs[p.exemplarPos]
|
||||||
|
p.exemplarPos++
|
||||||
|
if exProto != nil && exProto.GetTimestamp() != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.fieldPos = 0 // Start at 1st bucket for native histograms.
|
if exProto != nil && exProto.GetTimestamp() == nil {
|
||||||
}
|
return false
|
||||||
for p.fieldPos < len(bb) {
|
|
||||||
exProto = bb[p.fieldPos].GetExemplar()
|
|
||||||
if isClassic {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
p.fieldPos++
|
} else {
|
||||||
// We deliberately drop exemplars with no timestamp only for native histograms.
|
bb := m.GetHistogram().GetBucket()
|
||||||
if exProto != nil && (isClassic || exProto.GetTimestamp() != nil) {
|
if p.fieldPos < 0 {
|
||||||
break // Found a classic histogram exemplar or a native histogram exemplar with a timestamp.
|
if isClassic {
|
||||||
|
return false // At _count or _sum.
|
||||||
|
}
|
||||||
|
p.fieldPos = 0 // Start at 1st bucket for native histograms.
|
||||||
|
}
|
||||||
|
for p.fieldPos < len(bb) {
|
||||||
|
exProto = bb[p.fieldPos].GetExemplar()
|
||||||
|
if isClassic {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.fieldPos++
|
||||||
|
// We deliberately drop exemplars with no timestamp only for native histograms.
|
||||||
|
if exProto != nil && (isClassic || exProto.GetTimestamp() != nil) {
|
||||||
|
break // Found a classic histogram exemplar or a native histogram exemplar with a timestamp.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the last exemplar for native histograms has no timestamp, ignore it.
|
||||||
|
if !isClassic && exProto.GetTimestamp() == nil {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// If the last exemplar for native histograms has no timestamp, ignore it.
|
|
||||||
if !isClassic && exProto.GetTimestamp() == nil {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -596,6 +596,105 @@ metric: <
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
|
|
||||||
|
`,
|
||||||
|
`name: "test_histogram_with_native_histogram_exemplars"
|
||||||
|
help: "A histogram with native histogram exemplars."
|
||||||
|
type: HISTOGRAM
|
||||||
|
metric: <
|
||||||
|
histogram: <
|
||||||
|
sample_count: 175
|
||||||
|
sample_sum: 0.0008280461746287094
|
||||||
|
bucket: <
|
||||||
|
cumulative_count: 2
|
||||||
|
upper_bound: -0.0004899999999999998
|
||||||
|
>
|
||||||
|
bucket: <
|
||||||
|
cumulative_count: 4
|
||||||
|
upper_bound: -0.0003899999999999998
|
||||||
|
exemplar: <
|
||||||
|
label: <
|
||||||
|
name: "dummyID"
|
||||||
|
value: "59727"
|
||||||
|
>
|
||||||
|
value: -0.00039
|
||||||
|
timestamp: <
|
||||||
|
seconds: 1625851155
|
||||||
|
nanos: 146848499
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
bucket: <
|
||||||
|
cumulative_count: 16
|
||||||
|
upper_bound: -0.0002899999999999998
|
||||||
|
exemplar: <
|
||||||
|
label: <
|
||||||
|
name: "dummyID"
|
||||||
|
value: "5617"
|
||||||
|
>
|
||||||
|
value: -0.00029
|
||||||
|
>
|
||||||
|
>
|
||||||
|
schema: 3
|
||||||
|
zero_threshold: 2.938735877055719e-39
|
||||||
|
zero_count: 2
|
||||||
|
negative_span: <
|
||||||
|
offset: -162
|
||||||
|
length: 1
|
||||||
|
>
|
||||||
|
negative_span: <
|
||||||
|
offset: 23
|
||||||
|
length: 4
|
||||||
|
>
|
||||||
|
negative_delta: 1
|
||||||
|
negative_delta: 3
|
||||||
|
negative_delta: -2
|
||||||
|
negative_delta: -1
|
||||||
|
negative_delta: 1
|
||||||
|
positive_span: <
|
||||||
|
offset: -161
|
||||||
|
length: 1
|
||||||
|
>
|
||||||
|
positive_span: <
|
||||||
|
offset: 8
|
||||||
|
length: 3
|
||||||
|
>
|
||||||
|
positive_delta: 1
|
||||||
|
positive_delta: 2
|
||||||
|
positive_delta: -1
|
||||||
|
positive_delta: -1
|
||||||
|
exemplars: <
|
||||||
|
label: <
|
||||||
|
name: "dummyID"
|
||||||
|
value: "59780"
|
||||||
|
>
|
||||||
|
value: -0.00039
|
||||||
|
timestamp: <
|
||||||
|
seconds: 1625851155
|
||||||
|
nanos: 146848499
|
||||||
|
>
|
||||||
|
>
|
||||||
|
exemplars: <
|
||||||
|
label: <
|
||||||
|
name: "dummyID"
|
||||||
|
value: "5617"
|
||||||
|
>
|
||||||
|
value: -0.00029
|
||||||
|
>
|
||||||
|
exemplars: <
|
||||||
|
label: <
|
||||||
|
name: "dummyID"
|
||||||
|
value: "59772"
|
||||||
|
>
|
||||||
|
value: -0.00052
|
||||||
|
timestamp: <
|
||||||
|
seconds: 1625851160
|
||||||
|
nanos: 156848499
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
timestamp_ms: 1234568
|
||||||
|
>
|
||||||
|
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1141,6 +1240,42 @@ func TestProtobufParse(t *testing.T) {
|
||||||
"__name__", "test_gaugehistogram_with_createdtimestamp",
|
"__name__", "test_gaugehistogram_with_createdtimestamp",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars",
|
||||||
|
help: "A histogram with native histogram exemplars.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars",
|
||||||
|
typ: model.MetricTypeHistogram,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars",
|
||||||
|
t: 1234568,
|
||||||
|
shs: &histogram.Histogram{
|
||||||
|
Count: 175,
|
||||||
|
ZeroCount: 2,
|
||||||
|
Sum: 0.0008280461746287094,
|
||||||
|
ZeroThreshold: 2.938735877055719e-39,
|
||||||
|
Schema: 3,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: -161, Length: 1},
|
||||||
|
{Offset: 8, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: -162, Length: 1},
|
||||||
|
{Offset: 23, Length: 4},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 2, -1, -1},
|
||||||
|
NegativeBuckets: []int64{1, 3, -2, -1, 1},
|
||||||
|
},
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars",
|
||||||
|
),
|
||||||
|
e: []exemplar.Exemplar{
|
||||||
|
{Labels: labels.FromStrings("dummyID", "59780"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
|
||||||
|
{Labels: labels.FromStrings("dummyID", "59772"), Value: -0.00052, HasTs: true, Ts: 1625851160156},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1959,6 +2094,100 @@ func TestProtobufParse(t *testing.T) {
|
||||||
"__name__", "test_gaugehistogram_with_createdtimestamp",
|
"__name__", "test_gaugehistogram_with_createdtimestamp",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{ // 94
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars",
|
||||||
|
help: "A histogram with native histogram exemplars.",
|
||||||
|
},
|
||||||
|
{ // 95
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars",
|
||||||
|
typ: model.MetricTypeHistogram,
|
||||||
|
},
|
||||||
|
{ // 96
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars",
|
||||||
|
t: 1234568,
|
||||||
|
shs: &histogram.Histogram{
|
||||||
|
Count: 175,
|
||||||
|
ZeroCount: 2,
|
||||||
|
Sum: 0.0008280461746287094,
|
||||||
|
ZeroThreshold: 2.938735877055719e-39,
|
||||||
|
Schema: 3,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: -161, Length: 1},
|
||||||
|
{Offset: 8, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: -162, Length: 1},
|
||||||
|
{Offset: 23, Length: 4},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 2, -1, -1},
|
||||||
|
NegativeBuckets: []int64{1, 3, -2, -1, 1},
|
||||||
|
},
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars",
|
||||||
|
),
|
||||||
|
e: []exemplar.Exemplar{
|
||||||
|
{Labels: labels.FromStrings("dummyID", "59780"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
|
||||||
|
{Labels: labels.FromStrings("dummyID", "59772"), Value: -0.00052, HasTs: true, Ts: 1625851160156},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // 97
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars_count",
|
||||||
|
t: 1234568,
|
||||||
|
v: 175,
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars_count",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ // 98
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars_sum",
|
||||||
|
t: 1234568,
|
||||||
|
v: 0.0008280461746287094,
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars_sum",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ // 99
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0004899999999999998",
|
||||||
|
t: 1234568,
|
||||||
|
v: 2,
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||||
|
"le", "-0.0004899999999999998",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ // 100
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0003899999999999998",
|
||||||
|
t: 1234568,
|
||||||
|
v: 4,
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||||
|
"le", "-0.0003899999999999998",
|
||||||
|
),
|
||||||
|
e: []exemplar.Exemplar{
|
||||||
|
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // 101
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0002899999999999998",
|
||||||
|
t: 1234568,
|
||||||
|
v: 16,
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||||
|
"le", "-0.0002899999999999998",
|
||||||
|
),
|
||||||
|
e: []exemplar.Exemplar{
|
||||||
|
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.00029, HasTs: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // 102
|
||||||
|
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff+Inf",
|
||||||
|
t: 1234568,
|
||||||
|
v: 175,
|
||||||
|
lset: labels.FromStrings(
|
||||||
|
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||||
|
"le", "+Inf",
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue