Skip to content

Commit

Permalink
contrib/apmgometrics: go-metrics gatherer
Browse files Browse the repository at this point in the history
  • Loading branch information
axw committed Apr 27, 2018
1 parent 9cb0f0c commit 759ad47
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
40 changes: 40 additions & 0 deletions contrib/apmgometrics/gatherer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package apmgometrics

import (
"context"

"github.com/rcrowley/go-metrics"

"github.com/elastic/apm-agent-go"
)

// Wrap wraps r, a go-metrics Registry, so that it can be used
// as an elasticapm.MetricsGatherer.
func Wrap(r metrics.Registry) elasticapm.MetricsGatherer {
return gatherer{r}
}

type gatherer struct {
r metrics.Registry
}

// GatherMEtrics gathers metrics into m.
func (g gatherer) GatherMetrics(ctx context.Context, m *elasticapm.Metrics) error {
g.r.Each(func(name string, v interface{}) {
switch v := v.(type) {
case metrics.Counter:
// NOTE(axw) in go-metrics, counters can go up and down,
// hence we use a gauge here. Should we provide config
// to allow a user to specify that a counter is always
// increasing, hence represent it as a counter type?
m.AddGauge(name, nil, float64(v.Count()))
case metrics.Gauge:
m.AddGauge(name, nil, float64(v.Value()))
case metrics.GaugeFloat64:
m.AddGauge(name, nil, v.Value())
default:
// TODO(axw) Meter, Timer, Histogram, EWMA
}
})
return nil
}
54 changes: 54 additions & 0 deletions contrib/apmgometrics/gatherer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package apmgometrics_test

import (
"testing"

"github.com/rcrowley/go-metrics"
"github.com/stretchr/testify/assert"

"github.com/elastic/apm-agent-go"
"github.com/elastic/apm-agent-go/contrib/apmgometrics"
"github.com/elastic/apm-agent-go/model"
"github.com/elastic/apm-agent-go/transport/transporttest"
)

func TestGatherer(t *testing.T) {
r := metrics.NewRegistry()
httpReqsTotal := metrics.GetOrRegisterCounter("http.requests_total", r)
httpReqsInflight := metrics.GetOrRegisterGauge("http.requests_inflight", r)
httpReqsTotal.Inc(123)
httpReqsInflight.Update(10)

g := apmgometrics.Wrap(r)
metrics := gatherMetrics(g)

assert.Equal(t, []*model.Metrics{{
Samples: map[string]model.Metric{
"http.requests_total": {
// go-metrics's counters are gauges
// by our definition, hence the Value
// field is set and Count is not.
Value: newFloat64(123),
},
"http.requests_inflight": {
Value: newFloat64(10),
},
},
}}, metrics)
}

func gatherMetrics(g elasticapm.MetricsGatherer) []*model.Metrics {
tracer, transport := transporttest.NewRecorderTracer()
defer tracer.Close()
tracer.AddMetricsGatherer(g)
tracer.SendMetrics(nil)
metrics := transport.Payloads()[0].Metrics()
for _, m := range metrics {
m.Timestamp = model.Time{}
}
return metrics
}

func newFloat64(v float64) *float64 {
return &v
}

0 comments on commit 759ad47

Please sign in to comment.