diff --git a/go.mod b/go.mod index ee7fc37fb..9c354dfaf 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 github.com/davecgh/go-spew v1.1.1 github.com/json-iterator/go v1.1.12 - github.com/prometheus/client_model v0.3.0 + github.com/prometheus/client_model v0.4.0 github.com/prometheus/common v0.42.0 github.com/prometheus/procfs v0.11.1 golang.org/x/sys v0.10.0 diff --git a/go.sum b/go.sum index bd973bb2e..022e77354 100644 --- a/go.sum +++ b/go.sum @@ -151,8 +151,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= diff --git a/prometheus/counter_test.go b/prometheus/counter_test.go index 597a53ee0..cf0fd54d7 100644 --- a/prometheus/counter_test.go +++ b/prometheus/counter_test.go @@ -61,8 +61,15 @@ func TestCounterAdd(t *testing.T) { m := &dto.Metric{} counter.Write(m) - if expected, got := `label: label: counter: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) + expected := &dto.Metric{ + Label: []*dto.LabelPair{ + {Name: proto.String("a"), Value: proto.String("1")}, + {Name: proto.String("b"), Value: proto.String("2")}, + }, + Counter: &dto.Counter{Value: proto.Float64(67.42)}, + } + if !proto.Equal(expected, m) { + t.Errorf("expected %q, got %q", expected, m) } } @@ -164,8 +171,14 @@ func TestCounterAddInf(t *testing.T) { m := &dto.Metric{} counter.Write(m) - if expected, got := `counter: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) + expected := &dto.Metric{ + Counter: &dto.Counter{ + Value: proto.Float64(math.Inf(1)), + }, + } + + if !proto.Equal(expected, m) { + t.Errorf("expected %q, got %q", expected, m) } } @@ -188,8 +201,14 @@ func TestCounterAddLarge(t *testing.T) { m := &dto.Metric{} counter.Write(m) - if expected, got := fmt.Sprintf("counter: ", large), m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) + expected := &dto.Metric{ + Counter: &dto.Counter{ + Value: proto.Float64(large), + }, + } + + if !proto.Equal(expected, m) { + t.Errorf("expected %q, got %q", expected, m) } } @@ -210,8 +229,14 @@ func TestCounterAddSmall(t *testing.T) { m := &dto.Metric{} counter.Write(m) - if expected, got := fmt.Sprintf("counter: ", small), m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) + expected := &dto.Metric{ + Counter: &dto.Counter{ + Value: proto.Float64(small), + }, + } + + if !proto.Equal(expected, m) { + t.Errorf("expected %q, got %q", expected, m) } } diff --git a/prometheus/example_metricvec_test.go b/prometheus/example_metricvec_test.go index ff4bd1f6c..1f9dbb07b 100644 --- a/prometheus/example_metricvec_test.go +++ b/prometheus/example_metricvec_test.go @@ -14,8 +14,7 @@ package prometheus_test import ( - "fmt" - + "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" dto "github.com/prometheus/client_model/go" @@ -126,8 +125,12 @@ func ExampleMetricVec() { if err != nil || len(metricFamilies) != 1 { panic("unexpected behavior of custom test registry") } - fmt.Println(metricFamilies[0].String()) + metricAsJSON, err := protojson.Marshal(metricFamilies[0]) + if err != nil { + panic("error marshling metricFamily") + } + printlnNormalized(metricAsJSON) // Output: - // name:"library_version_info" help:"Versions of the libraries used in this binary." type:GAUGE metric: label: gauge: > metric: label: gauge: > + // {"name":"library_version_info","help":"Versions of the libraries used in this binary.","type":"GAUGE","metric":[{"label":[{"name":"library","value":"k8s.io/client-go"},{"name":"version","value":"0.18.8"}],"gauge":{"value":1}},{"label":[{"name":"library","value":"prometheus/client_golang"},{"name":"version","value":"1.7.1"}],"gauge":{"value":1}}]} } diff --git a/prometheus/examples_test.go b/prometheus/examples_test.go index f15c3409f..6b74cd0ef 100644 --- a/prometheus/examples_test.go +++ b/prometheus/examples_test.go @@ -25,6 +25,7 @@ import ( dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" + "google.golang.org/protobuf/encoding/protojson" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -319,10 +320,15 @@ func ExampleSummary() { // internally). metric := &dto.Metric{} temps.Write(metric) - fmt.Println(metric.String()) + + metricAsJSON, err := protojson.Marshal(metric) + if err != nil { + panic("error marshling metric") + } + printlnNormalized(metricAsJSON) // Output: - // summary: quantile: quantile: > + // {"summary":{"sampleCount":"1000","sampleSum":29969.50000000001,"quantile":[{"quantile":0.5,"value":31.1},{"quantile":0.9,"value":41.3},{"quantile":0.99,"value":41.9}]}} } func ExampleSummaryVec() { @@ -354,10 +360,14 @@ func ExampleSummaryVec() { if err != nil || len(metricFamilies) != 1 { panic("unexpected behavior of custom test registry") } - fmt.Println(metricFamilies[0].String()) + metricAsJSON, err := protojson.Marshal(metricFamilies[0]) + if err != nil { + panic("error marshling metric") + } + printlnNormalized(metricAsJSON) // Output: - // name:"pond_temperature_celsius" help:"The temperature of the frog pond." type:SUMMARY metric: summary: quantile: quantile: > > metric: summary: quantile: quantile: > > metric: summary: quantile: quantile: > > + // {"name":"pond_temperature_celsius","help":"The temperature of the frog pond.","type":"SUMMARY","metric":[{"label":[{"name":"species","value":"leiopelma-hochstetteri"}],"summary":{"sampleCount":"0","sampleSum":0,"quantile":[{"quantile":0.5,"value":"NaN"},{"quantile":0.9,"value":"NaN"},{"quantile":0.99,"value":"NaN"}]}},{"label":[{"name":"species","value":"lithobates-catesbeianus"}],"summary":{"sampleCount":"1000","sampleSum":31956.100000000017,"quantile":[{"quantile":0.5,"value":32.4},{"quantile":0.9,"value":41.4},{"quantile":0.99,"value":41.9}]}},{"label":[{"name":"species","value":"litoria-caerulea"}],"summary":{"sampleCount":"1000","sampleSum":29969.50000000001,"quantile":[{"quantile":0.5,"value":31.1},{"quantile":0.9,"value":41.3},{"quantile":0.99,"value":41.9}]}}]} } func ExampleNewConstSummary() { @@ -381,10 +391,14 @@ func ExampleNewConstSummary() { // internally). metric := &dto.Metric{} s.Write(metric) - fmt.Println(metric.String()) + metricAsJSON, err := protojson.Marshal(metric) + if err != nil { + panic("error marshling metric") + } + printlnNormalized(metricAsJSON) // Output: - // label: label: label: summary: quantile: > + // {"label":[{"name":"code","value":"200"},{"name":"method","value":"get"},{"name":"owner","value":"example"}],"summary":{"sampleCount":"4711","sampleSum":403.34,"quantile":[{"quantile":0.5,"value":42.3},{"quantile":0.9,"value":323.3}]}} } func ExampleHistogram() { @@ -404,10 +418,14 @@ func ExampleHistogram() { // internally). metric := &dto.Metric{} temps.Write(metric) - fmt.Println(metric.String()) + metricAsJSON, err := protojson.Marshal(metric) + if err != nil { + panic("error marshling metric") + } + printlnNormalized(metricAsJSON) // Output: - // histogram: bucket: bucket: bucket: bucket: > + // {"histogram":{"sampleCount":"1000","sampleSum":29969.50000000001,"bucket":[{"cumulativeCount":"192","upperBound":20},{"cumulativeCount":"366","upperBound":25},{"cumulativeCount":"501","upperBound":30},{"cumulativeCount":"638","upperBound":35},{"cumulativeCount":"816","upperBound":40}]}} } func ExampleNewConstHistogram() { @@ -431,10 +449,14 @@ func ExampleNewConstHistogram() { // internally). metric := &dto.Metric{} h.Write(metric) - fmt.Println(metric.String()) + metricAsJSON, err := protojson.Marshal(metric) + if err != nil { + panic("error marshling metric") + } + printlnNormalized(metricAsJSON) // Output: - // label: label: label: histogram: bucket: bucket: bucket: > + // {"label":[{"name":"code","value":"200"},{"name":"method","value":"get"},{"name":"owner","value":"example"}],"histogram":{"sampleCount":"4711","sampleSum":403.34,"bucket":[{"cumulativeCount":"121","upperBound":25},{"cumulativeCount":"2403","upperBound":50},{"cumulativeCount":"3221","upperBound":100},{"cumulativeCount":"4233","upperBound":200}]}} } func ExampleNewConstHistogram_WithExemplar() { @@ -469,10 +491,14 @@ func ExampleNewConstHistogram_WithExemplar() { // internally). metric := &dto.Metric{} h.Write(metric) - fmt.Println(metric.String()) + metricAsJSON, err := protojson.Marshal(metric) + if err != nil { + panic("error marshling metric") + } + printlnNormalized(metricAsJSON) // Output: - // label: label: label: histogram: value:24 timestamp: > > bucket: value:42 timestamp: > > bucket: value:89 timestamp: > > bucket: value:157 timestamp: > > > + // {"label":[{"name":"code","value":"200"},{"name":"method","value":"get"},{"name":"owner","value":"example"}],"histogram":{"sampleCount":"4711","sampleSum":403.34,"bucket":[{"cumulativeCount":"121","upperBound":25,"exemplar":{"label":[{"name":"testName","value":"testVal"}],"value":24,"timestamp":"2006-01-02T15:04:05Z"}},{"cumulativeCount":"2403","upperBound":50,"exemplar":{"label":[{"name":"testName","value":"testVal"}],"value":42,"timestamp":"2006-01-02T15:04:05Z"}},{"cumulativeCount":"3221","upperBound":100,"exemplar":{"label":[{"name":"testName","value":"testVal"}],"value":89,"timestamp":"2006-01-02T15:04:05Z"}},{"cumulativeCount":"4233","upperBound":200,"exemplar":{"label":[{"name":"testName","value":"testVal"}],"value":157,"timestamp":"2006-01-02T15:04:05Z"}}]}} } func ExampleAlreadyRegisteredError() { @@ -567,7 +593,13 @@ temperature_kelvin 4.5 gathering, err = gatherers.Gather() if err != nil { - fmt.Println(err) + // We expect error collected metric "temperature_kelvin" { label: gauge: } was collected before with the same name and label values + // We cannot assert it because of https://github.com/golang/protobuf/issues/1121 + if strings.HasPrefix(err.Error(), `collected metric "temperature_kelvin" `) { + fmt.Println("Found duplicated metric `temperature_kelvin`") + } else { + fmt.Print(err) + } } // Note that still as many metrics as possible are returned: out.Reset() @@ -589,7 +621,7 @@ temperature_kelvin 4.5 // temperature_kelvin{location="outside"} 273.14 // temperature_kelvin{location="somewhere else"} 4.5 // ---------- - // collected metric "temperature_kelvin" { label: gauge: } was collected before with the same name and label values + // Found duplicated metric `temperature_kelvin` // # HELP humidity_percent Humidity in %. // # TYPE humidity_percent gauge // humidity_percent{location="inside"} 33.2 @@ -625,8 +657,12 @@ func ExampleNewMetricWithTimestamp() { // internally). metric := &dto.Metric{} s.Write(metric) - fmt.Println(metric.String()) + metricAsJSON, err := protojson.Marshal(metric) + if err != nil { + panic("error marshling metric") + } + printlnNormalized(metricAsJSON) // Output: - // gauge: timestamp_ms:1257894000012 + // {"gauge":{"value":298.15},"timestampMs":"1257894000012"} } diff --git a/prometheus/expvar_collector_test.go b/prometheus/expvar_collector_test.go index 6bcd9b692..3e8112c16 100644 --- a/prometheus/expvar_collector_test.go +++ b/prometheus/expvar_collector_test.go @@ -15,11 +15,11 @@ package prometheus_test import ( "expvar" - "fmt" "sort" "strings" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/encoding/protojson" "github.com/prometheus/client_golang/prometheus" ) @@ -81,17 +81,21 @@ func ExampleNewExpvarCollector() { if !strings.Contains(m.Desc().String(), "expvar_memstats") { metric.Reset() m.Write(&metric) - metricStrings = append(metricStrings, metric.String()) + metricAsJSON, err := protojson.Marshal(&metric) + if err != nil { + panic("error marshling metric") + } + metricStrings = append(metricStrings, string(metricAsJSON)) } } sort.Strings(metricStrings) for _, s := range metricStrings { - fmt.Println(strings.TrimRight(s, " ")) + printlnNormalized([]byte(s)) } // Output: - // label: label: untyped: - // label: label: untyped: - // label: label: untyped: - // label: label: untyped: - // untyped: + // {"label":[{"name":"code","value":"200"},{"name":"method","value":"GET"}],"untyped":{"value":212}} + // {"label":[{"name":"code","value":"200"},{"name":"method","value":"POST"}],"untyped":{"value":11}} + // {"label":[{"name":"code","value":"404"},{"name":"method","value":"GET"}],"untyped":{"value":13}} + // {"label":[{"name":"code","value":"404"},{"name":"method","value":"POST"}],"untyped":{"value":3}} + // {"untyped":{"value":42}} } diff --git a/prometheus/gauge_test.go b/prometheus/gauge_test.go index f35889a82..26759fbbc 100644 --- a/prometheus/gauge_test.go +++ b/prometheus/gauge_test.go @@ -22,6 +22,7 @@ import ( "time" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" ) func listenGaugeStream(vals, result chan float64, done chan struct{}) { @@ -177,8 +178,18 @@ func TestGaugeFunc(t *testing.T) { m := &dto.Metric{} gf.Write(m) - if expected, got := `label: label: gauge: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) + expected := &dto.Metric{ + Label: []*dto.LabelPair{ + {Name: proto.String("a"), Value: proto.String("1")}, + {Name: proto.String("b"), Value: proto.String("2")}, + }, + Gauge: &dto.Gauge{ + Value: proto.Float64(3.1415), + }, + } + + if !proto.Equal(expected, m) { + t.Errorf("expected %q, got %q", expected, m) } } diff --git a/prometheus/histogram_test.go b/prometheus/histogram_test.go index 69ee88349..e2bc16240 100644 --- a/prometheus/histogram_test.go +++ b/prometheus/histogram_test.go @@ -477,36 +477,89 @@ func TestNativeHistogram(t *testing.T) { maxBuckets uint32 minResetDuration time.Duration maxZeroThreshold float64 - want string // String representation of protobuf. + want *dto.Histogram }{ { name: "no sparse buckets", observations: []float64{1, 2, 3}, factor: 1, - want: `sample_count:3 sample_sum:6 bucket: bucket: bucket: bucket: bucket: bucket: bucket: bucket: bucket: bucket: bucket: `, // Has conventional buckets because there are no sparse buckets. + want: &dto.Histogram{ + SampleCount: proto.Uint64(3), + SampleSum: proto.Float64(6), + Bucket: []*dto.Bucket{ + {CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.005)}, + {CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.01)}, + {CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.025)}, + {CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.05)}, + {CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.1)}, + {CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.25)}, + {CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.5)}, + {CumulativeCount: proto.Uint64(1), UpperBound: proto.Float64(1)}, + {CumulativeCount: proto.Uint64(2), UpperBound: proto.Float64(2.5)}, + {CumulativeCount: proto.Uint64(3), UpperBound: proto.Float64(5)}, + {CumulativeCount: proto.Uint64(3), UpperBound: proto.Float64(10)}, + }, + }, }, { name: "no observations", factor: 1.1, - want: `sample_count:0 sample_sum:0 schema:3 zero_threshold:2.938735877055719e-39 zero_count:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(0), + SampleSum: proto.Float64(0), + Schema: proto.Int32(3), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(0), + }, }, { name: "no observations and zero threshold of zero resulting in no-op span", factor: 1.1, zeroThreshold: NativeHistogramZeroThresholdZero, - want: `sample_count:0 sample_sum:0 schema:3 zero_threshold:0 zero_count:0 positive_span: `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(0), + SampleSum: proto.Float64(0), + Schema: proto.Int32(3), + ZeroThreshold: proto.Float64(0), + ZeroCount: proto.Uint64(0), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(0)}, + }, + }, }, { name: "factor 1.1 results in schema 3", observations: []float64{0, 1, 2, 3}, factor: 1.1, - want: `sample_count:4 sample_sum:6 schema:3 zero_threshold:2.938735877055719e-39 zero_count:1 positive_span: positive_span: positive_span: positive_delta:1 positive_delta:0 positive_delta:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(4), + SampleSum: proto.Float64(6), + Schema: proto.Int32(3), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(1)}, + {Offset: proto.Int32(7), Length: proto.Uint32(1)}, + {Offset: proto.Int32(4), Length: proto.Uint32(1)}, + }, + PositiveDelta: []int64{1, 0, 0}, + }, }, { name: "factor 1.2 results in schema 2", observations: []float64{0, 1, 1.2, 1.4, 1.8, 2}, factor: 1.2, - want: `sample_count:6 sample_sum:7.4 schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 positive_span: positive_delta:1 positive_delta:-1 positive_delta:2 positive_delta:-2 positive_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(6), + SampleSum: proto.Float64(7.4), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + PositiveDelta: []int64{1, -1, 2, -2, 2}, + }, }, { name: "factor 4 results in schema -1", @@ -519,7 +572,17 @@ func TestNativeHistogram(t *testing.T) { 33.33, // Bucket 3: (16, 64] }, factor: 4, - want: `sample_count:14 sample_sum:63.2581251 schema:-1 zero_threshold:2.938735877055719e-39 zero_count:0 positive_span: positive_delta:2 positive_delta:0 positive_delta:0 positive_delta:2 positive_delta:-1 positive_delta:-2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(14), + SampleSum: proto.Float64(63.2581251), + Schema: proto.Int32(-1), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(0), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(-2), Length: proto.Uint32(6)}, + }, + PositiveDelta: []int64{2, 0, 0, 2, -1, -2}, + }, }, { name: "factor 17 results in schema -2", @@ -530,58 +593,161 @@ func TestNativeHistogram(t *testing.T) { 33.33, // Bucket 2: (16, 256] }, factor: 17, - want: `sample_count:14 sample_sum:63.2581251 schema:-2 zero_threshold:2.938735877055719e-39 zero_count:0 positive_span: positive_delta:2 positive_delta:2 positive_delta:3 positive_delta:-6 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(14), + SampleSum: proto.Float64(63.2581251), + Schema: proto.Int32(-2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(0), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(-1), Length: proto.Uint32(4)}, + }, + PositiveDelta: []int64{2, 2, 3, -6}, + }, }, { name: "negative buckets", observations: []float64{0, -1, -1.2, -1.4, -1.8, -2}, factor: 1.2, - want: `sample_count:6 sample_sum:-7.4 schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 negative_span: negative_delta:1 negative_delta:-1 negative_delta:2 negative_delta:-2 negative_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(6), + SampleSum: proto.Float64(-7.4), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + NegativeDelta: []int64{1, -1, 2, -2, 2}, + }, }, { name: "negative and positive buckets", observations: []float64{0, -1, -1.2, -1.4, -1.8, -2, 1, 1.2, 1.4, 1.8, 2}, factor: 1.2, - want: `sample_count:11 sample_sum:0 schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 negative_span: negative_delta:1 negative_delta:-1 negative_delta:2 negative_delta:-2 negative_delta:2 positive_span: positive_delta:1 positive_delta:-1 positive_delta:2 positive_delta:-2 positive_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(11), + SampleSum: proto.Float64(0), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + NegativeDelta: []int64{1, -1, 2, -2, 2}, + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + PositiveDelta: []int64{1, -1, 2, -2, 2}, + }, }, { name: "wide zero bucket", observations: []float64{0, -1, -1.2, -1.4, -1.8, -2, 1, 1.2, 1.4, 1.8, 2}, factor: 1.2, zeroThreshold: 1.4, - want: `sample_count:11 sample_sum:0 schema:2 zero_threshold:1.4 zero_count:7 negative_span: negative_delta:2 positive_span: positive_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(11), + SampleSum: proto.Float64(0), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(1.4), + ZeroCount: proto.Uint64(7), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(4), Length: proto.Uint32(1)}, + }, + NegativeDelta: []int64{2}, + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(4), Length: proto.Uint32(1)}, + }, + PositiveDelta: []int64{2}, + }, }, { name: "NaN observation", observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.NaN()}, factor: 1.2, - want: `sample_count:7 sample_sum:nan schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 positive_span: positive_delta:1 positive_delta:-1 positive_delta:2 positive_delta:-2 positive_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(7), + SampleSum: proto.Float64(math.NaN()), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + PositiveDelta: []int64{1, -1, 2, -2, 2}, + }, }, { name: "+Inf observation", observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.Inf(+1)}, factor: 1.2, - want: `sample_count:7 sample_sum:inf schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 positive_span: positive_span: positive_delta:1 positive_delta:-1 positive_delta:2 positive_delta:-2 positive_delta:2 positive_delta:-1 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(7), + SampleSum: proto.Float64(math.Inf(+1)), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + {Offset: proto.Int32(4092), Length: proto.Uint32(1)}, + }, + PositiveDelta: []int64{1, -1, 2, -2, 2, -1}, + }, }, { name: "-Inf observation", observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.Inf(-1)}, factor: 1.2, - want: `sample_count:7 sample_sum:-inf schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 negative_span: negative_delta:1 positive_span: positive_delta:1 positive_delta:-1 positive_delta:2 positive_delta:-2 positive_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(7), + SampleSum: proto.Float64(math.Inf(-1)), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(4097), Length: proto.Uint32(1)}, + }, + NegativeDelta: []int64{1}, + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + PositiveDelta: []int64{1, -1, 2, -2, 2}, + }, }, { name: "limited buckets but nothing triggered", observations: []float64{0, 1, 1.2, 1.4, 1.8, 2}, factor: 1.2, maxBuckets: 4, - want: `sample_count:6 sample_sum:7.4 schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 positive_span: positive_delta:1 positive_delta:-1 positive_delta:2 positive_delta:-2 positive_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(6), + SampleSum: proto.Float64(7.4), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + PositiveDelta: []int64{1, -1, 2, -2, 2}, + }, }, { name: "buckets limited by halving resolution", observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3}, factor: 1.2, maxBuckets: 4, - want: `sample_count:8 sample_sum:11.5 schema:1 zero_threshold:2.938735877055719e-39 zero_count:1 positive_span: positive_delta:1 positive_delta:2 positive_delta:-1 positive_delta:-2 positive_delta:1 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(8), + SampleSum: proto.Float64(11.5), + Schema: proto.Int32(1), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + PositiveDelta: []int64{1, 2, -1, -2, 1}, + }, }, { name: "buckets limited by widening the zero bucket", @@ -589,7 +755,17 @@ func TestNativeHistogram(t *testing.T) { factor: 1.2, maxBuckets: 4, maxZeroThreshold: 1.2, - want: `sample_count:8 sample_sum:11.5 schema:2 zero_threshold:1 zero_count:2 positive_span: positive_delta:1 positive_delta:1 positive_delta:-2 positive_delta:2 positive_delta:-2 positive_delta:0 positive_delta:1 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(8), + SampleSum: proto.Float64(11.5), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(1), + ZeroCount: proto.Uint64(2), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(1), Length: proto.Uint32(7)}, + }, + PositiveDelta: []int64{1, 1, -2, 2, -2, 0, 1}, + }, }, { name: "buckets limited by widening the zero bucket twice", @@ -597,7 +773,17 @@ func TestNativeHistogram(t *testing.T) { factor: 1.2, maxBuckets: 4, maxZeroThreshold: 1.2, - want: `sample_count:9 sample_sum:15.5 schema:2 zero_threshold:1.189207115002721 zero_count:3 positive_span: positive_delta:2 positive_delta:-2 positive_delta:2 positive_delta:-2 positive_delta:0 positive_delta:1 positive_delta:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(9), + SampleSum: proto.Float64(15.5), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(1.189207115002721), + ZeroCount: proto.Uint64(3), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(2), Length: proto.Uint32(7)}, + }, + PositiveDelta: []int64{2, -2, 2, -2, 0, 1, 0}, + }, }, { name: "buckets limited by reset", @@ -606,21 +792,51 @@ func TestNativeHistogram(t *testing.T) { maxBuckets: 4, maxZeroThreshold: 1.2, minResetDuration: 5 * time.Minute, - want: `sample_count:2 sample_sum:7 schema:2 zero_threshold:2.938735877055719e-39 zero_count:0 positive_span: positive_delta:1 positive_delta:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(2), + SampleSum: proto.Float64(7), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(0), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(7), Length: proto.Uint32(2)}, + }, + PositiveDelta: []int64{1, 0}, + }, }, { name: "limited buckets but nothing triggered, negative observations", observations: []float64{0, -1, -1.2, -1.4, -1.8, -2}, factor: 1.2, maxBuckets: 4, - want: `sample_count:6 sample_sum:-7.4 schema:2 zero_threshold:2.938735877055719e-39 zero_count:1 negative_span: negative_delta:1 negative_delta:-1 negative_delta:2 negative_delta:-2 negative_delta:2 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(6), + SampleSum: proto.Float64(-7.4), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + NegativeDelta: []int64{1, -1, 2, -2, 2}, + }, }, { name: "buckets limited by halving resolution, negative observations", observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3}, factor: 1.2, maxBuckets: 4, - want: `sample_count:8 sample_sum:-11.5 schema:1 zero_threshold:2.938735877055719e-39 zero_count:1 negative_span: negative_delta:1 negative_delta:2 negative_delta:-1 negative_delta:-2 negative_delta:1 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(8), + SampleSum: proto.Float64(-11.5), + Schema: proto.Int32(1), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(1), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(5)}, + }, + NegativeDelta: []int64{1, 2, -1, -2, 1}, + }, }, { name: "buckets limited by widening the zero bucket, negative observations", @@ -628,7 +844,17 @@ func TestNativeHistogram(t *testing.T) { factor: 1.2, maxBuckets: 4, maxZeroThreshold: 1.2, - want: `sample_count:8 sample_sum:-11.5 schema:2 zero_threshold:1 zero_count:2 negative_span: negative_delta:1 negative_delta:1 negative_delta:-2 negative_delta:2 negative_delta:-2 negative_delta:0 negative_delta:1 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(8), + SampleSum: proto.Float64(-11.5), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(1), + ZeroCount: proto.Uint64(2), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(1), Length: proto.Uint32(7)}, + }, + NegativeDelta: []int64{1, 1, -2, 2, -2, 0, 1}, + }, }, { name: "buckets limited by widening the zero bucket twice, negative observations", @@ -636,7 +862,17 @@ func TestNativeHistogram(t *testing.T) { factor: 1.2, maxBuckets: 4, maxZeroThreshold: 1.2, - want: `sample_count:9 sample_sum:-15.5 schema:2 zero_threshold:1.189207115002721 zero_count:3 negative_span: negative_delta:2 negative_delta:-2 negative_delta:2 negative_delta:-2 negative_delta:0 negative_delta:1 negative_delta:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(9), + SampleSum: proto.Float64(-15.5), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(1.189207115002721), + ZeroCount: proto.Uint64(3), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(2), Length: proto.Uint32(7)}, + }, + NegativeDelta: []int64{2, -2, 2, -2, 0, 1, 0}, + }, }, { name: "buckets limited by reset, negative observations", @@ -645,7 +881,17 @@ func TestNativeHistogram(t *testing.T) { maxBuckets: 4, maxZeroThreshold: 1.2, minResetDuration: 5 * time.Minute, - want: `sample_count:2 sample_sum:-7 schema:2 zero_threshold:2.938735877055719e-39 zero_count:0 negative_span: negative_delta:1 negative_delta:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(2), + SampleSum: proto.Float64(-7), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(0), + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(7), Length: proto.Uint32(2)}, + }, + NegativeDelta: []int64{1, 0}, + }, }, { name: "buckets limited by halving resolution, then reset", @@ -653,7 +899,17 @@ func TestNativeHistogram(t *testing.T) { factor: 1.2, maxBuckets: 4, minResetDuration: 9 * time.Minute, - want: `sample_count:2 sample_sum:7 schema:2 zero_threshold:2.938735877055719e-39 zero_count:0 positive_span: positive_delta:1 positive_delta:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(2), + SampleSum: proto.Float64(7), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(0), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(7), Length: proto.Uint32(2)}, + }, + PositiveDelta: []int64{1, 0}, + }, }, { name: "buckets limited by widening the zero bucket, then reset", @@ -662,7 +918,17 @@ func TestNativeHistogram(t *testing.T) { maxBuckets: 4, maxZeroThreshold: 1.2, minResetDuration: 9 * time.Minute, - want: `sample_count:2 sample_sum:7 schema:2 zero_threshold:2.938735877055719e-39 zero_count:0 positive_span: positive_delta:1 positive_delta:0 `, + want: &dto.Histogram{ + SampleCount: proto.Uint64(2), + SampleSum: proto.Float64(7), + Schema: proto.Int32(2), + ZeroThreshold: proto.Float64(2.938735877055719e-39), + ZeroCount: proto.Uint64(0), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(7), Length: proto.Uint32(2)}, + }, + PositiveDelta: []int64{1, 0}, + }, }, } @@ -690,8 +956,8 @@ func TestNativeHistogram(t *testing.T) { if err := his.Write(m); err != nil { t.Fatal("unexpected error writing metric", err) } - got := m.Histogram.String() - if s.want != got { + got := m.Histogram + if !proto.Equal(s.want, got) { t.Errorf("want histogram %q, got %q", s.want, got) } }) diff --git a/prometheus/registry_test.go b/prometheus/registry_test.go index 4ffcb03a5..d1b7a192c 100644 --- a/prometheus/registry_test.go +++ b/prometheus/registry_test.go @@ -725,7 +725,11 @@ collected metric "broken_metric" { label: label: