Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@
!/.travis.yml
!/.promu.yml
!/api/v2/openapi.yaml
!examples/webhook/dingtalk/alertmanager.yml
!examples/webhook/feishu/alertmanager.yml
4 changes: 4 additions & 0 deletions config/notifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,10 @@ type WebhookConfig struct {
// Alerts exceeding this threshold will be truncated. Setting this to 0
// allows an unlimited number of alerts.
MaxAlerts uint64 `yaml:"max_alerts" json:"max_alerts"`

// Webhook content format
JSON string `yaml:"json,omitempty" json:"json,omitempty"`
Text string `yaml:"text,omitempty" json:"text,omitempty"`
}

// UnmarshalYAML implements the yaml.Unmarshaler interface.
Expand Down
93 changes: 93 additions & 0 deletions examples/webhook/dingtalk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
### Alert
```json
[
{
"labels": {
"alertname": "Test Alert Cvvtintokg.",
"env": "Test",
"group": "Ops",
"name": "Hbcqqq dzrvxi dxvftrprop dotm.",
"severity": "critical"
},
"annotations": {
"message": "Yqlvc qdxjqdw kmedspse adfbai rmw klqeosrv fgcronx usjp embhqt.\"\nNpctkymw mkezjf iynfo qae wdvfw fmxev.Jyhbt kcfepqp dhesgstrt vpvashto yfv wvpd gadptu hbzgjwi ctt rbg."
},
"startsAt": "2023-05-04T06:42:15.904Z",
"endsAt": "2023-05-04T07:42:15.904Z",
"generatorURL": "https://www.github.com"
}
]
```
### Template
```gotemplate
{{ define "dingTalk.json" }}
{{ $key_map := (`{"alertname":"Alert Name","name":"Service Name","group":"Group","service":"Service","severity":"Severity","message":"Message","instance":"Instance Name"}`|toMap) }}
{{ $alert_name := "" }}
{{ $alert_status := "" }}
{{ if eq .Status "firing" }}
{{ $alert_status = printf "[Firing: %d]" (.Alerts.Firing | len) }}
{{ else if eq .Status "resolved" }}
{{ $alert_status = printf "[Resolved: %d]" (.Alerts.Resolved | len) }}
{{ else }}
{{ $alert_status =(.Status | toUpper) }}
{{ end }}
{{ range .GroupLabels.SortedPairs }} {{ if eq .Name "alertname" }}{{ $alert_name = (.Value) }}{{end}} {{ end }}
{{ $alert_title := (printf "%s %s" $alert_status $alert_name ) }}
{{ $alert_msg := (printf "### %s %s" $alert_status $alert_name ) }}
{{ range .Alerts.Firing }}
{{ range .Labels.SortedPairs }}
{{ if (ne (index $key_map .Name) "") }}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg (index $key_map .Name) .Value ) }}
{{else}}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg .Name .Value ) }}
{{end}}
{{ end }}
{{ range .Annotations.SortedPairs }}
{{ if (ne (index $key_map .Name) "") }}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg (index $key_map .Name) .Value ) }}
{{else}}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg .Name .Value ) }}
{{end}}
{{ end }}
{{ $alert_msg = (printf "%s\n\n> [View Data](%s)" $alert_msg .GeneratorURL ) }}
{{ end }}
{
"msgtype": "markdown",
"markdown": {
"title":{{ $alert_title|toJson }},
"text": {{ $alert_msg|toJson }}
},
"at": {
"atMobiles": [
],
"isAtAll": false
}
}
{{ end }}
```
### Alertmanager Config
```yaml
receivers:
- name: 'web.hook'
webhook_configs:
- url: 'https://oapi.dingtalk.com/robot/send?access_token=<token>'
json: '{{ template "dingTalk.json" . }}'
```

### Webhook Content
```
{
"msgtype": "markdown",
"markdown": {
"title": "[Firing: 1] Test Alert Eijwywi wtuplkvno uix.",
"text": "### [Firing: 1] Test Alert Eijwywi wtuplkvno uix.\n\n\u003e Alert Name: Test Alert Eijwywi wtuplkvno uix.\n\n\u003e env: Test\n\n\u003e Group: Ops\n\n\u003e Service Name: Tdjafh qbhhpmyt aeekyhrhr tdjdbbap.\n\n\u003e Severity: critical\n\n\u003e Message: Bstg aenfwxmvk qbihjaxo.\"\nEoog xzrgupeeel yqyndiw appvaw wkkbre dhemrscsg egvofxxvs xqxj.Egwmievu xysgytr idwufuw.\n\n\u003e [View Data](https://www.github.com)"
},
"at": {
"atMobiles": [],
"isAtAll": false
}
}
```

