-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathservice.go
81 lines (68 loc) · 1.99 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package cwatch
import (
"context"
"log/slog"
"sync"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
awsx "github.com/nyaruka/gocommon/aws"
"github.com/nyaruka/gocommon/syncx"
)
type Service struct {
Client *cloudwatch.Client
namespace string
deployment types.Dimension
batcher *syncx.Batcher[types.MetricDatum]
}
// NewService creates a new Cloudwatch service with the given credentials and configuration
func NewService(accessKey, secretKey, region, namespace, deployment string) (*Service, error) {
cfg, err := awsx.NewConfig(accessKey, secretKey, region)
if err != nil {
return nil, err
}
return &Service{
Client: cloudwatch.NewFromConfig(cfg),
namespace: namespace,
deployment: types.Dimension{Name: aws.String("Deployment"), Value: aws.String(deployment)},
}, nil
}
func (s *Service) StartQueue(wg *sync.WaitGroup) {
if s.batcher != nil {
panic("queue already started")
}
s.batcher = syncx.NewBatcher(s.processBatch, 100, time.Second*3, 1000, wg)
s.batcher.Start()
}
func (s *Service) StopQueue() {
if s.batcher == nil {
panic("queue wasn't started")
}
s.batcher.Stop()
}
func (s *Service) Queue(d types.MetricDatum) {
s.batcher.Queue(d)
}
func (s *Service) Prepare(data []types.MetricDatum) *cloudwatch.PutMetricDataInput {
// add deployment as the first dimension to all metrics
for i := range data {
data[i].Dimensions = append([]types.Dimension{s.deployment}, data[i].Dimensions...)
}
return &cloudwatch.PutMetricDataInput{
Namespace: aws.String(s.namespace),
MetricData: data,
}
}
func (s *Service) processBatch(batch []types.MetricDatum) {
_, err := s.Client.PutMetricData(context.TODO(), s.Prepare(batch))
if err != nil {
slog.Error("error sending metrics to cloudwatch", "error", err, "count", len(batch))
}
}
type CWService interface {
Queue(d types.MetricDatum)
StartQueue(wg *sync.WaitGroup)
StopQueue()
}
var _ CWService = (*Service)(nil)