この記事は Mackerel Advent Calendar 2025 の16日目の記事です。15日目は
id:kazeburo の JSONL ログから柔軟にメトリクスを生成する ― mackerel-plugin-jsonl を作った話 でした。
みなさまMackerelのアラート履歴はどのように確認していますか?
- Web上からアラートの一覧を眺める?
- ツールで集計して以前との変化を確認する?
それとは別に、会議でダッシュボードを見る際にこんな状況になったことはありませんか?
- メトリックとイベントの突き合わせが早押しクイズになってしまう
- 「そのメトリックが変化したのはその日に障害があったのと関連していて...」など
- メトリックの変化をの理由を調べるアクションは出るものの、監視ルールの見直しなどはあまり話題に上がらない
その結果監視ルールの見直しもあまりできず、その他のアクションを出す会話もよくわかっている人頼みになってしまいがちでした。
こういった課題を解決するために、アラートの履歴をグラフアノテーションとして投稿し、ダッシュボード上で確認する取り組みを始めました。
(ちなみにダッシュボードでアノテーションを表示できる機能は2023/12にリリースされました。)
ダッシュボードでアラートをアノテーションに投稿すると見た目はこんな感じになります。

アノテーションの詳細には実際のアラートのURLを書くことでリンクになりそのまま当時のアラートへすぐ飛ぶこともできます。

もしprepalertも利用していれば、その先のアラートを開くだけでログや集計結果を確認でき一時調査もその場で済ませることができます。
これらにより、誰でもそのタイミングで何があったのかを調べやすくなり、効率よく改善を進めることがやりやすくなります。
目的別にアノテーションを分類する
実際には監視ルールには即時対応が必要なものだったり、キャパシティプランニングの通知目的であったりなど重要度が様々なものが存在します。
また、アラートがマイクロサービスなどサブコンポーネントにどのように影響を与え、逆にサブコンポーネントのアラートが本体にどのように影響を与えているかというのを知りたい場合もあります。
そういった監視ルールのアラートを同じように一箇所のサービス・ロールに追加することでアラートの傾向自体は分かりやすくなりますが、障害時などに大量のアラートでアノテーションが埋まってしまい、振り返るのが難しくなるというデメリットもありました。
そんな中、最近では以下のように監視名を設定していました。
| 監視ルールの prefix | 用途 |
|---|---|
| Alert:* | SLO自体もしくはSLOに大きな影響があり営業時間外でもすぐに対応が必要 |
| Issue:* | SLOにすぐには影響がなく、営業日などに対応すれば良い |
| Info:* | キャパシティプランニングや通知目的 |
この監視ルールをもとに投稿先を分類することで、アノテーションが混ざらないようにし振り返りやすくすることを行いました。
今回はこのような分類で投稿先のロールを変えるようにしました。
*-Only*に書いてあるアラートのみ表示- (例: Alert-OnlyならAlert:*から始まるアラートのみを投稿)
*-Level*のレベル以上のアラートのみ表示(ログレベルのようなイメージ)- (例: Issue-LevelならIssueとAlertのアラートのみを投稿)
監視ルールと投稿先の対応先はこんな感じになっています。
| 監視ルールのprefix | アノテーション投稿先ロール |
|---|---|
| Alert:* | Alert-Only, Alert-Level, Issue-Level, Info-Level |
| Issue:* | Issue-Only, Issue-Level, Info-Level |
| Info:* | Info-Only, Info-Level |
ダッシュボードを定期的に確認する際に、用途に応じて表示するアノテーションのロールを切り替えることで効率よくアラートを確認できます。
例えば、
- Alert-Levelでアノテーションを表示して、SLOに関連するアラート設定になっているか確認する
- SLI/SLOの状況と比較してアラートが多すぎる/少なすぎるを確認する
- Issue/Infoのみのアノテーションを表示して、キャパシティプランニングのアラートを確認する
- 重要なアラートをあえて表示しないことで埋もれずに確認できる
こういったようにアラートとメトリックを適切に紐づけて確認することで、メトリックの変化があった際にアラートのアノテーションで関連がすぐわかるのはもちろん、逆にアノテーションがない時に「アラート設定していないけど大丈夫?」みたいな会話を何も考えなくとも誰もが素早くできるようになるというメリットもあると思います。
EventBridge + Step Functionsで実装する
最初はこの機能をprepalertで実現しようとしていましたが、実現したいことの単純さもありEventBridge + Step Functionsで実装することにしました。
まずは、公式ドキュメントの通りにEventBridgeの設定を有効にしておきます。
その後、こんな感じの条件でアラートがクローズした際にStep Functionsが実行されるようにしておきます。
{ "source": [{ "prefix": "aws.partner/mackerel.io" }], "detail": { "alert": { "isOpen": [false] } } }
Step Functionsの定義はたったこれだけで、あとはアラートが来ると監視名を元に、適切な投稿先にアノテーションが投稿されるようになります。
{ "StartAt": "PostGraphAnnotation", "States": { "PostGraphAnnotation": { "QueryLanguage": "JSONata", "End": true, "Type": "Task", "Arguments": { "ApiEndpoint": "https://api.mackerelio.com/api/v0/graph-annotations", "Authentication": { "ConnectionArn": "ConnectionArn" }, "Method": "POST", "RequestBody": { "title": "{% $states.input.detail.alert.monitorName %}", "description": "{% $states.input.detail.alert.url %}", "from": "{% $states.input.detail.alert.openedAt %}", "to": "{% $states.input.detail.alert.closedAt %}", "service": "annotation-service", "roles": "{% $contains($states.input.detail.alert.monitorName, /^Alert:/) ? ['Alert-Only', 'Alert-Level', 'Issue-Level', 'Info-Level'] : $contains($states.input.detail.alert.monitorName, /^Issue:/) ? ['Issue-Only', 'Issue-Level', 'Info-Level'] : $contains($states.input.detail.alert.monitorName, /^Info:/) ? ['Info-Only', 'Info-Level'] : [] %}" } }, "Resource": "arn:aws:states:::http:invoke" } } }
今回は単純にJSONataで入力を変換することで1ステップだけで実現することができましたが、もっと細かく場合分けをしたい場合でも、Step FunctionsのChoiceやJSONataなどを組み合わせることでユースケースにあった形で実現ができると思います。
こんな感じでStep FunctionsのJSONataサポートもあり、Mackerelのイベントから何かするみたいなのをLambda要らずで簡単に実現できるようになりました。アラートに限らずMackerelのイベントを色々とStep Functionsに送ってみて運用をイージーにしてみてはいかがでしょうか。