2 | 2 |
import (
|
3 | 3 |
"errors"
|
4 | 4 |
"time"
|
|
5 |
|
|
6 |
"github.com/prometheus/client_golang/prometheus"
|
5 | 7 |
|
6 | 8 |
"github.com/go-kit/kit/log"
|
7 | 9 |
"github.com/go-kit/kit/metrics"
|
|
9 | 11 |
"github.com/go-kit/kit/metrics/graphite"
|
10 | 12 |
kitprom "github.com/go-kit/kit/metrics/prometheus"
|
11 | 13 |
"github.com/go-kit/kit/metrics/statsd"
|
12 | |
"github.com/prometheus/client_golang/prometheus"
|
13 | 14 |
)
|
14 | 15 |
|
15 | 16 |
// 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.
|
19 | 20 |
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
|
24 | 24 |
Stop()
|
25 | 25 |
}
|
26 | 26 |
|
27 | 27 |
// 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) {
|
35 | 32 |
if network == "" {
|
36 | 33 |
network = "udp"
|
37 | 34 |
}
|
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
|
40 | 41 |
}
|
41 | 42 |
|
42 | 43 |
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()
|
44 | 67 |
}
|
45 | 68 |
|
46 | 69 |
// 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) {
|
55 | 75 |
if network == "" {
|
56 | 76 |
network = "udp"
|
57 | 77 |
}
|
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
|
60 | 84 |
}
|
61 | 85 |
|
62 | 86 |
type statsdProvider struct {
|
63 | 87 |
e *statsd.Emitter
|
64 | 88 |
}
|
65 | 89 |
|
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)
|
68 | 95 |
}
|
69 | 96 |
|
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
|
72 | 100 |
}
|
73 | 101 |
|
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)
|
76 | 105 |
}
|
77 | 106 |
|
78 | 107 |
// 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()
|
81 | 110 |
}
|
82 | 111 |
|
83 | 112 |
// 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.
|
85 | 114 |
func NewExpvarProvider(prefix string) Provider {
|
86 | |
return &expvarProvider{prefix: prefix}
|
|
115 |
return expvarProvider{prefix: prefix}
|
87 | 116 |
}
|
88 | 117 |
|
89 | 118 |
type expvarProvider struct {
|
90 | 119 |
prefix string
|
91 | 120 |
}
|
92 | 121 |
|
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)
|
95 | 127 |
}
|
96 | 128 |
|
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
|
99 | 132 |
}
|
100 | 133 |
|
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)
|
107 | 137 |
}
|
108 | 138 |
|
109 | 139 |
// Stop is a no-op.
|
110 | |
func (e *expvarProvider) Stop() {}
|
|
140 |
func (expvarProvider) Stop() {}
|
111 | 141 |
|
112 | 142 |
type prometheusProvider struct {
|
113 | |
ns string
|
|
143 |
namespace string
|
|
144 |
subsystem string
|
114 | 145 |
}
|
115 | 146 |
|
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 |
}
|
120 | 159 |
}
|
121 | 160 |
|
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,
|
125 | 166 |
Name: name,
|
126 | |
}
|
127 | |
return kitprom.NewCounter(opts, nil)
|
|
167 |
Help: help,
|
|
168 |
}, nil)
|
128 | 169 |
}
|
129 | 170 |
|
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,
|
134 | 176 |
Name: name,
|
135 | |
}
|
136 | |
return kitprom.NewHistogram(opts, nil), nil
|
|
177 |
Help: help,
|
|
178 |
}, nil), nil
|
137 | 179 |
}
|
138 | 180 |
|
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,
|
142 | 186 |
Name: name,
|
143 | |
}
|
144 | |
return kitprom.NewGauge(opts, nil)
|
|
187 |
Help: help,
|
|
188 |
}, nil)
|
145 | 189 |
}
|
146 | 190 |
|
147 | |
// Stop is a no-op
|
148 | |
func (p *prometheusProvider) Stop() {}
|
|
191 |
// Stop is a no-op.
|
|
192 |
func (prometheusProvider) Stop() {}
|