❄️

Slack通知(デコ版)を作ってみる〜Webhook Notification版

がく@ちゅらデータです。

以前に

https://zenn.dev/churadata/articles/a553092387708b

という記事にて、Slack通知(デコ版)を書かせていただきました。

最近、
https://docs.snowflake.com/en/user-guide/notifications/webhook-notifications

という機能が発表されました。

こちらを使うとより簡素にかけるようになる事が期待できます。
実際にやってみましょう

Slack Webhook のシークレットを作成する

https://api.slack.com/messaging/webhooks#create_a_webhook

  1. https://api.slack.com/apps/new へアクセスする

使うWebhookのURLは下記のようになります。

https://hooks.slack.com/services/T********/B***********/K0**********************

Slack Webhook の通知統合を作成する

シークレットオブジェクトを作成する

my_slack_webhook_secretT********/B***********/K0**********************
がはいるシークレットを作成する

CREATE OR REPLACE SECRET my_slack_webhook_secret
  TYPE = GENERIC_STRING
  SECRET_STRING = 'T********/B***********/K0**********************';

Slack Webhook Integration(Webhook統合)の作成

CREATE OR REPLACE NOTIFICATION INTEGRATION my_slack_webhook_int
  TYPE=WEBHOOK
  ENABLED=TRUE
  WEBHOOK_URL='https://hooks.slack.com/services/SNOWFLAKE_WEBHOOK_SECRET'
  WEBHOOK_SECRET=my_secrets_db.my_secrets_schema.my_slack_webhook_secret
  WEBHOOK_BODY_TEMPLATE='{"text": "SNOWFLAKE_WEBHOOK_MESSAGE"}'
  WEBHOOK_HEADERS=('Content-Type'='application/json');

Slackで通知する(Simple版)

まずは、シンプルにSlackに通知してみます。
※deco版は後ほど

CALL SYSTEM$SEND_SNOWFLAKE_NOTIFICATION(
  SNOWFLAKE.NOTIFICATION.TEXT_PLAIN(
    SNOWFLAKE.NOTIFICATION.SANITIZE_WEBHOOK_CONTENT('my message : webhook integration test')
  ),
  SNOWFLAKE.NOTIFICATION.INTEGRATION('my_slack_webhook_int')
);

を実施

すると

SYSTEM$SEND_SNOWFLAKE_NOTIFICATION
Enqueued notifications

そしてSlackには

といった形で通知が成功しました

Slack通知する(デコ版)

次に、Slack通知といえば、色を付けたりしますよね!
info, warn, crit みたいな

これを実現しましょう

info なメッセージ の送信

いいやり方がまだわからなかったので、Notification Integrationを複数作る方法で実現してます。

CREATE OR REPLACE NOTIFICATION INTEGRATION my_slack_webhook_int_deco_info
  TYPE=WEBHOOK
  ENABLED=TRUE
  WEBHOOK_URL='https://hooks.slack.com/services/SNOWFLAKE_WEBHOOK_SECRET'
  WEBHOOK_SECRET=my_slack_webhook_secret
  WEBHOOK_BODY_TEMPLATE='{"channel": "_gaku_t",
    "attachments":[
      {
         "fallback":"Snowflake (info)",
         "pretext":"Snowflake (info)",
         "color":"good",
         "fields":[
            {
               "title":"Snowflake (info)",
               "value":"SNOWFLAKE_WEBHOOK_MESSAGE"
            }
         ]
      }
      ]
    }'
  WEBHOOK_HEADERS=('Content-Type'='application/json')
;

この中で、メッセージは「SNOWFLAKE_WEBHOOK_MESSAGE」に代入されます
本当は、colorに変数を代入したり、Snowflake (warn)のinfoな部分を引数で割り当てたりしたかったのですが、複数の値をいれる方法が不明だったので、今回の実装になりました。

※このメッセージを通知する際に、ALTER NOTIFICATION INTEGRATION my_slack_webhook_int_deco で WEBHOOK_BODY_TEMPLATE を入れ替えるという方法も可能かもしれません

