Merge pull request #12577 from prometheus/beorn7/histogram3

histograms: Fix parsing of float histograms without zero bucket
This commit is contained in:
Björn Rabenstein 2023-07-19 16:44:27 +02:00 committed by GitHub
commit 266e27870e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 107 additions and 16 deletions

View file

@ -105,7 +105,7 @@ func (p *ProtobufParser) Series() ([]byte, *int64, float64) {
v = float64(s.GetSampleCount()) v = float64(s.GetSampleCount())
case -1: case -1:
v = s.GetSampleSum() v = s.GetSampleSum()
// Need to detect a summaries without quantile here. // Need to detect summaries without quantile here.
if len(s.GetQuantile()) == 0 { if len(s.GetQuantile()) == 0 {
p.fieldsDone = true p.fieldsDone = true
} }
@ -564,8 +564,10 @@ func formatOpenMetricsFloat(f float64) string {
// deciding if a histogram should be ingested as a conventional one or a native // deciding if a histogram should be ingested as a conventional one or a native
// one. // one.
func isNativeHistogram(h *dto.Histogram) bool { func isNativeHistogram(h *dto.Histogram) bool {
return len(h.GetNegativeDelta()) > 0 || return h.GetZeroThreshold() > 0 ||
len(h.GetPositiveDelta()) > 0 ||
h.GetZeroCount() > 0 || h.GetZeroCount() > 0 ||
h.GetZeroThreshold() > 0 len(h.GetNegativeDelta()) > 0 ||
len(h.GetPositiveDelta()) > 0 ||
len(h.GetNegativeCount()) > 0 ||
len(h.GetPositiveCount()) > 0
} }

View file

@ -463,6 +463,24 @@ metric: <
> >
> >
`,
`name: "test_float_histogram_with_zerothreshold_zero"
help: "Test float histogram with a zero threshold of zero."
type: HISTOGRAM
metric: <
histogram: <
sample_count_float: 5.0
sample_sum: 12.1
schema: 3
positive_span: <
offset: 8
length: 2
>
positive_count: 2.0
positive_count: 3.0
>
>
`, `,
`name: "rpc_durations_seconds" `name: "rpc_durations_seconds"
help: "RPC latency distributions." help: "RPC latency distributions."
@ -850,6 +868,30 @@ func TestProtobufParse(t *testing.T) {
"foo", "baz", "foo", "baz",
), ),
}, },
{
m: "test_float_histogram_with_zerothreshold_zero",
help: "Test float histogram with a zero threshold of zero.",
},
{
m: "test_float_histogram_with_zerothreshold_zero",
typ: MetricTypeHistogram,
},
{
m: "test_float_histogram_with_zerothreshold_zero",
fhs: &histogram.FloatHistogram{
Count: 5.0,
Sum: 12.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
PositiveBuckets: []float64{2.0, 3.0},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "test_float_histogram_with_zerothreshold_zero",
),
},
{ {
m: "rpc_durations_seconds", m: "rpc_durations_seconds",
help: "RPC latency distributions.", help: "RPC latency distributions.",
@ -1550,14 +1592,38 @@ func TestProtobufParse(t *testing.T) {
), ),
}, },
{ // 67 { // 67
m: "test_float_histogram_with_zerothreshold_zero",
help: "Test float histogram with a zero threshold of zero.",
},
{ // 68
m: "test_float_histogram_with_zerothreshold_zero",
typ: MetricTypeHistogram,
},
{ // 69
m: "test_float_histogram_with_zerothreshold_zero",
fhs: &histogram.FloatHistogram{
Count: 5.0,
Sum: 12.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
PositiveBuckets: []float64{2.0, 3.0},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "test_float_histogram_with_zerothreshold_zero",
),
},
{ // 70
m: "rpc_durations_seconds", m: "rpc_durations_seconds",
help: "RPC latency distributions.", help: "RPC latency distributions.",
}, },
{ // 68 { // 71
m: "rpc_durations_seconds", m: "rpc_durations_seconds",
typ: MetricTypeSummary, typ: MetricTypeSummary,
}, },
{ // 69 { // 72
m: "rpc_durations_seconds_count\xffservice\xffexponential", m: "rpc_durations_seconds_count\xffservice\xffexponential",
v: 262, v: 262,
lset: labels.FromStrings( lset: labels.FromStrings(
@ -1565,7 +1631,7 @@ func TestProtobufParse(t *testing.T) {
"service", "exponential", "service", "exponential",
), ),
}, },
{ // 70 { // 73
m: "rpc_durations_seconds_sum\xffservice\xffexponential", m: "rpc_durations_seconds_sum\xffservice\xffexponential",
v: 0.00025551262820703587, v: 0.00025551262820703587,
lset: labels.FromStrings( lset: labels.FromStrings(
@ -1573,7 +1639,7 @@ func TestProtobufParse(t *testing.T) {
"service", "exponential", "service", "exponential",
), ),
}, },
{ // 71 { // 74
m: "rpc_durations_seconds\xffservice\xffexponential\xffquantile\xff0.5", m: "rpc_durations_seconds\xffservice\xffexponential\xffquantile\xff0.5",
v: 6.442786329648548e-07, v: 6.442786329648548e-07,
lset: labels.FromStrings( lset: labels.FromStrings(
@ -1582,7 +1648,7 @@ func TestProtobufParse(t *testing.T) {
"service", "exponential", "service", "exponential",
), ),
}, },
{ // 72 { // 75
m: "rpc_durations_seconds\xffservice\xffexponential\xffquantile\xff0.9", m: "rpc_durations_seconds\xffservice\xffexponential\xffquantile\xff0.9",
v: 1.9435742936658396e-06, v: 1.9435742936658396e-06,
lset: labels.FromStrings( lset: labels.FromStrings(
@ -1591,7 +1657,7 @@ func TestProtobufParse(t *testing.T) {
"service", "exponential", "service", "exponential",
), ),
}, },
{ // 73 { // 76
m: "rpc_durations_seconds\xffservice\xffexponential\xffquantile\xff0.99", m: "rpc_durations_seconds\xffservice\xffexponential\xffquantile\xff0.99",
v: 4.0471608667037015e-06, v: 4.0471608667037015e-06,
lset: labels.FromStrings( lset: labels.FromStrings(
@ -1600,22 +1666,22 @@ func TestProtobufParse(t *testing.T) {
"service", "exponential", "service", "exponential",
), ),
}, },
{ // 74 { // 77
m: "without_quantiles", m: "without_quantiles",
help: "A summary without quantiles.", help: "A summary without quantiles.",
}, },
{ // 75 { // 78
m: "without_quantiles", m: "without_quantiles",
typ: MetricTypeSummary, typ: MetricTypeSummary,
}, },
{ // 76 { // 79
m: "without_quantiles_count", m: "without_quantiles_count",
v: 42, v: 42,
lset: labels.FromStrings( lset: labels.FromStrings(
"__name__", "without_quantiles_count", "__name__", "without_quantiles_count",
), ),
}, },
{ // 77 { // 80
m: "without_quantiles_sum", m: "without_quantiles_sum",
v: 1.234, v: 1.234,
lset: labels.FromStrings( lset: labels.FromStrings(

View file

@ -335,18 +335,41 @@ func TestFederationWithNativeHistograms(t *testing.T) {
}, },
NegativeBuckets: []int64{1, 1, -1, 0}, NegativeBuckets: []int64{1, 1, -1, 0},
} }
histWithoutZeroBucket := &histogram.Histogram{
Count: 20,
Sum: 99.23,
Schema: 1,
PositiveSpans: []histogram.Span{
{Offset: 0, Length: 2},
{Offset: 1, Length: 2},
},
PositiveBuckets: []int64{2, 2, -2, 0},
NegativeSpans: []histogram.Span{
{Offset: 0, Length: 2},
{Offset: 1, Length: 2},
},
NegativeBuckets: []int64{2, 2, -2, 0},
}
app := db.Appender(context.Background()) app := db.Appender(context.Background())
for i := 0; i < 6; i++ { for i := 0; i < 6; i++ {
l := labels.FromStrings("__name__", "test_metric", "foo", fmt.Sprintf("%d", i)) l := labels.FromStrings("__name__", "test_metric", "foo", fmt.Sprintf("%d", i))
expL := labels.FromStrings("__name__", "test_metric", "instance", "", "foo", fmt.Sprintf("%d", i)) expL := labels.FromStrings("__name__", "test_metric", "instance", "", "foo", fmt.Sprintf("%d", i))
if i%3 == 0 { switch i {
case 0, 3:
_, err = app.Append(0, l, 100*60*1000, float64(i*100)) _, err = app.Append(0, l, 100*60*1000, float64(i*100))
expVec = append(expVec, promql.Sample{ expVec = append(expVec, promql.Sample{
T: 100 * 60 * 1000, T: 100 * 60 * 1000,
F: float64(i * 100), F: float64(i * 100),
Metric: expL, Metric: expL,
}) })
} else { case 4:
_, err = app.AppendHistogram(0, l, 100*60*1000, histWithoutZeroBucket.Copy(), nil)
expVec = append(expVec, promql.Sample{
T: 100 * 60 * 1000,
H: histWithoutZeroBucket.ToFloat(),
Metric: expL,
})
default:
hist.ZeroCount++ hist.ZeroCount++
_, err = app.AppendHistogram(0, l, 100*60*1000, hist.Copy(), nil) _, err = app.AppendHistogram(0, l, 100*60*1000, hist.Copy(), nil)
expVec = append(expVec, promql.Sample{ expVec = append(expVec, promql.Sample{