Merge pull request #9069 from prometheus/beorn7/protobuf

Add tests for protobuf parser
This commit is contained in:
Björn Rabenstein 2021-07-12 12:29:20 +02:00 committed by GitHub
commit b56f7e8527
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 433 additions and 7 deletions

View file

@ -231,9 +231,7 @@ foo_total 17.0 1520879607.789 # {xx="yy"} 5`
p.Metric(&res)
found := p.Exemplar(&e)
require.Equal(t, exp[i].m, string(m))
if e.HasTs {
require.Equal(t, exp[i].t, ts)
}
require.Equal(t, exp[i].v, v)
require.Equal(t, exp[i].lset, res)
if exp[i].e == nil {

View file

@ -78,11 +78,11 @@ func (p *ProtobufParser) Series() ([]byte, *int64, float64) {
)
switch p.mf.GetType() {
case dto.MetricType_COUNTER:
v = m.GetCounter().Value
v = m.GetCounter().GetValue()
case dto.MetricType_GAUGE:
v = m.GetGauge().Value
v = m.GetGauge().GetValue()
case dto.MetricType_UNTYPED:
v = m.GetUntyped().Value
v = m.GetUntyped().GetValue()
default:
panic("encountered unexpected metric type, this is a bug")
}
@ -150,7 +150,7 @@ func (p *ProtobufParser) Type() ([]byte, MetricType) {
case dto.MetricType_GAUGE:
return n, MetricTypeGauge
case dto.MetricType_HISTOGRAM:
return n, MetricTypeGaugeHistogram
return n, MetricTypeHistogram
}
return n, MetricTypeUnknown
}

View file

@ -0,0 +1,428 @@
// 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"
"io"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/pkg/exemplar"
"github.com/prometheus/prometheus/pkg/histogram"
"github.com/prometheus/prometheus/pkg/labels"
dto "github.com/prometheus/prometheus/prompb/io/prometheus/client"
)
func TestProtobufParse(t *testing.T) {
textMetricFamilies := []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
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.0003919818421972943
timestamp: <
seconds: 1625851155
nanos: 146848499
>
>
>
bucket: <
cumulative_count: 16
upper_bound: -0.0002899999999999998
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: -0.0002956962622126468
timestamp: <
seconds: 1625851150
nanos: 233181498
>
>
>
sb_schema: 3
sb_zero_threshold: 2.938735877055719e-39
sb_zero_count: 2
sb_negative: <
span: <
offset: -162
length: 1
>
span: <
offset: 23
length: 4
>
delta: 1
delta: 3
delta: -2
delta: -1
delta: 1
>
sb_positive: <
span: <
offset: -161
length: 1
>
span: <
offset: 8
length: 3
>
delta: 1
delta: 2
delta: -1
delta: -1
>
>
timestamp_ms: 1234568
>
`,
`name: "test_histogram2"
help: "Same histogram as before but now without sparse buckets."
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.0003919818421972943
timestamp: <
seconds: 1625851155
nanos: 146848499
>
>
>
bucket: <
cumulative_count: 16
upper_bound: -0.0002899999999999998
exemplar: <
label: <
name: "dummyID"
value: "5617"
>
value: -0.0002956962622126468
timestamp: <
seconds: 1625851150
nanos: 233181498
>
>
>
sb_schema: 0
sb_zero_threshold: 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
>
>
>
`,
}
varintBuf := make([]byte, binary.MaxVarintLen32)
inputBuf := &bytes.Buffer{}
for _, tmf := range textMetricFamilies {
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)))
inputBuf.Write(varintBuf[:varintLength])
inputBuf.Write(protoBuf)
}
exp := []struct {
lset labels.Labels
m string
t int64
v float64
typ MetricType
help string
unit string
comment string
shs histogram.SparseHistogram
e *exemplar.Exemplar
}{
{
m: "go_build_info",
help: "Build information about the main Go module.",
},
{
m: "go_build_info",
typ: 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",
typ: MetricTypeCounter,
},
{
m: "go_memstats_alloc_bytes_total",
v: 1.546544e+06,
lset: labels.FromStrings(
"__name__", "go_memstats_alloc_bytes_total",
),
},
{
m: "something_untyped",
help: "Just to test the untyped type.",
},
{
m: "something_untyped",
typ: MetricTypeUnknown,
},
{
m: "something_untyped",
t: 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: MetricTypeHistogram,
},
{
m: "test_histogram",
t: 1234568,
shs: histogram.SparseHistogram{
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",
),
},
}
p := NewProtobufParser(inputBuf.Bytes())
i := 0
var res labels.Labels
for {
et, err := p.Next()
if err == io.EOF {
break
}
require.NoError(t, err)
switch et {
case EntrySeries:
m, ts, v := p.Series()
var e exemplar.Exemplar
p.Metric(&res)
found := p.Exemplar(&e)
require.Equal(t, exp[i].m, string(m))
if ts != nil {
require.Equal(t, exp[i].t, *ts)
} else {
require.Equal(t, exp[i].t, int64(0))
}
require.Equal(t, exp[i].v, v)
require.Equal(t, exp[i].lset, res)
if exp[i].e == nil {
require.Equal(t, false, found)
} else {
require.Equal(t, true, found)
require.Equal(t, *exp[i].e, e)
}
res = res[:0]
case EntryHistogram:
m, ts, shs := p.Histogram()
p.Metric(&res)
require.Equal(t, exp[i].m, string(m))
if ts != nil {
require.Equal(t, exp[i].t, *ts)
} else {
require.Equal(t, exp[i].t, int64(0))
}
require.Equal(t, exp[i].lset, res)
res = res[:0]
require.Equal(t, exp[i].m, string(m))
require.Equal(t, exp[i].shs, shs)
case EntryType:
m, typ := p.Type()
require.Equal(t, exp[i].m, string(m))
require.Equal(t, exp[i].typ, typ)
case EntryHelp:
m, h := p.Help()
require.Equal(t, exp[i].m, string(m))
require.Equal(t, exp[i].help, string(h))
case EntryUnit:
m, u := p.Unit()
require.Equal(t, exp[i].m, string(m))
require.Equal(t, exp[i].unit, string(u))
case EntryComment:
require.Equal(t, exp[i].comment, string(p.Comment()))
}
i++
}
// TODO(beorn7): Once supported by the parser, test exemplars for
// counters, exemplars for sparse histograms, legacy histograms including exemplars,
// summaries.
require.Equal(t, len(exp), i)
}