CALL SYSTEM$SEND_SNOWFLAKE_NOTIFICATION(
  SNOWFLAKE.NOTIFICATION.TEXT_PLAIN(
    SNOWFLAKE.NOTIFICATION.SANITIZE_WEBHOOK_CONTENT('my message deco ( info )')
  ),
  SNOWFLAKE.NOTIFICATION.INTEGRATION('my_slack_webhook_int_deco_info')
);

こちらを実行すると

のようにデコメッセージ(info=正常)が通知できました!

warn なメッセージ の送信

warnなSlack通知もしてみましょう。実装は凄くシンプルです。もっといい方法があるかもしれませんが、それは今後の研究ですね。

CREATE OR REPLACE NOTIFICATION INTEGRATION my_slack_webhook_int_deco_warn
  TYPE=WEBHOOK
  ENABLED=TRUE
  WEBHOOK_URL='https://hooks.slack.com/services/SNOWFLAKE_WEBHOOK_SECRET'
  WEBHOOK_SECRET=gaku_training_db.slack_webhook_notification.my_slack_webhook_secret
  WEBHOOK_BODY_TEMPLATE='{"channel": "_gaku_t",
    "attachments":[
      {
         "fallback":"Snowflake (warn)",
         "pretext":"Snowflake (warn)",
         "color":"warning",
         "fields":[
            {
               "title":"Snowflake (warn)",
               "value":"SNOWFLAKE_WEBHOOK_MESSAGE"
            }
         ]
      }
      ]
    }'
  WEBHOOK_HEADERS=('Content-Type'='application/json')
;
CALL SYSTEM$SEND_SNOWFLAKE_NOTIFICATION(
  SNOWFLAKE.NOTIFICATION.TEXT_PLAIN(
    SNOWFLAKE.NOTIFICATION.SANITIZE_WEBHOOK_CONTENT('my message deco ( warn )')
  ),
  SNOWFLAKE.NOTIFICATION.INTEGRATION('my_slack_webhook_int_deco_warn')
);

crit なメッセージ の送信

critなSlack通知もしてみます。こちらもinfo, warnとほぼ同じです。
違いは、colorがdangerなところぐらい

CREATE OR REPLACE NOTIFICATION INTEGRATION my_slack_webhook_int_deco_crit
  TYPE=WEBHOOK
  ENABLED=TRUE
  WEBHOOK_URL='https://hooks.slack.com/services/SNOWFLAKE_WEBHOOK_SECRET'
  WEBHOOK_SECRET=gaku_training_db.slack_webhook_notification.my_slack_webhook_secret
  WEBHOOK_BODY_TEMPLATE='{"channel": "_gaku_t",
    "attachments":[
      {
         "fallback":"Snowflake (crit)",
         "pretext":"Snowflake (crit)",
         "color":"danger",
         "fields":[
            {
               "title":"Snowflake (crit)",
               "value":"SNOWFLAKE_WEBHOOK_MESSAGE"
            }
         ]
      }
      ]
    }'
  WEBHOOK_HEADERS=('Content-Type'='application/json')
;
CALL SYSTEM$SEND_SNOWFLAKE_NOTIFICATION(
  SNOWFLAKE.NOTIFICATION.TEXT_PLAIN(
    SNOWFLAKE.NOTIFICATION.SANITIZE_WEBHOOK_CONTENT('my message deco ( crit )')
  ),
  SNOWFLAKE.NOTIFICATION.INTEGRATION('my_slack_webhook_int_deco_crit')
);

WEBHOOK_BODY_TEMPLATEを使わない方法を試してみる

CREATE OR REPLACE NOTIFICATION INTEGRATION my_slack_webhook_int_deco_non_template
  TYPE=WEBHOOK
  ENABLED=TRUE
  WEBHOOK_URL='https://hooks.slack.com/services/SNOWFLAKE_WEBHOOK_SECRET'
  WEBHOOK_SECRET=my_slack_webhook_secret
  WEBHOOK_HEADERS=('Content-Type'='application/json')
