-
Notifications
You must be signed in to change notification settings - Fork 3
/
api.go
178 lines (148 loc) · 4.8 KB
/
api.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//Package cloudhealth contains routines for writing to cloud health
package cloudhealth
import (
"github.com/Symantec/scotty/lib/yamlutil"
"time"
)
const (
// Default endpoint for cloudhealth service.
DefaultEndpoint = "https://chapi.cloudhealthtech.com/metrics/v1"
)
// FVariable represents a floating point cloudhealth variable rolled up over
// some amount of time
type FVariable struct {
Count uint64
Min float64
Max float64
Sum float64
}
// IsEmpty returns true if no values have been added to this variable
func (v FVariable) IsEmpty() bool {
return v.Count == 0
}
// Add adds x to this variable
func (v *FVariable) Add(x float64) {
v.add(x)
}
// Clear clears out this variable.
func (v *FVariable) Clear() {
*v = FVariable{}
}
// Avg returns the average of this variable
func (v FVariable) Avg() float64 {
return v.Sum / float64(v.Count)
}
// IVariable represents an integer cloudhealth variable rolled up over
// some amount of time
type IVariable struct {
Count uint64
Min uint64
Max uint64
Sum uint64
}
// IsEmpty returns true if no values have been added to this variable
func (v IVariable) IsEmpty() bool {
return v.Count == 0
}
// Add adds x to this variable
func (v *IVariable) Add(x uint64) {
v.add(x)
}
// Clear clears out this variable.
func (v *IVariable) Clear() {
*v = IVariable{}
}
// Avg returns the average of this variable
func (v IVariable) Avg() uint64 {
return v.Sum / v.Count
}
const InstanceDataPointCount = 12 // 4 variables * (min,max,avg)
// InstanceData contains rolled up data for a particular instance
type InstanceData struct {
AccountNumber string // account number if different from default
InstanceId string // The aws instance ID
Ts time.Time // The timestamp at one hour granularity
CpuUsedPercent FVariable
MemoryFreeBytes IVariable
MemorySizeBytes IVariable
MemoryUsedPercent FVariable
}
const FsDataPointCount = 9 // 3 variables * (min,max,avg)
// Maximum datapoints that can be written to cloudhealth at once
const MaxDataPoints = 1000
// FsData contains rolled up data for a particular file system
type FsData struct {
AccountNumber string // account number if different from default
InstanceId string // the aws instance ID
MountPoint string // The mount point of file system
Ts time.Time // The timestamp at one hour granularity
FsSizeBytes IVariable
FsUsedBytes IVariable
FsUsedPercent FVariable
}
// Config configures the writer
type Config struct {
ApiKey string `yaml:"apiKey"`
DataCenter string `yaml:"dataCenter"` // e.g us-east-1
AccountNumber string `yaml:"accountNumber"` // default account number
DryRun bool `yaml:"dryRun"` // If true, runs in dry run mode
// like "http://somehost.com:1234/endpoint" If omitted, defaults to
// standard endpoint for cloudhealth.
Endpoint string `yaml:"endpoint"`
}
func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
type configFields Config
return yamlutil.StrictUnmarshalYAML(unmarshal, (*configFields)(c))
}
func (c *Config) Reset() {
*c = Config{}
}
type Writer struct {
config Config
urlStr string
}
// NewWriter returns a new Writer instance.
func NewWriter(config Config) (*Writer, error) {
return newWriter(config)
}
// Write writes the provided data in a single request.
// Write returns an error if the number of data points exceeds 1000. That is,
// len(instances)*InstanceDataPointCount + len(fss)*FsDataPointCount >= 1000.
// Write returns the http response code along with an error if applicable.
// If the write is parital success, Write returns 200 along with the error.
// Write will never return a 429 response. If Write receives a 429, it
// retries using exponential backoff internally until it receives a non
// 429 response and returns that.
func (w *Writer) Write(
instances []InstanceData, fss []FsData) (
responseCode int, err error) {
return w.write(instances, fss)
}
// Buffer buffers data to add to cloudhealth
type Buffer struct {
instances []InstanceData
fss []FsData
}
// NewBuffer returns a new, empty buffer
func NewBuffer() *Buffer {
return &Buffer{}
}
// Add adds an instance and its file systems returning true if the
// add succeeded. Add returns false if adding the instance and the filesystem
// would cause the number of data points to exceed the cloudhealth limit.
func (b *Buffer) Add(instance InstanceData, fss []FsData) bool {
return b.add(instance, fss)
}
// Get returns a defensive copy of what is in this buffer
func (b *Buffer) Get() ([]InstanceData, []FsData) {
return b.get()
}
// Clear clears this buffer so that IsEmpty returns true
func (b *Buffer) Clear() {
b.instances = b.instances[:0]
b.fss = b.fss[:0]
}
// IsEmpty returns true if this buffer is empty
func (b *Buffer) IsEmpty() bool {
return len(b.instances) == 0 && len(b.fss) == 0
}