Codebase list golang-github-go-kit-kit / f7bcf6a
Add histogram instrument. Update WriteLoop to put all metrics at once. Cameron Stitt 6 years ago
1 changed file(s) with 88 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
33 "sync"
44
55 "time"
6
7 "strconv"
8
9 "fmt"
610
711 "github.com/aws/aws-sdk-go/aws"
812 "github.com/aws/aws-sdk-go/service/cloudwatch"
1317
1418 // CloudWatch ...
1519 type CloudWatch struct {
16 mtx sync.RWMutex
17 prefix string
18 svc *cloudwatch.CloudWatch
19 counters map[string]*Counter
20 gauges map[string]*Gauge
21 logger log.Logger
20 mtx sync.RWMutex
21 namespace string
22 svc *cloudwatch.CloudWatch
23 counters map[string]*Counter
24 gauges map[string]*Gauge
25 histograms map[string]*Histogram
26 logger log.Logger
2227 }
2328
2429 // New ...
25 func New(prefix string, logger log.Logger, svc *cloudwatch.CloudWatch) *CloudWatch {
30 func New(namespace string, logger log.Logger, svc *cloudwatch.CloudWatch) *CloudWatch {
2631 return &CloudWatch{
27 prefix: prefix,
28 svc: svc,
29 counters: map[string]*Counter{},
30 gauges: map[string]*Gauge{},
31 logger: logger,
32 namespace: namespace,
33 svc: svc,
34 counters: map[string]*Counter{},
35 gauges: map[string]*Gauge{},
36 histograms: map[string]*Histogram{},
37 logger: logger,
3238 }
3339 }
3440
3541 func (cw *CloudWatch) NewCounter(name string) *Counter {
3642 c := NewCounter(name)
3743 cw.mtx.Lock()
38 cw.counters[cw.prefix+name] = c
44 cw.counters[name] = c
3945 cw.mtx.Unlock()
4046 return c
4147 }
4248
4349 func (cw *CloudWatch) NewGauge(name string) *Gauge {
44 c := NewGauge(name)
50 g := NewGauge(name)
4551 cw.mtx.Lock()
46 cw.counters[cw.prefix+name] = c
52 cw.gauges[name] = g
4753 cw.mtx.Unlock()
48 return c
54 return g
55 }
56
57 func (cw *CloudWatch) NewHistogram(name string, quantiles []float64, buckets int) *Histogram {
58 h := NewHistogram(name, quantiles, buckets)
59 cw.mtx.Lock()
60 cw.histograms[name] = h
61 cw.mtx.Unlock()
62 return h
4963 }
5064
5165 // WriteLoop is a helper method that invokes WriteTo to the passed writer every
5872 defer cw.mtx.RUnlock()
5973 now := time.Now()
6074
75 datums := []*cloudwatch.MetricDatum{}
76
6177 for name, c := range cw.counters {
62 _, err := cw.svc.PutMetricData(&cloudwatch.PutMetricDataInput{
63 Namespace: aws.String(cw.prefix),
64 MetricData: []*cloudwatch.MetricDatum{
65 {
66 MetricName: aws.String(name),
67 Dimensions: makeDimensions(c.c.LabelValues()...),
68 Value: aws.Float64(c.c.Value()),
69 Timestamp: aws.Time(now),
70 },
71 },
78 datums = append(datums, &cloudwatch.MetricDatum{
79 MetricName: aws.String(name),
80 Dimensions: makeDimensions(c.c.LabelValues()...),
81 Value: aws.Float64(c.c.Value()),
82 Timestamp: aws.Time(now),
7283 })
73 if err != nil {
74 cw.logger.Log("during", "WriteLoop", "err", err)
84 }
85
86 for name, g := range cw.gauges {
87 datums = append(datums, &cloudwatch.MetricDatum{
88 MetricName: aws.String(name),
89 Dimensions: makeDimensions(g.g.LabelValues()...),
90 Value: aws.Float64(g.g.Value()),
91 Timestamp: aws.Time(now),
92 })
93 }
94
95 for name, h := range cw.histograms {
96 for _, quantile := range h.quantiles {
97 quantileStr := strconv.FormatFloat(quantile, 'f', 2, 64)
98 datums = append(datums, &cloudwatch.MetricDatum{
99 MetricName: aws.String(fmt.Sprintf("%s_%s", name, quantileStr)),
100 Dimensions: makeDimensions(h.h.LabelValues()...),
101 Value: aws.Float64(h.h.Quantile(quantile)),
102 Timestamp: aws.Time(now),
103 })
75104 }
76105 }
77106
78 for name, g := range cw.gauges {
79 _, err := cw.svc.PutMetricData(&cloudwatch.PutMetricDataInput{
80 Namespace: aws.String(cw.prefix),
81 MetricData: []*cloudwatch.MetricDatum{
82 {
83 MetricName: aws.String(name),
84 Dimensions: makeDimensions(g.g.LabelValues()...),
85 Value: aws.Float64(g.g.Value()),
86 Timestamp: aws.Time(now),
87 },
88 },
89 })
90 if err != nil {
91 cw.logger.Log("during", "WriteLoop", "err", err)
92 }
107 _, err := cw.svc.PutMetricData(&cloudwatch.PutMetricDataInput{
108 Namespace: aws.String(cw.namespace),
109 MetricData: datums,
110 })
111 if err != nil {
112 cw.logger.Log("during", "WriteLoop", "err", err)
93113 }
94114 }
95115 }
130150
131151 func (g *Gauge) With(labelValues ...string) metrics.Gauge {
132152 return &Gauge{
133 g: g.g.With(labelValues...),
153 g: g.g.With(labelValues...).(*generic.Gauge),
134154 }
135155 }
136156
140160
141161 func (g *Gauge) Add(delta float64) {
142162 g.g.Add(delta)
163 }
164
165 // Histogram is a CloudWatch histogram metric
166 type Histogram struct {
167 quantiles []float64
168 h *generic.Histogram
169 }
170
171 // NewHistogram returns a new usable histogram metric
172 func NewHistogram(name string, quantiles []float64, buckets int) *Histogram {
173 return &Histogram{
174 quantiles: quantiles,
175 h: generic.NewHistogram(name, buckets),
176 }
177 }
178
179 func (h *Histogram) With(labelValues ...string) metrics.Histogram {
180 return &Histogram{
181 h: h.h.With(labelValues...).(*generic.Histogram),
182 }
183 }
184
185 func (h *Histogram) Observe(value float64) {
186 h.h.Observe(value)
143187 }
144188
145189 func makeDimensions(labelValues ...string) []*cloudwatch.Dimension {