;

こちらで、送信時に、JSONを組み立てます

CALL SYSTEM$SEND_SNOWFLAKE_NOTIFICATION(
  SNOWFLAKE.NOTIFICATION.APPLICATION_JSON('{"channel": "_gaku_t",
    "attachments":[
      {
         "fallback":"Snowflake (warn)",
         "pretext":"Snowflake (warn)",
         "color":"warning",
         "fields":[
            {
               "title":"Snowflake (warn)",
               "value":"non japanese!"
            }
         ]
      }
      ]
    }'),
  SNOWFLAKE.NOTIFICATION.INTEGRATION('my_slack_webhook_int_deco_non_template')
);

これでも送信ができました。
Stored Procedureを作る際に、変数を埋め込んでJSONをつくれば、ある程度うまくいきそうですね

まとめ

今回は、Webhookを用いた通知を

  • シンプル
  • デコ(info、warn, crit)
  • WEBHOOK_BODY_TEMPLATEを使わない方法

で試してみました。

試行錯誤したけど・・・・

  • メッセージに2バイト文字をいれると文字化けしました!
CALL SYSTEM$SEND_SNOWFLAKE_NOTIFICATION(
  SNOWFLAKE.NOTIFICATION.TEXT_PLAIN(
    SNOWFLAKE.NOTIFICATION.SANITIZE_WEBHOOK_CONTENT('日本語メッセージを入れてみる(warn)')
  ),
  SNOWFLAKE.NOTIFICATION.INTEGRATION('my_slack_webhook_int_deco_crit')
);

「Slack 通知 文字化け」で調べて、HEADERを下記のようにするといいよー
とあったので

  WEBHOOK_HEADERS=('Content-Type'='application/json; charset=UTF-8');

でためしてみたのですが、バケラッタのままでしたorz

  • WEBHOOK_BODY_TEMPLATEを使う方法では、変数は一つ(SNOWFLAKE_WEBHOOK_MESSAGE)しか使えませんでした、SYSTEM$SEND_SNOWFLAKE_NOTIFICATIONの第1引数は (message, [message, massage)と配列で持てるのでうまくやる方法はありそうな気はしていますが、今回はやり方を見つけることはできませんでした。
  • SNOWFLAKE_WEBHOOK_MESSAGEをWEBHOOK_BODY_TEMPLATEの複数箇所にいれてみたのですが、一箇所しか入れられないよ!ってエラーメッセージが出て、NOTIFICATION INTEGRATIONが作れませんでした

だめだったSQL
SNOWFLAKE_WEBHOOK_MESSAGEを4箇所に埋め込んでみました

WEBHOOK_BODY_TEMPLATE='{"channel": "_gaku_t",
    "attachments":[
      {
         "fallback":"Snowflake (SNOWFLAKE_WEBHOOK_MESSAGE)",
         "pretext":"Snowflake (SNOWFLAKE_WEBHOOK_MESSAGE)",
         "color":"danger",
         "fields":[
            {
               "title":"Snowflake (SNOWFLAKE_WEBHOOK_MESSAGE)",
               "value":"SNOWFLAKE_WEBHOOK_MESSAGE"
            }
         ]
      }
      ]
    }'

今後の課題

  • 今回は、NOTIFICATION INTEGRATIONを3種類(info, warn, crit)の3つを作る方法で実装しましたが、もっといい方法は有りそうだよなぁと思ってます
  • 一つの案としては、NOTIFICATION INTEGRATIONを一つ作成、都度、ALTER NOTIFICATION INTEGRATIONで、WEBHOOK_BODY_TEMPLATEを指定する方法があるかなとは思います。
  • WEBHOOK_BODY_TEMPLATEを使わない方法は試してみましたが、SANITIZEをしていなかったりもありますので、ここはStored Procedureを作る形で対応できればなと思っています
ちゅらデータ株式会社

Discussion