19 | 19 |
//
|
20 | 20 |
// To regularly report metrics to CloudWatch, use the WriteLoop helper method.
|
21 | 21 |
type CloudWatch struct {
|
22 | |
mtx sync.RWMutex
|
23 | |
namespace string
|
24 | |
svc cloudwatchiface.CloudWatchAPI
|
25 | |
counters map[string]*counter
|
26 | |
gauges map[string]*gauge
|
27 | |
histograms map[string]*histogram
|
28 | |
logger log.Logger
|
|
22 |
mtx sync.RWMutex
|
|
23 |
namespace string
|
|
24 |
numConcurrentRequests int
|
|
25 |
svc cloudwatchiface.CloudWatchAPI
|
|
26 |
counters map[string]*counter
|
|
27 |
gauges map[string]*gauge
|
|
28 |
histograms map[string]*histogram
|
|
29 |
logger log.Logger
|
29 | 30 |
}
|
30 | 31 |
|
31 | 32 |
// New returns a CloudWatch object that may be used to create metrics.
|
|
34 | 35 |
// manually or with one of the helper methods.
|
35 | 36 |
func New(namespace string, svc cloudwatchiface.CloudWatchAPI, logger log.Logger) *CloudWatch {
|
36 | 37 |
return &CloudWatch{
|
37 | |
namespace: namespace,
|
|
38 |
namespace: namespace,
|
|
39 |
numConcurrentRequests: 10,
|
38 | 40 |
svc: svc,
|
39 | 41 |
counters: map[string]*counter{},
|
40 | 42 |
gauges: map[string]*gauge{},
|
41 | 43 |
histograms: map[string]*histogram{},
|
42 | 44 |
logger: logger,
|
43 | 45 |
}
|
|
46 |
}
|
|
47 |
|
|
48 |
// SetConcurrency overrides the default number (10) of concurrent requests sent to CloudWatch.
|
|
49 |
// CloudWatch allows a maximum of 20 metrics to be sent per request, so when Send is called,
|
|
50 |
// we partition the metrics and concurrently call their API. This parameter sets maximum number
|
|
51 |
// of concurrent requests.
|
|
52 |
func (cw *CloudWatch) SetConcurrency(numConcurrentRequests int) *CloudWatch {
|
|
53 |
cw.numConcurrentRequests = numConcurrentRequests
|
|
54 |
return cw
|
44 | 55 |
}
|
45 | 56 |
|
46 | 57 |
// NewCounter returns a counter. Observations are aggregated and emitted once
|
|
132 | 143 |
}
|
133 | 144 |
}
|
134 | 145 |
|
135 | |
_, err := cw.svc.PutMetricData(&cloudwatch.PutMetricDataInput{
|
136 | |
Namespace: aws.String(cw.namespace),
|
137 | |
MetricData: datums,
|
138 | |
})
|
139 | |
return err
|
|
146 |
var tokens = make(chan struct{}, cw.numConcurrentRequests)
|
|
147 |
var errors = make(chan error)
|
|
148 |
var n int
|
|
149 |
|
|
150 |
for len(datums) > 0 {
|
|
151 |
var batch []*cloudwatch.MetricDatum
|
|
152 |
lim := min(len(datums), cw.numConcurrentRequests)
|
|
153 |
batch, datums = datums[:lim], datums[lim:]
|
|
154 |
n++
|
|
155 |
go func(batch []*cloudwatch.MetricDatum) {
|
|
156 |
tokens <- struct{}{}
|
|
157 |
_, err := cw.svc.PutMetricData(&cloudwatch.PutMetricDataInput{
|
|
158 |
Namespace: aws.String(cw.namespace),
|
|
159 |
MetricData: batch,
|
|
160 |
})
|
|
161 |
<-tokens
|
|
162 |
errors <- err
|
|
163 |
}(batch)
|
|
164 |
}
|
|
165 |
|
|
166 |
var firstErr error
|
|
167 |
for ; n > 0; n-- {
|
|
168 |
if err := <-errors; err != nil && firstErr != nil {
|
|
169 |
firstErr = err
|
|
170 |
}
|
|
171 |
}
|
|
172 |
|
|
173 |
return firstErr
|
|
174 |
}
|
|
175 |
|
|
176 |
func min(a, b int) int {
|
|
177 |
if a < b {
|
|
178 |
return a
|
|
179 |
}
|
|
180 |
return b
|
140 | 181 |
}
|
141 | 182 |
|
142 | 183 |
// counter is a CloudWatch counter metric.
|