Azure Application Insights への特定のログ出力を Azure Monitor で監視し、Slack 通知する方法

先日、Azure Function の異常終了を検知し、Slack に通知する仕組みを構築しました。
今回は、Azure Application Insights に特定のログが出力されたら Slack に通知する仕組みを構築する手順を書きます。

使用するもの

  • Slack
    • 通知を受けるチャンネル
    • Incoming Webhook
  • Azure
    • Azure Application Insights ※エラーログの出力先
    • Azure Monitor ※エラーログを監視する
      • アクショングループ
      • アラートルール
    • Logic App ※エラーログ発生時に、Azure Monitor からトリガーし、Slack Incoming Webhook にメッセージを送信

概要

  1. Azure Function が異常終了すると Azure Function に severityLevel が 3 のログ(※1)が出力される
  2. Azure Monitor の アラートルール で上記のログの出力を監視
  3. ログを検知したら、アラートルール の アクショングループ から Locig App をトリガーする
    • アラートルールから直接、Slack の Incoming Webhook にメッセージを送信できない為、Locic Apps 経由で送信します
      • Logic Apps で Slack の Incoming Webhook に対応した payload を生成して送信する必要がある
  4. Logic Apps から Slack の Incoming Webhook にメッセージを送信

※1 のログを検索する KQL

traces | where operation_Name contains "対象Function名" 
  and message contains "Executed 'Functions.対象Function名'"
  and severityLevel != 1

構築手順

  1. Incoming Webhook の URL を取得
  2. (Azure Monitor から Logic App に送信されるペイロードを取得しておく)
    • Logic App 作成時に、要求本文のJSONスキーマ を設定します。この際、実際のペイロードを元に、スキーマを生成する為、予めペイロードを取得しておきます。
  3. Logic App を作成
  4. Azure Monitor の アクショングループ を作成
  5. Azure Monitor の アラートルール を作成

0. 監視対象の Azure Function を作成

  • 今回はログ監視の構築が主旨の為、Azure Portal 上でTimer Trigger の Function を作成し、5分毎に実行結果のログが Application Insights に出力されるようにしておきます

1. Incoming Webhook の URL を取得

  • 後ほど Logic App からの送信先に指定しますので、Webhook URL をコピーしておきます。

2. Azure Monitor から Logic App に送信されるペイロードを取得

  • ※後ほど、Logic Appのワークフローで送信するSlack通知メッセージに、アラート内容等を含める為に、 要求本文のJSONスキーマ の作成が必要になります

    • 要求本文のJSONスキーマ の作成に、実際のペイロードが必要な為、予め取得しておきます
  • 公式ドキュメントにペイロードのサンプルがあるので、どのサンプルが利用できれるかを予め把握できている場合は 手順 2. はスキップしてok です。

  • 取得方法としては、Logic Appを仮設定で作成し、アクショングループの作成(手順 4.)、及び、アラートルールの作成(手順 5.)を行い、一度、実際にペイロードを受信します

  • トリガーを HTTP要求の受信時 とし、要求本文のJSONスキーマ{} で作成します

    • (ここではペイロードが取得しただけなので) 以降のアクション(= HTTP の部分)は未設定でもok
  • (アラートルールからLogic Appがトリガーされるのを待つ)

  • Logic Appsの実行履歴より、ペイロードを取得します

  • 採取したペイロード

