1
1
package alertmanager
2
2
3
3
import (
4
+ "fmt"
5
+
6
+ "github.com/prometheus/common/model"
4
7
corev1 "k8s.io/api/core/v1"
5
8
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6
9
"k8s.io/apimachinery/pkg/runtime"
7
10
8
11
"github.com/gitpod-io/observability/installer/pkg/common"
12
+ "github.com/gitpod-io/observability/installer/pkg/config"
9
13
)
10
14
15
+ const queryString = `{{ reReplaceAll "%22" "%5C%22" (index .Alerts 0).GeneratorURL | reReplaceAll ".*expr=" "https://grafana.gitpod.io/explore?orgId=1&left=%7B%22range%22:%7B%22from%22:%22now-1h%22,%22to%22:%22now%22%7D,%22datasource%22:%22VictoriaMetrics%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22" | reReplaceAll "&g0.tab=1" "%22%7D%5D%7D" | reReplaceAll ` + `\+` + ` "%20" | reReplaceAll "%0A" "" | reReplaceAll "%28" "(" | reReplaceAll "%29" ")" }}`
16
+
11
17
func configSecret (ctx * common.RenderContext ) ([]runtime.Object , error ) {
18
+ var receivers []* config.Receiver
19
+
20
+ receivers = append (receivers , criticalReceiver (ctx ))
21
+ receivers = append (receivers , defaultReceivers (ctx )... )
22
+ receivers = append (receivers , teamSlackReceivers (ctx )... )
23
+ resolveTimeout , _ := model .ParseDuration ("5m" )
24
+
25
+ alertingConfig := config.AlertmanagerConfig {
26
+ Global : & config.GlobalConfig {
27
+ ResolveTimeout : & resolveTimeout ,
28
+ },
29
+ Route : & config.Route {
30
+ Receiver : "Black_Hole" ,
31
+ GroupByStr : []string {"..." },
32
+ GroupWait : "30s" ,
33
+ GroupInterval : "5m" ,
34
+ RepeatInterval : "6h" ,
35
+ Routes : routes (ctx ),
36
+ },
37
+ InhibitRules : inhibitRules (),
38
+ Receivers : receivers ,
39
+ }
40
+
12
41
return []runtime.Object {
13
42
& corev1.Secret {
14
43
TypeMeta : metav1.TypeMeta {
@@ -21,8 +50,188 @@ func configSecret(ctx *common.RenderContext) ([]runtime.Object, error) {
21
50
Labels : common .Labels (Name , Component , App , Version ),
22
51
},
23
52
StringData : map [string ]string {
24
- "alertmanager.yaml" : ctx . Config . Alerting . Config .String (),
53
+ "alertmanager.yaml" : alertingConfig .String (),
25
54
},
26
55
},
27
56
}, nil
28
57
}
58
+
59
+ func routes (ctx * common.RenderContext ) []* config.Route {
60
+ var routes []* config.Route
61
+
62
+ routes = append (routes , & config.Route {
63
+ Receiver : "criticalReceiver" ,
64
+ Match : map [string ]string {
65
+ "severity" : "critical" ,
66
+ },
67
+ Continue : false ,
68
+ })
69
+
70
+ for _ , tRoute := range ctx .Config .Alerting .TeamRoutes {
71
+ routes = append (routes , & config.Route {
72
+ Receiver : fmt .Sprintf ("%s-slackReceiver" , tRoute .TeamLabel ),
73
+ Match : map [string ]string {
74
+ "team" : tRoute .TeamLabel ,
75
+ },
76
+ Continue : false ,
77
+ })
78
+ }
79
+
80
+ routes = append (routes , & config.Route {
81
+ Receiver : "genericReceiver" ,
82
+ MatchRE : map [string ]string {
83
+ "severity" : "info|warning" ,
84
+ },
85
+ Continue : false ,
86
+ })
87
+
88
+ return routes
89
+ }
90
+
91
+ func inhibitRules () []* config.InhibitRule {
92
+ var inhibitRules []* config.InhibitRule
93
+
94
+ inhibitRules = append (inhibitRules , & config.InhibitRule {
95
+ SourceMatch : map [string ]string {
96
+ "severity" : "critical" ,
97
+ },
98
+ TargetMatchRE : map [string ]string {
99
+ "severity" : "info|warning" ,
100
+ },
101
+ Equal : []string {"alertname" },
102
+ })
103
+
104
+ inhibitRules = append (inhibitRules , & config.InhibitRule {
105
+ SourceMatch : map [string ]string {
106
+ "severity" : "warning" ,
107
+ },
108
+ TargetMatchRE : map [string ]string {
109
+ "severity" : "info" ,
110
+ },
111
+ Equal : []string {"alertname" },
112
+ })
113
+
114
+ return inhibitRules
115
+ }
116
+
117
+ func criticalReceiver (ctx * common.RenderContext ) * config.Receiver {
118
+ if ctx .Config .Alerting .PagerDutyRoutingKey != "" {
119
+ return & config.Receiver {
120
+ Name : "criticalReceiver" ,
121
+ PagerdutyConfigs : []* config.PagerdutyConfig {
122
+ {
123
+ VSendResolved : common .ToPointer (true ),
124
+ RoutingKey : ctx .Config .Alerting .PagerDutyRoutingKey ,
125
+ Links : []config.PagerdutyLink {
126
+ {
127
+ Href : "{{ .CommonAnnotations.runbook_url }}" ,
128
+ Text : "Runbook" ,
129
+ },
130
+ {
131
+ Href : queryString ,
132
+ Text : "Query" ,
133
+ },
134
+ {
135
+ Href : "{{ .CommonAnnotations.dashboard_url}}" ,
136
+ Text : "Dashboard" ,
137
+ },
138
+ },
139
+ },
140
+ },
141
+ }
142
+ } else {
143
+ return & config.Receiver {
144
+ Name : "criticalReceiver" ,
145
+ SlackConfigs : []* config.SlackConfig {
146
+ {
147
+ VSendResolved : common .ToPointer (true ),
148
+ APIURL : "https://slack.com/api/chat.postMessage" ,
149
+ Channel : ctx .Config .Alerting .GenericSlackChannel ,
150
+ Color : "{{ if eq .Status \" firing\" -}}{{ if eq .CommonLabels.severity \" warning\" -}}warning{{- else if eq .CommonLabels.severity \" critical\" -}}danger{{- else -}}#439FE0{{- end -}}{{ else -}}good{{- end }}" ,
151
+ Title : "[{{ .CommonLabels.alertname }} {{ .Status | toUpper }} {{ if eq .Status \" firing\" }}{{ end }}]" ,
152
+ Text : "{{ range .Alerts }}\n *Summary*: {{ .Annotations.summary }}\n *Severity: {{ .Labels.severity }}*\n *Cluster:* {{ .Labels.cluster }}\n *Alert:* {{ .Labels.alertname }}\n *Description:* {{ .Annotations.description }}\n {{ end }}" ,
153
+ HTTPConfig : & config.HTTPClientConfig {
154
+ Authorization : & config.Authorization {
155
+ Credentials : ctx .Config .Alerting .SlackOAuthToken ,
156
+ },
157
+ },
158
+ Actions : slackButtons (),
159
+ },
160
+ },
161
+ }
162
+ }
163
+ }
164
+
165
+ func defaultReceivers (ctx * common.RenderContext ) []* config.Receiver {
166
+ var receivers []* config.Receiver
167
+
168
+ receivers = append (receivers , & config.Receiver {Name : "Black_Hole" })
169
+ receivers = append (receivers , & config.Receiver {
170
+ Name : "genericReceiver" ,
171
+ SlackConfigs : []* config.SlackConfig {
172
+ {
173
+ VSendResolved : common .ToPointer (true ),
174
+ APIURL : "https://slack.com/api/chat.postMessage" ,
175
+ Channel : ctx .Config .Alerting .GenericSlackChannel ,
176
+ Color : "{{ if eq .Status \" firing\" -}}{{ if eq .CommonLabels.severity \" warning\" -}}warning{{- else if eq .CommonLabels.severity \" critical\" -}}danger{{- else -}}#439FE0{{- end -}}{{ else -}}good{{- end }}" ,
177
+ Title : "[{{ .CommonLabels.alertname }} {{ .Status | toUpper }} {{ if eq .Status \" firing\" }}{{ end }}]" ,
178
+ Text : "{{ range .Alerts }}\n *Summary*: {{ .Annotations.summary }}\n *Severity: {{ .Labels.severity }}*\n *Cluster:* {{ .Labels.cluster }}\n *Alert:* {{ .Labels.alertname }}\n *Description:* {{ .Annotations.description }}\n {{ end }}" ,
179
+ HTTPConfig : & config.HTTPClientConfig {
180
+ Authorization : & config.Authorization {
181
+ Credentials : ctx .Config .Alerting .SlackOAuthToken ,
182
+ },
183
+ },
184
+ Actions : slackButtons (),
185
+ },
186
+ },
187
+ })
188
+ return receivers
189
+ }
190
+
191
+ func teamSlackReceivers (ctx * common.RenderContext ) []* config.Receiver {
192
+ var receivers []* config.Receiver
193
+ for _ , tRoute := range ctx .Config .Alerting .TeamRoutes {
194
+ var receiver config.Receiver
195
+
196
+ receiver .Name = fmt .Sprintf ("%s-slackReceiver" , tRoute .TeamLabel )
197
+ receiver .SlackConfigs = []* config.SlackConfig {
198
+ {
199
+ VSendResolved : common .ToPointer (true ),
200
+ APIURL : "https://slack.com/api/chat.postMessage" ,
201
+ Channel : tRoute .SlackChannel ,
202
+ Color : "{{ if eq .Status \" firing\" -}}{{ if eq .CommonLabels.severity \" warning\" -}}warning{{- else if eq .CommonLabels.severity \" critical\" -}}danger{{- else -}}#439FE0{{- end -}}{{ else -}}good{{- end }}" ,
203
+ Title : "[{{ .CommonLabels.alertname }} {{ .Status | toUpper }} {{ if eq .Status \" firing\" }}{{ end }}]" ,
204
+ Text : "{{ range .Alerts }}\n *Summary*: {{ .Annotations.summary }}\n *Severity: {{ .Labels.severity }}*\n *Cluster:* {{ .Labels.cluster }}\n *Alert:* {{ .Labels.alertname }}\n *Description:* {{ .Annotations.description }}\n {{ end }}" ,
205
+ HTTPConfig : & config.HTTPClientConfig {
206
+ Authorization : & config.Authorization {
207
+ Credentials : ctx .Config .Alerting .SlackOAuthToken ,
208
+ },
209
+ },
210
+ Actions : slackButtons (),
211
+ },
212
+ }
213
+
214
+ receivers = append (receivers , & receiver )
215
+ }
216
+ return receivers
217
+ }
218
+
219
+ func slackButtons () []config.SlackAction {
220
+ return []config.SlackAction {
221
+ {
222
+ Type : "button" ,
223
+ Text : "Runbbok :runbook" ,
224
+ URL : "{{ .CommonAnnotations.runbook_url }}" ,
225
+ },
226
+ {
227
+ Type : "button" ,
228
+ Text : "Query :prometheus:" ,
229
+ URL : queryString ,
230
+ },
231
+ {
232
+ Type : "button" ,
233
+ Text : "Dashboard :grafana:" ,
234
+ URL : "{{ .CommonAnnotations.dashboard_url}}" ,
235
+ },
236
+ }
237
+ }
0 commit comments