Skip to content

Commit

Permalink
feat: grafana inlet (resolve #45)
Browse files Browse the repository at this point in the history
  • Loading branch information
muety committed Aug 21, 2022
1 parent a8a2dff commit b7e682d
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ Following inlets are currently available:
|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|
| `default` | Simply passes the request through without any changes ||
| `alertmanager` | Consumes [Alertmanager webhook requests](https://prometheus.io/docs/alerting/configuration/#webhook_config) ||
| `grafana` | Consumes [Grafana webhook requests](https://grafana.com/docs/grafana/latest/alerting/contact-points/notifiers/webhook-notifier/) ||
| `webmentionio` | Accepts [Webmention.io](https://webmention.io/) webhook requests to notify about a new Webmention of one of your articles ||
| `bitbucket` | Accepts [Bitbucket webhook requests](https://confluence.atlassian.com/bitbucket/tutorial-create-and-trigger-a-webhook-747606432.html) to notify about a pipeline status change ||

Expand Down
2 changes: 1 addition & 1 deletion config/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.0
3.3.0
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ require (
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 // indirect
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect
google.golang.org/protobuf v1.28.1 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 h1:9vYwv7OjYaky/tlAeD7C4oC9EsPTlaFl1H2jS++V+ME=
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
7 changes: 7 additions & 0 deletions inlets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ receivers:
- url: 'http://localhost:8080/api/inlets/alertmanager_webhook/5hd9mx'
```
## `grafana`
`/api/inlets/grafana/<recipient>`

Accepts, transforms and forwards alerts sent by [Grafana](https://grafana.com/docs/grafana/latest/alerting/) to a Telegram chat.

Create a new contact point with `POST` method and URL `https://telepush.dev/api/inlets/grafana/<recipient>`. Also see [webhook-notifier](https://grafana.com/docs/grafana/latest/alerting/contact-points/notifiers/webhook-notifier/).

## `bitbucket`
`/api/inlets/bitbucket/<recipient>`

Expand Down
5 changes: 0 additions & 5 deletions inlets/alertmanager/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"strings"

"github.com/muety/telepush/config"
Expand All @@ -15,10 +14,6 @@ import (
"github.com/muety/telepush/util"
)

var (
tokenRegex = regexp.MustCompile("^Bearer (.+)$")
)

type AlertmanagerInlet struct{}

func New() inlets.Inlet {
Expand Down
33 changes: 33 additions & 0 deletions inlets/grafana/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package alertmanager

import "time"

// See https://grafana.com/docs/grafana/latest/alerting/contact-points/notifiers/webhook-notifier/

type Message struct {
Receiver string `json:"receiver"`
Status string `json:"status"`
OrgId int `json:"orgId"`
Alerts []*Alert `json:"alerts"`
ExternalURL string `json:"externalURL"`
Version string `json:"version"`
GroupKey string `json:"groupKey"`
Title string `json:"title"`
State string `json:"state"`
Message string `json:"message"`
}

type Alert struct {
Status string `json:"status"`
Url string `json:"url"`
Labels map[string]string `json:"labels"`
Annotations map[string]string `json:"annotations"`
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
GeneratorURL string `json:"generatorURL"`
SilenceURL string `json:"silenceURL"`
DashboardURL string `json:"dashboardURL"`
PanelURL string `json:"panelURL"`
Fingerprint string `json:"fingerprint"`
ValueString string `json:"valueString"`
}
97 changes: 97 additions & 0 deletions inlets/grafana/webhook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package alertmanager

import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/muety/telepush/config"
"github.com/muety/telepush/inlets"
"github.com/muety/telepush/model"
"github.com/muety/telepush/resolvers"
"github.com/muety/telepush/util"
)

type GrafanaInlet struct{}

func New() inlets.Inlet {
return &GrafanaInlet{}
}

func (i *GrafanaInlet) Handler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var m Message

dec := json.NewDecoder(r.Body)
if err := dec.Decode(&m); err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}

message := transformMessage(&m)

ctx := r.Context()
ctx = context.WithValue(ctx, config.KeyMessage, message)
ctx = context.WithValue(ctx, config.KeyParams, &model.MessageParams{DisableLinkPreviews: true})

h.ServeHTTP(w, r.WithContext(ctx))
})
}

func transformMessage(in *Message) *model.DefaultMessage {
var sb strings.Builder
sb.WriteString("*Grafana* wrote:\n\n")

for i, a := range in.Alerts {
// Status
var statusEmoji string
switch a.Status {
case "firing":
statusEmoji = "❗️"
break
case "resolved":
statusEmoji = "✅"
}
sb.WriteString(fmt.Sprintf("*⌛️ Status:* %s %s\n", a.Status, statusEmoji))

// Source URL
sb.WriteString(fmt.Sprintf("*🔗 Source*: [Link](%s)\n", a.Url))

// Labels
if len(a.Labels) > 0 {
sb.WriteString(fmt.Sprintf("*🏷 Labels:*\n"))
for k, v := range a.Labels {
k = util.EscapeMarkdown(k)
v = util.EscapeMarkdown(v)
sb.WriteString(fmt.Sprintf("– `%s` = `%s`\n", k, v))
}
}

// Annotations
if len(a.Annotations) > 0 {
sb.WriteString(fmt.Sprintf("*📝 Annotations:*\n"))
for k, v := range a.Annotations {
k = util.EscapeMarkdown(k)
v = util.EscapeMarkdown(v)
sb.WriteString(fmt.Sprintf("– `%s` = `%s`\n", k, v))
}
}

if a.ValueString != "" {
sb.WriteString(fmt.Sprintf("*📌 Value String:*\n"))
sb.WriteString(fmt.Sprintf("`%s`\n", a.ValueString))
}

if i < len(in.Alerts)-1 {
sb.WriteString("---\n\n")
}
}

return &model.DefaultMessage{
Text: sb.String(),
Type: resolvers.TextType,
}
}
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/muety/telepush/handlers"
alertmanagerIn "github.com/muety/telepush/inlets/alertmanager"
bitbucketIn "github.com/muety/telepush/inlets/bitbucket"
grafanaIn "github.com/muety/telepush/inlets/grafana"
webmentionioIn "github.com/muety/telepush/inlets/webmentionio"
"github.com/muety/telepush/services"
"github.com/muety/telepush/util"
Expand Down Expand Up @@ -126,6 +127,7 @@ func main() {
apiRouter.Methods(http.MethodGet, http.MethodPost).Path("/messages/{recipient}").Handler(messageChain.Append(defaultIn.New().Handler).Then(messageHandler))
apiRouter.Methods(http.MethodGet, http.MethodPost).Path("/inlets/default/{recipient}").Handler(messageChain.Append(defaultIn.New().Handler).Then(messageHandler))
apiRouter.Methods(http.MethodGet, http.MethodPost).Path("/inlets/alertmanager/{recipient}").Handler(messageChain.Append(alertmanagerIn.New().Handler).Then(messageHandler))
apiRouter.Methods(http.MethodGet, http.MethodPost).Path("/inlets/grafana/{recipient}").Handler(messageChain.Append(grafanaIn.New().Handler).Then(messageHandler))
apiRouter.Methods(http.MethodGet, http.MethodPost).Path("/inlets/bitbucket/{recipient}").Handler(messageChain.Append(bitbucketIn.New().Handler).Then(messageHandler))
apiRouter.Methods(http.MethodGet, http.MethodPost).Path("/inlets/webmentionio/{recipient}").Handler(messageChain.Append(webmentionioIn.New().Handler).Then(messageHandler))

Expand Down

0 comments on commit b7e682d

Please sign in to comment.