概要
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を新規作成します。
本文は例えばこんな感じです。
レイアウトブロックで適当なメッセージを作っています。
モニター変数の箇所は、実際の通知文では値が入ります。
※お好みで加工してください
{
"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
とします。
本文はこんな感じです (色を変えただけです)
{
"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 を作成します。
まず正常時の通知設定を作ります。
名前はcommand_slack_on_success
とします。
MessageRef (どのMessageを参照するか)で先ほど作ったメッセージslack_on_success
を選びます。
Command にて、Slack通知用のコマンドを登録します。
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 を新たに追加してください。
CommandFragmentRef にて、先ほど作った command_slack_on_success を選びます。
NotificationObjects - WorkflowsRef に通知対象の設定が選択されていることをご確認ください。
※デフォルトはnone(対象なし)となっています。
同様に、エラー時の設定にも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
とします。
本文はこんな感じです。
{
"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
を選んでください。
コマンドは下記のようになります。
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設定のtypeSUCCESS
,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を実行して、正しく通知が飛ぶことを確認してください。
動作チェックには下記のサンプル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を使った通知のカスタマイズ設定に慣れれば、通知系はもちろん、監視、ログ転送などにも応用ができそうです。