Codebase list golang-github-go-kit-kit / 6b32d24
applying a @peterbourgon patch: https://gist.github.com/peterbourgon/669cc7808a2fb37f008650106992807a JP Robinson 7 years ago
2 changed file(s) with 164 addition(s) and 72 deletion(s). Raw diff Collapse all Expand all
22 import (
33 "errors"
44 "time"
5
6 "github.com/prometheus/client_golang/prometheus"
57
68 "github.com/go-kit/kit/log"
79 "github.com/go-kit/kit/metrics"
911 "github.com/go-kit/kit/metrics/graphite"
1012 kitprom "github.com/go-kit/kit/metrics/prometheus"
1113 "github.com/go-kit/kit/metrics/statsd"
12 "github.com/prometheus/client_golang/prometheus"
1314 )
1415
1516 // Provider represents a union set of constructors and lifecycle management
16 // functions for each supported metrics backend. It should be used by those
17 // who need to easily swap out implementations, e.g. dynamically, or at a
18 // single point in an intermediating framework.
17 // functions for each supported metrics backend. It should be used by those who
18 // need to easily swap out implementations, e.g. dynamically, or at a single
19 // point in an intermediating framework.
1920 type Provider interface {
20 NewCounter(name string) metrics.Counter
21 NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error)
22 NewGauge(name string) metrics.Gauge
23
21 NewCounter(name, help string) metrics.Counter
22 NewHistogram(name, help string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error)
23 NewGauge(name, help string) metrics.Gauge
2424 Stop()
2525 }
2626
2727 // NewGraphiteProvider will return a Provider implementation that is a simple
28 // wrapper around a graphite.Emitter. All metrics names will get prefixed
29 // with the given value and data will be emitted once every interval.
30 // If no network value is given, it will get defaulted to "udp".
31 func NewGraphiteProvider(addr, network, prefix string, interval time.Duration, logger log.Logger) (Provider, error) {
32 if addr == "" {
33 return nil, errors.New("graphite server address is required")
34 }
28 // wrapper around a graphite.Emitter. All metric names will be prefixed with the
29 // given value and data will be emitted once every interval. If no network value
30 // is given, it will default to "udp".
31 func NewGraphiteProvider(network, address, prefix string, interval time.Duration, logger log.Logger) (Provider, error) {
3532 if network == "" {
3633 network = "udp"
3734 }
38 e := graphite.NewEmitter(addr, network, prefix, interval, logger)
39 return &graphiteProvider{Emitter: e}, nil
35 if address == "" {
36 return nil, errors.New("address is required")
37 }
38 return graphiteProvider{
39 e: graphite.NewEmitter(network, address, prefix, interval, logger),
40 }, nil
4041 }
4142
4243 type graphiteProvider struct {
43 *graphite.Emitter
44 e *graphite.Emitter
45 }
46
47 var _ Provider = graphiteProvider{}
48
49 // NewCounter implements Provider. Help is ignored.
50 func (p graphiteProvider) NewCounter(name, _ string) metrics.Counter {
51 return p.e.NewCounter(name)
52 }
53
54 // NewHistogram implements Provider. Help is ignored.
55 func (p graphiteProvider) NewHistogram(name, _ string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
56 return p.e.NewHistogram(name, min, max, sigfigs, quantiles...)
57 }
58
59 // NewGauge implements Provider. Help is ignored.
60 func (p graphiteProvider) NewGauge(name, _ string) metrics.Gauge {
61 return p.e.NewGauge(name)
62 }
63
64 // Stop implements Provider.
65 func (p graphiteProvider) Stop() {
66 p.e.Stop()
4467 }
4568
4669 // NewStatsdProvider will return a Provider implementation that is a simple
47 // wrapper around a statsd.Emitter. All metrics names will get prefixed
48 // with the given value and data will be emitted once every interval
49 // or when the buffer has reached its max size.
50 // If no network value is given, it will get defaulted to "udp".
51 func NewStatsdProvider(addr, network, prefix string, interval time.Duration, logger log.Logger) (Provider, error) {
52 if addr == "" {
53 return nil, errors.New("statsd server address is required")
54 }
70 // wrapper around a statsd.Emitter. All metric names will be prefixed with the
71 // given value and data will be emitted once every interval or when the buffer
72 // has reached its max size. If no network value is given, it will default to
73 // "udp".
74 func NewStatsdProvider(network, address, prefix string, interval time.Duration, logger log.Logger) (Provider, error) {
5575 if network == "" {
5676 network = "udp"
5777 }
58 e := statsd.NewEmitter(addr, network, prefix, interval, logger)
59 return &statsdProvider{e: e}, nil
78 if address == "" {
79 return nil, errors.New("address is required")
80 }
81 return statsdProvider{
82 e: statsd.NewEmitter(network, address, prefix, interval, logger),
83 }, nil
6084 }
6185
6286 type statsdProvider struct {
6387 e *statsd.Emitter
6488 }
6589
66 func (s *statsdProvider) NewCounter(name string) metrics.Counter {
67 return s.e.NewCounter(name)
90 var _ Provider = statsdProvider{}
91
92 // NewCounter implements Provider. Help is ignored.
93 func (p statsdProvider) NewCounter(name, _ string) metrics.Counter {
94 return p.e.NewCounter(name)
6895 }
6996
70 func (s *statsdProvider) NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
71 return s.e.NewHistogram(name), nil
97 // NewHistogram implements Provider. Help is ignored.
98 func (p statsdProvider) NewHistogram(name, _ string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
99 return p.e.NewHistogram(name), nil
72100 }
73101
74 func (s *statsdProvider) NewGauge(name string) metrics.Gauge {
75 return s.e.NewGauge(name)
102 // NewGauge implements Provider. Help is ignored.
103 func (p statsdProvider) NewGauge(name, _ string) metrics.Gauge {
104 return p.e.NewGauge(name)
76105 }
77106
78107 // Stop will call the underlying statsd.Emitter's Stop method.
79 func (s *statsdProvider) Stop() {
80 s.e.Stop()
108 func (p statsdProvider) Stop() {
109 p.e.Stop()
81110 }
82111
83112 // NewExpvarProvider is a very thin wrapper over the expvar package.
84 // If a prefix is provided, it will prefix in metric names.
113 // If a prefix is provided, it will prefix all metric names.
85114 func NewExpvarProvider(prefix string) Provider {
86 return &expvarProvider{prefix: prefix}
115 return expvarProvider{prefix: prefix}
87116 }
88117
89118 type expvarProvider struct {
90119 prefix string
91120 }
92121
93 func (e *expvarProvider) pref(name string) string {
94 return e.prefix + name
122 var _ Provider = expvarProvider{}
123
124 // NewCounter implements Provider. Help is ignored.
125 func (p expvarProvider) NewCounter(name, _ string) metrics.Counter {
126 return kitexp.NewCounter(p.prefix + name)
95127 }
96128
97 func (e *expvarProvider) NewCounter(name string) metrics.Counter {
98 return kitexp.NewCounter(e.pref(name))
129 // NewHistogram implements Provider. Help is ignored.
130 func (p expvarProvider) NewHistogram(name, _ string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
131 return kitexp.NewHistogram(p.prefix+name, min, max, sigfigs, quantiles...), nil
99132 }
100133
101 func (e *expvarProvider) NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
102 return kitexp.NewHistogram(e.pref(name), min, max, sigfigs, quantiles...), nil
103 }
104
105 func (e *expvarProvider) NewGauge(name string) metrics.Gauge {
106 return kitexp.NewGauge(e.pref(name))
134 // NewGauge implements Provider. Help is ignored.
135 func (p expvarProvider) NewGauge(name, _ string) metrics.Gauge {
136 return kitexp.NewGauge(p.prefix + name)
107137 }
108138
109139 // Stop is a no-op.
110 func (e *expvarProvider) Stop() {}
140 func (expvarProvider) Stop() {}
111141
112142 type prometheusProvider struct {
113 ns string
143 namespace string
144 subsystem string
114145 }
115146
116 // NewPrometheusProvider will use the given namespace
117 // for all metrics' Opts.
118 func NewPrometheusProvider(namespace string) Provider {
119 return &prometheusProvider{ns: namespace}
147 var _ Provider = prometheusProvider{}
148
149 // NewPrometheusProvider returns a Prometheus provider that uses the provided
150 // namespace and subsystem for all metrics. Help is not provided, which is very
151 // much against Prometheus guidelines. Therefore, avoid using the Prometheus
152 // provider unless it is absolutely necessary; prefer constructing Prometheus
153 // metrics directly.
154 func NewPrometheusProvider(namespace, subsystem string) Provider {
155 return prometheusProvider{
156 namespace: namespace,
157 subsystem: subsystem,
158 }
120159 }
121160
122 func (p *prometheusProvider) NewCounter(name string) metrics.Counter {
123 opts := prometheus.CounterOpts{
124 Namespace: p.ns,
161 // NewCounter implements Provider.
162 func (p prometheusProvider) NewCounter(name, help string) metrics.Counter {
163 return kitprom.NewCounter(prometheus.CounterOpts{
164 Namespace: p.namespace,
165 Subsystem: p.subsystem,
125166 Name: name,
126 }
127 return kitprom.NewCounter(opts, nil)
167 Help: help,
168 }, nil)
128169 }
129170
130 // NewHistogram ignores all NewHistogram parameters but `name`.
131 func (p *prometheusProvider) NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
132 opts := prometheus.HistogramOpts{
133 Namespace: p.ns,
171 // NewHistogram ignores all parameters except name and help.
172 func (p prometheusProvider) NewHistogram(name, help string, _, _ int64, _ int, _ ...int) (metrics.Histogram, error) {
173 return kitprom.NewHistogram(prometheus.HistogramOpts{
174 Namespace: p.namespace,
175 Subsystem: p.subsystem,
134176 Name: name,
135 }
136 return kitprom.NewHistogram(opts, nil), nil
177 Help: help,
178 }, nil), nil
137179 }
138180
139 func (p *prometheusProvider) NewGauge(name string) metrics.Gauge {
140 opts := prometheus.GaugeOpts{
141 Namespace: p.ns,
181 // NewGauge implements Provider.
182 func (p prometheusProvider) NewGauge(name, help string) metrics.Gauge {
183 return kitprom.NewGauge(prometheus.GaugeOpts{
184 Namespace: p.namespace,
185 Subsystem: p.subsystem,
142186 Name: name,
143 }
144 return kitprom.NewGauge(opts, nil)
187 Help: help,
188 }, nil)
145189 }
146190
147 // Stop is a no-op
148 func (p *prometheusProvider) Stop() {}
191 // Stop is a no-op.
192 func (prometheusProvider) Stop() {}
0 package provider
1
2 import (
3 "testing"
4 "time"
5
6 "github.com/go-kit/kit/log"
7 )
8
9 func TestGraphite(t *testing.T) {
10 p, err := NewGraphiteProvider("network", "address", "prefix", time.Second, log.NewNopLogger())
11 if err != nil {
12 t.Fatal(err)
13 }
14 testProvider(t, "Graphite", p)
15 }
16
17 func TestStatsd(t *testing.T) {
18 p, err := NewStatsdProvider("network", "address", "prefix", time.Second, log.NewNopLogger())
19 if err != nil {
20 t.Fatal(err)
21 }
22 testProvider(t, "Statsd", p)
23 }
24
25 func TestExpvar(t *testing.T) {
26 testProvider(t, "Expvar", NewExpvarProvider("prefix"))
27 }
28
29 func TestPrometheus(t *testing.T) {
30 testProvider(t, "Prometheus", NewPrometheusProvider("namespace", "subsystem"))
31 }
32
33 func testProvider(t *testing.T, what string, p Provider) {
34 c := p.NewCounter("counter", "Counter help.")
35 c.Add(1)
36
37 h, err := p.NewHistogram("histogram", "Histogram help.", 1, 100, 3, 50, 95, 99)
38 if err != nil {
39 t.Errorf("%s: NewHistogram: %v", what, err)
40 }
41 h.Observe(99)
42
43 g := p.NewGauge("gauge", "Gauge help.")
44 g.Set(123)
45
46 p.Stop()
47 }