parent
79305e704b
commit
9cdd9cfb8e
@ -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) |
||||
} |
||||
Loading…
Reference in new issue