Merge pull request #80 from t0mk/html_template
HTML template for notifications with FlowDock
This commit is contained in:
commit
80743177b8
|
@ -20,6 +20,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
|
htmltemplate "html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
@ -62,6 +63,23 @@ Payload labels:
|
||||||
{{range $label, $value := .Alert.Payload}}
|
{{range $label, $value := .Alert.Payload}}
|
||||||
{{$label}} = "{{$value}}"{{end}}`))
|
{{$label}} = "{{$value}}"{{end}}`))
|
||||||
|
|
||||||
|
var contentTmpl = htmltemplate.Must(htmltemplate.New("content").Parse(
|
||||||
|
`<p><b><i>{{.Alert.Description}}</i></b></p>
|
||||||
|
|
||||||
|
<div><i>Grouping labels</i></div>
|
||||||
|
<ul>
|
||||||
|
{{range $label, $value := .Alert.Labels}}
|
||||||
|
<li><b>{{$label}}:</b> {{$value}}</li>
|
||||||
|
{{end}}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div><i>Payload labels</i></div>
|
||||||
|
<ul>
|
||||||
|
{{range $label, $value := .Alert.Payload}}
|
||||||
|
<li><b>{{$label}}:</b> {{$value}}</li>
|
||||||
|
{{end}}
|
||||||
|
</ul>`))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
notificationBufferSize = flag.Int("notification.buffer-size", 1000, "Size of buffer for pending notifications.")
|
notificationBufferSize = flag.Int("notification.buffer-size", 1000, "Size of buffer for pending notifications.")
|
||||||
pagerdutyAPIURL = flag.String("notification.pagerduty.url", "https://events.pagerduty.com/generic/2010-04-15/create_event.json", "PagerDuty API URL.")
|
pagerdutyAPIURL = flag.String("notification.pagerduty.url", "https://events.pagerduty.com/generic/2010-04-15/create_event.json", "PagerDuty API URL.")
|
||||||
|
@ -356,7 +374,10 @@ type flowdockMessage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *notifier) sendFlowdockNotification(op notificationOp, config *pb.FlowdockConfig, a *Alert) error {
|
func (n *notifier) sendFlowdockNotification(op notificationOp, config *pb.FlowdockConfig, a *Alert) error {
|
||||||
flowdockMessage := newFlowdockMessage(op, config, a)
|
flowdockMessage, err := newFlowdockMessage(op, config, a)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
url := strings.TrimRight(*flowdockURL, "/") + "/" + config.GetApiToken()
|
url := strings.TrimRight(*flowdockURL, "/") + "/" + config.GetApiToken()
|
||||||
jsonMessage, err := json.Marshal(flowdockMessage)
|
jsonMessage, err := json.Marshal(flowdockMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -372,7 +393,7 @@ func (n *notifier) sendFlowdockNotification(op notificationOp, config *pb.Flowdo
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFlowdockMessage(op notificationOp, config *pb.FlowdockConfig, a *Alert) *flowdockMessage {
|
func newFlowdockMessage(op notificationOp, config *pb.FlowdockConfig, a *Alert) (*flowdockMessage, error) {
|
||||||
status := ""
|
status := ""
|
||||||
switch op {
|
switch op {
|
||||||
case notificationOpTrigger:
|
case notificationOpTrigger:
|
||||||
|
@ -380,17 +401,22 @@ func newFlowdockMessage(op notificationOp, config *pb.FlowdockConfig, a *Alert)
|
||||||
case notificationOpResolve:
|
case notificationOpResolve:
|
||||||
status = "resolved"
|
status = "resolved"
|
||||||
}
|
}
|
||||||
|
contentBuf := &bytes.Buffer{}
|
||||||
|
err := contentTmpl.Execute(contentBuf, struct{ Alert *Alert }{Alert: a})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
msg := &flowdockMessage{
|
msg := &flowdockMessage{
|
||||||
Source: "Prometheus",
|
Source: "Prometheus",
|
||||||
FromAddress: config.GetFromAddress(),
|
FromAddress: config.GetFromAddress(),
|
||||||
Subject: html.EscapeString(a.Summary),
|
Subject: html.EscapeString(a.Summary),
|
||||||
Format: "html",
|
Format: "html",
|
||||||
Content: fmt.Sprintf("*%s %s*: %s (<%s|view>)", html.EscapeString(a.Labels["alertname"]), status, html.EscapeString(a.Summary), a.Payload["generatorURL"]),
|
Content: contentBuf.String(),
|
||||||
Link: a.Payload["generatorURL"],
|
Link: a.Payload["generatorURL"],
|
||||||
Tags: append(config.GetTag(), status),
|
Tags: append(config.GetTag(), status),
|
||||||
}
|
}
|
||||||
return msg
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type webhookMessage struct {
|
type webhookMessage struct {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -225,3 +226,74 @@ func TestSendWebhookNotification(t *testing.T) {
|
||||||
t.Errorf("incorrect webhook notification: Expected: %s Actual: %s", expected, msg)
|
t.Errorf("incorrect webhook notification: Expected: %s Actual: %s", expected, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSendFlowdockNotification(t *testing.T) {
|
||||||
|
var body []byte
|
||||||
|
var url string
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var err error
|
||||||
|
url = r.URL.String()
|
||||||
|
body, err = ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error reading flowdock notification: %s", err)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
flowdockURL = &ts.URL
|
||||||
|
testApiToken := "123"
|
||||||
|
testFromAddress := "from@prometheus.io"
|
||||||
|
testTag := []string{"T1", "T2"}
|
||||||
|
|
||||||
|
config := &pb.FlowdockConfig{
|
||||||
|
ApiToken: &testApiToken,
|
||||||
|
FromAddress: &testFromAddress,
|
||||||
|
Tag: testTag,
|
||||||
|
}
|
||||||
|
alert := &Alert{
|
||||||
|
Summary: "Testsummary",
|
||||||
|
Description: "Test alert description, something went wrong here.",
|
||||||
|
Labels: AlertLabelSet{
|
||||||
|
"alertname": "TestAlert",
|
||||||
|
},
|
||||||
|
Payload: AlertPayload{
|
||||||
|
"payload_label1": "payload_value1",
|
||||||
|
"generatorURL": "http://graph",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
n := ¬ifier{}
|
||||||
|
err := n.sendFlowdockNotification(notificationOpTrigger, config, alert)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error sending flowdock notification: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg flowdockMessage
|
||||||
|
|
||||||
|
expectedUrl := "/" + testApiToken
|
||||||
|
if url != expectedUrl {
|
||||||
|
t.Error("Flowdock message POSTed to wrong URL, expected %s and got %s", expectedUrl, url)
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(body, &msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error unmarshalling flowdock notification: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentBuf := &bytes.Buffer{}
|
||||||
|
err = contentTmpl.Execute(contentBuf, struct{ Alert *Alert }{Alert: alert})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error expanding expected HTML content for Flowdock message: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := flowdockMessage{
|
||||||
|
Source: "Prometheus",
|
||||||
|
FromAddress: testFromAddress,
|
||||||
|
Subject: html.EscapeString(alert.Summary),
|
||||||
|
Format: "html",
|
||||||
|
Content: contentBuf.String(),
|
||||||
|
Link: "http://graph",
|
||||||
|
Tags: append(testTag, "firing"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(msg, expected) {
|
||||||
|
t.Errorf("incorrect Flowdock notification: Expected: %s Actual: %s", expected, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue