forked from spaceapegames/go-wavefront
-
Notifications
You must be signed in to change notification settings - Fork 0
/
alert.go
225 lines (182 loc) · 5.85 KB
/
alert.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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package wavefront
import (
"encoding/json"
"fmt"
"io/ioutil"
)
const (
AlertTypeThreshold = "THRESHOLD"
AlertTypeClassic = "CLASSIC"
)
// Alert represents a single Wavefront Alert
type Alert struct {
// Name is the name given to an Alert
Name string `json:"name"`
// ID is the Wavefront-assigned ID of an existing Alert
ID *string `json:"id,omitempty"`
// AlertType should be either CLASSIC or THRESHOLD
AlertType string `json:"alertType,omitempty"`
// AdditionalInfo is any extra information about the Alert
AdditionalInfo string `json:"additionalInformation"`
// Target is a comma-separated list of targets for the Alert
Target string `json:"target,omitempty"`
// For THRESHOLD alerts. Targets is a map[string]string. This maps severity to lists of targets.
// Valid keys are: severe, smoke, warn or info
Targets map[string]string `json:"targets"`
// Condition is the condition under which the Alert will fire
Condition string `json:"condition"`
// For THRESHOLD alerts. Conditions is a map[string]string. This maps severity to respective conditions.
// Valid keys are: severe, smoke, warn or info
Conditions map[string]string `json:"conditions"`
// DisplayExpression is the ts query to generate a graph of this Alert, in the UI
DisplayExpression string `json:"displayExpression,omitempty"`
// Minutes is the number of minutes the Condition must be met, before the
// Alert will fire
Minutes int `json:"minutes"`
// ResolveAfterMinutes is the number of minutes the Condition must be un-met
// before the Alert is considered resolved
ResolveAfterMinutes int `json:"resolveAfterMinutes,omitempty"`
// Minutes to wait before re-sending notification of firing alert.
NotificationResendFrequencyMinutes int `json:"notificationResendFrequencyMinutes"`
// Severity is the severity of the Alert, and can be one of SEVERE,
// SMOKE, WARN or INFO
Severity string `json:"severity,omitempty"`
// For THRESHOLD alerts. SeverityList is a list of strings. Different severities applicable to this alert.
// Valid elements are: SEVERE, SMOKE, WARN or INFO
SeverityList []string `json:"severityList"`
// Status is the current status of the Alert
Status []string `json:"status"`
// Tags are the tags applied to the Alert
Tags []string
FailingHostLabelPairs []SourceLabelPair `json:"failingHostLabelPairs,omitempty"`
InMaintenanceHostLabelPairs []SourceLabelPair `json:"inMaintenanceHostLabelPairs,omitempty"`
}
type SourceLabelPair struct {
Host string `json:"host"`
Firing int `json:"firing"`
}
// Alerts is used to perform alert-related operations against the Wavefront API
type Alerts struct {
// client is the Wavefront client used to perform alert-related operations
client Wavefronter
}
const baseAlertPath = "/api/v2/alert"
// UnmarshalJSON is a custom JSON unmarshaller for an Alert, used in order to
// populate the Tags field in a more intuitive fashion
func (a *Alert) UnmarshalJSON(b []byte) error {
type alert Alert
temp := struct {
Tags map[string][]string `json:"tags"`
*alert
}{
alert: (*alert)(a),
}
if err := json.Unmarshal(b, &temp); err != nil {
return err
}
a.Tags = temp.Tags["customerTags"]
return nil
}
func (a *Alert) MarshalJSON() ([]byte, error) {
type alert Alert
return json.Marshal(&struct {
Tags map[string][]string `json:"tags"`
*alert
}{
Tags: map[string][]string{
"customerTags": a.Tags,
},
alert: (*alert)(a),
})
}
// Alerts is used to return a client for alert-related operations
func (c *Client) Alerts() *Alerts {
return &Alerts{client: c}
}
// Get is used to retrieve an existing Alert by ID.
// The ID field must be provided
func (a Alerts) Get(alert *Alert) error {
if *alert.ID == "" {
return fmt.Errorf("Alert id field is not set")
}
return a.crudAlert("GET", fmt.Sprintf("%s/%s", baseAlertPath, *alert.ID), alert)
}
// Find returns all alerts filtered by the given search conditions.
// If filter is nil, all alerts are returned.
func (a Alerts) Find(filter []*SearchCondition) ([]*Alert, error) {
search := &Search{
client: a.client,
Type: "alert",
Params: &SearchParams{
Conditions: filter,
},
}
var results []*Alert
moreItems := true
for moreItems == true {
resp, err := search.Execute()
if err != nil {
return nil, err
}
var tmpres []*Alert
err = json.Unmarshal(resp.Response.Items, &tmpres)
if err != nil {
return nil, err
}
results = append(results, tmpres...)
moreItems = resp.Response.MoreItems
search.Params.Offset = resp.NextOffset
}
return results, nil
}
// Create is used to create an Alert in Wavefront.
// If successful, the ID field of the alert will be populated.
func (a Alerts) Create(alert *Alert) error {
return a.crudAlert("POST", baseAlertPath, alert)
}
// Update is used to update an existing Alert.
// The ID field of the alert must be populated
func (a Alerts) Update(alert *Alert) error {
if alert.ID == nil {
return fmt.Errorf("alert id field not set")
}
return a.crudAlert("PUT", fmt.Sprintf("%s/%s", baseAlertPath, *alert.ID), alert)
}
// Delete is used to delete an existing Alert.
// The ID field of the alert must be populated
func (a Alerts) Delete(alert *Alert) error {
if alert.ID == nil {
return fmt.Errorf("alert id field not set")
}
err := a.crudAlert("DELETE", fmt.Sprintf("%s/%s", baseAlertPath, *alert.ID), alert)
if err != nil {
return err
}
//reset the ID field so deletion is not attempted again
alert.ID = nil
return nil
}
func (a Alerts) crudAlert(method, path string, alert *Alert) error {
payload, err := json.Marshal(alert)
if err != nil {
return err
}
req, err := a.client.NewRequest(method, path, nil, payload)
if err != nil {
return err
}
resp, err := a.client.Do(req)
if err != nil {
return err
}
defer resp.Close()
body, err := ioutil.ReadAll(resp)
if err != nil {
return err
}
return json.Unmarshal(body, &struct {
Response *Alert `json:"response"`
}{
Response: alert,
})
}