Diary of a Perpetual Student

Perpetual Student: A person who remains at university far beyond the normal period

Mackerel Slackアプリを雑に作ってみる: unfurl編

arthur-1 Mackerel Advent Calendar 2023ラソン24日目・およびSlack Japan Champions Network (JCN) アドベントカレンダー 2023 24日目の記事です。

MackerelとSlackのインテグレーション

Mackerelの通知チャンネルとして、Slackを選択することができます。これはIncoming WebhookのURLを設定する方式になっており、Mackerelでアラート発報などのイベントが起こるとSlackのWebhookにリクエストを送り、結果としてメッセージが投稿されます。

これでも十分便利なのですが、Slackアプリとして提供するともっと良い体験ができるはずだと思っています。例えば、

  • *Mackerelのリンクが貼られたらその情報を展開する
  • Slack上でアラートを閉じられる
  • アラートの状況が変化したらSlackの投稿も変化する
  • 同じアラートに関する通知が1つのスレッドにまとまる

などのことができるようになるでしょう。

今回はお試しとして、「*Mackerelのリンクが貼られたらその情報を展開する」が実現できるSlackアプリを作っていきましょう。

リンクの展開

SlackにURLが貼られたとき、その下にサイトの情報が表示されることがあります。これをリンクの展開(unfurling)と呼びます。

基本はSlackのクローラーかアプリがリクエストを投げて取ってくるのでパブリックなサイトでしか表示できないのですが、Slackアプリを使うとプライベートなサイトのリンクに対しても展開することができるようになります。

api.slack.com

この機能を用いて、Mackerelのアラートのリンクが貼られた時にその情報を展開するようなSlackアプリを作ります。

できたもの

Mackerelのアラートリンクを貼ると展開してくれるSlackアプリが以下のようにできました。

ソースコードGitHubの以下のリポジトリに掲載しています。

github.com

コードの解説

Slackアプリが簡単に作れるBolt for Javascriptフレームワークを用いています。Slackにリンクが貼られたときのイベントをハンドリングするには以下のような関数を作ります。

app.event("link_shared", async ({ event, client, logger }) => {
  // ここにリンクが貼られたときの処理を書く
})

event.linksの中にURLの情報が入っているので、これをパースしてMackerelのアラートのURLかを判定します。MackerelのアラートURLであればURLの最後のパスはアラートIDなので、これを取り出してMackerelのAPIのアラート取得エンドポイントにリクエストを投げます。

const url = new URL(link.url);
const paths = url.pathname.split("/");
const res = await fetch(
  `https://api.mackerelio.com/api/v0/alerts/${paths[4]}`,
  {
    headers: {
      "X-Api-Key": process.env.MACKEREL_API_KEY ?? "",
    },
  }
);
const alert = await res.json();

あとはSlackのchat.unfurl APIにリクエストするclient methhodを呼び出し、先ほど取得したアラート情報から組み立てたLinkUnfurlsというオブジェクトや、情報を付与したい投稿のID(ts: タイムスタンプ)やチャンネルIDを渡します。

const unfurls: LinkUnfurls = {
  [link.url]: {
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: alert.status,
        },
      },
    ],
  },
};
client.chat.unfurl({
  ts: event.message_ts,
  channel: event.channel,
  unfurls: unfurls,
});

これでアプリケーションとしては完成ですが、Slack Appとして動かすにはSlack側での設定も必要です。Slackアプリのmanifestファイルを以下に掲載しておきます。

display_information:
  name: Mackerel
features:
  bot_user:
    display_name: Mackerel
    always_online: false
  unfurl_domains:
    - mackerel.io
oauth_config:
  scopes:
    bot:
      - links:read
      - links:write
settings:
  event_subscriptions:
    request_url: ***your_request_url***
    bot_events:
      - link_shared
  org_deploy_enabled: false
  socket_mode_enabled: false
  token_rotation_enabled: false

ポイントはlink_sharedイベントを購読する際にはunfurl_domainsの指定が必要なことです。今回はMackerelのドメインだけを引っ掛けてイベントを送信するようにmackerel.ioと指定しました。

最後に

このようにSlackアプリは簡単に作ることができます。このソースコードを育てて機能を増やすとともに、最終的には認証認可周りも頑張って、ユーザーが各自のワークスペースにインストールするものとして仕上げられたら良いなと思っています。