Codebase list golang-github-go-kit-kit / 3aad148
Use WriteLoop approach to reduce api overhead. Cameron Stitt 7 years ago
1 changed file(s) with 50 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
22 import (
33 "sync"
44
5 "time"
6
7 "github.com/aws/aws-sdk-go/aws"
58 "github.com/aws/aws-sdk-go/service/cloudwatch"
69 "github.com/go-kit/kit/log"
710 "github.com/go-kit/kit/metrics"
1417 prefix string
1518 svc *cloudwatch.CloudWatch
1619 counters map[string]*Counter
17 //gauges map[string]*Gauge
18 //histograms map[string]*Histogram
19 logger log.Logger
20 logger log.Logger
2021 }
2122
23 // New ...
2224 func New(prefix string, logger log.Logger, svc *cloudwatch.CloudWatch) *CloudWatch {
2325 return &CloudWatch{
2426 prefix: prefix,
2931 }
3032
3133 func (cw *CloudWatch) NewCounter(name string) *Counter {
32 c := NewCounter(cw.prefix, name)
34 c := NewCounter(name)
3335 cw.mtx.Lock()
3436 cw.counters[cw.prefix+name] = c
3537 cw.mtx.Unlock()
3638 return c
3739 }
3840
39 // Counter is a Graphite counter metric.
41 // WriteLoop is a helper method that invokes WriteTo to the passed writer every
42 // time the passed channel fires. This method blocks until the channel is
43 // closed, so clients probably want to run it in its own goroutine. For typical
44 // usage, create a time.Ticker and pass its C channel to this method.
45 func (cw *CloudWatch) WriteLoop(c <-chan time.Time) {
46 for range c {
47 cw.mtx.RLock()
48 defer cw.mtx.RUnlock()
49 now := time.Now()
50
51 for name, c := range cw.counters {
52 _, err := cw.svc.PutMetricData(&cloudwatch.PutMetricDataInput{
53 Namespace: aws.String(cw.prefix),
54 MetricData: []*cloudwatch.MetricDatum{
55 {
56 MetricName: aws.String(name),
57 Dimensions: makeDimensions(c.c.LabelValues()...),
58 Value: aws.Float64(c.c.Value()),
59 Timestamp: aws.Time(now),
60 },
61 },
62 })
63 if err != nil {
64 cw.logger.Log("during", "WriteLoop", "err", err)
65 }
66 }
67 }
68 }
69
70 // Counter is a CloudWatch counter metric.
4071 type Counter struct {
41 namespace string
42 c *generic.Counter
72 c *generic.Counter
4373 }
4474
4575 // NewCounter returns a new usable counter metric.
46 func NewCounter(namespace, name string) *Counter {
76 func NewCounter(name string) *Counter {
4777 return &Counter{
48 namespace: namespace,
49 c: generic.NewCounter(name),
78 c: generic.NewCounter(name),
5079 }
5180 }
5281
5988 func (c *Counter) Add(delta float64) {
6089 c.c.Add(delta)
6190 }
91
92 func makeDimensions(labelValues ...string) []*cloudwatch.Dimension {
93 dimensions := make([]*cloudwatch.Dimension, len(labelValues)/2)
94 for i, j := 0, 0; i < len(labelValues); i, j := i+2, j+1 {
95 dimensions[j] = &cloudwatch.Dimension{
96 Name: aws.String(labelValues[i]),
97 Value: aws.String(labelValues[i+1]),
98 }
99 }
100 return dimensions
101 }