### Feishu message
![image](./dingTalk_message.png)
22 changes: 22 additions & 0 deletions examples/webhook/dingtalk/alertmanager.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
global:
resolve_timeout: 5m

route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1m
receiver: 'web.hook'
receivers:
- name: 'web.hook'
webhook_configs:
- url: 'https://oapi.dingtalk.com/robot/send?access_token=<token>'
json: '{{ template "dingTalk.json" . }}'
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
templates:
- "json.tmpl"
Binary file added examples/webhook/dingtalk/dingTalk_message.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions examples/webhook/dingtalk/json.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{{ define "dingTalk.json" }}
{{ $key_map := (`{"alertname":"Alert Name","name":"Service Name","group":"Group","service":"Service","severity":"Severity","message":"Message","instance":"Instance Name"}`|toMap) }}
{{ $alert_name := "" }}
{{ $alert_status := "" }}
{{ if eq .Status "firing" }}
{{ $alert_status = printf "[Firing: %d]" (.Alerts.Firing | len) }}
{{ else if eq .Status "resolved" }}
{{ $alert_status = printf "[Resolved: %d]" (.Alerts.Resolved | len) }}
{{ else }}
{{ $alert_status =(.Status | toUpper) }}
{{ end }}
{{ range .GroupLabels.SortedPairs }} {{ if eq .Name "alertname" }}{{ $alert_name = (.Value) }}{{end}} {{ end }}
{{ $alert_title := (printf "%s %s" $alert_status $alert_name ) }}
{{ $alert_msg := (printf "### %s %s" $alert_status $alert_name ) }}
{{ range .Alerts.Firing }}
{{ range .Labels.SortedPairs }}
{{ if (ne (index $key_map .Name) "") }}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg (index $key_map .Name) .Value ) }}
{{else}}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg .Name .Value ) }}
{{end}}
{{ end }}
{{ range .Annotations.SortedPairs }}
{{ if (ne (index $key_map .Name) "") }}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg (index $key_map .Name) .Value ) }}
{{else}}
{{ $alert_msg = (printf "%s\n\n> %s: %s" $alert_msg .Name .Value ) }}
{{end}}
{{ end }}
{{ $alert_msg = (printf "%s\n\n> [View Data](%s)" $alert_msg .GeneratorURL ) }}
{{ end }}
{
"msgtype": "markdown",
"markdown": {
"title":{{ $alert_title|toJson }},
"text": {{ $alert_msg|toJson }}
},
"at": {
"atMobiles": [
],
"isAtAll": false
}
}
{{ end }}
96 changes: 96 additions & 0 deletions examples/webhook/feishu/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
### Alert
```json
[
{
"labels": {
"alertname": "Test Alert Temiydom wgatpelzn eiesvt.",
"env": "Test",
"group": "Ops",
"name": "Teft dwqokj yqka jbroocrw xwz.",
"severity": "critical"
},
"annotations": {
"message": "Zxoiyg mnukiqqa imgxyh gwahxoe rixwdzgfn.\"\nLcxdl dpcmu gcrwhvyb qbipfn ifipq omumebq whwmupxag rnbryqneyu gih mszuxf.Tfwbmtj dxuwskbctr ostv kpmxujo tlydykp."
},
"startsAt": "2023-05-04T03:45:54.173Z",
"endsAt": "2023-05-04T04:45:54.173Z",
"generatorURL": "https://www.github.com"
}
]
```
### Template
```gotemplate
{{- define "feishu.title" -}}
{{- if eq .Status "firing" -}}
[Firing {{- .Alerts.Firing | len -}}/{{- .Alerts | len -}}]
{{- else if eq .Status "resolved" -}}
[Resolved {{- .Alerts.Resolved | len -}}]
{{- else -}}
[{{- .Status | toUpper | safeJson -}}]
{{- end -}}
{{" "}}{{- range .GroupLabels.SortedPairs -}} {{- if eq .Name "alertname" -}}{{- .Value | safeJson -}}{{- end -}} {{- end -}}
{{- end -}}

{{- define "feishu.msg" -}}
### {{ template "feishu.title" . -}}\n
{{- range $idx,$elem := .Alerts.Firing -}}
{{- range .Labels.SortedPairs -}}
**{{- .Name | safeJson -}}**:{{" "}}{{- .Value | safeJson -}}\n
{{- end -}}
{{- range .Annotations.SortedPairs -}}
**{{- .Name | safeJson -}}**:{{" "}}{{- .Value | safeJson -}}\n
{{- end -}}
**Srart Time**:{{" "}}{{- .StartsAt -}}\n
{{- if eq .Status "firing" -}}
[View data]({{.GeneratorURL | safeJson}})
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "feishu.json" -}}
{
"msg_type": "interactive",
"card": {
"elements": [
{
"content": "{{- template "feishu.msg" . -}}",
"tag": "markdown"
}
],
"config": {
"wide_screen_mode": true
}
}
}
{{- end -}}

```
### Alertmanager Config
```yaml
receivers:
- name: "web.hook"
webhook_configs:
- url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxx'
json: '{{ template "feishu.json" . }}'
send_resolved: true
```

