Codebase list golang-github-go-kit-kit / 74c47d6
[wip] initial providers commit JP Robinson 7 years ago
1 changed file(s) with 176 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 package provider
1
2 import (
3 "errors"
4 "net"
5 "time"
6
7 "github.com/go-kit/kit/log"
8 "github.com/go-kit/kit/metrics"
9 kitexp "github.com/go-kit/kit/metrics/expvar"
10 "github.com/go-kit/kit/metrics/graphite"
11 kitprom "github.com/go-kit/kit/metrics/prometheus"
12 "github.com/go-kit/kit/metrics/statsd"
13 "github.com/prometheus/client_golang/prometheus"
14 )
15
16 // Provider represents a union set of constructors and lifecycle management
17 // functions for each supported metrics backend. It should be used by those
18 // who need to easily swap out implementations, e.g. dynamically, or at a
19 // single point in an intermediating framework.
20 type Provider interface {
21 NewCounter(name string) metrics.Counter
22 NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error)
23 NewGauge(name string) metrics.Gauge
24
25 Stop()
26 }
27
28 // NewGraphiteProvider will return a Provider implementation that is a simple
29 // wrapper around a graphite.Emitter. All metrics names will get prefixed
30 // with the given value and data will be emitted once every interval.
31 func NewGraphiteProvider(addr, net, prefix string, interval time.Duration, logger log.Logger) (Provider, error) {
32 if addr == "" {
33 return nil, errors.New("graphite server address is required")
34 }
35 if net == "" {
36 net = "udp"
37 }
38 // nop logger for now :\
39 e := graphite.NewEmitter(addr, net, prefix, interval, logger)
40 return &graphiteProvider{Emitter: e}, nil
41 }
42
43 type graphiteProvider struct {
44 *graphite.Emitter
45 }
46
47 // NewStatsdProvider will create a UDP connection for each metric
48 // with the given address. All metrics will use the given interval
49 // and, if a prefix is provided, it will be included in metric names
50 // with this format:
51 // "prefix.name"
52 func NewStatsdProvider(addr, prefix string, interval time.Duration, logger log.Logger) (Provider, error) {
53 return &statsdProvider{addr: addr, prefix: prefix, interval: interval}, nil
54 }
55
56 type statsdProvider struct {
57 addr string
58
59 interval time.Duration
60 prefix string
61
62 logger log.Logger
63 }
64
65 func (s *statsdProvider) conn() (net.Conn, error) {
66 return net.Dial("udp", s.addr)
67 }
68
69 func (s *statsdProvider) pref(name string) string {
70 if len(s.prefix) > 0 {
71 return s.prefix + "." + name
72 }
73 return name
74 }
75
76 func (s *statsdProvider) NewCounter(name string) metrics.Counter {
77 conn, err := s.conn()
78 if err != nil {
79 s.logger.Log("during", "new counter", "err", err)
80 return nil
81 }
82 return statsd.NewCounter(conn, s.pref(name), s.interval)
83 }
84
85 func (s *statsdProvider) NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
86 conn, err := s.conn()
87 if err != nil {
88 return nil, err
89 }
90 return statsd.NewHistogram(conn, s.pref(name), s.interval), nil
91 }
92
93 func (s *statsdProvider) NewGauge(name string) metrics.Gauge {
94 conn, err := s.conn()
95 if err != nil {
96 s.logger.Log("during", "new gauge", "err", err)
97 return nil
98 }
99 return statsd.NewGauge(conn, s.pref(name), s.interval)
100 }
101
102 // Stop is a no-op (should we try to close the UDP connections here?)
103 func (s *statsdProvider) Stop() {}
104
105 // NewExpvarProvider is a very thin wrapper over the expvar package.
106 // If a prefix is provided, it will be included in metric names with this
107 // format:
108 // "prefix.name"
109 func NewExpvarProvider(prefix string) Provider {
110 return &expvarProvider{prefix: prefix}
111 }
112
113 type expvarProvider struct {
114 prefix string
115 }
116
117 func (e *expvarProvider) pref(name string) string {
118 if len(e.prefix) > 0 {
119 return e.prefix + "." + name
120 }
121 return name
122 }
123
124 func (e *expvarProvider) NewCounter(name string) metrics.Counter {
125 return kitexp.NewCounter(e.pref(name))
126 }
127
128 func (e *expvarProvider) NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
129 return kitexp.NewHistogram(e.pref(name), min, max, sigfigs, quantiles...), nil
130 }
131
132 func (e *expvarProvider) NewGauge(name string) metrics.Gauge {
133 return kitexp.NewGauge(e.pref(name))
134 }
135
136 // Stop is a no-op.
137 func (e *expvarProvider) Stop() {}
138
139 type prometheusProvider struct {
140 ns string
141 }
142
143 // NewPrometheusProvider will use the given namespace
144 // for all metrics' Opts.
145 func NewPrometheusProvider(namespace string) Provider {
146 return &prometheusProvider{ns: namespace}
147 }
148
149 func (p *prometheusProvider) NewCounter(name string) metrics.Counter {
150 opts := prometheus.CounterOpts{
151 Namespace: p.ns,
152 Name: name,
153 }
154 return kitprom.NewCounter(opts, nil)
155 }
156
157 // NewHistogram ignores all NewHistogram parameters but `name`.
158 func (p *prometheusProvider) NewHistogram(name string, min, max int64, sigfigs int, quantiles ...int) (metrics.Histogram, error) {
159 opts := prometheus.HistogramOpts{
160 Namespace: p.ns,
161 Name: name,
162 }
163 return kitprom.NewHistogram(opts, nil), nil
164 }
165
166 func (p *prometheusProvider) NewGauge(name string) metrics.Gauge {
167 opts := prometheus.GaugeOpts{
168 Namespace: p.ns,
169 Name: name,
170 }
171 return kitprom.NewGauge(opts, nil)
172 }
173
174 // Stop is a no-op
175 func (p *prometheusProvider) Stop() {}