1 package pcp 2 3 import ( 4 "github.com/performancecopilot/speed/v4" 5 6 "github.com/go-kit/kit/metrics" 7 ) 8 9 // Reporter encapsulates a speed client. 10 type Reporter struct { 11 c *speed.PCPClient 12 } 13 14 // NewReporter creates a new Reporter instance. The first parameter is the 15 // application name and is used to create the speed client. Hence it should be a 16 // valid speed parameter name and should not contain spaces or the path 17 // separator for your operating system. 18 func NewReporter(appname string) (*Reporter, error) { 19 c, err := speed.NewPCPClient(appname) 20 if err != nil { 21 return nil, err 22 } 23 24 return &Reporter{c}, nil 25 } 26 27 // Start starts the underlying speed client so it can start reporting registered 28 // metrics to your PCP installation. 29 func (r *Reporter) Start() { r.c.MustStart() } 30 31 // Stop stops the underlying speed client so it can stop reporting registered 32 // metrics to your PCP installation. 33 func (r *Reporter) Stop() { r.c.MustStop() } 34 35 // Counter implements metrics.Counter via a single dimensional speed.Counter. 36 type Counter struct { 37 c speed.Counter 38 } 39 40 // NewCounter creates a new Counter. This requires a name parameter and can 41 // optionally take a couple of description strings, that are used to create the 42 // underlying speed.Counter and are reported by PCP. 43 func (r *Reporter) NewCounter(name string, desc ...string) (*Counter, error) { 44 c, err := speed.NewPCPCounter(0, name, desc...) 45 if err != nil { 46 return nil, err 47 } 48 49 r.c.MustRegister(c) 50 return &Counter{c}, nil 51 } 52 53 // With is a no-op. 54 func (c *Counter) With(labelValues ...string) metrics.Counter { return c } 55 56 // Add increments Counter. speed.Counters only take int64, so delta is converted 57 // to int64 before observation. 58 func (c *Counter) Add(delta float64) { c.c.Inc(int64(delta)) } 59 60 // Gauge implements metrics.Gauge via a single dimensional speed.Gauge. 61 type Gauge struct { 62 g speed.Gauge 63 } 64 65 // NewGauge creates a new Gauge. This requires a name parameter and can 66 // optionally take a couple of description strings, that are used to create the 67 // underlying speed.Gauge and are reported by PCP. 68 func (r *Reporter) NewGauge(name string, desc ...string) (*Gauge, error) { 69 g, err := speed.NewPCPGauge(0, name, desc...) 70 if err != nil { 71 return nil, err 72 } 73 74 r.c.MustRegister(g) 75 return &Gauge{g}, nil 76 } 77 78 // With is a no-op. 79 func (g *Gauge) With(labelValues ...string) metrics.Gauge { return g } 80 81 // Set sets the value of the gauge. 82 func (g *Gauge) Set(value float64) { g.g.Set(value) } 83 84 // Add adds a value to the gauge. 85 func (g *Gauge) Add(delta float64) { g.g.Inc(delta) } 86 87 // Histogram wraps a speed Histogram. 88 type Histogram struct { 89 h speed.Histogram 90 } 91 92 // NewHistogram creates a new Histogram. The minimum observeable value is 0. The 93 // maximum observeable value is 3600000000 (3.6e9). 94 // 95 // The required parameters are a metric name, the minimum and maximum observable 96 // values, and a metric unit for the units of the observed values. 97 // 98 // Optionally, it can also take a couple of description strings. 99 func (r *Reporter) NewHistogram(name string, min, max int64, unit speed.MetricUnit, desc ...string) (*Histogram, error) { 100 h, err := speed.NewPCPHistogram(name, min, max, 5, unit, desc...) 101 if err != nil { 102 return nil, err 103 } 104 105 r.c.MustRegister(h) 106 return &Histogram{h}, nil 107 } 108 109 // With is a no-op. 110 func (h *Histogram) With(labelValues ...string) metrics.Histogram { return h } 111 112 // Observe observes a value. 113 // 114 // This converts float64 value to int64 before observation, as the Histogram in 115 // speed is backed using codahale/hdrhistogram, which only observes int64 116 // values. Additionally, the value is interpreted in the metric unit used to 117 // construct the histogram. 118 func (h *Histogram) Observe(value float64) { h.h.MustRecord(int64(value)) } 119 120 // Mean returns the mean of the values observed so far by the Histogram. 121 func (h *Histogram) Mean() float64 { return h.h.Mean() } 122 123 // Percentile returns a percentile value for the given percentile 124 // between 0 and 100 for all values observed by the histogram. 125 func (h *Histogram) Percentile(p float64) int64 { return h.h.Percentile(p) } 126