### Webhook Content
```
{
"msg_type": "interactive",
"card": {
"elements": [
{
"content": "### [Firing1/1] Test Alert Temiydom wgatpelzn eiesvt.\n**alertname**: Test Alert Temiydom wgatpelzn eiesvt.\n**env**: Test\n**group**: Ops\n**name**: Teft dwqokj yqka jbroocrw xwz.\n**severity**: critical\n**message**: Zxoiyg mnukiqqa imgxyh gwahxoe rixwdzgfn.\"\nLcxdl dpcmu gcrwhvyb qbipfn ifipq omumebq whwmupxag rnbryqneyu gih mszuxf.Tfwbmtj dxuwskbctr ostv kpmxujo tlydykp.\n**Srart Time**: 2023-05-04 03:45:54.173 +0000 UTC\n[View data](https://www.github.com)",
"tag": "markdown"
}
],
"config": {
"wide_screen_mode": true
}
}
}
```

### Feishu message
![image](./feishu_message.png)
26 changes: 26 additions & 0 deletions examples/webhook/feishu/alertmanager.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
global:
resolve_timeout: 5m
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 24h

receiver: 'web.hook'

receivers:
- name: 'web.hook'
webhook_configs:
- url: 'https://open.feishu.cn/open-apis/bot/v2/hook/<token>'
json: '{{ template "feishu.json" . }}'
send_resolved: true

inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']

templates:
- "json.tmpl"
Binary file added examples/webhook/feishu/feishu_message.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions examples/webhook/feishu/json.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{{- define "feishu.title" -}}
{{- if eq .Status "firing" -}}
[Firing {{- .Alerts.Firing | len -}}/{{- .Alerts | len -}}]
{{- else if eq .Status "resolved" -}}
[Resolved {{- .Alerts.Resolved | len -}}]
{{- else -}}
[{{- .Status | toUpper | safeJson -}}]
{{- end -}}
{{" "}}{{- range .GroupLabels.SortedPairs -}} {{- if eq .Name "alertname" -}}{{- .Value | safeJson -}}{{- end -}} {{- end -}}
{{- end -}}

{{- define "feishu.msg" -}}
### {{ template "feishu.title" . -}}\n
{{- range $idx,$elem := .Alerts.Firing -}}
{{- range .Labels.SortedPairs -}}
**{{- .Name | safeJson -}}**:{{" "}}{{- .Value | safeJson -}}\n
{{- end -}}
{{- range .Annotations.SortedPairs -}}
**{{- .Name | safeJson -}}**:{{" "}}{{- .Value | safeJson -}}\n
{{- end -}}
**Srart Time**:{{" "}}{{- .StartsAt -}}\n
{{- if eq .Status "firing" -}}
[View data]({{.GeneratorURL | safeJson}})
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "feishu.json" -}}
{
"msg_type": "interactive",
"card": {
"elements": [
{
"content": "{{- template "feishu.msg" . -}}",
"tag": "markdown"
}
],
"config": {
"wide_screen_mode": true
}
}
}
{{- end -}}
23 changes: 21 additions & 2 deletions notify/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,27 @@ func (n *Notifier) Notify(ctx context.Context, alerts ...*types.Alert) (bool, er
}

var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(msg); err != nil {
return false, err
if n.conf.JSON != "" {
body, err := n.tmpl.ExecuteTextString(n.conf.JSON, data)
if err != nil {
return false, err
}
if !json.Valid([]byte(body)) {
return false, fmt.Errorf("json format error: %s ", body)
}
if err := json.Indent(&buf, []byte(body), "", " "); err != nil {
return false, fmt.Errorf("json format error: %s ", body)
}
} else if n.conf.Text != "" {
if body, err := n.tmpl.ExecuteTextString(n.conf.Text, data); err != nil {
return false, err
} else if _, err = buf.WriteString(body); err != nil {
return false, err
}
} else {
if err := json.NewEncoder(&buf).Encode(msg); err != nil {
return false, err
}
}

var url string
Expand Down
Loading