prometheus/model/textparse/protobufparse_test.go

4352 lines
112 KiB
Go
Raw Permalink Normal View History

// Copyright 2021 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package textparse
import (
"bytes"
"encoding/binary"
fix(textparse/protobuf): metric family name corrupted by NHCB parser (#17156) * fix(textparse): implement NHCB parsing in ProtoBuf parser directly The NHCB conversion does some validation, but we can only return error from Parser.Next() not Parser.Histogram(). So the conversion needs to happen in Next(). There are 2 cases: 1. "always_scrape_classic_histograms" is enabled, in which case we convert after returning the classic series. This is to be consistent with the PromParser text parser, which collects NHCB while spitting out classic series; then returns the NHCB. 2. "always_scrape_classic_histograms" is disabled. In which case we never return the classic series. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * refactor(textparse): skip classic series instead of adding NHCB around Do not return the first classic series from the EntryType state, switch to EntrySeries. This means we need to start the histogram field state from -3 , not -2. In EntrySeries, skip classic series if needed. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * reuse nhcb converter Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * test(textparse/nhcb): test corrupting metric family name NHCB parse doesn't always copy the metric name from the underlying parser. When called via HELP, UNIT, the string is directly referenced which means that the read-ahead of NHCB can corrupt it. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
2025-09-08 23:26:41 +08:00
"fmt"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/exemplar"
Style cleanup of all the changes in sparsehistogram so far A lot of this code was hacked together, literally during a hackathon. This commit intends not to change the code substantially, but just make the code obey the usual style practices. A (possibly incomplete) list of areas: * Generally address linter warnings. * The `pgk` directory is deprecated as per dev-summit. No new packages should be added to it. I moved the new `pkg/histogram` package to `model` anticipating what's proposed in #9478. * Make the naming of the Sparse Histogram more consistent. Including abbreviations, there were just too many names for it: SparseHistogram, Histogram, Histo, hist, his, shs, h. The idea is to call it "Histogram" in general. Only add "Sparse" if it is needed to avoid confusion with conventional Histograms (which is rare because the TSDB really has no notion of conventional Histograms). Use abbreviations only in local scope, and then really abbreviate (not just removing three out of seven letters like in "Histo"). This is in the spirit of https://github.com/golang/go/wiki/CodeReviewComments#variable-names * Several other minor name changes. * A lot of formatting of doc comments. For one, following https://github.com/golang/go/wiki/CodeReviewComments#comment-sentences , but also layout question, anticipating how things will look like when rendered by `godoc` (even where `godoc` doesn't render them right now because they are for unexported types or not a doc comment at all but just a normal code comment - consistency is queen!). * Re-enabled `TestQueryLog` and `TestEndopints` (they pass now, leaving them disabled was presumably an oversight). * Bucket iterator for histogram.Histogram is now created with a method. * HistogramChunk.iterator now allows iterator recycling. (I think @dieterbe only commented it out because he was confused by the question in the comment.) * HistogramAppender.Append panics now because we decided to treat staleness marker differently. Signed-off-by: beorn7 <beorn@grafana.com>
2021-10-09 21:57:07 +08:00
"github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels"
dto "github.com/prometheus/prometheus/prompb/io/prometheus/client"
)
fix(textparse/protobuf): metric family name corrupted by NHCB parser (#17156) * fix(textparse): implement NHCB parsing in ProtoBuf parser directly The NHCB conversion does some validation, but we can only return error from Parser.Next() not Parser.Histogram(). So the conversion needs to happen in Next(). There are 2 cases: 1. "always_scrape_classic_histograms" is enabled, in which case we convert after returning the classic series. This is to be consistent with the PromParser text parser, which collects NHCB while spitting out classic series; then returns the NHCB. 2. "always_scrape_classic_histograms" is disabled. In which case we never return the classic series. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * refactor(textparse): skip classic series instead of adding NHCB around Do not return the first classic series from the EntryType state, switch to EntrySeries. This means we need to start the histogram field state from -3 , not -2. In EntrySeries, skip classic series if needed. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * reuse nhcb converter Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * test(textparse/nhcb): test corrupting metric family name NHCB parse doesn't always copy the metric name from the underlying parser. When called via HELP, UNIT, the string is directly referenced which means that the read-ahead of NHCB can corrupt it. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
2025-09-08 23:26:41 +08:00
func metricFamiliesToProtobuf(t testing.TB, testMetricFamilies []string) *bytes.Buffer {
varintBuf := make([]byte, binary.MaxVarintLen32)
buf := &bytes.Buffer{}
for _, tmf := range testMetricFamilies {
pb := &dto.MetricFamily{}
// From text to proto message.
require.NoError(t, proto.UnmarshalText(tmf, pb))
// From proto message to binary protobuf.
protoBuf, err := proto.Marshal(pb)
require.NoError(t, err)
// Write first length, then binary protobuf.
varintLength := binary.PutUvarint(varintBuf, uint64(len(protoBuf)))
buf.Write(varintBuf[:varintLength])
buf.Write(protoBuf)
}
return buf
}
func createTestProtoBuf(t testing.TB) *bytes.Buffer {
t.Helper()
testMetricFamilies := []string{
`name: "go_build_info"
help: "Build information about the main Go module."
type: GAUGE
metric: <
label: <
name: "checksum"
value: ""
>
label: <
name: "path"
value: "github.com/prometheus/client_golang"
>
label: <
name: "version"
value: "(devel)"
>
gauge: <
value: 1
>
>
`,
`name: "go_memstats_alloc_bytes_total"
help: "Total number of bytes allocated, even if freed."
type: COUNTER
unit: "bytes"
metric: <
counter: <
value: 1.546544e+06
exemplar: <
label: <
name: "dummyID"
value: "42"
>
value: 12
timestamp: <
seconds: 1625851151
nanos: 233181499
>
>
>
>
`,
`name: "something_untyped"
help: "Just to test the untyped type."
type: UNTYPED
metric: <
untyped: <
value: 42
>
timestamp_ms: 1234567
>
`,
`name: "test_histogram"
help: "Test histogram with many buckets removed to keep it manageable in size."
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
>
timestamp_ms: 1234568
>
`,
`name: "test_gauge_histogram"
help: "Like test_histogram but as gauge histogram."
type: GAUGE_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
>
timestamp_ms: 1234568
>
`,
`name: "test_float_histogram"
help: "Test float histogram with many buckets removed to keep it manageable in size."
type: HISTOGRAM
metric: <
histogram: <
sample_count_float: 175.0
sample_sum: 0.0008280461746287094
bucket: <
cumulative_count_float: 2.0
upper_bound: -0.0004899999999999998
>
bucket: <
cumulative_count_float: 4.0
upper_bound: -0.0003899999999999998
exemplar: <
label: <
name: "dummyID"
value: "59727"
>
value: -0.00039
timestamp: <
seconds: 1625851155
nanos: 146848499
>
>
>
bucket: <
cumulative_count_float: 16
upper_bound: -0.0002899999999999998
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: -0.00029
>
>
schema: 3
zero_threshold: 2.938735877055719e-39
zero_count_float: 2.0
negative_span: <
offset: -162
length: 1
>
negative_span: <
offset: 23
length: 4
>
negative_count: 1.0
negative_count: 3.0
negative_count: -2.0
negative_count: -1.0
negative_count: 1.0
positive_span: <
offset: -161
length: 1
>
positive_span: <
offset: 8
length: 3
>
positive_count: 1.0
positive_count: 2.0
positive_count: -1.0
positive_count: -1.0
>
timestamp_ms: 1234568
>
`,
`name: "test_gauge_float_histogram"
help: "Like test_float_histogram but as gauge histogram."
type: GAUGE_HISTOGRAM
metric: <
histogram: <
sample_count_float: 175.0
sample_sum: 0.0008280461746287094
bucket: <
cumulative_count_float: 2.0
upper_bound: -0.0004899999999999998
>
bucket: <
cumulative_count_float: 4.0
upper_bound: -0.0003899999999999998
exemplar: <
label: <
name: "dummyID"
value: "59727"
>
value: -0.00039
timestamp: <
seconds: 1625851155
nanos: 146848499
>
>
>
bucket: <
cumulative_count_float: 16
upper_bound: -0.0002899999999999998
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: -0.00029
>
>
schema: 3
zero_threshold: 2.938735877055719e-39
zero_count_float: 2.0
negative_span: <
offset: -162
length: 1
>
negative_span: <
offset: 23
length: 4
>
negative_count: 1.0
negative_count: 3.0
negative_count: -2.0
negative_count: -1.0
negative_count: 1.0
positive_span: <
offset: -161
length: 1
>
positive_span: <
offset: 8
length: 3
>
positive_count: 1.0
positive_count: 2.0
positive_count: -1.0
positive_count: -1.0
>
timestamp_ms: 1234568
>
`,
`name: "test_histogram2"
help: "Similar histogram as before but now without sparse buckets."
type: HISTOGRAM
metric: <
histogram: <
sample_count: 175
sample_sum: 0.000828
bucket: <
cumulative_count: 2
upper_bound: -0.00048
>
bucket: <
cumulative_count: 4
upper_bound: -0.00038
exemplar: <
label: <
name: "dummyID"
value: "59727"
>
value: -0.00038
timestamp: <
seconds: 1625851153
nanos: 146848499
>
>
>
bucket: <
cumulative_count: 16
upper_bound: 1
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: -0.000295
>
>
schema: 0
zero_threshold: 0
>
>
`,
`name: "test_histogram3"
help: "Similar histogram as before but now with integer buckets."
type: HISTOGRAM
metric: <
histogram: <
sample_count: 6
sample_sum: 50
bucket: <
cumulative_count: 2
upper_bound: -20
>
bucket: <
cumulative_count: 4
upper_bound: 20
exemplar: <
label: <
name: "dummyID"
value: "59727"
>
value: 15
timestamp: <
seconds: 1625851153
nanos: 146848499
>
>
>
bucket: <
cumulative_count: 6
upper_bound: 30
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: 25
>
>
schema: 0
zero_threshold: 0
>
>
`,
`name: "test_histogram_family"
help: "Test histogram metric family with two very simple histograms."
type: HISTOGRAM
metric: <
label: <
name: "foo"
value: "bar"
>
histogram: <
sample_count: 5
sample_sum: 12.1
bucket: <
cumulative_count: 2
upper_bound: 1.1
>
bucket: <
cumulative_count: 3
upper_bound: 2.2
>
schema: 3
positive_span: <
offset: 8
length: 2
>
positive_delta: 2
positive_delta: 1
>
>
metric: <
label: <
name: "foo"
value: "baz"
>
histogram: <
sample_count: 6
sample_sum: 13.1
bucket: <
cumulative_count: 1
upper_bound: 1.1
>
bucket: <
cumulative_count: 5
upper_bound: 2.2
>
schema: 3
positive_span: <
offset: 8
length: 2
>
positive_delta: 1
positive_delta: 4
>
>
`,
`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"
help: "RPC latency distributions."
type: SUMMARY
metric: <
label: <
name: "service"
value: "exponential"
>
summary: <
sample_count: 262
sample_sum: 0.00025551262820703587
quantile: <
quantile: 0.5
value: 6.442786329648548e-07
>
quantile: <
quantile: 0.9
value: 1.9435742936658396e-06
>
quantile: <
quantile: 0.99
value: 4.0471608667037015e-06
>
>
>
`,
`name: "without_quantiles"
help: "A summary without quantiles."
type: SUMMARY
metric: <
summary: <
sample_count: 42
sample_sum: 1.234
>
>
`,
`name: "empty_histogram"
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram."
type: HISTOGRAM
metric: <
histogram: <
positive_span: <
offset: 0
length: 0
>
>
>
`,
`name: "test_counter_with_createdtimestamp"
help: "A counter with a created timestamp."
type: COUNTER
metric: <
counter: <
value: 42
created_timestamp: <
seconds: 1625851153
nanos: 146848499
>
>
>
`,
`name: "test_summary_with_createdtimestamp"
help: "A summary with a created timestamp."
type: SUMMARY
metric: <
summary: <
sample_count: 42
sample_sum: 1.234
created_timestamp: <
seconds: 1625851153
nanos: 146848499
>
>
>
`,
`name: "test_histogram_with_createdtimestamp"
help: "A histogram with a created timestamp."
type: HISTOGRAM
metric: <
histogram: <
created_timestamp: <
seconds: 1625851153
nanos: 146848499
>
positive_span: <
offset: 0
length: 0
>
>
>
`,
`name: "test_gaugehistogram_with_createdtimestamp"
help: "A gauge histogram with a created timestamp."
type: GAUGE_HISTOGRAM
metric: <
histogram: <
created_timestamp: <
seconds: 1625851153
nanos: 146848499
>
positive_span: <
offset: 0
length: 0
>
>
>
`,
`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
>
`,
`name: "test_histogram_with_native_histogram_exemplars2"
help: "Another 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
>
bucket: <
cumulative_count: 16
upper_bound: -0.0002899999999999998
>
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
>
>
>
timestamp_ms: 1234568
>
`,
}
fix(textparse/protobuf): metric family name corrupted by NHCB parser (#17156) * fix(textparse): implement NHCB parsing in ProtoBuf parser directly The NHCB conversion does some validation, but we can only return error from Parser.Next() not Parser.Histogram(). So the conversion needs to happen in Next(). There are 2 cases: 1. "always_scrape_classic_histograms" is enabled, in which case we convert after returning the classic series. This is to be consistent with the PromParser text parser, which collects NHCB while spitting out classic series; then returns the NHCB. 2. "always_scrape_classic_histograms" is disabled. In which case we never return the classic series. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * refactor(textparse): skip classic series instead of adding NHCB around Do not return the first classic series from the EntryType state, switch to EntrySeries. This means we need to start the histogram field state from -3 , not -2. In EntrySeries, skip classic series if needed. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * reuse nhcb converter Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * test(textparse/nhcb): test corrupting metric family name NHCB parse doesn't always copy the metric name from the underlying parser. When called via HELP, UNIT, the string is directly referenced which means that the read-ahead of NHCB can corrupt it. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
2025-09-08 23:26:41 +08:00
return metricFamiliesToProtobuf(t, testMetricFamilies)
}
func TestProtobufParse(t *testing.T) {
inputBuf := createTestProtoBuf(t)
scenarios := []struct {
name string
parser Parser
expected []parsedEntry
}{
{
feature: type-and-unit-labels (PROM-39 implementation) (#16228) * feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> * Fix compilation errors Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Lint Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Revert change made to protobuf 'Accept' header Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Fix compilation errors for 'dedupelabels' tag Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Rectored into schema.Metadata Signed-off-by: bwplotka <bwplotka@gmail.com> * texparse: Added tests for PromParse Signed-off-by: bwplotka <bwplotka@gmail.com> * add OM tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add proto tests Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * add schema label tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * fix tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add promql tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * lint Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> --------- Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com>
2025-05-17 17:37:25 +08:00
name: "parseClassicHistograms=false/enableTypeAndUnitLabels=false",
fix(textparse/protobuf): metric family name corrupted by NHCB parser (#17156) * fix(textparse): implement NHCB parsing in ProtoBuf parser directly The NHCB conversion does some validation, but we can only return error from Parser.Next() not Parser.Histogram(). So the conversion needs to happen in Next(). There are 2 cases: 1. "always_scrape_classic_histograms" is enabled, in which case we convert after returning the classic series. This is to be consistent with the PromParser text parser, which collects NHCB while spitting out classic series; then returns the NHCB. 2. "always_scrape_classic_histograms" is disabled. In which case we never return the classic series. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * refactor(textparse): skip classic series instead of adding NHCB around Do not return the first classic series from the EntryType state, switch to EntrySeries. This means we need to start the histogram field state from -3 , not -2. In EntrySeries, skip classic series if needed. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * reuse nhcb converter Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * test(textparse/nhcb): test corrupting metric family name NHCB parse doesn't always copy the metric name from the underlying parser. When called via HELP, UNIT, the string is directly referenced which means that the read-ahead of NHCB can corrupt it. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
2025-09-08 23:26:41 +08:00
parser: NewProtobufParser(inputBuf.Bytes(), false, false, false, labels.NewSymbolTable()),
expected: []parsedEntry{
{
m: "go_build_info",
help: "Build information about the main Go module.",
},
{
m: "go_build_info",
typ: model.MetricTypeGauge,
},
{
feature: type-and-unit-labels (PROM-39 implementation) (#16228) * feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> * Fix compilation errors Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Lint Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Revert change made to protobuf 'Accept' header Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Fix compilation errors for 'dedupelabels' tag Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Rectored into schema.Metadata Signed-off-by: bwplotka <bwplotka@gmail.com> * texparse: Added tests for PromParse Signed-off-by: bwplotka <bwplotka@gmail.com> * add OM tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add proto tests Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * add schema label tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * fix tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add promql tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * lint Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> --------- Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com>
2025-05-17 17:37:25 +08:00
m: "go_build_info\xffchecksum\xff\xffpath\xffgithub.com/prometheus/client_golang\xffversion\xff(devel)",
v: 1,
lset: labels.FromStrings(
"__name__", "go_build_info",
"checksum", "",
"path", "github.com/prometheus/client_golang",
"version", "(devel)",
),
},
{
m: "go_memstats_alloc_bytes_total",
help: "Total number of bytes allocated, even if freed.",
},
{
m: "go_memstats_alloc_bytes_total",
unit: "bytes",
},
{
m: "go_memstats_alloc_bytes_total",
typ: model.MetricTypeCounter,
},
{
m: "go_memstats_alloc_bytes_total",
v: 1.546544e+06,
lset: labels.FromStrings(
"__name__", "go_memstats_alloc_bytes_total",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "42"), Value: 12, HasTs: true, Ts: 1625851151233},
},
},
{
m: "something_untyped",
help: "Just to test the untyped type.",
},
{
m: "something_untyped",
typ: model.MetricTypeUnknown,
},
{
m: "something_untyped",
t: int64p(1234567),
v: 42,
lset: labels.FromStrings(
"__name__", "something_untyped",
),
},
{
m: "test_histogram",
help: "Test histogram with many buckets removed to keep it manageable in size.",
},
{
m: "test_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram",
t: int64p(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",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_histogram",
help: "Like test_histogram but as gauge histogram.",
},
{
m: "test_gauge_histogram",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gauge_histogram",
t: int64p(1234568),
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
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_gauge_histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_float_histogram",
help: "Test float histogram with many buckets removed to keep it manageable in size.",
},
{
m: "test_float_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "test_float_histogram",
t: int64p(1234568),
fhs: &histogram.FloatHistogram{
Count: 175.0,
ZeroCount: 2.0,
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: []float64{1.0, 2.0, -1.0, -1.0},
NegativeBuckets: []float64{1.0, 3.0, -2.0, -1.0, 1.0},
},
lset: labels.FromStrings(
"__name__", "test_float_histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_float_histogram",
help: "Like test_float_histogram but as gauge histogram.",
},
{
m: "test_gauge_float_histogram",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gauge_float_histogram",
t: int64p(1234568),
fhs: &histogram.FloatHistogram{
CounterResetHint: histogram.GaugeType,
Count: 175.0,
ZeroCount: 2.0,
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: []float64{1.0, 2.0, -1.0, -1.0},
NegativeBuckets: []float64{1.0, 3.0, -2.0, -1.0, 1.0},
},
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_histogram2",
help: "Similar histogram as before but now without sparse buckets.",
},
{
m: "test_histogram2",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram2_count",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram2_count",
),
},
{
m: "test_histogram2_sum",
v: 0.000828,
lset: labels.FromStrings(
"__name__", "test_histogram2_sum",
),
},
{
m: "test_histogram2_bucket\xffle\xff-0.00048",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "-0.00048",
),
},
{
m: "test_histogram2_bucket\xffle\xff-0.00038",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "-0.00038",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram2_bucket\xffle\xff1.0",
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "1.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.000295, HasTs: false},
},
},
{
m: "test_histogram2_bucket\xffle\xff+Inf",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram3",
help: "Similar histogram as before but now with integer buckets.",
},
{
m: "test_histogram3",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram3_count",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_count",
),
},
{
m: "test_histogram3_sum",
v: 50,
lset: labels.FromStrings(
"__name__", "test_histogram3_sum",
),
},
{
m: "test_histogram3_bucket\xffle\xff-20.0",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "-20.0",
),
},
{
m: "test_histogram3_bucket\xffle\xff20.0",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "20.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram3_bucket\xffle\xff30.0",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "30.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: false},
},
},
{
m: "test_histogram3_bucket\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram_family",
help: "Test histogram metric family with two very simple histograms.",
},
{
m: "test_histogram_family",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_family\xfffoo\xffbar",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 5,
Sum: 12.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 1},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"foo", "bar",
),
},
{
m: "test_histogram_family\xfffoo\xffbaz",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 13.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{1, 4},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"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: model.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",
help: "RPC latency distributions.",
},
{
m: "rpc_durations_seconds",
typ: model.MetricTypeSummary,
},
{
m: "rpc_durations_seconds_count\xffservice\xffexponential",
v: 262,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds_count",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds_sum\xffservice\xffexponential",
v: 0.00025551262820703587,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds_sum",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xffquantile\xff0.5\xffservice\xffexponential",
v: 6.442786329648548e-07,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"quantile", "0.5",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xffquantile\xff0.9\xffservice\xffexponential",
v: 1.9435742936658396e-06,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"quantile", "0.9",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xffquantile\xff0.99\xffservice\xffexponential",
v: 4.0471608667037015e-06,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"quantile", "0.99",
"service", "exponential",
),
},
{
m: "without_quantiles",
help: "A summary without quantiles.",
},
{
m: "without_quantiles",
typ: model.MetricTypeSummary,
},
{
m: "without_quantiles_count",
v: 42,
lset: labels.FromStrings(
"__name__", "without_quantiles_count",
),
},
{
m: "without_quantiles_sum",
v: 1.234,
lset: labels.FromStrings(
"__name__", "without_quantiles_sum",
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "empty_histogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
),
},
{
m: "test_counter_with_createdtimestamp",
help: "A counter with a created timestamp.",
},
{
m: "test_counter_with_createdtimestamp",
typ: model.MetricTypeCounter,
},
{
m: "test_counter_with_createdtimestamp",
v: 42,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_counter_with_createdtimestamp",
),
},
{
m: "test_summary_with_createdtimestamp",
help: "A summary with a created timestamp.",
},
{
m: "test_summary_with_createdtimestamp",
typ: model.MetricTypeSummary,
},
{
m: "test_summary_with_createdtimestamp_count",
v: 42,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_count",
),
},
{
m: "test_summary_with_createdtimestamp_sum",
v: 1.234,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_sum",
),
},
{
m: "test_histogram_with_createdtimestamp",
help: "A histogram with a created timestamp.",
},
{
m: "test_histogram_with_createdtimestamp",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_with_createdtimestamp",
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "test_histogram_with_createdtimestamp",
),
},
{
m: "test_gaugehistogram_with_createdtimestamp",
help: "A gauge histogram with a created timestamp.",
},
{
m: "test_gaugehistogram_with_createdtimestamp",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gaugehistogram_with_createdtimestamp",
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__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: int64p(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",
),
es: []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},
},
},
{
m: "test_histogram_with_native_histogram_exemplars2",
help: "Another histogram with native histogram exemplars.",
},
{
m: "test_histogram_with_native_histogram_exemplars2",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_with_native_histogram_exemplars2",
t: int64p(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_exemplars2",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59780"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
},
},
{
feature: type-and-unit-labels (PROM-39 implementation) (#16228) * feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> * Fix compilation errors Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Lint Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Revert change made to protobuf 'Accept' header Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Fix compilation errors for 'dedupelabels' tag Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Rectored into schema.Metadata Signed-off-by: bwplotka <bwplotka@gmail.com> * texparse: Added tests for PromParse Signed-off-by: bwplotka <bwplotka@gmail.com> * add OM tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add proto tests Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * add schema label tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * fix tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add promql tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * lint Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> --------- Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com>
2025-05-17 17:37:25 +08:00
name: "parseClassicHistograms=false/enableTypeAndUnitLabels=true",
fix(textparse/protobuf): metric family name corrupted by NHCB parser (#17156) * fix(textparse): implement NHCB parsing in ProtoBuf parser directly The NHCB conversion does some validation, but we can only return error from Parser.Next() not Parser.Histogram(). So the conversion needs to happen in Next(). There are 2 cases: 1. "always_scrape_classic_histograms" is enabled, in which case we convert after returning the classic series. This is to be consistent with the PromParser text parser, which collects NHCB while spitting out classic series; then returns the NHCB. 2. "always_scrape_classic_histograms" is disabled. In which case we never return the classic series. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * refactor(textparse): skip classic series instead of adding NHCB around Do not return the first classic series from the EntryType state, switch to EntrySeries. This means we need to start the histogram field state from -3 , not -2. In EntrySeries, skip classic series if needed. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * reuse nhcb converter Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * test(textparse/nhcb): test corrupting metric family name NHCB parse doesn't always copy the metric name from the underlying parser. When called via HELP, UNIT, the string is directly referenced which means that the read-ahead of NHCB can corrupt it. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
2025-09-08 23:26:41 +08:00
parser: NewProtobufParser(inputBuf.Bytes(), false, false, true, labels.NewSymbolTable()),
expected: []parsedEntry{
{
m: "go_build_info",
help: "Build information about the main Go module.",
},
{
m: "go_build_info",
typ: model.MetricTypeGauge,
},
{
feature: type-and-unit-labels (PROM-39 implementation) (#16228) * feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> * Fix compilation errors Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Lint Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Revert change made to protobuf 'Accept' header Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Fix compilation errors for 'dedupelabels' tag Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Rectored into schema.Metadata Signed-off-by: bwplotka <bwplotka@gmail.com> * texparse: Added tests for PromParse Signed-off-by: bwplotka <bwplotka@gmail.com> * add OM tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add proto tests Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * add schema label tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * fix tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add promql tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * lint Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> --------- Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com>
2025-05-17 17:37:25 +08:00
m: "go_build_info\xff__type__\xffgauge\xffchecksum\xff\xffpath\xffgithub.com/prometheus/client_golang\xffversion\xff(devel)",
v: 1,
lset: labels.FromStrings(
"__name__", "go_build_info",
"__type__", string(model.MetricTypeGauge),
"checksum", "",
"path", "github.com/prometheus/client_golang",
"version", "(devel)",
),
},
{
m: "go_memstats_alloc_bytes_total",
help: "Total number of bytes allocated, even if freed.",
},
{
m: "go_memstats_alloc_bytes_total",
unit: "bytes",
},
{
m: "go_memstats_alloc_bytes_total",
typ: model.MetricTypeCounter,
},
{
m: "go_memstats_alloc_bytes_total\xff__type__\xffcounter\xff__unit__\xffbytes",
v: 1.546544e+06,
lset: labels.FromStrings(
"__name__", "go_memstats_alloc_bytes_total",
"__type__", string(model.MetricTypeCounter),
"__unit__", "bytes",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "42"), Value: 12, HasTs: true, Ts: 1625851151233},
},
},
{
m: "something_untyped",
help: "Just to test the untyped type.",
},
{
m: "something_untyped",
typ: model.MetricTypeUnknown,
},
{
m: "something_untyped",
t: int64p(1234567),
v: 42,
lset: labels.FromStrings(
"__name__", "something_untyped",
),
},
{
m: "test_histogram",
help: "Test histogram with many buckets removed to keep it manageable in size.",
},
{
m: "test_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram\xff__type__\xffhistogram",
t: int64p(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",
"__type__", string(model.MetricTypeHistogram),
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_histogram",
help: "Like test_histogram but as gauge histogram.",
},
{
m: "test_gauge_histogram",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gauge_histogram\xff__type__\xffgaugehistogram",
t: int64p(1234568),
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
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_gauge_histogram",
"__type__", string(model.MetricTypeGaugeHistogram),
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_float_histogram",
help: "Test float histogram with many buckets removed to keep it manageable in size.",
},
{
m: "test_float_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "test_float_histogram\xff__type__\xffhistogram",
t: int64p(1234568),
fhs: &histogram.FloatHistogram{
Count: 175.0,
ZeroCount: 2.0,
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: []float64{1.0, 2.0, -1.0, -1.0},
NegativeBuckets: []float64{1.0, 3.0, -2.0, -1.0, 1.0},
},
lset: labels.FromStrings(
"__name__", "test_float_histogram",
"__type__", string(model.MetricTypeHistogram),
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_float_histogram",
help: "Like test_float_histogram but as gauge histogram.",
},
{
m: "test_gauge_float_histogram",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gauge_float_histogram\xff__type__\xffgaugehistogram",
t: int64p(1234568),
fhs: &histogram.FloatHistogram{
CounterResetHint: histogram.GaugeType,
Count: 175.0,
ZeroCount: 2.0,
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: []float64{1.0, 2.0, -1.0, -1.0},
NegativeBuckets: []float64{1.0, 3.0, -2.0, -1.0, 1.0},
},
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram",
"__type__", string(model.MetricTypeGaugeHistogram),
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_histogram2",
help: "Similar histogram as before but now without sparse buckets.",
},
{
m: "test_histogram2",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram2_count\xff__type__\xffhistogram",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram2_count",
"__type__", string(model.MetricTypeHistogram),
),
},
{
m: "test_histogram2_sum\xff__type__\xffhistogram",
v: 0.000828,
lset: labels.FromStrings(
"__name__", "test_histogram2_sum",
"__type__", string(model.MetricTypeHistogram),
),
},
{
m: "test_histogram2_bucket\xff__type__\xffhistogram\xffle\xff-0.00048",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "-0.00048",
),
},
{
m: "test_histogram2_bucket\xff__type__\xffhistogram\xffle\xff-0.00038",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "-0.00038",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram2_bucket\xff__type__\xffhistogram\xffle\xff1.0",
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "1.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.000295, HasTs: false},
},
},
{
m: "test_histogram2_bucket\xff__type__\xffhistogram\xffle\xff+Inf",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "+Inf",
),
},
{
m: "test_histogram3",
help: "Similar histogram as before but now with integer buckets.",
},
{
m: "test_histogram3",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram3_count\xff__type__\xffhistogram",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_count",
"__type__", string(model.MetricTypeHistogram),
),
},
{
m: "test_histogram3_sum\xff__type__\xffhistogram",
v: 50,
lset: labels.FromStrings(
"__name__", "test_histogram3_sum",
"__type__", string(model.MetricTypeHistogram),
),
},
{
m: "test_histogram3_bucket\xff__type__\xffhistogram\xffle\xff-20.0",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "-20.0",
),
},
{
m: "test_histogram3_bucket\xff__type__\xffhistogram\xffle\xff20.0",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "20.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram3_bucket\xff__type__\xffhistogram\xffle\xff30.0",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "30.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: false},
},
},
{
m: "test_histogram3_bucket\xff__type__\xffhistogram\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"__type__", string(model.MetricTypeHistogram),
"le", "+Inf",
),
},
{
m: "test_histogram_family",
help: "Test histogram metric family with two very simple histograms.",
},
{
m: "test_histogram_family",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_family\xff__type__\xffhistogram\xfffoo\xffbar",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 5,
Sum: 12.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 1},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"__type__", string(model.MetricTypeHistogram),
"foo", "bar",
),
},
{
m: "test_histogram_family\xff__type__\xffhistogram\xfffoo\xffbaz",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 13.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{1, 4},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"__type__", string(model.MetricTypeHistogram),
"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: model.MetricTypeHistogram,
},
{
m: "test_float_histogram_with_zerothreshold_zero\xff__type__\xffhistogram",
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",
"__type__", string(model.MetricTypeHistogram),
),
},
{
m: "rpc_durations_seconds",
help: "RPC latency distributions.",
},
{
m: "rpc_durations_seconds",
typ: model.MetricTypeSummary,
},
{
m: "rpc_durations_seconds_count\xff__type__\xffsummary\xffservice\xffexponential",
v: 262,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds_count",
"__type__", string(model.MetricTypeSummary),
"service", "exponential",
),
},
{
m: "rpc_durations_seconds_sum\xff__type__\xffsummary\xffservice\xffexponential",
v: 0.00025551262820703587,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds_sum",
"__type__", string(model.MetricTypeSummary),
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xff__type__\xffsummary\xffquantile\xff0.5\xffservice\xffexponential",
v: 6.442786329648548e-07,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"__type__", string(model.MetricTypeSummary),
"quantile", "0.5",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xff__type__\xffsummary\xffquantile\xff0.9\xffservice\xffexponential",
v: 1.9435742936658396e-06,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"__type__", string(model.MetricTypeSummary),
"quantile", "0.9",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xff__type__\xffsummary\xffquantile\xff0.99\xffservice\xffexponential",
v: 4.0471608667037015e-06,
lset: labels.FromStrings(
"__type__", string(model.MetricTypeSummary),
"__name__", "rpc_durations_seconds",
"quantile", "0.99",
"service", "exponential",
),
},
{
m: "without_quantiles",
help: "A summary without quantiles.",
},
{
m: "without_quantiles",
typ: model.MetricTypeSummary,
},
{
m: "without_quantiles_count\xff__type__\xffsummary",
v: 42,
lset: labels.FromStrings(
"__name__", "without_quantiles_count",
"__type__", string(model.MetricTypeSummary),
),
},
{
m: "without_quantiles_sum\xff__type__\xffsummary",
v: 1.234,
lset: labels.FromStrings(
"__name__", "without_quantiles_sum",
"__type__", string(model.MetricTypeSummary),
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "empty_histogram\xff__type__\xffhistogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
"__type__", string(model.MetricTypeHistogram),
),
},
{
m: "test_counter_with_createdtimestamp",
help: "A counter with a created timestamp.",
},
{
m: "test_counter_with_createdtimestamp",
typ: model.MetricTypeCounter,
},
{
m: "test_counter_with_createdtimestamp\xff__type__\xffcounter",
v: 42,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_counter_with_createdtimestamp",
"__type__", string(model.MetricTypeCounter),
),
},
{
m: "test_summary_with_createdtimestamp",
help: "A summary with a created timestamp.",
},
{
m: "test_summary_with_createdtimestamp",
typ: model.MetricTypeSummary,
},
{
m: "test_summary_with_createdtimestamp_count\xff__type__\xffsummary",
v: 42,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_count",
"__type__", string(model.MetricTypeSummary),
),
},
{
m: "test_summary_with_createdtimestamp_sum\xff__type__\xffsummary",
v: 1.234,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_sum",
"__type__", string(model.MetricTypeSummary),
),
},
{
m: "test_histogram_with_createdtimestamp",
help: "A histogram with a created timestamp.",
},
{
m: "test_histogram_with_createdtimestamp",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_with_createdtimestamp\xff__type__\xffhistogram",
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "test_histogram_with_createdtimestamp",
"__type__", string(model.MetricTypeHistogram),
),
},
{
m: "test_gaugehistogram_with_createdtimestamp",
help: "A gauge histogram with a created timestamp.",
},
{
m: "test_gaugehistogram_with_createdtimestamp",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gaugehistogram_with_createdtimestamp\xff__type__\xffgaugehistogram",
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "test_gaugehistogram_with_createdtimestamp",
"__type__", string(model.MetricTypeGaugeHistogram),
),
},
{
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\xff__type__\xffhistogram",
t: int64p(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",
"__type__", string(model.MetricTypeHistogram),
),
es: []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},
},
},
{
m: "test_histogram_with_native_histogram_exemplars2",
help: "Another histogram with native histogram exemplars.",
},
{
m: "test_histogram_with_native_histogram_exemplars2",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_with_native_histogram_exemplars2\xff__type__\xffhistogram",
t: int64p(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_exemplars2",
"__type__", string(model.MetricTypeHistogram),
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59780"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
},
},
{
name: "parseClassicHistograms=true/enableTypeAndUnitLabels=false",
fix(textparse/protobuf): metric family name corrupted by NHCB parser (#17156) * fix(textparse): implement NHCB parsing in ProtoBuf parser directly The NHCB conversion does some validation, but we can only return error from Parser.Next() not Parser.Histogram(). So the conversion needs to happen in Next(). There are 2 cases: 1. "always_scrape_classic_histograms" is enabled, in which case we convert after returning the classic series. This is to be consistent with the PromParser text parser, which collects NHCB while spitting out classic series; then returns the NHCB. 2. "always_scrape_classic_histograms" is disabled. In which case we never return the classic series. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * refactor(textparse): skip classic series instead of adding NHCB around Do not return the first classic series from the EntryType state, switch to EntrySeries. This means we need to start the histogram field state from -3 , not -2. In EntrySeries, skip classic series if needed. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * reuse nhcb converter Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * test(textparse/nhcb): test corrupting metric family name NHCB parse doesn't always copy the metric name from the underlying parser. When called via HELP, UNIT, the string is directly referenced which means that the read-ahead of NHCB can corrupt it. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
2025-09-08 23:26:41 +08:00
parser: NewProtobufParser(inputBuf.Bytes(), true, false, false, labels.NewSymbolTable()),
feature: type-and-unit-labels (PROM-39 implementation) (#16228) * feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> feature: type-and-unit-labels (extended MetricIdentity) Experimental implementation of https://github.com/prometheus/proposals/pull/39 Previous (unmerged) experiments: * https://github.com/prometheus/prometheus/compare/main...dashpole:prometheus:type_and_unit_labels * https://github.com/prometheus/prometheus/pull/16025 Signed-off-by: bwplotka <bwplotka@gmail.com> * Fix compilation errors Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Lint Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Revert change made to protobuf 'Accept' header Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Fix compilation errors for 'dedupelabels' tag Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> * Rectored into schema.Metadata Signed-off-by: bwplotka <bwplotka@gmail.com> * texparse: Added tests for PromParse Signed-off-by: bwplotka <bwplotka@gmail.com> * add OM tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add proto tests Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * add schema label tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> * fix tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * add promql tests. Signed-off-by: bwplotka <bwplotka@gmail.com> * lint Signed-off-by: bwplotka <bwplotka@gmail.com> * Addressed comments. Signed-off-by: bwplotka <bwplotka@gmail.com> --------- Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com> Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com>
2025-05-17 17:37:25 +08:00
expected: []parsedEntry{
{
m: "go_build_info",
help: "Build information about the main Go module.",
},
{
m: "go_build_info",
typ: model.MetricTypeGauge,
},
{
m: "go_build_info\xffchecksum\xff\xffpath\xffgithub.com/prometheus/client_golang\xffversion\xff(devel)",
v: 1,
lset: labels.FromStrings(
"__name__", "go_build_info",
"checksum", "",
"path", "github.com/prometheus/client_golang",
"version", "(devel)",
),
},
{
m: "go_memstats_alloc_bytes_total",
help: "Total number of bytes allocated, even if freed.",
},
{
m: "go_memstats_alloc_bytes_total",
unit: "bytes",
},
{
m: "go_memstats_alloc_bytes_total",
typ: model.MetricTypeCounter,
},
{
m: "go_memstats_alloc_bytes_total",
v: 1.546544e+06,
lset: labels.FromStrings(
"__name__", "go_memstats_alloc_bytes_total",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "42"), Value: 12, HasTs: true, Ts: 1625851151233},
},
},
{
m: "something_untyped",
help: "Just to test the untyped type.",
},
{
m: "something_untyped",
typ: model.MetricTypeUnknown,
},
{
m: "something_untyped",
t: int64p(1234567),
v: 42,
lset: labels.FromStrings(
"__name__", "something_untyped",
),
},
{
m: "test_histogram",
help: "Test histogram with many buckets removed to keep it manageable in size.",
},
{
m: "test_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram",
t: int64p(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",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_histogram_count",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram_count",
),
},
{
m: "test_histogram_sum",
t: int64p(1234568),
v: 0.0008280461746287094,
lset: labels.FromStrings(
"__name__", "test_histogram_sum",
),
},
{
m: "test_histogram_bucket\xffle\xff-0.0004899999999999998",
t: int64p(1234568),
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram_bucket",
"le", "-0.0004899999999999998",
),
},
{
m: "test_histogram_bucket\xffle\xff-0.0003899999999999998",
t: int64p(1234568),
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram_bucket",
"le", "-0.0003899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_histogram_bucket\xffle\xff-0.0002899999999999998",
t: int64p(1234568),
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram_bucket",
"le", "-0.0002899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.00029, HasTs: false},
},
},
{
m: "test_histogram_bucket\xffle\xff+Inf",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram_bucket",
"le", "+Inf",
),
},
{
m: "test_gauge_histogram",
help: "Like test_histogram but as gauge histogram.",
},
{
m: "test_gauge_histogram",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gauge_histogram",
t: int64p(1234568),
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
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_gauge_histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_histogram_count",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_gauge_histogram_count",
),
},
{
m: "test_gauge_histogram_sum",
t: int64p(1234568),
v: 0.0008280461746287094,
lset: labels.FromStrings(
"__name__", "test_gauge_histogram_sum",
),
},
{
m: "test_gauge_histogram_bucket\xffle\xff-0.0004899999999999998",
t: int64p(1234568),
v: 2,
lset: labels.FromStrings(
"__name__", "test_gauge_histogram_bucket",
"le", "-0.0004899999999999998",
),
},
{
m: "test_gauge_histogram_bucket\xffle\xff-0.0003899999999999998",
t: int64p(1234568),
v: 4,
lset: labels.FromStrings(
"__name__", "test_gauge_histogram_bucket",
"le", "-0.0003899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_histogram_bucket\xffle\xff-0.0002899999999999998",
t: int64p(1234568),
v: 16,
lset: labels.FromStrings(
"__name__", "test_gauge_histogram_bucket",
"le", "-0.0002899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.00029, HasTs: false},
},
},
{
m: "test_gauge_histogram_bucket\xffle\xff+Inf",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_gauge_histogram_bucket",
"le", "+Inf",
),
},
{
m: "test_float_histogram",
help: "Test float histogram with many buckets removed to keep it manageable in size.",
},
{
m: "test_float_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "test_float_histogram",
t: int64p(1234568),
fhs: &histogram.FloatHistogram{
Count: 175.0,
ZeroCount: 2.0,
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: []float64{1.0, 2.0, -1.0, -1.0},
NegativeBuckets: []float64{1.0, 3.0, -2.0, -1.0, 1.0},
},
lset: labels.FromStrings(
"__name__", "test_float_histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_float_histogram_count",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_float_histogram_count",
),
},
{
m: "test_float_histogram_sum",
t: int64p(1234568),
v: 0.0008280461746287094,
lset: labels.FromStrings(
"__name__", "test_float_histogram_sum",
),
},
{
m: "test_float_histogram_bucket\xffle\xff-0.0004899999999999998",
t: int64p(1234568),
v: 2,
lset: labels.FromStrings(
"__name__", "test_float_histogram_bucket",
"le", "-0.0004899999999999998",
),
},
{
m: "test_float_histogram_bucket\xffle\xff-0.0003899999999999998",
t: int64p(1234568),
v: 4,
lset: labels.FromStrings(
"__name__", "test_float_histogram_bucket",
"le", "-0.0003899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_float_histogram_bucket\xffle\xff-0.0002899999999999998",
t: int64p(1234568),
v: 16,
lset: labels.FromStrings(
"__name__", "test_float_histogram_bucket",
"le", "-0.0002899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.00029, HasTs: false},
},
},
{
m: "test_float_histogram_bucket\xffle\xff+Inf",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_float_histogram_bucket",
"le", "+Inf",
),
},
{
m: "test_gauge_float_histogram",
help: "Like test_float_histogram but as gauge histogram.",
},
{
m: "test_gauge_float_histogram",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gauge_float_histogram",
t: int64p(1234568),
fhs: &histogram.FloatHistogram{
CounterResetHint: histogram.GaugeType,
Count: 175.0,
ZeroCount: 2.0,
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: []float64{1.0, 2.0, -1.0, -1.0},
NegativeBuckets: []float64{1.0, 3.0, -2.0, -1.0, 1.0},
},
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_float_histogram_count",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram_count",
),
},
{
m: "test_gauge_float_histogram_sum",
t: int64p(1234568),
v: 0.0008280461746287094,
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram_sum",
),
},
{
m: "test_gauge_float_histogram_bucket\xffle\xff-0.0004899999999999998",
t: int64p(1234568),
v: 2,
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram_bucket",
"le", "-0.0004899999999999998",
),
},
{
m: "test_gauge_float_histogram_bucket\xffle\xff-0.0003899999999999998",
t: int64p(1234568),
v: 4,
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram_bucket",
"le", "-0.0003899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_gauge_float_histogram_bucket\xffle\xff-0.0002899999999999998",
t: int64p(1234568),
v: 16,
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram_bucket",
"le", "-0.0002899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.00029, HasTs: false},
},
},
{
m: "test_gauge_float_histogram_bucket\xffle\xff+Inf",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_gauge_float_histogram_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram2",
help: "Similar histogram as before but now without sparse buckets.",
},
{
m: "test_histogram2",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram2_count",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram2_count",
),
},
{
m: "test_histogram2_sum",
v: 0.000828,
lset: labels.FromStrings(
"__name__", "test_histogram2_sum",
),
},
{
m: "test_histogram2_bucket\xffle\xff-0.00048",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "-0.00048",
),
},
{
m: "test_histogram2_bucket\xffle\xff-0.00038",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "-0.00038",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram2_bucket\xffle\xff1.0",
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "1.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.000295, HasTs: false},
},
},
{
m: "test_histogram2_bucket\xffle\xff+Inf",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram2_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram3",
help: "Similar histogram as before but now with integer buckets.",
},
{
m: "test_histogram3",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram3_count",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_count",
),
},
{
m: "test_histogram3_sum",
v: 50,
lset: labels.FromStrings(
"__name__", "test_histogram3_sum",
),
},
{
m: "test_histogram3_bucket\xffle\xff-20.0",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "-20.0",
),
},
{
m: "test_histogram3_bucket\xffle\xff20.0",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "20.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram3_bucket\xffle\xff30.0",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "30.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: false},
},
},
{
m: "test_histogram3_bucket\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram3_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram_family",
help: "Test histogram metric family with two very simple histograms.",
},
{
m: "test_histogram_family",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_family\xfffoo\xffbar",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 5,
Sum: 12.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 1},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"foo", "bar",
),
},
{
m: "test_histogram_family_count\xfffoo\xffbar",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_count",
"foo", "bar",
),
},
{
m: "test_histogram_family_sum\xfffoo\xffbar",
v: 12.1,
lset: labels.FromStrings(
"__name__", "test_histogram_family_sum",
"foo", "bar",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbar\xffle\xff1.1",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "bar",
"le", "1.1",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbar\xffle\xff2.2",
v: 3,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "bar",
"le", "2.2",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbar\xffle\xff+Inf",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "bar",
"le", "+Inf",
),
},
{
m: "test_histogram_family\xfffoo\xffbaz",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 13.1,
Schema: 3,
PositiveSpans: []histogram.Span{
{Offset: 8, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{1, 4},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"foo", "baz",
),
},
{
m: "test_histogram_family_count\xfffoo\xffbaz",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram_family_count",
"foo", "baz",
),
},
{
m: "test_histogram_family_sum\xfffoo\xffbaz",
v: 13.1,
lset: labels.FromStrings(
"__name__", "test_histogram_family_sum",
"foo", "baz",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbaz\xffle\xff1.1",
v: 1,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "baz",
"le", "1.1",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbaz\xffle\xff2.2",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "baz",
"le", "2.2",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbaz\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "baz",
"le", "+Inf",
),
},
{
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: model.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",
help: "RPC latency distributions.",
},
{
m: "rpc_durations_seconds",
typ: model.MetricTypeSummary,
},
{
m: "rpc_durations_seconds_count\xffservice\xffexponential",
v: 262,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds_count",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds_sum\xffservice\xffexponential",
v: 0.00025551262820703587,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds_sum",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xffquantile\xff0.5\xffservice\xffexponential",
v: 6.442786329648548e-07,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"quantile", "0.5",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xffquantile\xff0.9\xffservice\xffexponential",
v: 1.9435742936658396e-06,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"quantile", "0.9",
"service", "exponential",
),
},
{
m: "rpc_durations_seconds\xffquantile\xff0.99\xffservice\xffexponential",
v: 4.0471608667037015e-06,
lset: labels.FromStrings(
"__name__", "rpc_durations_seconds",
"quantile", "0.99",
"service", "exponential",
),
},
{
m: "without_quantiles",
help: "A summary without quantiles.",
},
{
m: "without_quantiles",
typ: model.MetricTypeSummary,
},
{
m: "without_quantiles_count",
v: 42,
lset: labels.FromStrings(
"__name__", "without_quantiles_count",
),
},
{
m: "without_quantiles_sum",
v: 1.234,
lset: labels.FromStrings(
"__name__", "without_quantiles_sum",
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "empty_histogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
),
},
{
m: "test_counter_with_createdtimestamp",
help: "A counter with a created timestamp.",
},
{
m: "test_counter_with_createdtimestamp",
typ: model.MetricTypeCounter,
},
{
m: "test_counter_with_createdtimestamp",
v: 42,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_counter_with_createdtimestamp",
),
},
{
m: "test_summary_with_createdtimestamp",
help: "A summary with a created timestamp.",
},
{
m: "test_summary_with_createdtimestamp",
typ: model.MetricTypeSummary,
},
{
m: "test_summary_with_createdtimestamp_count",
v: 42,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_count",
),
},
{
m: "test_summary_with_createdtimestamp_sum",
v: 1.234,
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_sum",
),
},
{
m: "test_histogram_with_createdtimestamp",
help: "A histogram with a created timestamp.",
},
{
m: "test_histogram_with_createdtimestamp",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_with_createdtimestamp",
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "test_histogram_with_createdtimestamp",
),
},
{
m: "test_gaugehistogram_with_createdtimestamp",
help: "A gauge histogram with a created timestamp.",
},
{
m: "test_gaugehistogram_with_createdtimestamp",
typ: model.MetricTypeGaugeHistogram,
},
{
m: "test_gaugehistogram_with_createdtimestamp",
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__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: int64p(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",
),
es: []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},
},
},
{
m: "test_histogram_with_native_histogram_exemplars_count",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars_count",
),
},
{
m: "test_histogram_with_native_histogram_exemplars_sum",
t: int64p(1234568),
v: 0.0008280461746287094,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars_sum",
),
},
{
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0004899999999999998",
t: int64p(1234568),
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
"le", "-0.0004899999999999998",
),
},
{
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0003899999999999998",
t: int64p(1234568),
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
"le", "-0.0003899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0002899999999999998",
t: int64p(1234568),
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
"le", "-0.0002899999999999998",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.00029, HasTs: false},
},
},
{
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff+Inf",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram_with_native_histogram_exemplars2",
help: "Another histogram with native histogram exemplars.",
},
{
m: "test_histogram_with_native_histogram_exemplars2",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_with_native_histogram_exemplars2",
t: int64p(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_exemplars2",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59780"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
},
},
{
m: "test_histogram_with_native_histogram_exemplars2_count",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars2_count",
),
},
{
m: "test_histogram_with_native_histogram_exemplars2_sum",
t: int64p(1234568),
v: 0.0008280461746287094,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars2_sum",
),
},
{
m: "test_histogram_with_native_histogram_exemplars2_bucket\xffle\xff-0.0004899999999999998",
t: int64p(1234568),
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars2_bucket",
"le", "-0.0004899999999999998",
),
},
{
m: "test_histogram_with_native_histogram_exemplars2_bucket\xffle\xff-0.0003899999999999998",
t: int64p(1234568),
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars2_bucket",
"le", "-0.0003899999999999998",
),
},
{
m: "test_histogram_with_native_histogram_exemplars2_bucket\xffle\xff-0.0002899999999999998",
t: int64p(1234568),
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars2_bucket",
"le", "-0.0002899999999999998",
),
},
{
m: "test_histogram_with_native_histogram_exemplars2_bucket\xffle\xff+Inf",
t: int64p(1234568),
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram_with_native_histogram_exemplars2_bucket",
"le", "+Inf",
),
},
},
},
}
for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) {
var (
p = scenario.parser
exp = scenario.expected
)
got := testParse(t, p)
requireEntries(t, exp, got)
})
}
}
fix(textparse/protobuf): metric family name corrupted by NHCB parser (#17156) * fix(textparse): implement NHCB parsing in ProtoBuf parser directly The NHCB conversion does some validation, but we can only return error from Parser.Next() not Parser.Histogram(). So the conversion needs to happen in Next(). There are 2 cases: 1. "always_scrape_classic_histograms" is enabled, in which case we convert after returning the classic series. This is to be consistent with the PromParser text parser, which collects NHCB while spitting out classic series; then returns the NHCB. 2. "always_scrape_classic_histograms" is disabled. In which case we never return the classic series. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * refactor(textparse): skip classic series instead of adding NHCB around Do not return the first classic series from the EntryType state, switch to EntrySeries. This means we need to start the histogram field state from -3 , not -2. In EntrySeries, skip classic series if needed. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * reuse nhcb converter Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com> * test(textparse/nhcb): test corrupting metric family name NHCB parse doesn't always copy the metric name from the underlying parser. When called via HELP, UNIT, the string is directly referenced which means that the read-ahead of NHCB can corrupt it. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
2025-09-08 23:26:41 +08:00
// TestProtobufParseWithNHCB is only concerned with classic histograms.
func TestProtobufParseWithNHCB(t *testing.T) {
testMetricFamilies := []string{
`name: "test_histogram1"
help: "Similar histogram as before but now without sparse buckets."
type: HISTOGRAM
metric: <
histogram: <
sample_count: 175
sample_sum: 0.000828
bucket: <
cumulative_count: 2
upper_bound: -0.00048
>
bucket: <
cumulative_count: 4
upper_bound: -0.00038
exemplar: <
label: <
name: "dummyID"
value: "59727"
>
value: -0.00038
timestamp: <
seconds: 1625851153
nanos: 146848499
>
>
>
bucket: <
cumulative_count: 16
upper_bound: 1
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: -0.000295
>
>
schema: 0
zero_threshold: 0
>
>
`,
`name: "test_histogram2_seconds"
help: "Similar histogram as before but now with integer buckets."
type: HISTOGRAM
unit: "seconds"
metric: <
histogram: <
sample_count: 6
sample_sum: 50
bucket: <
cumulative_count: 2
upper_bound: -20
>
bucket: <
cumulative_count: 4
upper_bound: 20
exemplar: <
label: <
name: "dummyID"
value: "59727"
>
value: 15
timestamp: <
seconds: 1625851153
nanos: 146848499
>
>
>
bucket: <
cumulative_count: 6
upper_bound: 30
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: 25
timestamp: <
seconds: 1625851153
nanos: 146848499
>
>
>
schema: 0
zero_threshold: 0
>
>
`,
`name: "test_histogram_family"
help: "Test histogram metric family with two very simple histograms."
type: HISTOGRAM
metric: <
label: <
name: "foo"
value: "bar"
>
histogram: <
sample_count: 5
sample_sum: 12.1
bucket: <
cumulative_count: 2
upper_bound: 1.1
>
bucket: <
cumulative_count: 3
upper_bound: 2.2
>
>
>
metric: <
label: <
name: "foo"
value: "baz"
>
histogram: <
sample_count: 6
sample_sum: 13.1
bucket: <
cumulative_count: 0
upper_bound: 1.1
>
bucket: <
cumulative_count: 5
upper_bound: 2.2
>
>
>
`,
`name: "empty_histogram"
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram."
type: HISTOGRAM
metric: <
histogram: <
positive_span: <
offset: 0
length: 0
>
>
>
`,
}
buf := metricFamiliesToProtobuf(t, testMetricFamilies)
data := buf.Bytes()
testCases := []struct {
keepClassic bool
typeAndUnit bool
expected []parsedEntry
}{
{
keepClassic: false,
typeAndUnit: false,
expected: []parsedEntry{
{
m: "test_histogram1",
help: "Similar histogram as before but now without sparse buckets.",
},
{
m: "test_histogram1",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram1",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 175,
Sum: 0.000828,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 4},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 10, 147},
CustomValues: []float64{-0.00048, -0.00038, 1},
},
lset: labels.FromStrings(
"__name__", "test_histogram1",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
// The second exemplar has no timestamp.
},
},
{
m: "test_histogram2_seconds",
help: "Similar histogram as before but now with integer buckets.",
},
{
m: "test_histogram2_seconds",
unit: "seconds",
},
{
m: "test_histogram2_seconds",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram2_seconds",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 50,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 0},
CustomValues: []float64{-20, 20, 30},
},
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram_family",
help: "Test histogram metric family with two very simple histograms.",
},
{
m: "test_histogram_family",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_family\xfffoo\xffbar",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 5,
Sum: 12.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, -1, 1},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"foo", "bar",
),
},
{
m: "test_histogram_family\xfffoo\xffbaz",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 13.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Offset: 1, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{5, -4},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"foo", "baz",
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "empty_histogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
),
},
},
},
{
keepClassic: true,
typeAndUnit: false,
expected: []parsedEntry{
{
m: "test_histogram1",
help: "Similar histogram as before but now without sparse buckets.",
},
{
m: "test_histogram1",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram1_count",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram1_count",
),
},
{
m: "test_histogram1_sum",
v: 0.000828,
lset: labels.FromStrings(
"__name__", "test_histogram1_sum",
),
},
{
m: "test_histogram1_bucket\xffle\xff-0.00048",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"le", "-0.00048",
),
},
{
m: "test_histogram1_bucket\xffle\xff-0.00038",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"le", "-0.00038",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram1_bucket\xffle\xff1.0",
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"le", "1.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.000295, HasTs: false},
},
},
{
m: "test_histogram1_bucket\xffle\xff+Inf",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram1",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 175,
Sum: 0.000828,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 4},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 10, 147},
CustomValues: []float64{-0.00048, -0.00038, 1},
},
lset: labels.FromStrings(
"__name__", "test_histogram1",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
// The second exemplar has no timestamp.
},
},
{
m: "test_histogram2_seconds",
help: "Similar histogram as before but now with integer buckets.",
},
{
m: "test_histogram2_seconds",
unit: "seconds",
},
{
m: "test_histogram2_seconds",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram2_seconds_count",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_count",
),
},
{
m: "test_histogram2_seconds_sum",
v: 50,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_sum",
),
},
{
m: "test_histogram2_seconds_bucket\xffle\xff-20.0",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"le", "-20.0",
),
},
{
m: "test_histogram2_seconds_bucket\xffle\xff20.0",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"le", "20.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram2_seconds_bucket\xffle\xff30.0",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"le", "30.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram2_seconds_bucket\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"le", "+Inf",
),
},
{
m: "test_histogram2_seconds",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 50,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 0},
CustomValues: []float64{-20, 20, 30},
},
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram_family",
help: "Test histogram metric family with two very simple histograms.",
},
{
m: "test_histogram_family",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_family_count\xfffoo\xffbar",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_count",
"foo", "bar",
),
},
{
m: "test_histogram_family_sum\xfffoo\xffbar",
v: 12.1,
lset: labels.FromStrings(
"__name__", "test_histogram_family_sum",
"foo", "bar",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbar\xffle\xff1.1",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "bar",
"le", "1.1",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbar\xffle\xff2.2",
v: 3,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "bar",
"le", "2.2",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbar\xffle\xff+Inf",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "bar",
"le", "+Inf",
),
},
{
m: "test_histogram_family\xfffoo\xffbar",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 5,
Sum: 12.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, -1, 1},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"foo", "bar",
),
},
{
m: "test_histogram_family_count\xfffoo\xffbaz",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram_family_count",
"foo", "baz",
),
},
{
m: "test_histogram_family_sum\xfffoo\xffbaz",
v: 13.1,
lset: labels.FromStrings(
"__name__", "test_histogram_family_sum",
"foo", "baz",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbaz\xffle\xff1.1",
v: 0,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "baz",
"le", "1.1",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbaz\xffle\xff2.2",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "baz",
"le", "2.2",
),
},
{
m: "test_histogram_family_bucket\xfffoo\xffbaz\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"foo", "baz",
"le", "+Inf",
),
},
{
m: "test_histogram_family\xfffoo\xffbaz",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 13.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Offset: 1, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{5, -4},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"foo", "baz",
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "empty_histogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
),
},
},
},
{
keepClassic: false,
typeAndUnit: true,
expected: []parsedEntry{
{
m: "test_histogram1",
help: "Similar histogram as before but now without sparse buckets.",
},
{
m: "test_histogram1",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram1\xff__type__\xffhistogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 175,
Sum: 0.000828,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 4},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 10, 147},
CustomValues: []float64{-0.00048, -0.00038, 1},
},
lset: labels.FromStrings(
"__name__", "test_histogram1",
"__type__", "histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
// The second exemplar has no timestamp.
},
},
{
m: "test_histogram2_seconds",
help: "Similar histogram as before but now with integer buckets.",
},
{
m: "test_histogram2_seconds",
unit: "seconds",
},
{
m: "test_histogram2_seconds",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram2_seconds\xff__type__\xffhistogram\xff__unit__\xffseconds",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 50,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 0},
CustomValues: []float64{-20, 20, 30},
},
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds",
"__type__", "histogram",
"__unit__", "seconds",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram_family",
help: "Test histogram metric family with two very simple histograms.",
},
{
m: "test_histogram_family",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_family\xff__type__\xffhistogram\xfffoo\xffbar",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 5,
Sum: 12.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, -1, 1},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"__type__", "histogram",
"foo", "bar",
),
},
{
m: "test_histogram_family\xff__type__\xffhistogram\xfffoo\xffbaz",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 13.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Offset: 1, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{5, -4},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"__type__", "histogram",
"foo", "baz",
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "empty_histogram\xff__type__\xffhistogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
"__type__", "histogram",
),
},
},
},
{
keepClassic: true,
typeAndUnit: true,
expected: []parsedEntry{
{
m: "test_histogram1",
help: "Similar histogram as before but now without sparse buckets.",
},
{
m: "test_histogram1",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram1_count\xff__type__\xffhistogram",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram1_count",
"__type__", "histogram",
),
},
{
m: "test_histogram1_sum\xff__type__\xffhistogram",
v: 0.000828,
lset: labels.FromStrings(
"__name__", "test_histogram1_sum",
"__type__", "histogram",
),
},
{
m: "test_histogram1_bucket\xff__type__\xffhistogram\xffle\xff-0.00048",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"__type__", "histogram",
"le", "-0.00048",
),
},
{
m: "test_histogram1_bucket\xff__type__\xffhistogram\xffle\xff-0.00038",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"__type__", "histogram",
"le", "-0.00038",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram1_bucket\xff__type__\xffhistogram\xffle\xff1.0",
v: 16,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"__type__", "histogram",
"le", "1.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.000295, HasTs: false},
},
},
{
m: "test_histogram1_bucket\xff__type__\xffhistogram\xffle\xff+Inf",
v: 175,
lset: labels.FromStrings(
"__name__", "test_histogram1_bucket",
"__type__", "histogram",
"le", "+Inf",
),
},
{
m: "test_histogram1\xff__type__\xffhistogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 175,
Sum: 0.000828,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 4},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 10, 147},
CustomValues: []float64{-0.00048, -0.00038, 1},
},
lset: labels.FromStrings(
"__name__", "test_histogram1",
"__type__", "histogram",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00038, HasTs: true, Ts: 1625851153146},
// The second exemplar has no timestamp.
},
},
{
m: "test_histogram2_seconds",
help: "Similar histogram as before but now with integer buckets.",
},
{
m: "test_histogram2_seconds",
unit: "seconds",
},
{
m: "test_histogram2_seconds",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram2_seconds_count\xff__type__\xffhistogram\xff__unit__\xffseconds",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_count",
"__type__", "histogram",
"__unit__", "seconds",
),
},
{
m: "test_histogram2_seconds_sum\xff__type__\xffhistogram\xff__unit__\xffseconds",
v: 50,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_sum",
"__type__", "histogram",
"__unit__", "seconds",
),
},
{
m: "test_histogram2_seconds_bucket\xff__type__\xffhistogram\xff__unit__\xffseconds\xffle\xff-20.0",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"__type__", "histogram",
"__unit__", "seconds",
"le", "-20.0",
),
},
{
m: "test_histogram2_seconds_bucket\xff__type__\xffhistogram\xff__unit__\xffseconds\xffle\xff20.0",
v: 4,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"__type__", "histogram",
"__unit__", "seconds",
"le", "20.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram2_seconds_bucket\xff__type__\xffhistogram\xff__unit__\xffseconds\xffle\xff30.0",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"__type__", "histogram",
"__unit__", "seconds",
"le", "30.0",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram2_seconds_bucket\xff__type__\xffhistogram\xff__unit__\xffseconds\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds_bucket",
"__type__", "histogram",
"__unit__", "seconds",
"le", "+Inf",
),
},
{
m: "test_histogram2_seconds\xff__type__\xffhistogram\xff__unit__\xffseconds",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 50,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, 0, 0},
CustomValues: []float64{-20, 20, 30},
},
lset: labels.FromStrings(
"__name__", "test_histogram2_seconds",
"__type__", "histogram",
"__unit__", "seconds",
),
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("dummyID", "59727"), Value: 15, HasTs: true, Ts: 1625851153146},
{Labels: labels.FromStrings("dummyID", "5617"), Value: 25, HasTs: true, Ts: 1625851153146},
},
},
{
m: "test_histogram_family",
help: "Test histogram metric family with two very simple histograms.",
},
{
m: "test_histogram_family",
typ: model.MetricTypeHistogram,
},
{
m: "test_histogram_family_count\xff__type__\xffhistogram\xfffoo\xffbar",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_count",
"__type__", "histogram",
"foo", "bar",
),
},
{
m: "test_histogram_family_sum\xff__type__\xffhistogram\xfffoo\xffbar",
v: 12.1,
lset: labels.FromStrings(
"__name__", "test_histogram_family_sum",
"__type__", "histogram",
"foo", "bar",
),
},
{
m: "test_histogram_family_bucket\xff__type__\xffhistogram\xfffoo\xffbar\xffle\xff1.1",
v: 2,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"__type__", "histogram",
"foo", "bar",
"le", "1.1",
),
},
{
m: "test_histogram_family_bucket\xff__type__\xffhistogram\xfffoo\xffbar\xffle\xff2.2",
v: 3,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"__type__", "histogram",
"foo", "bar",
"le", "2.2",
),
},
{
m: "test_histogram_family_bucket\xff__type__\xffhistogram\xfffoo\xffbar\xffle\xff+Inf",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"__type__", "histogram",
"foo", "bar",
"le", "+Inf",
),
},
{
m: "test_histogram_family\xff__type__\xffhistogram\xfffoo\xffbar",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 5,
Sum: 12.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Length: 3},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{2, -1, 1},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"__type__", "histogram",
"foo", "bar",
),
},
{
m: "test_histogram_family_count\xff__type__\xffhistogram\xfffoo\xffbaz",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram_family_count",
"__type__", "histogram",
"foo", "baz",
),
},
{
m: "test_histogram_family_sum\xff__type__\xffhistogram\xfffoo\xffbaz",
v: 13.1,
lset: labels.FromStrings(
"__name__", "test_histogram_family_sum",
"__type__", "histogram",
"foo", "baz",
),
},
{
m: "test_histogram_family_bucket\xff__type__\xffhistogram\xfffoo\xffbaz\xffle\xff1.1",
v: 0,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"__type__", "histogram",
"foo", "baz",
"le", "1.1",
),
},
{
m: "test_histogram_family_bucket\xff__type__\xffhistogram\xfffoo\xffbaz\xffle\xff2.2",
v: 5,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"__type__", "histogram",
"foo", "baz",
"le", "2.2",
),
},
{
m: "test_histogram_family_bucket\xff__type__\xffhistogram\xfffoo\xffbaz\xffle\xff+Inf",
v: 6,
lset: labels.FromStrings(
"__name__", "test_histogram_family_bucket",
"__type__", "histogram",
"foo", "baz",
"le", "+Inf",
),
},
{
m: "test_histogram_family\xff__type__\xffhistogram\xfffoo\xffbaz",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
Count: 6,
Sum: 13.1,
Schema: -53,
PositiveSpans: []histogram.Span{
{Offset: 1, Length: 2},
},
NegativeSpans: []histogram.Span{},
PositiveBuckets: []int64{5, -4},
CustomValues: []float64{1.1, 2.2},
},
lset: labels.FromStrings(
"__name__", "test_histogram_family",
"__type__", "histogram",
"foo", "baz",
),
},
{
m: "empty_histogram",
help: "A histogram without observations and with a zero threshold of zero but with a no-op span to identify it as a native histogram.",
},
{
m: "empty_histogram",
typ: model.MetricTypeHistogram,
},
{
m: "empty_histogram\xff__type__\xffhistogram",
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
NegativeSpans: []histogram.Span{},
},
lset: labels.FromStrings(
"__name__", "empty_histogram",
"__type__", "histogram",
),
},
},
},
}
for _, tc := range testCases {
name := fmt.Sprintf("keepClassic=%v,typeAndUnit=%v", tc.keepClassic, tc.typeAndUnit)
t.Run(name, func(t *testing.T) {
p := NewProtobufParser(data, tc.keepClassic, true, tc.typeAndUnit, labels.NewSymbolTable())
got := testParse(t, p)
requireEntries(t, tc.expected, got)
})
}
}