LoginSignup
1
0

More than 1 year has passed since last update.

JS7® JobScheduler Slack通知設定

Last updated at Posted at 2022-04-10

概要

JS7 JobScheduler にて、WorkFlowの正常終了/エラー時に、Slack通知を送る方法です。
(通知の基本的な説明は省略します)
CommandFragmentを使った基本的な設定と、通知をカスタマイズする方法を説明します。

前提条件

  • JS7 jobscheduler の環境準備、初期設定を済ませていること。
    まだの方はこちらから
    JS7® JobScheduler 初期設定、サンプルWorkFlowの登録
  • 通知設定の基本的な理解ができていること
    こちらの記事でまとめてあります。
    JS7® JobScheduler メール通知設定
  • Slack通知用のIncoming Webhook のURLを用意してください。
  • 本例はJOCがLinux環境を前提としています。
    WindowsでSlack通知の設定を行うにはCommandFragmentをPowerShell用などに置き換えてください。
  • Slack通知に curlコマンドを使用します。
    Docker sosberlin/js7:joc-2-x-x にはcurlが含まれていません。別途追加してください。
    同様に、Docker版ではdateコマンドでの処理用にcoreutilsを追加してください。

Slack通知 基本設定

まずは、CommandFragment を使った基本的な設定方法でSlack通知設定を行います。

MessageFragment(本文)

まず通知用のメッセージを定義します。
MessageFragments から、 Add Child Node でMessageを新規作成します。
image.png

名前は slack_on_successとします。
image.png

本文は例えばこんな感じです。
レイアウトブロックで適当なメッセージを作っています。
モニター変数の箇所は、実際の通知文では値が入ります。
※お好みで加工してください

slack_on_success
{
  "attachments": [
    {
      "color": "#28a745",
      "blocks": [
        {
          "type": "header",
          "text": {
            "type": "plain_text",
            "text": "Workflow: ${MON_O_WORKFLOW_NAME} - ${MON_O_SEVERITY}"
          }
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Controller ID:*\n${MON_O_CONTROLLER_ID}"
            },
            {
              "type": "mrkdwn",
              "text": "*Agent ID:*\n${MON_OS_AGENT_ID}"
            }
          ]
        },
        {
          "type": "divider"
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Order ID:*\n<${JOC_HREF_ORDER}|${MON_O_ORDER_ID}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Order Log:*\n<${JOC_HREF_ORDER_LOG}|Link>"
            },
            {
              "type": "mrkdwn",
              "text": "*Status:*\n${MON_O_SEVERITY}"
            },
            {
              "type": "mrkdwn",
              "text": "*Time elapsed:*\n${MON_O_TIME_ELAPSED}"
            },
            {
              "type": "mrkdwn",
              "text": "*Start Time:*\n${MON_O_START_TIME}"
            },
            {
              "type": "mrkdwn",
              "text": "*End Time:*\n${MON_O_END_TIME}"
            }
          ]
        },
        {
          "type": "divider"
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Workflow Path:*\n<${JOC_HREF_WORKFLOW}|${MON_O_WORKFLOW_PATH}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Name:*\n<${JOC_HREF_JOB}|${MON_OS_JOB_NAME}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Criticality:*\n${MON_OS_JOB_CRITICALITY}"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Log:*\n<${JOC_HREF_JOB_LOG}|Link>"
            }
          ]
        }
      ]
    }
  ]
}

同様に、エラー通知用のメッセージも作成します。
名前は slack_on_failure とします。
本文はこんな感じです (色を変えただけです)

slack_on_failure
{
  "attachments": [
    {
      "color": "#dc3545",
      "blocks": [
        {
          "type": "header",
          "text": {
            "type": "plain_text",
            "text": "Workflow: ${MON_O_WORKFLOW_NAME} - ${MON_O_SEVERITY}"
          }
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Controller ID:*\n${MON_O_CONTROLLER_ID}"
            },
            {
              "type": "mrkdwn",
              "text": "*Agent ID:*\n${MON_OS_AGENT_ID}"
            }
          ]
        },
        {
          "type": "divider"
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Order ID:*\n<${JOC_HREF_ORDER}|${MON_O_ORDER_ID}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Order Log:*\n<${JOC_HREF_ORDER_LOG}|Link>"
            },
            {
              "type": "mrkdwn",
              "text": "*Status:*\n${MON_O_SEVERITY}"
            },
            {
              "type": "mrkdwn",
              "text": "*Time elapsed:*\n${MON_O_TIME_ELAPSED}"
            },
            {
              "type": "mrkdwn",
              "text": "*Start Time:*\n${MON_O_START_TIME}"
            },
            {
              "type": "mrkdwn",
              "text": "*End Time:*\n${MON_O_END_TIME}"
            }
          ]
        },
        {
          "type": "divider"
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Workflow Path:*\n<${JOC_HREF_WORKFLOW}|${MON_O_WORKFLOW_PATH}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Name:*\n<${JOC_HREF_JOB}|${MON_OS_JOB_NAME}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Criticality:*\n${MON_OS_JOB_CRITICALITY}"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Log:*\n<${JOC_HREF_JOB_LOG}|Link>"
            }
          ]
        }
      ]
    }
  ]
}

MonitorFragment (通知手段)

次にSlack通知用のコマンドの設定を行います。
MonitorFragment より、CommandFragment を作成します。

image.png

まず正常時の通知設定を作ります。
名前はcommand_slack_on_successとします。
image.png

MessageRef (どのMessageを参照するか)で先ほど作ったメッセージslack_on_successを選びます。
image.png

Command にて、Slack通知用のコマンドを登録します。
image.png

command_slack_on_success
curl -s -X POST -H "Content-type: application/json" --data '${MESSAGE}' https://hooks.slack.com/services/xxxxxxxx

ここで${MESSAGE}は、直前の MessageRef にて選択したMessageの内容が含まれます。

${MESSAGE}はシングルクォートで囲ってください。(ダブルクォートはNG)
コマンド実行時は、${MESSAGE}および本文中のモニター変数が最初から展開された状態となります。
シェル変数、環境変数と、通知設定で使うモニター変数とでは、展開されるタイミングが異なります。

同様に、エラー時の通知設定を作成してください。

項目
name command_slack_on_failure
MessageRef slack_on_failure
Command curl -s -X POST -H "Content-type: application/json" --data '${MESSAGE}' https://hooks.slack.com/services/xxxxxxxx

Notifications(ステータスと設定の関連付け)

既存の設定に、Slack通知を追加します。

Notification notify_on_success の NotificationMonitors にて、CommandFragmentRef を新たに追加してください。
image.png

CommandFragmentRef にて、先ほど作った command_slack_on_success を選びます。
image.png

NotificationObjects - WorkflowsRef に通知対象の設定が選択されていることをご確認ください。
※デフォルトはnone(対象なし)となっています。
image.png

同様に、エラー時の設定にもSlack通知を追加してください。

項目
name notify_on_failure
CommandFragmentRef command_slack_on_failure

Slack通知 カスタマイズ設定

基本設定の方法では気になる点がいくつかありました。

  • 時刻がUTCとなってしまう(Ver 2.3以前のみ)、日時表記を調整したい
  • わずかな違い(色違い)のメッセージを2つ作る必要がある
  • エラーメッセージをうまく表記しづらい(空文字だとSlackでエラーとなる)
  • jocのリンク内容がいまひとつ
    • httpsで表示されるべきところがhttpとなる。
    • ドメイン名であるべきところがIPアドレスとなる。
    • フロントでport 80, 443 でアクセスするようにしても port 4446となってしまう。

ここでは、CommandFragment の定義にカスタマイズ用の処理を記述することで、上記の問題をクリアした通知設定を行います。

MessageFragment(本文)

新規にMessageを作成してください。
名前はslack_commonとします。
本文はこんな感じです。

