Allow unregistration of metrics (#6)

* Allow unregistration of metrics

* Provide metrics.WritePrometheusSet to write using a dedicated metric set

* Cleanup unregister metrics patch, add generic WriteProcessMetrics
This commit is contained in:
Roland Lammel 2020-02-26 18:52:38 +01:00 committed by GitHub
parent 0ee6a1fa32
commit 900c892625
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 2 deletions

View File

@ -41,7 +41,24 @@ var defaultSet = NewSet()
func WritePrometheus(w io.Writer, exposeProcessMetrics bool) {
defaultSet.WritePrometheus(w)
if exposeProcessMetrics {
writeGoMetrics(w)
writeProcessMetrics(w)
WriteProcessMetrics(w)
}
}
// WriteProcessMetrics writes additional process metrics in Prometheus format to w.
//
// Various `go_*` and `process_*` metrics are exposed for the currently
// running process.
//
// The WriteProcessMetrics func is usually called in combination with writing Set metrics
// inside "/metrics" handler:
//
// http.HandleFunc("/metrics", func(w http.ResponseWriter, req *http.Request) {
// mySet.WritePrometheus(w)
// metrics.WriteProcessMetrics(w)
// })
//
func WriteProcessMetrics(w io.Writer) {
writeGoMetrics(w)
writeProcessMetrics(w)
}

25
set.go
View File

@ -438,3 +438,28 @@ func (s *Set) registerMetric(name string, m metric) {
panic(fmt.Errorf("BUG: metric %q is already registered", name))
}
}
// UnregisterMetric will remove a registered metric
func (s *Set) UnregisterMetric(name string) bool {
s.mu.Lock()
nm, ok := s.m[name]
if ok {
delete(s.m, name)
for i, a := range s.a {
if a == nm {
s.a = append(s.a[:i], s.a[i+1:]...)
}
}
}
s.mu.Unlock()
return ok
}
// ListMetricNames will return a list of all registered metrics
func (s *Set) ListMetricNames() []string {
var list []string
for name := range s.m {
list = append(list, name)
}
return list
}

View File

@ -34,3 +34,61 @@ func TestNewSet(t *testing.T) {
}
}
}
func TestListMetricNames(t *testing.T) {
s := NewSet()
expect := []string{"cnt1", "cnt2", "cnt3"}
// Initialize a few counters
for _, n := range expect {
c := s.NewCounter(n)
c.Inc()
}
list := s.ListMetricNames()
if len(list) != len(expect) {
t.Fatalf("Metrics count is wrong for listing")
}
for _, e := range expect {
found := false
for _, n := range list {
if e == n {
found = true
}
}
if !found {
t.Fatalf("Metric %s not found in listing", e)
}
}
}
func TestUnregisterMetric(t *testing.T) {
s := NewSet()
// Initialize a few counters
for i := 0; i < 5; i++ {
c := s.NewCounter(fmt.Sprintf("counter_%d", i))
c.Inc()
}
// Unregister existing counters
ok := s.UnregisterMetric("counter_1")
if !ok {
t.Fatalf("Metric counter_1 should return true for deregistering")
}
// Unregister twice must return false
ok = s.UnregisterMetric("counter_1")
if ok {
t.Fatalf("Metric counter_1 should not return false on unregister twice")
}
// Validate counters are removed
ok = false
for _, n := range s.ListMetricNames() {
if n == "counter_1" {
ok = true
}
}
if ok {
t.Fatalf("Metric counter_1 and counter_3 must not be listed anymore after unregister")
}
}