mirror of
https://github.com/prometheus/prometheus.git
synced 2025-02-02 08:31:11 -08:00
Initial promlint counter _total suffix check (#2624)
This commit is contained in:
parent
254cb1ec29
commit
34a4813464
|
@ -86,6 +86,7 @@ func lint(mf dto.MetricFamily) []Problem {
|
||||||
fns := []func(mf dto.MetricFamily) []Problem{
|
fns := []func(mf dto.MetricFamily) []Problem{
|
||||||
lintHelp,
|
lintHelp,
|
||||||
lintMetricUnits,
|
lintMetricUnits,
|
||||||
|
lintCounter,
|
||||||
}
|
}
|
||||||
|
|
||||||
var problems []Problem
|
var problems []Problem
|
||||||
|
@ -135,6 +136,31 @@ func lintMetricUnits(mf dto.MetricFamily) []Problem {
|
||||||
return problems
|
return problems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lintCounter detects issues specific to counters, as well as patterns that should
|
||||||
|
// only be used with counters.
|
||||||
|
func lintCounter(mf dto.MetricFamily) []Problem {
|
||||||
|
var problems []Problem
|
||||||
|
|
||||||
|
isCounter := *mf.Type == dto.MetricType_COUNTER
|
||||||
|
isUntyped := *mf.Type == dto.MetricType_UNTYPED
|
||||||
|
hasTotalSuffix := strings.HasSuffix(*mf.Name, "_total")
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case isCounter && !hasTotalSuffix:
|
||||||
|
problems = append(problems, Problem{
|
||||||
|
Metric: *mf.Name,
|
||||||
|
Text: `counter metrics should have "_total" suffix`,
|
||||||
|
})
|
||||||
|
case !isUntyped && !isCounter && hasTotalSuffix:
|
||||||
|
problems = append(problems, Problem{
|
||||||
|
Metric: *mf.Name,
|
||||||
|
Text: `non-counter metrics should not have "_total" suffix`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return problems
|
||||||
|
}
|
||||||
|
|
||||||
// metricUnits attempts to detect known unit types used as part of a metric name,
|
// metricUnits attempts to detect known unit types used as part of a metric name,
|
||||||
// e.g. "foo_bytes_total" or "bar_baz_milligrams".
|
// e.g. "foo_bytes_total" or "bar_baz_milligrams".
|
||||||
func metricUnits(m string) (unit string, base string, ok bool) {
|
func metricUnits(m string) (unit string, base string, ok bool) {
|
||||||
|
|
|
@ -251,3 +251,84 @@ thermometers_kelvin 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLintCounter(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
in string
|
||||||
|
problems []promlint.Problem
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "counter without _total suffix",
|
||||||
|
in: `
|
||||||
|
# HELP x_bytes Test metric.
|
||||||
|
# TYPE x_bytes counter
|
||||||
|
x_bytes 10
|
||||||
|
`,
|
||||||
|
problems: []promlint.Problem{{
|
||||||
|
Metric: "x_bytes",
|
||||||
|
Text: `counter metrics should have "_total" suffix`,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gauge with _total suffix",
|
||||||
|
in: `
|
||||||
|
# HELP x_bytes_total Test metric.
|
||||||
|
# TYPE x_bytes_total gauge
|
||||||
|
x_bytes_total 10
|
||||||
|
`,
|
||||||
|
problems: []promlint.Problem{{
|
||||||
|
Metric: "x_bytes_total",
|
||||||
|
Text: `non-counter metrics should not have "_total" suffix`,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "counter with _total suffix",
|
||||||
|
in: `
|
||||||
|
# HELP x_bytes_total Test metric.
|
||||||
|
# TYPE x_bytes_total counter
|
||||||
|
x_bytes_total 10
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gauge without _total suffix",
|
||||||
|
in: `
|
||||||
|
# HELP x_bytes Test metric.
|
||||||
|
# TYPE x_bytes gauge
|
||||||
|
x_bytes 10
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "untyped with _total suffix",
|
||||||
|
in: `
|
||||||
|
# HELP x_bytes_total Test metric.
|
||||||
|
# TYPE x_bytes_total untyped
|
||||||
|
x_bytes_total 10
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "untyped without _total suffix",
|
||||||
|
in: `
|
||||||
|
# HELP x_bytes Test metric.
|
||||||
|
# TYPE x_bytes untyped
|
||||||
|
x_bytes 10
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
l := promlint.New(strings.NewReader(tt.in))
|
||||||
|
|
||||||
|
problems, err := l.Lint()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if want, got := tt.problems, problems; !reflect.DeepEqual(want, got) {
|
||||||
|
t.Fatalf("unexpected problems:\n- want: %v\n- got: %v",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue