2022/04/21に更新

【GASで監視】GASのエラー通知をSlackに転送する

SlackAPI業務改善トリガー

トリガーで実行されたスクリプトが失敗したときに送信されるエラー通知メールを、Slackに転送するGoogle Apps Scriptです。メールはトリガーの設定者にしか飛ばないため、他のメンバーに共有したいときにどうぞ。

こんな悩みを解決します


  • トリガーで実行しているGASのエラーメールを、メンバー全員に通知したい。
  • メールの自動転送ではなく、Slackに通知したい。

用意するもの


特にありません。
スプレッドシートのコンテナバインド型スクリプトとして作成していますが、スタンドアロン型でも問題なく動くはずです。

このスクリプトで出来ること


  • Gmailに届いた、GASのエラーメール(Summary of failures for Google Apps Script)をSlackに通知することができます。
  • 検知間隔はパラメータの変更およびトリガーの間隔を変えることで、任意のタイミングに変更できます。

使い方


1.事前準備

このようなエラーメールが来ていることをご確認ください(サンプルのメールがないと動作確認ができないため)。

Slackと連携するために、「Incoming Webhook」を使用します。
GASからSlackに投稿するための「入り口」を作ります。
詳しい手順はこちらをご確認ください。

https://myfunc.jp/items/00066/index.html

Webhook URLが発行されたら完了です。URLをコピーしておきましょう。

コードを少し書き換えます。事前設定エリアの「SlackのWebhook URL」、「メールの検索期間」をご自身の環境に合わせて書き換えてください。

書き換えて保存したら、関数「onOpen」を一度実行して権限の承認をしてください。

2.動作確認

実際はトリガーで実行しますが、一度確認のため手動で実行してみます。
上のメニューにある「スクリプト実行」から「GASのエラー通知メールをSlackに転送する」を実行します。

事前準備で用意したSlackチャンネルに対して、メッセージが届けば成功です。

3.トリガーの設定

動作確認に問題なければ、トリガーで定期的に実行しましょう。
実行間隔は事前設定で指定した時間と合わせてください。差があると転送が漏れたり、同じエラーが複数回転送されてしまうかもしれません。
サンプルスクリプトでは過去24時間以内のメールを対象にしているので、トリガーは1日に1回で登録してみます。

  • 実行する関数: send_error_notification_to_slack
  • 実行するデプロイ: HEAD
  • イベントのソース: 時間主導型
  • 時間ベースのトリガーのタイプ: 日付ベースのタイマー
  • 時刻をを選択: 午前9時〜10時

スクリプト


/**
 * このスクリプトの説明、使い方はこちら。
 * https://myfunc.jp/items/00073/index.html
 */

function onOpen() {
  // スプレッドシートを開いたときに実行される関数

  // UIの取得
  const ui = SpreadsheetApp.getUi()

  // メニューの表示名
  const menu = ui.createMenu('スクリプト実行');

  // メニューに追加するボタン
  menu.addItem('GASのエラー通知メールをSlackに転送する', 'send_error_notification_to_slack');

  // メニューを画面に追加する
  menu.addToUi();
}

function send_error_notification_to_slack() {

  // ######### 事前設定ここから ########

  // SlackのWebhook URLを入力してください
  const slack_webhook_url = 'https://hooks.slack.com/services/********************';

  // 過去何時間のメールを検索するか指定してください(24だと24時間以内のメールから、GASのエラー通知さがします);
  const hours = 24;

  // ######### 事前設定ここまで ########


  // 検索期間を指定するための日付を取得する
  let date = new Date(); // 現在の日時を取得
  let unixtime = Math.floor(date.getTime() / 1000); // メール検索条件に使うため、UNIX時に変換する
  unixtime = unixtime - (hours * 3600); // 事前設定で指定された時間分、マイナスする

  // メールを検索するための条件を作る
  const query = 'Subject:"Summary of failures for Google Apps Script" after:' + unixtime;

  // Gmailからメールを取得する
  const threads = GmailApp.search(query);

  if (threads.length == 0) {
    // スレッド(メール)が1つも見つからない場合は処理を終了する
    return;
  }


  // メールから必要な部分を抜き出して格納するための配列を宣言する
  let result = [];

  // スレッドを1つずつ処理する
  for (let i = 0; i < threads.length; i++) {

    // 1スレッドに複数のメッセージ(=メール)が入っているので取得
    let messages = threads[i].getMessages();

    // メールを1通ずつ処理していく
    for (let j = 0; j < messages.length; j++) {

      // メール本文を取得する。HTML形式ではなくプレーンテキストとして取得。
      let body = messages[j].getPlainBody();

      // メールを改行コードで配列に分割する。\nではなく\r\nが使われている
      body = body.split('\r\n');

      // メール本文から必要な部分を取り出すために、flagをセット。trueなら取得、falseなら不要部分。
      let flag = false;

      // メール本文を1行ずつ処理していく
      for (let k = 0; k < body.length; k++) {

        // 空の行はスキップ
        if (body[k] == '') {
          continue;
        }

        // 項目名の次の行から取得したいので、この文字列を見つけたらflagをtrueにする。
        if (body[k].match(/起動 関数 エラー メッセージ トリガー End/)) {
          flag = true;
          continue;
        }

        // この行以降は不要な部分なので、flagをfalseに戻してループを終了する。
        if (body[k].match(/よろしくお願いいたします。/)) {
          flag = false;
          break;
        }

        // flagがtrueなら、配列に追加する。1つのエラーメッセージが2行に分かれてしまっているので2行を連結してカウンタkを進める
        if (flag == true) {
          result.push(body[k] + body[k + 1]);
          k++;
        }
      }
    }
  }

  // メール本文の配列を改行で連結し、Slack投稿用テキストとする
  const text = result.join('\n');

  // SlackのWebhook URLに投稿するデータをまとめる
  const json =
  {
    'username': 'GASのエラー通知',
    'icon_emoji': ':warning:',
    'text': text
  };

  // SlackのWebhook URLに送信するデータをJSONに変換する
  const payload = JSON.stringify(json);

  // UrlFetchAppで使用するメソッドやコンテントタイプを指定
  const options =
  {
    'method': 'post',
    'contentType': 'application/json',
    'payload': payload
  };

  // Slackに送信
  UrlFetchApp.fetch(slack_webhook_url, options);

}

関連するアプリ


タグ一覧

最新のアプリ

人気のアプリ

ページトップに戻る
myfunc.jp