metrics
metrics copied to clipboard
name composer: fast and slow (reflect-based) implementations
Context && Motivation
To create a new metric we have to manually write the full metric name (+ stringified labels) e.g. foo{bar="baz",aaa="b"} That can be tricky and overwhelming when doing it manually: raw strings always give a chance to make a typo (invalid syntax, wrong name, wrong type, missing/extra labels, etc)
Solution
Provide a helper function "NameCompose" that will let us to compose full metric name with given metric_name and labels. To avoid using raw maps (that still can lead to typos and issues explained above), let's do the type-safe solution, using structs.
Two possible solutions are available here:
1. Fast solution (but manual declaring helper for each labels set)
type MyLabelsSet struct {
Foo string
Bar int
Flag bool
}
func (s MyLabelsSet) ToLabelsString() string {
return `{foo="`+s.Foo+`",bar="`+fmt.Sprintf("%d", s.Bar)+`",flag="`+fmt.Sprintf("%t", s.Flag)+`"}`
}
GetOrCreateCounter(NameCompose("my_counter", MyLabelsSet{
Foo: "foo1", Bar: 3, Flag: true
}).Inc()
// -> my_counter{foo:"foo1",bar:"3",flag:"true"}
2. Auto-compose solution (but slow, reflect is involved)
// + No need to declare a custom method to a struct
// + Type can be defined on-the-fly inside a function
func SomeFunc() {
type MyLabelsAuto struct {
AutoLabelComposer // making this labels set to let it automatically generate labels string
Foo string
Bar int
Flag bool
}
GetOrCreateCounter(NameComposeAuto("my_counter", MyLabelsAuto{
Foo: "foo1", Bar: 3, Flag: true
}).Inc()
// -> my_counter{foo:"foo1",bar:"3",flag:"true"}
Notes:
- Reflect is involved but optional. You can always declare your own
ToLabelsString()method to your labels struct and use it. - Reflect as a dependency by itself doesn't harm the "lightweight" factor of the library.
What do you think about such a feature?