{
  "schemaId": "azureMonitorCommonAlertSchema",
  "data": {
    "essentials": {
      "alertId": "/subscriptions/c86f8ad8-7f32-4f84-8cf5-9ba182bd2a40/providers/Microsoft.AlertsManagement/alerts/ddc294f2-8510-62be-114c-4fd9e3300027",
      "alertRule": "TimerTrigger1関数のエラー終了",
      "severity": "Sev2",
      "signalType": "Log",
      "monitorCondition": "Fired",
      "monitoringService": "Log Alerts V2",
      "alertTargetIDs": [
        "/subscriptions/c86f8ad8-7f32-4f84-8cf5-9ba182bd2a40/resourcegroups/blog20231223/providers/microsoft.insights/components/sampleapptimertrigger"
      ],
      "configurationItems": [
        "/subscriptions/c86f8ad8-7f32-4f84-8cf5-9ba182bd2a40/resourceGroups/blog20231223/providers/microsoft.insights/components/SampleAppTimerTrigger"
      ],
      "originAlertId": "bef8427b-d266-440e-84be-4cbe66cd588e",
      "firedDateTime": "2023-12-23T03:23:02.1147771Z",
      "description": "TimerTrigger1関数がエラー終了しました",
      "essentialsVersion": "1.0",
      "alertContextVersion": "1.0"
    },
    "alertContext": {
      "properties": {},
      "conditionType": "LogQueryCriteria",
      "condition": {
        "windowSize": "PT1H",
        "allOf": [
          {
            "searchQuery": "traces | where operation_Name contains \"TimerTrigger1\" \nand message contains \"Executed 'Functions.TimerTrigger1'\"\nand severityLevel == 1",
            "metricMeasureColumn": null,
            "targetResourceTypes": "['microsoft.insights/components']",
            "operator": "GreaterThan",
            "threshold": "1",
            "timeAggregation": "Count",
            "dimensions": [],
            "metricValue": 8,
            "failingPeriods": {
              "numberOfEvaluationPeriods": 1,
              "minFailingPeriodsToAlert": 1
            },
            "linkToSearchResultsUI": "https://portal.azure.com#@6a02fd2f-7f98-4f16-9639-951b0994621f/blade/Microsoft_Azure_Monitoring_Logs/LogsBlade/source/Alerts.EmailLinks/scope/%7B%22resources%22%3A%5B%7B%22resourceId%22%3A%22%2Fsubscriptions%2Fc86f8ad8-7f32-4f84-8cf5-9ba182bd2a40%2FresourceGroups%2Fblog20231223%2Fproviders%2Fmicrosoft.insights%2Fcomponents%2FSampleAppTimerTrigger%22%7D%5D%7D/q/eJxVjDsOwkAMBXtOYW2TDikHSAkVokqPrM3TxhLrRbYDQeLwfKpQTTMzYZzh9KLHDAO1G4xDml7OXEG5abCoUxqlwkaTUmB9oh3rRBXuXLbWYUVeAhN1x0Xz9%2BP7v7JLv9Jxh0k8Tx9eaRiofwM%3D/prettify/1/timespan/2023-12-23T02%3a22%3a25.0000000Z%2f2023-12-23T03%3a22%3a25.0000000Z",
            "linkToFilteredSearchResultsUI": "https://portal.azure.com#@6a02fd2f-7f98-4f16-9639-951b0994621f/blade/Microsoft_Azure_Monitoring_Logs/LogsBlade/source/Alerts.EmailLinks/scope/%7B%22resources%22%3A%5B%7B%22resourceId%22%3A%22%2Fsubscriptions%2Fc86f8ad8-7f32-4f84-8cf5-9ba182bd2a40%2FresourceGroups%2Fblog20231223%2Fproviders%2Fmicrosoft.insights%2Fcomponents%2FSampleAppTimerTrigger%22%7D%5D%7D/q/eJxVjDsOwkAMBXtOYW2TDikHSAkVokqPrM3TxhLrRbYDQeLwfKpQTTMzYZzh9KLHDAO1G4xDml7OXEG5abCoUxqlwkaTUmB9oh3rRBXuXLbWYUVeAhN1x0Xz9%2BP7v7JLv9Jxh0k8Tx9eaRiofwM%3D/prettify/1/timespan/2023-12-23T02%3a22%3a25.0000000Z%2f2023-12-23T03%3a22%3a25.0000000Z",
            "linkToSearchResultsAPI": "https://api.applicationinsights.io/v1/apps/ec3b3196-ebf9-49af-814c-585faba48434/query?query=traces%20%7C%20where%20operation_Name%20contains%20%22TimerTrigger1%22%20%0Aand%20message%20contains%20%22Executed%20%27Functions.TimerTrigger1%27%22%0Aand%20severityLevel%20%3D%3D%201&timespan=2023-12-23T02%3a22%3a25.0000000Z%2f2023-12-23T03%3a22%3a25.0000000Z",
            "linkToFilteredSearchResultsAPI": "https://api.applicationinsights.io/v1/apps/ec3b3196-ebf9-49af-814c-585faba48434/query?query=traces%20%7C%20where%20operation_Name%20contains%20%22TimerTrigger1%22%20%0Aand%20message%20contains%20%22Executed%20%27Functions.TimerTrigger1%27%22%0Aand%20severityLevel%20%3D%3D%201&timespan=2023-12-23T02%3a22%3a25.0000000Z%2f2023-12-23T03%3a22%3a25.0000000Z"
          }
        ],
        "windowStartTime": "2023-12-23T02:22:25Z",
        "windowEndTime": "2023-12-23T03:22:25Z"
      }
    },
    "customProperties": {}
  }
}

3. Logic App を作成

  • プランの種類=消費 で作成します

  • ロジック アプリ デザイナー でワークフローを作成します

  • アラートルール からの HTTPリクエストをトリガーとする想定の為、HTTP 要求の受診時 を選択します

  • 上記で取得したペイロードを使用してスキーマを生成します

  • +新しいステップ を押下し、HTTP アクションを追加します

    • URI に Slack の Incoming Webhook のエンドポイントを指定
    • 本文 に、Slack Incoming Webhook のメッセージの送り方 (※2) に準拠したJSONを登録
      • メッセージに 動的なコンテンツの追加 よりdescriptionlinkToSearchResultsUI を含める事で、アラート概要と、当該KQLへのリンクをメッセージに含める事ができます
  • ※2 Slack Incoming Webhook のメッセージの送り方

  • 保存します

4. Azure Monitor の アクショングループ を作成

  • アクションタブより、上記で設定した Logic Apps をアラート発生時のアクションとして設定します

  • テストを実行し、Logic App 経由で Slack 通知が届く事を確認しておきます

5. Azure Monitor の アラートルール を作成

  • 監視対象の Function の 監視 > ログ より、Application Insights の画面に移動します

  • 監視対象となるログを検索し、+新しいアラートルール を押下します

※今回は severityLevel3 のログは出力されないので 1 を監視対象にしています

traces | where operation_Name contains "TimerTrigger1" 
and message contains "Executed 'Functions.TimerTrigger1'"
and severityLevel == 1
  • 以下の内容でアラートルールを作成します

  • 留意点

    • 以下の意味になります
      • 集計の粒度 = 過去何分間で出力されたログをアラート対象にするか
      • 評価の頻度 = 何分起きにログをチェックするか
    • 今回は、 集計の粒度 = 1時間、評価の頻度 = 5分 とし、過去1時間以内のログを、5分おきに監視します
  • アラート タブより、アラート検知時のアクションを、上記で作成したアクショングループに設定します

  • 詳細 タブより、アラートルール名 アラートルールの説明 を設定します

    • アラートルールの説明手順 3.動的なコンテンツ として取得できるので、 Slack 通知メッセージで利用します

Slack通知内容

  • エラーログを検知すると以下のSlack通知が飛ぶようになりました!
    • リンクから対象のエラーログに飛べます