❄️

【Snowflake】コピペで使えるちょっとだけリッチなSlack通知関数(スレッド内にも通知しよう)

2024/05/12に公開

本記事で参考になるケース

  • Snowflake内からSlack通知をしたい
  • Slackのスレッドにも通知したい
  • コピペでワンパスしたい
  • Slack通知をカスタマイズしたい

注意! 本記事にはslack側の設定は記載していません

slack側の設定など含め、全体的な設定は下記のお方のZenn記事をご参考にしてください.(わかりやすいです!)
https://zenn.dev/dataheroes/articles/slack-notification

他参考にできる記事
https://zenn.dev/tf_takada/articles/d5d2c6c03b39a8

記事の概要

  • Slack通知までに必要なSnowflake内の設定を記載
  • Slack側はIncoming Webhookを利用する方法とSlack Appを利用する方法がありますが、今回はSlack Appを利用する方法で記載
  • Slackに通知後、通知先のスレッドに追加で通知する方法も記載

方法

1. Slackへのネットワークを設定

CREATE DATABASE SLACK;
CREATE SCHEMA SLACK.NOTIFY;

CREATE OR REPLACE NETWORK RULE SLACK.NOTIFY.RULE
  MODE = EGRESS
  TYPE = HOST_PORT
  VALUE_LIST = ('slack.com');


CREATE OR REPLACE SECRET SLACK.NOTIFY.SLACK_APP_TOKEN
  TYPE = GENERIC_STRING
  SECRET_STRING = 'xoxb-xxxxxxxx';

-- SECRET_STRINGに設定された xoxb-xxxxxx は
-- Slack Appの OAuth Tokens For Your Workspace ・ Bot User OAuth Token である

CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION SLACK_API
  ALLOWED_NETWORK_RULES = ( SLACK.NOTIFY.RULE )
  ALLOWED_AUTHENTICATION_SECRETS = ( SLACK.NOTIFY.SLACK_APP_TOKEN )
  ENABLED = true;

2. Slackへ通知する際に利用する関数を作成

CREATE DATABASE USERDB;
CREATE SCHEMA USERDB.UTIL;

CREATE OR REPLACE FUNCTION USERDB.UTIL.SLACK_MESSAGE(
    channel VARCHAR 
    ,message VARCHAR DEFAULT ''
    ,attachments VARIANT DEFAULT []
    ,blocks VARIANT DEFAULT []
    ,link_names BOOLEAN DEFAULT True
    ,mrkdwn BOOLEAN DEFAULT True
    ,parse VARCHAR DEFAULT ''
    ,reply_broadcast BOOLEAN DEFAULT False
    ,thread_ts VARCHAR DEFAULT ''
    ,unfurl_link BOOLEAN DEFAULT False
    ,unfurl_media BOOLEAN DEFAULT False
    )
RETURNS VARCHAR
LANGUAGE python
RUNTIME_VERSION = 3.9
HANDLER = 'main'
EXTERNAL_ACCESS_INTEGRATIONS = (SLACK_API)
PACKAGES = ('requests')
SECRETS = ('cred' = SLACK.NOTIFY.SLACK_APP_TOKEN)
AS
$$
import _snowflake
import requests
import json
def main(
    channel
    ,message
    ,attachments
    ,blocks
    ,link_names
    ,mrkdwn
    ,parse
    ,reply_broadcast
    ,thread_ts
    ,unfurl_link
    ,unfurl_media
    ):
     api_key = _snowflake.get_generic_secret_string('cred')
     url = 'https://slack.com/api/chat.postMessage'
     header = {'Authorization': 'Bearer '+ api_key}
     body_json = {
          'channel': channel
          ,'text': message
          ,'blocks': blocks
          ,'attachments': attachments
          ,'link_names': link_names
          ,'mrkdwn': mrkdwn
          ,'parse': parse
          ,'reply_broadcast': reply_broadcast
          ,'thread_ts': thread_ts
          ,'unfurl_links': unfurl_link
          ,'unfurl_media': unfurl_media           
     }
     response = requests.post(url ,headers=header ,json = body_json)
     return str(response.json()['ts'])
$$;

3. ユーザ関数実行権限を付与(ここは読み飛ばしてもOK)

GRANT USAGE ON DATABASE USERDB TO ROLE <user_role>;
GRANT USAGE ON SCHEMA USERDB.UTIL TO ROLE <user_role>;
GRANT USAGE ON USERDB.UTIL.SLACK_MESSAGE(VARCHAR, VARCHAR, VARIANT, VARIANT,  BOOLEAN,  BOOLEAN, VARCHAR,  BOOLEAN,  VARCHAR,  BOOLEAN,  BOOLEAN) TO ROLE <user_role>;

4. slackへ通知

SELECT USERDB.UTIL.SLACK_MESSAGE(
    channel=>'CXXXXXXX',   -- SlskのチャンネルID
    message=>'Hello!'
) as slack_notify;

Snowflake上の実行結果 例

>SLACK_NOTIFY
>1715445469.860479

スレッドに通知しよう

SELECT USERDB.UTIL.SLACK_MESSAGE(
    channel=>'CXXXXXXX',   -- SlskのチャンネルID
    thread_ts=>'1715445469.860479', -- 投稿メッセージのthread_tsの値. 上記関数で通知した際には実行返り値として出力されているのでこれを利用
    message=>'Hello! スレッド!'
) as slack_notify;

参考

ちょっとカスタムした通知

SELECT slack_message(
    channel=>'CXXXXXXX',
    message=>':mega: Hello!!',
    thread_ts=>'1715445469.860479',
    attachments=>[{
                'color': '#ff0000',
                'blocks': [
                    {
                        'type': 'section',
                        'text': {
                            'type': 'mrkdwn',
                            'text': '*Title*'
                        }
                    },
                    {
                        'type': 'section',
                        'text': {
                            'type': 'mrkdwn',
                            'text': ':alert: Good Morning!!'
                        }
                    },
                    {
                        'type': 'actions',
                        'elements':[{
                            'type': 'button',
                            'text': {
                                'type' : 'plain_text',
                                'text' : 'Google!!',
                                'emoji': True
                                },
                            'url': 'https://www.google.co.jp'
                            }
                        ]
                    }
                ]
            }],
    reply_broadcast=>True
) as slack_notify;

Snowflake Data Heroes

Discussion