Reimplement package multi
Peter Bourgon
7 years ago
0 | // Package multi provides adapters that send observations to multiple metrics | |
1 | // simultaneously. This is useful if your service needs to emit to multiple | |
2 | // instrumentation systems at the same time, for example if your organization is | |
3 | // transitioning from one system to another. | |
4 | package multi | |
5 | ||
6 | import "github.com/go-kit/kit/metrics" | |
7 | ||
8 | // Counter collects multiple individual counters and treats them as a unit. | |
9 | type Counter []metrics.Counter | |
10 | ||
11 | // NewCounter returns a multi-counter, wrapping the passed counters. | |
12 | func NewCounter(c ...metrics.Counter) Counter { | |
13 | return Counter(c) | |
14 | } | |
15 | ||
16 | // Add implements counter. | |
17 | func (c Counter) Add(delta float64) { | |
18 | for _, counter := range c { | |
19 | counter.Add(delta) | |
20 | } | |
21 | } | |
22 | ||
23 | // With implements counter. | |
24 | func (c Counter) With(labelValues ...string) metrics.Counter { | |
25 | next := make(Counter, len(c)) | |
26 | for i := range c { | |
27 | next[i] = c[i].With(labelValues...) | |
28 | } | |
29 | return next | |
30 | } | |
31 | ||
32 | // Gauge collects multiple individual gauges and treats them as a unit. | |
33 | type Gauge []metrics.Gauge | |
34 | ||
35 | // NewGauge returns a multi-gauge, wrapping the passed gauges. | |
36 | func NewGauge(g ...metrics.Gauge) Gauge { | |
37 | return Gauge(g) | |
38 | } | |
39 | ||
40 | // Set implements Gauge. | |
41 | func (g Gauge) Set(value float64) { | |
42 | for _, gauge := range g { | |
43 | gauge.Set(value) | |
44 | } | |
45 | } | |
46 | ||
47 | // With implements gauge. | |
48 | func (g Gauge) With(labelValues ...string) metrics.Gauge { | |
49 | next := make(Gauge, len(g)) | |
50 | for i := range g { | |
51 | next[i] = g[i].With(labelValues...) | |
52 | } | |
53 | return next | |
54 | } | |
55 | ||
56 | // Histogram collects multiple individual histograms and treats them as a unit. | |
57 | type Histogram []metrics.Histogram | |
58 | ||
59 | // NewHistogram returns a multi-histogram, wrapping the passed histograms. | |
60 | func NewHistogram(h ...metrics.Histogram) Histogram { | |
61 | return Histogram(h) | |
62 | } | |
63 | ||
64 | // Observe implements Histogram. | |
65 | func (h Histogram) Observe(value float64) { | |
66 | for _, histogram := range h { | |
67 | histogram.Observe(value) | |
68 | } | |
69 | } | |
70 | ||
71 | // With implements histogram. | |
72 | func (h Histogram) With(labelValues ...string) metrics.Histogram { | |
73 | next := make(Histogram, len(h)) | |
74 | for i := range h { | |
75 | next[i] = h[i].With(labelValues...) | |
76 | } | |
77 | return next | |
78 | } |
0 | package multi | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "testing" | |
5 | ||
6 | "github.com/go-kit/kit/metrics" | |
7 | ) | |
8 | ||
9 | func TestMultiCounter(t *testing.T) { | |
10 | c1 := &mockCounter{} | |
11 | c2 := &mockCounter{} | |
12 | c3 := &mockCounter{} | |
13 | mc := NewCounter(c1, c2, c3) | |
14 | ||
15 | mc.Add(123) | |
16 | mc.Add(456) | |
17 | ||
18 | want := "[123 456]" | |
19 | for i, m := range []fmt.Stringer{c1, c2, c3} { | |
20 | if have := m.String(); want != have { | |
21 | t.Errorf("c%d: want %q, have %q", i+1, want, have) | |
22 | } | |
23 | } | |
24 | } | |
25 | ||
26 | func TestMultiGauge(t *testing.T) { | |
27 | g1 := &mockGauge{} | |
28 | g2 := &mockGauge{} | |
29 | g3 := &mockGauge{} | |
30 | mg := NewGauge(g1, g2, g3) | |
31 | ||
32 | mg.Set(9) | |
33 | mg.Set(8) | |
34 | mg.Set(7) | |
35 | ||
36 | want := "[9 8 7]" | |
37 | for i, m := range []fmt.Stringer{g1, g2, g3} { | |
38 | if have := m.String(); want != have { | |
39 | t.Errorf("g%d: want %q, have %q", i+1, want, have) | |
40 | } | |
41 | } | |
42 | } | |
43 | ||
44 | func TestMultiHistogram(t *testing.T) { | |
45 | h1 := &mockHistogram{} | |
46 | h2 := &mockHistogram{} | |
47 | h3 := &mockHistogram{} | |
48 | mh := NewHistogram(h1, h2, h3) | |
49 | ||
50 | mh.Observe(1) | |
51 | mh.Observe(2) | |
52 | mh.Observe(4) | |
53 | mh.Observe(8) | |
54 | ||
55 | want := "[1 2 4 8]" | |
56 | for i, m := range []fmt.Stringer{h1, h2, h3} { | |
57 | if have := m.String(); want != have { | |
58 | t.Errorf("g%d: want %q, have %q", i+1, want, have) | |
59 | } | |
60 | } | |
61 | } | |
62 | ||
63 | type mockCounter struct { | |
64 | obs []float64 | |
65 | } | |
66 | ||
67 | func (c *mockCounter) Add(delta float64) { c.obs = append(c.obs, delta) } | |
68 | func (c *mockCounter) With(...string) metrics.Counter { return c } | |
69 | func (c *mockCounter) String() string { return fmt.Sprintf("%v", c.obs) } | |
70 | ||
71 | type mockGauge struct { | |
72 | obs []float64 | |
73 | } | |
74 | ||
75 | func (g *mockGauge) Set(value float64) { g.obs = append(g.obs, value) } | |
76 | func (g *mockGauge) With(...string) metrics.Gauge { return g } | |
77 | func (g *mockGauge) String() string { return fmt.Sprintf("%v", g.obs) } | |
78 | ||
79 | type mockHistogram struct { | |
80 | obs []float64 | |
81 | } | |
82 | ||
83 | func (h *mockHistogram) Observe(value float64) { h.obs = append(h.obs, value) } | |
84 | func (h *mockHistogram) With(...string) metrics.Histogram { return h } | |
85 | func (h *mockHistogram) String() string { return fmt.Sprintf("%v", h.obs) } |