SlackでBigQueryの構文エラー内容を共有する Feb 13, 2021 会社ではあるグループにメンションして質問すると犬が有識者を連れてきたり、朝会の時間になるとムックが知らせてくれたりする。 また、システムの障害を通知してくれるなどサービスの安定稼働において重要な役割を担っていたりもする。 Slackを仕事で使い始めて約2年くらいになるが、これらの機能を提供するSlack Appsの仕組みについて何も知らずに使い続けてきたが、流石にエンジニアとしてSlack Appsくらい必要なときにサクッと作れないとまずいかなと思い1つアプリを作ってみた。 SlackでBigQueryの構文エラーを共有する 最近、非エンジニアの方も普通にBigQueryでSQL書いてデータを見たりする場面がある。SQLの構文エラーの原因がわからない場合、WebUIのスクショをSlackに添付したりして質問するかたちになるが、問題のSQLだけSlackに貼ってエラー内容については自動で共有できたら楽だろうなと思った。 そこで、SlackにSQLを投稿するとそのクエリに対するBigQueryのDry Run結果を表示するSlack Appsを作った。 使い方としては、/bq_checkというslashコマンドを登録しておいて以下の様に入力する。 するとこんな感じで、構文エラーがある場合はエラーの内容が表示され、エラーが無い場合は処理されるバイト数が表示される。 アプリの構成 Slack Appsの作り方を調べてみると、リクエストとレスポンスについて同期型と非同期型の2パターンがある。 同期型 スラッシュコマンドを打つとアプリのAPIを提供するサーバにHTTPリクエストを投げて、そのレスポンスのボディのデータをSlackのタイムラインに返すもの。 Slackの制約によりレスポンスは3秒以内に返さないとエラーとなってしまうので、今回の用途では要件を満たさない。 非同期型 スラッシュコマンドを打った際、HTTPリクエストのペイロード(JSON形式)にresponse_urlというチャンネル投稿用のエンドポイントのURLが渡される。 そこで、スラッシュコマンドへのレスポンスはすぐに返しておいて、サーバのバックエンドでの処理結果は処理完了次第このresponse_urlにPOSTすれば3秒以上掛かる処理の結果もSlackへ返すことができる。 BigQueryへのDry Run実行には3秒以上掛かることがあるので今回はこちらのパターンを採用。 構成 BigQueryへのAPIコールがメインなのでAPIサーバはCloud Functionsを使った。また、非同期型の構成を取るため、APIリクエストのエンドポイント用インスタンスからCloud Pub/Sub経由でバックエンド処理・レスポンス用のインスタンスをキックする構成とした。(参考: Slack のチュートリアル - Slash コマンド) APIエンドポイントのコード リクエストのペイロードに含まれる投稿メッセージとresponse_urlをCloud Pub/Subのトピックにpublishしてすぐにレスポンスを返すだけ。 from google.cloud import pubsub_v1 from slack.signature import SignatureVerifier publisher = pubsub_v1.PublisherClient() def verify_signature(request): request.get_data() verifier = SignatureVerifier(os.environ['SLACK_SECRET']) if not verifier.is_valid_request(request.data, request.headers): raise ValueError('Invalid request/credentials.') def bq_check(request): if request.method != 'POST': return 'Only POST requests are accepted. ...