test(go.d/prometheus): add V1 compatibility manifest golden tests (#22641)
Ilya Mashchenko committed
Jun 6, 2026 at 13:50 UTC
369a28ba0b8569f0c56d81d566131d978b050f5d
14 files changed
+742
src/go/plugin/go.d/collector/prometheus/manifest_test.go
new
+310
@@ -0,0 +1,310 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package prometheus
4
+
5
+import (
6
+ "context"
7
+ "encoding/json"
8
+ "flag"
9
+ "net/http"
10
+ "net/http/httptest"
11
+ "os"
12
+ "path/filepath"
13
+ "sort"
14
+ "strings"
15
+ "testing"
16
+
17
+ "github.com/stretchr/testify/assert"
18
+ "github.com/stretchr/testify/require"
19
+
20
+ "github.com/netdata/netdata/go/plugins/pkg/prometheus/selector"
21
+ "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
22
+)
23
+
24
+// updateGolden, when set, makes the manifest test (re)write the golden files and
25
+// skip the comparison. The goldens are a frozen baseline of the V1 collector's
26
+// observable contract; the V2 migration (PR5) checks parity by diffing its render
27
+// against them. Regenerate ONLY when intentionally adding a fixture or accepting a
28
+// contract change, then review the git diff — never to silently absorb V2 drift,
29
+// which would defeat the baseline. Hand-editing the JSON is error-prone, so this is
30
+// the supported way to maintain them:
31
+//
32
+// go test ./plugin/go.d/collector/prometheus/ -run TestCollector_compatManifest -update-golden
33
+var updateGolden = flag.Bool("update-golden", false, "regenerate the prometheus compat-manifest golden files")
34
+
35
+// The compat manifest captures the V1 collector's observable CONTRACT, so the V2
36
+// migration (PR5) can be verified to preserve it.
37
+//
38
+// manifestChart top-level fields are the HARD contract a V2 migration must
39
+// reproduce: the chart context, its labels (incl. label_prefix), and its dims by
40
+// semantic name with algo + the real (de-scaled) value. `soft` holds best-effort
41
+// fields autogen may derive differently (units/family/type). The V1 chart-ID
42
+// strings and the ×1000 / ×1e6 precision divisor are INTENTIONALLY excluded — both
43
+// change by design in V2 (autogen chart-IDs; float dimensions). Values are
44
+// de-scaled (mx ÷ Div) to the real number V2's float dims emit directly.
45
+//
46
+// Note: V1 scales values into int64 (×1000 / ×1e6), so sub-precision values are
47
+// truncated (0.00147889 → 1 → 0.001). The manifest records V1's truncated value;
48
+// the PR5 verification must diff values float-tolerantly (V2 is more precise).
49
+type manifestChart struct {
50
+ Context string `json:"context"`
51
+ Labels map[string]string `json:"labels,omitempty"`
52
+ Dims []manifestDim `json:"dims"`
53
+ Soft manifestSoft `json:"soft"`
54
+}
55
+
56
+type manifestDim struct {
57
+ Name string `json:"name"`
58
+ Algo string `json:"algo"`
59
+ Value float64 `json:"value"`
60
+}
61
+
62
+type manifestSoft struct {
63
+ Units string `json:"units"`
64
+ Family string `json:"family"`
65
+ Type string `json:"type"`
66
+}
67
+
68
+func renderManifest(charts *collectorapi.Charts, mx map[string]int64) []manifestChart {
69
+ out := make([]manifestChart, 0, len(*charts))
70
+
71
+ for _, ch := range *charts {
72
+ if ch.Obsolete {
73
+ continue
74
+ }
75
+
76
+ mc := manifestChart{
77
+ Context: ch.Ctx,
78
+ Soft: manifestSoft{Units: ch.Units, Family: ch.Fam, Type: string(ch.Type)},
79
+ }
80
+ if len(ch.Labels) > 0 {
81
+ mc.Labels = make(map[string]string, len(ch.Labels))
82
+ for _, l := range ch.Labels {
83
+ mc.Labels[l.Key] = l.Value
84
+ }
85
+ }
86
+ for _, d := range ch.Dims {
87
+ div := d.Div
88
+ if div == 0 {
89
+ div = 1
90
+ }
91
+ algo := "absolute"
92
+ if d.Algo != "" {
93
+ algo = string(d.Algo)
94
+ }
95
+ mc.Dims = append(mc.Dims, manifestDim{
96
+ Name: d.Name,
97
+ Algo: algo,
98
+ Value: float64(mx[d.ID]) / float64(div),
99
+ })
100
+ }
101
+ sort.Slice(mc.Dims, func(i, j int) bool { return mc.Dims[i].Name < mc.Dims[j].Name })
102
+
103
+ out = append(out, mc)
104
+ }
105
+
106
+ sort.Slice(out, func(i, j int) bool {
107
+ if out[i].Context != out[j].Context {
108
+ return out[i].Context < out[j].Context
109
+ }
110
+ return manifestLabelsKey(out[i].Labels) < manifestLabelsKey(out[j].Labels)
111
+ })
112
+
113
+ return out
114
+}
115
+
116
+func manifestLabelsKey(m map[string]string) string {
117
+ keys := make([]string, 0, len(m))
118
+ for k := range m {
119
+ keys = append(keys, k)
120
+ }
121
+ sort.Strings(keys)
122
+
123
+ var sb strings.Builder
124
+ for _, k := range keys {
125
+ sb.WriteString(k + "=" + m[k] + ";")
126
+ }
127
+ return sb.String()
128
+}
129
+
130
+func TestCollector_compatManifest(t *testing.T) {
131
+ tests := map[string]struct {
132
+ prepare func() *Collector
133
+ input string
134
+ }{
135
+ "gauge": {
136
+ prepare: New,
137
+ input: `
138
+# HELP test_gauge_metric A gauge.
139
+# TYPE test_gauge_metric gauge
140
+test_gauge_metric{label1="value1"} 11
141
+test_gauge_metric{label1="value2"} 12.5
142
+`,
143
+ },
144
+ "counter": {
145
+ prepare: New,
146
+ input: `
147
+# TYPE test_counter_metric_total counter
148
+test_counter_metric_total{label1="value1"} 11
149
+`,
150
+ },
151
+ "summary": {
152
+ prepare: New,
153
+ input: `
154
+# TYPE test_summary_duration_seconds summary
155
+test_summary_duration_seconds{label1="value1",quantile="0.5"} 0.25
156
+test_summary_duration_seconds{label1="value1",quantile="0.99"} 0.5
157
+test_summary_duration_seconds_sum{label1="value1"} 12.5
158
+test_summary_duration_seconds_count{label1="value1"} 42
159
+`,
160
+ },
161
+ "histogram": {
162
+ prepare: New,
163
+ input: `
164
+# TYPE test_histogram_duration_seconds histogram
165
+test_histogram_duration_seconds_bucket{label1="value1",le="0.1"} 4
166
+test_histogram_duration_seconds_bucket{label1="value1",le="+Inf"} 6
167
+test_histogram_duration_seconds_sum{label1="value1"} 2.5
168
+test_histogram_duration_seconds_count{label1="value1"} 6
169
+`,
170
+ },
171
+ "untyped_total": {
172
+ prepare: New,
173
+ input: `
174
+test_untyped_metric_total{label1="value1"} 11
175
+`,
176
+ },
177
+ "app": {
178
+ prepare: func() *Collector { c := New(); c.Application = "custom_app"; return c },
179
+ input: `
180
+# TYPE test_gauge_metric gauge
181
+test_gauge_metric{label1="value1"} 11
182
+`,
183
+ },
184
+ "app_job_name": {
185
+ // Application empty -> the app segment falls back to the job Name (charts.go:238-241).
186
+ prepare: func() *Collector { c := New(); c.Name = "job_app"; return c },
187
+ input: `
188
+# TYPE test_gauge_metric gauge
189
+test_gauge_metric{label1="value1"} 11
190
+`,
191
+ },
192
+ "label_prefix": {
193
+ prepare: func() *Collector { c := New(); c.LabelPrefix = "px"; return c },
194
+ input: `
195
+# TYPE test_gauge_metric gauge
196
+test_gauge_metric{label1="value1"} 11
197
+`,
198
+ },
199
+ "snmp_units": {
200
+ // Special unit mappings (charts.go getChartUnits): uppercase snmp-exporter
201
+ // names octets->bytes, pkts->packets, mtu->octets, speed->bits; underscore
202
+ // suffix hertz->Hz.
203
+ prepare: New,
204
+ input: `
205
+# TYPE ifOutOctets gauge
206
+ifOutOctets{ifDescr="eth0"} 12345
207
+# TYPE ifOutUcastPkts gauge
208
+ifOutUcastPkts{ifDescr="eth0"} 678
209
+# TYPE ifMtu gauge
210
+ifMtu{ifDescr="eth0"} 1500
211
+# TYPE ifHighSpeed gauge
212
+ifHighSpeed{ifDescr="eth0"} 1000
213
+# TYPE test_clock_hertz gauge
214
+test_clock_hertz{cpu="0"} 2400
215
+`,
216
+ },
217
+ "selector": {
218
+ prepare: func() *Collector {
219
+ c := New()
220
+ c.Selector = selector.Expr{Allow: []string{"test_gauge_metric_keep"}}
221
+ return c
222
+ },
223
+ input: `
224
+# TYPE test_gauge_metric_keep gauge
225
+test_gauge_metric_keep{label1="value1"} 11
226
+# TYPE test_gauge_metric_drop gauge
227
+test_gauge_metric_drop{label1="value1"} 22
228
+`,
229
+ },
230
+ "info_skipped": {
231
+ prepare: New,
232
+ input: `
233
+# TYPE test_metric gauge
234
+test_metric{label1="value1"} 11
235
+# TYPE test_metric_info gauge
236
+test_metric_info{version="1.2.3"} 1
237
+`,
238
+ },
239
+ "fallback_gauge": {
240
+ prepare: func() *Collector {
241
+ c := New()
242
+ c.FallbackType.Gauge = []string{"test_untyped_metric"}
243
+ return c
244
+ },
245
+ input: `
246
+test_untyped_metric{label1="value1"} 11
247
+`,
248
+ },
249
+ "fallback_counter": {
250
+ // Untyped metric forced to counter by regex — a distinct path from the
251
+ // _total auto-counter (independent `if` at collect.go:176); algo incremental.
252
+ prepare: func() *Collector {
253
+ c := New()
254
+ c.FallbackType.Counter = []string{"test_untyped_metric"}
255
+ return c
256
+ },
257
+ input: `
258
+test_untyped_metric{label1="value1"} 11
259
+`,
260
+ },
261
+ }
262
+
263
+ for name, tc := range tests {
264
+ t.Run(name, func(t *testing.T) {
265
+ srv := httptest.NewServer(http.HandlerFunc(
266
+ func(w http.ResponseWriter, _ *http.Request) { _, _ = w.Write([]byte(tc.input)) }))
267
+ defer srv.Close()
268
+
269
+ collr := tc.prepare()
270
+ collr.URL = srv.URL
271
+ require.NoError(t, collr.Init(context.Background()))
272
+
273
+ mx := collr.Collect(context.Background())
274
+ require.NotNil(t, mx)
275
+
276
+ got := renderManifest(collr.Charts(), mx)
277
+ data, err := json.MarshalIndent(got, "", " ")
278
+ require.NoError(t, err)
279
+ data = append(data, '\n')
280
+
281
+ path := filepath.Join("testdata", "golden", goldenName(name)+".json")
282
+ if *updateGolden {
283
+ require.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755))
284
+ require.NoError(t, os.WriteFile(path, data, 0o644))
285
+ return
286
+ }
287
+
288
+ want, err := os.ReadFile(path)
289
+ require.NoErrorf(t, err, "missing golden %q — run: go test -run TestCollector_compatManifest -update-golden ./...", path)
290
+ assert.Equal(t, string(want), string(data))
291
+ })
292
+ }
293
+}
294
+
295
+// Config defaults the V2 migration (PR5) must preserve: update_every is the
296
+// registered Creator default (collectorapi.Defaults); max_time_series[_per_metric]
297
+// are New() defaults. A V2 re-registration can silently drop them.
298
+func TestCollector_compatConfigDefaults(t *testing.T) {
299
+ creator, ok := collectorapi.DefaultRegistry.Lookup("prometheus")
300
+ require.True(t, ok, "prometheus collector must be registered")
301
+ assert.Equal(t, 10, creator.Defaults.UpdateEvery, "update_every default")
302
+
303
+ c := New()
304
+ assert.Equal(t, 2000, c.MaxTS, "max_time_series default")
305
+ assert.Equal(t, 200, c.MaxTSPerMetric, "max_time_series_per_metric default")
306
+}
307
+
308
+func goldenName(name string) string {
309
+ return strings.NewReplacer(" ", "_", "(", "", ")", "", ">", "", "-", "_", ".", "_", "/", "_", "<", "").Replace(name)
310
+}
src/go/plugin/go.d/collector/prometheus/testdata/golden/app.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.custom_app.test_gauge_metric",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_gauge_metric",
10
+ "algo": "absolute",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric",
16
+ "family": "test_gauge",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/app_job_name.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.job_app.test_gauge_metric",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_gauge_metric",
10
+ "algo": "absolute",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric",
16
+ "family": "test_gauge",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/counter.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_counter_metric_total",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_counter_metric_total",
10
+ "algo": "incremental",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric/s",
16
+ "family": "test_counter",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/fallback_counter.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_untyped_metric",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_untyped_metric",
10
+ "algo": "incremental",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric/s",
16
+ "family": "test_untyped",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/fallback_gauge.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_untyped_metric",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_untyped_metric",
10
+ "algo": "absolute",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric",
16
+ "family": "test_untyped",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/gauge.json
new
+38
@@ -0,0 +1,38 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_gauge_metric",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_gauge_metric",
10
+ "algo": "absolute",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric",
16
+ "family": "test_gauge",
17
+ "type": "line"
18
+ }
19
+ },
20
+ {
21
+ "context": "prometheus.test_gauge_metric",
22
+ "labels": {
23
+ "label1": "value2"
24
+ },
25
+ "dims": [
26
+ {
27
+ "name": "test_gauge_metric",
28
+ "algo": "absolute",
29
+ "value": 12.5
30
+ }
31
+ ],
32
+ "soft": {
33
+ "units": "metric",
34
+ "family": "test_gauge",
35
+ "type": "line"
36
+ }
37
+ }
38
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/histogram.json
new
+61
@@ -0,0 +1,61 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_histogram_duration_seconds",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "bucket_+Inf",
10
+ "algo": "incremental",
11
+ "value": 6
12
+ },
13
+ {
14
+ "name": "bucket_0.1",
15
+ "algo": "incremental",
16
+ "value": 4
17
+ }
18
+ ],
19
+ "soft": {
20
+ "units": "observations/s",
21
+ "family": "test_histogram",
22
+ "type": ""
23
+ }
24
+ },
25
+ {
26
+ "context": "prometheus.test_histogram_duration_seconds_count",
27
+ "labels": {
28
+ "label1": "value1"
29
+ },
30
+ "dims": [
31
+ {
32
+ "name": "test_histogram_duration_seconds_count",
33
+ "algo": "incremental",
34
+ "value": 6
35
+ }
36
+ ],
37
+ "soft": {
38
+ "units": "events/s",
39
+ "family": "test_histogram",
40
+ "type": ""
41
+ }
42
+ },
43
+ {
44
+ "context": "prometheus.test_histogram_duration_seconds_sum",
45
+ "labels": {
46
+ "label1": "value1"
47
+ },
48
+ "dims": [
49
+ {
50
+ "name": "test_histogram_duration_seconds_sum",
51
+ "algo": "incremental",
52
+ "value": 2.5
53
+ }
54
+ ],
55
+ "soft": {
56
+ "units": "seconds",
57
+ "family": "test_histogram",
58
+ "type": ""
59
+ }
60
+ }
61
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/info_skipped.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_metric",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_metric",
10
+ "algo": "absolute",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric",
16
+ "family": "test_metric",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/label_prefix.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_gauge_metric",
4
+ "labels": {
5
+ "px_label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_gauge_metric",
10
+ "algo": "absolute",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric",
16
+ "family": "test_gauge",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/selector.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_gauge_metric_keep",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_gauge_metric_keep",
10
+ "algo": "absolute",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "keep",
16
+ "family": "test_gauge",
17
+ "type": "line"
18
+ }
19
+ }
20
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/snmp_units.json
new
+92
@@ -0,0 +1,92 @@
1
+[
2
+ {
3
+ "context": "prometheus.ifHighSpeed",
4
+ "labels": {
5
+ "ifDescr": "eth0"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "ifHighSpeed",
10
+ "algo": "absolute",
11
+ "value": 1000
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "bits",
16
+ "family": "ifHighSpeed",
17
+ "type": "line"
18
+ }
19
+ },
20
+ {
21
+ "context": "prometheus.ifMtu",
22
+ "labels": {
23
+ "ifDescr": "eth0"
24
+ },
25
+ "dims": [
26
+ {
27
+ "name": "ifMtu",
28
+ "algo": "absolute",
29
+ "value": 1500
30
+ }
31
+ ],
32
+ "soft": {
33
+ "units": "octets",
34
+ "family": "ifMtu",
35
+ "type": "line"
36
+ }
37
+ },
38
+ {
39
+ "context": "prometheus.ifOutOctets",
40
+ "labels": {
41
+ "ifDescr": "eth0"
42
+ },
43
+ "dims": [
44
+ {
45
+ "name": "ifOutOctets",
46
+ "algo": "absolute",
47
+ "value": 12345
48
+ }
49
+ ],
50
+ "soft": {
51
+ "units": "bytes",
52
+ "family": "ifOutOctets",
53
+ "type": "area"
54
+ }
55
+ },
56
+ {
57
+ "context": "prometheus.ifOutUcastPkts",
58
+ "labels": {
59
+ "ifDescr": "eth0"
60
+ },
61
+ "dims": [
62
+ {
63
+ "name": "ifOutUcastPkts",
64
+ "algo": "absolute",
65
+ "value": 678
66
+ }
67
+ ],
68
+ "soft": {
69
+ "units": "packets",
70
+ "family": "ifOutUcastPkts",
71
+ "type": "line"
72
+ }
73
+ },
74
+ {
75
+ "context": "prometheus.test_clock_hertz",
76
+ "labels": {
77
+ "cpu": "0"
78
+ },
79
+ "dims": [
80
+ {
81
+ "name": "test_clock_hertz",
82
+ "algo": "absolute",
83
+ "value": 2400
84
+ }
85
+ ],
86
+ "soft": {
87
+ "units": "Hz",
88
+ "family": "test_clock",
89
+ "type": "line"
90
+ }
91
+ }
92
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/summary.json
new
+61
@@ -0,0 +1,61 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_summary_duration_seconds",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "quantile_0.5",
10
+ "algo": "absolute",
11
+ "value": 0.25
12
+ },
13
+ {
14
+ "name": "quantile_0.99",
15
+ "algo": "absolute",
16
+ "value": 0.5
17
+ }
18
+ ],
19
+ "soft": {
20
+ "units": "seconds",
21
+ "family": "test_summary",
22
+ "type": ""
23
+ }
24
+ },
25
+ {
26
+ "context": "prometheus.test_summary_duration_seconds_count",
27
+ "labels": {
28
+ "label1": "value1"
29
+ },
30
+ "dims": [
31
+ {
32
+ "name": "test_summary_duration_seconds_count",
33
+ "algo": "incremental",
34
+ "value": 42
35
+ }
36
+ ],
37
+ "soft": {
38
+ "units": "events/s",
39
+ "family": "test_summary",
40
+ "type": ""
41
+ }
42
+ },
43
+ {
44
+ "context": "prometheus.test_summary_duration_seconds_sum",
45
+ "labels": {
46
+ "label1": "value1"
47
+ },
48
+ "dims": [
49
+ {
50
+ "name": "test_summary_duration_seconds_sum",
51
+ "algo": "incremental",
52
+ "value": 12.5
53
+ }
54
+ ],
55
+ "soft": {
56
+ "units": "seconds",
57
+ "family": "test_summary",
58
+ "type": ""
59
+ }
60
+ }
61
+]
src/go/plugin/go.d/collector/prometheus/testdata/golden/untyped_total.json
new
+20
@@ -0,0 +1,20 @@
1
+[
2
+ {
3
+ "context": "prometheus.test_untyped_metric_total",
4
+ "labels": {
5
+ "label1": "value1"
6
+ },
7
+ "dims": [
8
+ {
9
+ "name": "test_untyped_metric_total",
10
+ "algo": "incremental",
11
+ "value": 11
12
+ }
13
+ ],
14
+ "soft": {
15
+ "units": "metric/s",
16
+ "family": "test_untyped",
17
+ "type": "line"
18
+ }
19
+ }
20
+]