Skip to content

Commit

Permalink
histogram: Identify native histograms even without observations
Browse files Browse the repository at this point in the history
Native histograms without observations and with a zero threshold of
zero look the same as classic histograms in the protobuf exposition
format. According to
prometheus/client_golang#1127 , the idea is
to add a no-op span to those histograms to mark them as native
histograms. This commit enables Prometheus to detect that no-op span
and adds a doc comment to the proto spec describing the behavior.

Signed-off-by: beorn7 <beorn@grafana.com>
  • Loading branch information
beorn7 committed Jul 20, 2023
1 parent 0e12f11 commit 94081a8
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 15 deletions.
27 changes: 12 additions & 15 deletions model/textparse/protobufparse.go
Expand Up @@ -554,20 +554,17 @@ func formatOpenMetricsFloat(f float64) string {
return s + ".0"
}

// isNativeHistogram returns false iff the provided histograms has no sparse
// buckets and a zero threshold of 0 and a zero count of 0. In principle, this
// could still be meant to be a native histogram (with a zero threshold of 0 and
// no observations yet), but for now, we'll treat this case as a conventional
// histogram.
//
// TODO(beorn7): In the final format, there should be an unambiguous way of
// deciding if a histogram should be ingested as a conventional one or a native
// one.
// isNativeHistogram returns false iff the provided histograms has no spans at
// all (neither positive nor negative) and a zero threshold of 0 and a zero
// count of 0. In principle, this could still be meant to be a native histogram
// with a zero threshold of 0 and no observations yet. In that case,
// instrumentation libraries should add a "no-op" span (e.g. length zero, offset
// zero) to signal that the histogram is meant to be parsed as a native
// histogram. Failing to do so will cause Prometheus to parse it as a classic
// histogram as long as no observations have happened.
func isNativeHistogram(h *dto.Histogram) bool {
return h.GetZeroThreshold() > 0 ||
h.GetZeroCount() > 0 ||
len(h.GetNegativeDelta()) > 0 ||
len(h.GetPositiveDelta()) > 0 ||
len(h.GetNegativeCount()) > 0 ||
len(h.GetPositiveCount()) > 0
return len(h.GetPositiveSpan()) > 0 ||
len(h.GetNegativeSpan()) > 0 ||
h.GetZeroThreshold() > 0 ||
h.GetZeroCount() > 0
}
51 changes: 51 additions & 0 deletions model/textparse/protobufparse_test.go
Expand Up @@ -517,6 +517,19 @@ metric: <
sample_sum: 1.234
>
>
`,
`name: "empty_histogram"
help: "A histogram without observations and with a zero threshold of zero but with a no-op spam to identify it as a native histogram."
type: HISTOGRAM
metric: <
histogram: <
positive_span: <
offset: 0
length: 0
>
>
>
`,
}

Expand Down Expand Up @@ -965,6 +978,25 @@ func TestProtobufParse(t *testing.T) {
"__name__", "without_quantiles_sum",
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op spam to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: MetricTypeHistogram,
},
{
m: "empty_histogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
),
},
},
},
{
Expand Down Expand Up @@ -1688,6 +1720,25 @@ func TestProtobufParse(t *testing.T) {
"__name__", "without_quantiles_sum",
),
},
{ // 78
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op spam to identify it as a native histogram.",
},
{ // 79
m: "empty_histogram",
typ: MetricTypeHistogram,
},
{ // 80
m: "empty_histogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
),
},
},
},
}
Expand Down
3 changes: 3 additions & 0 deletions prompb/io/prometheus/client/metrics.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions prompb/io/prometheus/client/metrics.proto
Expand Up @@ -97,6 +97,9 @@ message Histogram {
repeated double negative_count = 11; // Absolute count of each bucket.

// Positive buckets for the native histogram.
// Use a no-op span (offset 0, length 0) for a native histogram without any
// observations yet and with a zero_threshold of 0. Otherwise, it would be
// indistinguishable from a classic histogram.
repeated BucketSpan positive_span = 12 [(gogoproto.nullable) = false];
// Use either "positive_delta" or "positive_count", the former for
// regular histograms with integer counts, the latter for float
Expand Down

0 comments on commit 94081a8

Please sign in to comment.