slack_common
{
  "attachments": [
    {
      "color": "$color",
      "blocks": [
        {
          "type": "header",
          "text": {
            "type": "plain_text",
            "text": "Workflow: ${MON_O_WORKFLOW_NAME} - ${MON_N_TYPE}"
          }
        },
        {
          "type": "section",
         "text": {
            "type": "mrkdwn",
            "text": "${TMP_MSG}"
          },
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Controller ID:*\n${MON_O_CONTROLLER_ID}"
            },
            {
              "type": "mrkdwn",
              "text": "*Agent ID:*\n${MON_OS_AGENT_ID}"
            }
          ]
        },
        {
          "type": "divider"
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Order ID:*\n<${TMP_JOC_HREF_ORDER}|${MON_O_ORDER_ID}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Order Log:*\n<${TMP_JOC_HREF_ORDER_LOG}|Link>"
            },
            {
              "type": "mrkdwn",
              "text": "*Status:*\n${MON_O_SEVERITY}"
            },
            {
              "type": "mrkdwn",
              "text": "*Time elapsed:*\n${MON_O_TIME_ELAPSED}"
            },
            {
              "type": "mrkdwn",
              "text": "*Start Time:*\n${TMP_MON_O_START_TIME}"
            },
            {
              "type": "mrkdwn",
              "text": "*End Time:*\n${TMP_MON_O_END_TIME}"
            }
          ]
        },
        {
          "type": "divider"
        },
        {
          "type": "section",
          "fields": [
            {
              "type": "mrkdwn",
              "text": "*Workflow Path:*\n<${TMP_JOC_HREF_WORKFLOW}|${MON_O_WORKFLOW_PATH}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Name:*\n<${TMP_JOC_HREF_JOB}|${MON_OS_JOB_NAME}>"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Criticality:*\n${MON_OS_JOB_CRITICALITY}"
            },
            {
              "type": "mrkdwn",
              "text": "*Job Log:*\n<${TMP_JOC_HREF_JOB_LOG}|Link>"
            }
          ]
        }
      ]
    }
  ]
}

ポイントは、モニター変数以外に、カスタマイズ用に、シェル変数を使っていることです。
例:$color, ${TMP_MSG} 時刻、リンク関連の変数${TMP_MON_O_XXX}, ${TMP_JOC_XXX}

MonitorFragment (通知手段)

新規にCommandFragment を作成してください。
名前は command_slack_commonとします。
MessageRef は slack_commonを選んでください。

コマンドは下記のようになります。

command_slack_common
slack_url="https://hooks.slack.com/services/xxxxxxxx"
rep_url="https://js7.saitamanokusa.com"

# status で色分け  0-OK, 1-WARNING, 2-CRITICAL, 3- UNKNOWN
case "${MON_N_STATUS}" in
  0 ) color="#28a745" ;;
  1 ) color="#ffc107" ;;
  2 ) color="#dc3545";;
  * ) color="#17a2b8";;
esac

# メッセージがある場合
[ -n "${MON_O_ERROR_TEXT}" ] && TMP_MSG="${TMP_MSG}*ErrorMessage:* ${MON_O_ERROR_TEXT}"
[ -n "$TMP_MSG" ] && TMP_MSG="${TMP_MSG}\n"
[ -n "${MON_OS_ERROR_TEXT}" ] && TMP_MSG="${TMP_MSG}*Error:* ${MON_OS_ERROR_TEXT}"
[ -n "$TMP_MSG" ] && TMP_MSG="${TMP_MSG}\n"
[ -n "${MON_N_WARN_TEXT}" ] && TMP_MSG="${TMP_MSG}*Warning:* ${MON_N_WARN_TEXT}"
[ -z "$TMP_MSG" ] && TMP_MSG=" "

# URL 修正
TMP_JOC_HREF_ORDER=$(echo "${JOC_HREF_ORDER}" | sed -r "s|^http(s)?://[^/]+?|$rep_url|g")
TMP_JOC_HREF_JOB_LOG=$(echo "${JOC_HREF_JOB_LOG}" | sed -r "s|^http(s)?://[^/]+?|$rep_url|g")
TMP_JOC_HREF_ORDER_LOG=$(echo "${JOC_HREF_ORDER_LOG}" | sed -r "s|^http(s)?://[^/]+?|$rep_url|g")
TMP_JOC_HREF_WORKFLOW=$(echo "${JOC_HREF_WORKFLOW}" | sed -r "s|^http(s)?://[^/]+?|$rep_url|g")
TMP_JOC_HREF_JOB=$(echo "${JOC_HREF_JOB}" | sed -r "s|^http(s)?://[^/]+?|$rep_url|g")

