Codebase list golang-github-go-kit-kit / e049844
Merge pull request #363 from suyash/pcp-go-kit-pr metrics: add support for PCP Peter Bourgon authored 7 years ago GitHub committed 7 years ago
3 changed file(s) with 205 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
5454 // influx n custom custom custom
5555 // prometheus n native native native
5656 // circonus 1 native native native
57 // pcp 1 native native native
5758 //
5859 package metrics
0 package pcp
1
2 import (
3 "github.com/performancecopilot/speed"
4
5 "github.com/go-kit/kit/metrics"
6 )
7
8 // Reporter encapsulates a speed client.
9 type Reporter struct {
10 c *speed.PCPClient
11 }
12
13 // NewReporter creates a new Reporter instance.
14 // The first parameter is the application name and is used to create
15 // the speed client. Hence it should be a valid speed parameter name and
16 // should not contain spaces or the path separator for your operating system.
17 func NewReporter(appname string) (*Reporter, error) {
18 c, err := speed.NewPCPClient(appname)
19 if err != nil {
20 return nil, err
21 }
22
23 return &Reporter{c}, nil
24 }
25
26 // Start starts the underlying speed client so it can start reporting registered
27 // metrics to your PCP installation.
28 func (r *Reporter) Start() { r.c.MustStart() }
29
30 // Stop stops the underlying speed client so it can stop reporting registered
31 // metrics to your PCP installation.
32 func (r *Reporter) Stop() { r.c.MustStop() }
33
34 // Counter implements metrics.Counter via a single dimensional speed.Counter.
35 type Counter struct {
36 c speed.Counter
37 }
38
39 // NewCounter creates a new Counter.
40 //
41 // This requires a name parameter and can optionally take a couple of
42 // description strings, that are used to create the underlying speed.Counter
43 // and are reported by PCP.
44 func (r *Reporter) NewCounter(name string, desc ...string) (*Counter, error) {
45 c, err := speed.NewPCPCounter(0, name, desc...)
46 if err != nil {
47 return nil, err
48 }
49
50 r.c.MustRegister(c)
51 return &Counter{c}, nil
52 }
53
54 // With is a no-op.
55 func (c *Counter) With(labelValues ...string) metrics.Counter { return c }
56
57 // Add increments Counter.
58 // speed Counters only take int64, so delta is converted to int64 before
59 // observation. speed Gauges can take float64 and `Add(float64)`
60 // is implemented by metrics.Gauge.
61 func (c *Counter) Add(delta float64) { c.c.Inc(int64(delta)) }
62
63 // Gauge implements metrics.Gauge via a single dimensional speed.Gauge.
64 type Gauge struct {
65 g speed.Gauge
66 }
67
68 // NewGauge creates a new Gauge.
69 //
70 // This requires a name parameter, and again, can take a couple of
71 // optional description strings.
72 func (r *Reporter) NewGauge(name string, desc ...string) (*Gauge, error) {
73 g, err := speed.NewPCPGauge(0, name, desc...)
74 if err != nil {
75 return nil, err
76 }
77
78 r.c.MustRegister(g)
79 return &Gauge{g}, nil
80 }
81
82 // With is a no-op.
83 func (g *Gauge) With(labelValues ...string) metrics.Gauge { return g }
84
85 // Set sets the value of the gauge.
86 func (g *Gauge) Set(value float64) { g.g.Set(value) }
87
88 // Add adds a value to the gauge.
89 func (g *Gauge) Add(value float64) { g.g.Inc(value) }
90
91 // Histogram wraps a speed Histogram.
92 type Histogram struct {
93 h speed.Histogram
94 }
95
96 // NewHistogram creates a new Histogram.
97 // Minimum observeable value is 0.
98 // Maximum observeable value is 3600000000.
99 //
100 // The required parameters are a metric name,
101 // the minimum and maximum observable values,
102 // and a metric unit for the units of the observed values.
103 //
104 // Optionally, it can also take a couple of description strings.
105 func (r *Reporter) NewHistogram(name string, min, max int64, unit speed.MetricUnit, desc ...string) (*Histogram, error) {
106 h, err := speed.NewPCPHistogram(name, min, max, 5, unit, desc...)
107 if err != nil {
108 return nil, err
109 }
110
111 r.c.MustRegister(h)
112 return &Histogram{h}, nil
113 }
114
115 // With is a no-op.
116 func (h *Histogram) With(labelValues ...string) metrics.Histogram { return h }
117
118 // Observe observes a value.
119 //
120 // This converts float64 value to int64 before observation, as the Histogram in
121 // speed is backed using codahale/hdrhistogram, which only observes int64
122 // values. Additionally, the value is interpreted in the metric unit used to
123 // construct the histogram.
124 func (h *Histogram) Observe(value float64) { h.h.MustRecord(int64(value)) }
125
126 // Mean returns the mean of the values observed so far by the Histogram.
127 func (h *Histogram) Mean() float64 { return h.h.Mean() }
128
129 // Percentile returns a percentile value for the given percentile
130 // between 0 and 100 for all values observed by the histogram.
131 func (h *Histogram) Percentile(p float64) int64 { return h.h.Percentile(p) }
0 package pcp
1
2 import (
3 "testing"
4
5 "github.com/performancecopilot/speed"
6
7 "github.com/go-kit/kit/metrics/teststat"
8 )
9
10 func TestCounter(t *testing.T) {
11 r, err := NewReporter("test_counter")
12 if err != nil {
13 t.Fatal(err)
14 }
15
16 counter, err := r.NewCounter("speed_counter")
17 if err != nil {
18 t.Fatal(err)
19 }
20
21 counter = counter.With("label values", "not supported").(*Counter)
22
23 value := func() float64 { f := counter.c.Val(); return float64(f) }
24 if err := teststat.TestCounter(counter, value); err != nil {
25 t.Fatal(err)
26 }
27 }
28
29 func TestGauge(t *testing.T) {
30 r, err := NewReporter("test_gauge")
31 if err != nil {
32 t.Fatal(err)
33 }
34
35 gauge, err := r.NewGauge("speed_gauge")
36 if err != nil {
37 t.Fatal(err)
38 }
39
40 gauge = gauge.With("label values", "not supported").(*Gauge)
41
42 value := func() float64 { f := gauge.g.Val(); return f }
43 if err := teststat.TestGauge(gauge, value); err != nil {
44 t.Fatal(err)
45 }
46 }
47
48 func TestHistogram(t *testing.T) {
49 r, err := NewReporter("test_histogram")
50 if err != nil {
51 t.Fatal(err)
52 }
53
54 histogram, err := r.NewHistogram("speed_histogram", 0, 3600000000, speed.OneUnit)
55 if err != nil {
56 t.Fatal(err)
57 }
58
59 histogram = histogram.With("label values", "not supported").(*Histogram)
60
61 quantiles := func() (float64, float64, float64, float64) {
62 p50 := float64(histogram.Percentile(50))
63 p90 := float64(histogram.Percentile(90))
64 p95 := float64(histogram.Percentile(95))
65 p99 := float64(histogram.Percentile(99))
66 return p50, p90, p95, p99
67 }
68 if err := teststat.TestHistogram(histogram, quantiles, 0.01); err != nil {
69 t.Fatal(err)
70 }
71 }