Codebase list golang-github-go-kit-kit / da91884
Merge pull request #442 from go-kit/rm-circonus metrics: remove circonus, it is too flaky Peter Bourgon authored 7 years ago GitHub committed 7 years ago
4 changed file(s) with 0 addition(s) and 260 deletion(s). Raw diff Collapse all Expand all
+0
-103
metrics/circonus/circonus.go less more
0 // Package circonus provides a Circonus backend for metrics.
1 package circonus
2
3 import (
4 "sync"
5
6 "github.com/circonus-labs/circonus-gometrics"
7
8 "github.com/go-kit/kit/metrics"
9 )
10
11 // Circonus wraps a CirconusMetrics object and provides constructors for each of
12 // the Go kit metrics. The CirconusMetrics object manages aggregation of
13 // observations and emission to the Circonus server.
14 type Circonus struct {
15 m *circonusgometrics.CirconusMetrics
16 }
17
18 // New creates a new Circonus object wrapping the passed CirconusMetrics, which
19 // the caller should create and set in motion. The Circonus object can be used
20 // to construct individual Go kit metrics.
21 func New(m *circonusgometrics.CirconusMetrics) *Circonus {
22 return &Circonus{
23 m: m,
24 }
25 }
26
27 // NewCounter returns a counter metric with the given name.
28 func (c *Circonus) NewCounter(name string) *Counter {
29 return &Counter{
30 name: name,
31 m: c.m,
32 }
33 }
34
35 // NewGauge returns a gauge metric with the given name.
36 func (c *Circonus) NewGauge(name string) *Gauge {
37 return &Gauge{
38 name: name,
39 m: c.m,
40 }
41 }
42
43 // NewHistogram returns a histogram metric with the given name.
44 func (c *Circonus) NewHistogram(name string) *Histogram {
45 return &Histogram{
46 h: c.m.NewHistogram(name),
47 }
48 }
49
50 // Counter is a Circonus implementation of a counter metric.
51 type Counter struct {
52 name string
53 m *circonusgometrics.CirconusMetrics
54 }
55
56 // With implements Counter, but is a no-op, because Circonus metrics have no
57 // concept of per-observation label values.
58 func (c *Counter) With(labelValues ...string) metrics.Counter { return c }
59
60 // Add implements Counter. Delta is converted to uint64; precision will be lost.
61 func (c *Counter) Add(delta float64) { c.m.Add(c.name, uint64(delta)) }
62
63 // Gauge is a Circonus implementation of a gauge metric.
64 type Gauge struct {
65 name string
66 m *circonusgometrics.CirconusMetrics
67 val float64
68 mtx sync.RWMutex
69 }
70
71 // With implements Gauge, but is a no-op, because Circonus metrics have no
72 // concept of per-observation label values.
73 func (g *Gauge) With(labelValues ...string) metrics.Gauge { return g }
74
75 // Set implements Gauge.
76 func (g *Gauge) Set(value float64) {
77 g.mtx.Lock()
78 defer g.mtx.Unlock()
79 g.val = value
80 g.m.SetGauge(g.name, value)
81 }
82
83 // Add implements metrics.Gauge.
84 func (g *Gauge) Add(delta float64) {
85 g.mtx.Lock()
86 defer g.mtx.Unlock()
87 value := g.val + delta
88 g.val = value
89 g.m.SetGauge(g.name, value)
90 }
91
92 // Histogram is a Circonus implementation of a histogram metric.
93 type Histogram struct {
94 h *circonusgometrics.Histogram
95 }
96
97 // With implements Histogram, but is a no-op, because Circonus metrics have no
98 // concept of per-observation label values.
99 func (h *Histogram) With(labelValues ...string) metrics.Histogram { return h }
100
101 // Observe implements Histogram. No precision is lost.
102 func (h *Histogram) Observe(value float64) { h.h.RecordValue(value) }
+0
-120
metrics/circonus/circonus_test.go less more
0 package circonus
1
2 import (
3 "encoding/json"
4 "net/http"
5 "net/http/httptest"
6 "regexp"
7 "strconv"
8 "testing"
9
10 "github.com/circonus-labs/circonus-gometrics"
11 "github.com/circonus-labs/circonus-gometrics/checkmgr"
12
13 "github.com/go-kit/kit/metrics/generic"
14 "github.com/go-kit/kit/metrics/teststat"
15 )
16
17 func TestCounter(t *testing.T) {
18 // The only way to extract values from Circonus is to pose as a Circonus
19 // server and receive real HTTP writes.
20 const name = "abc"
21 var val int64
22 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
23 var res map[string]struct {
24 Value int64 `json:"_value"` // reverse-engineered :\
25 }
26 json.NewDecoder(r.Body).Decode(&res)
27 val = res[name].Value
28 }))
29 defer s.Close()
30
31 // Set up a Circonus object, submitting to our HTTP server.
32 m := newCirconusMetrics(s.URL)
33 counter := New(m).NewCounter(name).With("label values", "not supported")
34 value := func() float64 { m.Flush(); return float64(val) }
35
36 // Engage.
37 if err := teststat.TestCounter(counter, value); err != nil {
38 t.Fatal(err)
39 }
40 }
41
42 func TestGauge(t *testing.T) {
43 const name = "def"
44 var val float64
45 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
46 var res map[string]struct {
47 Value string `json:"_value"`
48 }
49 json.NewDecoder(r.Body).Decode(&res)
50 val, _ = strconv.ParseFloat(res[name].Value, 64)
51 }))
52 defer s.Close()
53
54 m := newCirconusMetrics(s.URL)
55 gauge := New(m).NewGauge(name).With("label values", "not supported")
56 value := func() float64 { m.Flush(); return val }
57
58 if err := teststat.TestGauge(gauge, value); err != nil {
59 t.Fatal(err)
60 }
61 }
62
63 func TestHistogram(t *testing.T) {
64 const name = "ghi"
65
66 // Circonus just emits bucketed counts. We'll dump them into a generic
67 // histogram (losing some precision) and take statistics from there. Note
68 // this does assume that the generic histogram computes statistics properly,
69 // but we have another test for that :)
70 re := regexp.MustCompile(`^H\[([0-9\.e\+]+)\]=([0-9]+)$`) // H[1.2e+03]=456
71
72 var p50, p90, p95, p99 float64
73 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
74 var res map[string]struct {
75 Values []string `json:"_value"` // reverse-engineered :\
76 }
77 json.NewDecoder(r.Body).Decode(&res)
78
79 h := generic.NewHistogram("dummy", len(res[name].Values)) // match tbe bucket counts
80 for _, v := range res[name].Values {
81 match := re.FindStringSubmatch(v)
82 f, _ := strconv.ParseFloat(match[1], 64)
83 n, _ := strconv.ParseInt(match[2], 10, 64)
84 for i := int64(0); i < n; i++ {
85 h.Observe(f)
86 }
87 }
88
89 p50 = h.Quantile(0.50)
90 p90 = h.Quantile(0.90)
91 p95 = h.Quantile(0.95)
92 p99 = h.Quantile(0.99)
93 }))
94 defer s.Close()
95
96 m := newCirconusMetrics(s.URL)
97 histogram := New(m).NewHistogram(name).With("label values", "not supported")
98 quantiles := func() (float64, float64, float64, float64) { m.Flush(); return p50, p90, p95, p99 }
99
100 // Circonus metrics, because they do their own bucketing, are less precise
101 // than other systems. So, we bump the tolerance to 5 percent.
102 if err := teststat.TestHistogram(histogram, quantiles, 0.05); err != nil {
103 t.Fatal(err)
104 }
105 }
106
107 func newCirconusMetrics(url string) *circonusgometrics.CirconusMetrics {
108 m, err := circonusgometrics.NewCirconusMetrics(&circonusgometrics.Config{
109 CheckManager: checkmgr.Config{
110 Check: checkmgr.CheckConfig{
111 SubmissionURL: url,
112 },
113 },
114 })
115 if err != nil {
116 panic(err)
117 }
118 return m
119 }
9090 // expvar 1 atomic atomic synthetic, batch, in-place expose
9191 // influx n custom custom custom
9292 // prometheus n native native native
93 // circonus 1 native native native
9493 // pcp 1 native native native
9594 //
9695 package metrics
+0
-36
metrics/provider/circonus.go less more
0 package provider
1
2 import (
3 "github.com/go-kit/kit/metrics"
4 "github.com/go-kit/kit/metrics/circonus"
5 )
6
7 type circonusProvider struct {
8 c *circonus.Circonus
9 }
10
11 // NewCirconusProvider takes the given Circonnus object and returns a Provider
12 // that produces Circonus metrics.
13 func NewCirconusProvider(c *circonus.Circonus) Provider {
14 return &circonusProvider{
15 c: c,
16 }
17 }
18
19 // NewCounter implements Provider.
20 func (p *circonusProvider) NewCounter(name string) metrics.Counter {
21 return p.c.NewCounter(name)
22 }
23
24 // NewGauge implements Provider.
25 func (p *circonusProvider) NewGauge(name string) metrics.Gauge {
26 return p.c.NewGauge(name)
27 }
28
29 // NewHistogram implements Provider. The buckets parameter is ignored.
30 func (p *circonusProvider) NewHistogram(name string, _ int) metrics.Histogram {
31 return p.c.NewHistogram(name)
32 }
33
34 // Stop implements Provider, but is a no-op.
35 func (p *circonusProvider) Stop() {}