metrics: use constants for metric types

NewMultiLabelMap does not return an error so it's easy for someone to
pass an incorrect/unsupported metric type and serve invalid metrics to
Prometheus.

This would read as `metrics.Counter` and `metrics.Gauge` when used,
which seems readable enough; but if you think bare strings are better,
an alternative to this approach might be to verify string value in
`NewMultiLabelMap` and panic?

Updates tailscale/corp#22075

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
This commit is contained in:
Anton Tolchanov 2024-08-13 07:37:47 +01:00
parent 10662c4282
commit b615a1d4db
2 changed files with 11 additions and 4 deletions

View File

@ -13,6 +13,13 @@
"sync"
)
// MetricType is a Prometheus metric type. At the moment we only support
// counter and gauge.
type MetricType string
const Counter MetricType = "counter"
const Gauge MetricType = "gauge"
// MultiLabelMap is a struct-value-to-Var map variable that satisfies the
// [expvar.Var] interface but also allows for multiple Prometheus labels to be
// associated with each value.
@ -22,7 +29,7 @@
// The struct fields must all be strings, and the string values must be valid
// Prometheus label values without requiring quoting.
type MultiLabelMap[T comparable] struct {
Type string // optional Prometheus type ("counter", "gauge")
Type MetricType
Help string // optional Prometheus help string
m sync.Map // map[T]expvar.Var
@ -33,7 +40,7 @@ type MultiLabelMap[T comparable] struct {
// NewMultiLabelMap creates and publishes (via expvar.Publish) a new
// MultiLabelMap[T] variable with the given name and returns it.
func NewMultiLabelMap[T comparable](name string, promType, helpText string) *MultiLabelMap[T] {
func NewMultiLabelMap[T comparable](name string, promType MetricType, helpText string) *MultiLabelMap[T] {
m := &MultiLabelMap[T]{
Type: promType,
Help: helpText,
@ -105,7 +112,7 @@ func (v *MultiLabelMap[T]) WritePrometheus(w io.Writer, name string) {
io.WriteString(w, "# TYPE ")
io.WriteString(w, name)
io.WriteString(w, " ")
io.WriteString(w, v.Type)
io.WriteString(w, string(v.Type))
io.WriteString(w, "\n")
}
if v.Help != "" {

View File

@ -82,7 +82,7 @@ type LabelTypes struct {
}
m := new(MultiLabelMap[LabelTypes])
m.Type = "counter"
m.Type = Counter
m.Help = "some good stuff"
m.Add(LabelTypes{"a", true, -1, 2}, 3)
var buf bytes.Buffer