Initial promlint counter _total suffix check (#2624)

pull/2625/head
Matt Layher 8 years ago committed by Julius Volz
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…
Cancel
Save