LoginSignup
2
2

More than 5 years have passed since last update.

PagerDuty互換APIを作ってAlertmanagerから通知させる〜其の壱〜

Posted at

Alertmanagerからの通知先に自作システムを利用したいが、webhookだとなんかダサいかなと思っているので、タイトルの通りに最近巷でアツいPagerDutyの互換APIを自作システムに持たせてアラートを送りたくなったのでやってみました。

其の壱のゴール

Alertmanagerのpagerduty_configで互換APIを指定し、アラート通知が届くこと

Alertmanagerとは

メールやSlack、webhookなどと言った先に通知を送るシステムです。Prometheusと併せてよく使われますが、別のプロダクトで単体でも使えます。

また、以下のような特徴を持ちます。

  • グルーピング:類似のアラートを、単一の通知に分類
  • インヒビション:他のアラートが発生している時に、特定のアラート通知を抑制する
  • サイレンス:一定時間、アラートをミュートにする

PagerDutyとは

システム管理者およびサポートチーム向けのアラーム集約およびディスパッチサービスです。監視ツールからアラートを収集し、すべての監視アラームを全体的に表示し、問題がある場合は担当者に警告します。

参照:PagerDuty - Digital Stacks

本編

TL;DR

できた!ソースはこちら(Transnano / pagerduty-api · GitLab

互換API

最近はGoにハマっているのでGo/Ginで書いてみました。(サブタイトルを其の壱と付けたようにまだまだここは適当です。とりあえずエンドポイントとエラーコードを揃えたくらいです。)
内容としてはAlertmanagerからの通知を受け取ってそのまま出力します。

...
    r.POST("/v2/enqueue", func(c *gin.Context) {
        buf := make([]byte, 2048)
        n, _ := c.Request.Body.Read(buf)
        b := string(buf[0:n])
        fmt.Println(b)
        num := len(b)
        switch {
        case num == 0:
            c.JSON(http.StatusBadRequest, gin.H{
                "status":  "invalid event",
                "message": "Event object is invalid",
                "errors":  "Length of 'routing_key' is incorrect (should be 32 characters)",
            })
        case num > 500:
            c.AbortWithStatus(http.StatusTooManyRequests)
        default:
            c.JSON(http.StatusAccepted, gin.H{
                "status":    "success",
                "message":   "Event processed",
                "dedup_key": "samplekeyhere",
            })
        }
    })
    r.Run()
...

Alertmanagerの設定

通知に関する設定は以下のようなymlファイルになります。

---
receivers:
- name: 'team-X-pager'
  pagerduty_configs:
  - routing_key: dummykey_length_is_32_characters
    url: http://pagerduty-api:8080/v2/enqueue
---

ポイントはPagerDutyのV2のAPIを呼び出すため、routing_keyを使っていることと自作したシステムのエンドポイントをurlで指定していることです。

サンプル

こちらのソースsample · master · Transnano / pagerduty-api · GitLabにも用意してまが、以下の手順でAlertmangerにアラート発生をリクエストすると自作システムが出力したログを確認できます。

# Alertmangerにアラート発生をリクエストする
$ curl -d '[{"labels": {"Alertname": "PagerDuty Test"}}]' http://localhost:9093/api/v1/alerts

# 自作システムのログ

[GIN-debug] POST   /v2/enqueue               --> main.main.func3 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default

...(障害発生)

{"routing_key":"dummykey_length_is_32_characters","dedup_key":"<dedup_key>","event_action":"trigger","payload":{"summary":"[FIRING:1] PagerDuty Test ","source":"AlertManager","severity":"error","custom_details":{"firing":"Labels:\n - alertname = PagerDuty Test\nAnnotations:\nSource: \n","num_firing":"1","num_resolved":"0","resolved":""}},"client":"AlertManager","client_url":"http://alertmanager:9093/#/alerts?receiver=team-X-pager"}

[GIN] 2019/03/22 - 11:00:49 | 202 |      1.3033ms |      172.25.0.4 | POST     /v2/enqueue

...(障害復旧)

{"routing_key":"dummykey_length_is_32_characters","dedup_key":"<dedup_key>","event_action":"resolve","payload":{"summary":"[RESOLVED] PagerDuty Test ","source":"AlertManager","severity":"error","custom_details":{"firing":"","num_firing":"0","num_resolved":"1","resolved":"Labels:\n - alertname = PagerDuty Test\nAnnotations:\nSource: \n"}},"client":"AlertManager","client_url":"http://alertmanager:9093/#/alerts?receiver=team-X-pager"}

[GIN] 2019/03/22 - 11:15:31 | 202 |       207.8µs |      172.25.0.4 | POST     /v2/enqueue

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2