# TimeZone反映、日付表記調整
[ -n "${MON_O_START_TIME}" ] && TMP_MON_O_START_TIME=$(env TZ=JST-9 date -d"${MON_O_START_TIME}" +"%F %T %Z")
[ -n "${MON_O_END_TIME}" ] && TMP_MON_O_END_TIME=$(env TZ=JST-9 date -d"${MON_O_END_TIME}" +"%F %T %Z")
# Ver 2.3.x 以前はこちら
# [ -n "${MON_O_START_TIME}" ] && TMP_MON_O_START_TIME=$(env TZ=JST-9 date -d"${MON_O_START_TIME}Z" +"%F %T %Z")
# [ -n "${MON_O_END_TIME}" ] && TMP_MON_O_END_TIME=$(env TZ=JST-9 date -d"${MON_O_END_TIME}Z" +"%F %T %Z")


# Slack通知
json=$(cat << EOS
${MESSAGE}
EOS
)
curl -s -X POST -H "Content-type: application/json" --data "$json" ${slack_url}
  • ${MON_N_STATUS}が Notification設定のtype SUCCESS,WARNING,ERROR該当します。
    この値で色分けをします。
  • Error,Warning時のメッセージを追加します。空の場合はSlackエラー防止でスペースを入れます。
  • JOCの各リンク用URLを$rep_urlで置換します。※この処理が不要な場合は消してください。
  • 日時の表記をyyyy-mm-dd hh:mm:ss JSTとなるように調整します。(お好みで修正してください)
    ※busybox date コマンドでは date -d の値によってはエラーとなるため、coreutils の追加インストールが必要。
    ※ver 2.4以降は値にTimeZoneが付くため、利用バージョンに応じて処理は変更してください。
  • ${MESSAGE}はシェル変数を含む複数行が展開されるため、ヒアドキュメント内に納まるようにしています。

コマンドの処理の内容は、service-monitor.logで確認できます。

参考 モニター変数と環境変数の使い分け

こちらでも説明してますが、モニター変数は、環境変数$JS7_XXXでも同じ値を参照できます。
JS7® JobScheduler メール通知設定

モニター変数は展開タイミングが特殊であるため、慣れが必要です。
最初は、環境変数$JS7_XXXのほうが扱いやすいかと思います。

モニター変数を使うことで、service-monitor.logにて、モニター変数が展開された(値が入った)、実際に実行されるコマンド内容が出力されます。そのため具体的にどのコマンドの部分でエラーになっているか、原因が掴みやすくなります。
※環境変数では展開されない。
そのため、動作に慣れてきたら、モニター変数を使うのも便利です。

Notifications(ステータスと設定の関連付け)

Notification の正常時、エラー時の設定にSlack通知を追加してください(もしくは置き換え)

項目
name notify_on_success
CommandFragmentRef command_slack_common
項目
name notify_on_failure
CommandFragmentRef command_slack_common

以上で設定終了です。

WorkFlowを実行して、正しく通知が飛ぶことを確認してください。
image.png

動作チェックには下記のサンプルWorkflowを実行しています。

  • Success時 01_HelloWorld/jduHelloWorld
  • Warning時 04_ErrorHandling/jduWarnIfShorterThan
  • Error時 04_ErrorHandling/jduFail

jocをdocker版で起動している場合は、curlコマンドが入っているか確認してください。
もしなければapk add curlで追加してください。
また、dateコマンドでの処理用にcoreutilsも追加してください。 apk add coreutils

最後に

今回で行ったように、CommandFragmentを使った通知のカスタマイズ設定に慣れれば、通知系はもちろん、監視、ログ転送などにも応用ができそうです。

1
0
1

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
1
0