forked from ansrivas/consul-alerts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
victorops-notifier.go
136 lines (111 loc) · 4.13 KB
/
victorops-notifier.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
// Package notifier manages notifications for consul-alerts
package notifier
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
log "github.com/Sirupsen/logrus"
)
// VictorOpsNotifier provides configuration options for the VictorOps notifier
type VictorOpsNotifier struct {
Enabled bool
APIKey string `json:"api-key"`
RoutingKey string `json:"routing-key"`
}
// VictorOpsEvent represents the options we'll pass to the VictorOps API
type VictorOpsEvent struct {
// Explicitly listed by http://victorops.force.com/knowledgebase/articles/Integration/Alert-Ingestion-API-Documentation/
MessageType string `json:"message_type"`
EntityID string `json:"entity_id"`
Timestamp uint32 `json:"timestamp"`
StateMessage string `json:"state_message"`
MonitoringTool string `json:"monitoring_tool"`
EntityDisplayName string `json:"entity_display_name"`
// Helpful fields from http://victorops.force.com/knowledgebase/articles/Getting_Started/Incident-Fields-Glossary/?l=en_US&fs=RelatedArticle
HostName string `json:"host_name"`
MonitorName string `json:"monitor_name"`
// VictorOps lets you add arbitrary fields to help custom notification logic, so we'll set
// node, service, service ID, check, and check ID
ConsulNode string `json:"consul_node"`
ConsulService string `json:"consul_service,omitempty"`
ConsulServiceID string `json:"consul_service_id,omitempty"`
ConsulCheck string `json:"consul_check"`
ConsulCheckID string `json:"consul_check_id"`
}
const monitoringToolName string = "consul"
const apiEndpointTemplate string = "https://alert.victorops.com/integrations/generic/20131114/alert/%s/%s"
// NotifierName provides name for notifier selection
func (vo *VictorOpsNotifier) NotifierName() string {
return "victorops"
}
func (vo *VictorOpsNotifier) Copy() Notifier {
notifier := *vo
return ¬ifier
}
// Notify sends messages to the endpoint notifier
func (vo *VictorOpsNotifier) Notify(messages Messages) bool {
endpoint := fmt.Sprintf(apiEndpointTemplate, vo.APIKey, vo.RoutingKey)
ok := true
for _, message := range messages {
entityID := fmt.Sprintf("%s:", message.Node)
entityDisplayName := entityID
// This might be a node level check without an explicit service
if message.ServiceId == "" {
entityID += message.CheckId
entityDisplayName += message.Check
} else {
entityID += message.ServiceId
entityDisplayName += message.Service
}
var messageType string
switch {
case message.IsCritical():
messageType = "CRITICAL"
case message.IsWarning():
messageType = "WARNING"
case message.IsPassing():
messageType = "RECOVERY"
default:
log.Warn(fmt.Sprintf("Message with status %s was neither critical, warning, nor passing, reporting to VictorOps as INFO", message.Status))
messageType = "INFO"
}
// VictorOps automatically displays the entity display name in notifications and page SMSs / emails,
// so for brevity we don't repeat it in the "StateMessage" field
stateMessage := fmt.Sprintf("%s: %s\n%s", messageType, message.Notes, message.Output)
event := VictorOpsEvent{
MessageType: messageType,
EntityID: entityID,
Timestamp: uint32(message.Timestamp.Unix()),
StateMessage: stateMessage,
MonitoringTool: monitoringToolName,
EntityDisplayName: entityDisplayName,
HostName: message.Node,
MonitorName: message.Check,
ConsulNode: message.Node,
ConsulService: message.Service,
ConsulServiceID: message.ServiceId,
ConsulCheck: message.Check,
ConsulCheckID: message.CheckId,
}
eventJSON, jsonError := json.Marshal(event)
if jsonError != nil {
ok = false
log.Error("Error JSON-ifying VictorOps alert. ", jsonError)
continue
}
response, httpError := http.Post(endpoint, "application/json", bytes.NewBuffer(eventJSON))
if httpError != nil {
ok = false
log.Error("Error hitting VictorOps API. ", httpError)
continue
}
if response.StatusCode != 200 {
ok = false
log.Error(fmt.Sprintf("Expected VictorOps endpoint to return 200, but it returned %d", response.StatusCode))
continue
}
}
log.Println("VictorOps notification sent.")
return ok
}