詩と創作・思索のひろば

ドキドキギュンギュンダイアリーです!!!

Fork me on GitHub

SlackのログをBigQueryにインポートする(手動)

Admin 限定技だけど、Slack にはデータのエクスポートという機能があって、ワークスペースのパブリックチャンネルの会話データを zip でダウンロードすることができる。これがまあまあ便利な代物で、通常なら API を叩きまくらないと得られない諸々の情報を一括で手に入れることができる。

エクスポートした zip の中身はこんな感じになっている:

.
├── channels.json
├── integration_logs.json
├── users.json
├── <channel>
│   ├── yyyy-mm-dd.json
│   ├── ...
│   └── yyyy-mm-dd.json
└── <channel>...
    └── ...

この channels.json とかは conversations.list API の結果である……のかと思いきや、少しスキーマが違うようで、独自のものを返している模様。

こんな感じになっている:

[
{
    "id": "CXXXXXXXX",
    "name": "general",
    "created": ...
    "creator": "UXXXXXXXX",
    "is_archived": false,
    "is_general": true,
    "members": [
        "UXXXXXXXX",
        ...
    ],
    "topic": { ... },
    "purpose": { ... }
},
...
]

members なんかがあるのは特殊なんじゃなかろうか。yyyy-mm-dd.json も:

[
    {
        "client_msg_id": ...
        "type": "message",
        "text": "うんこ",
        "user": "UXXXXXXXX",
        "ts": "##########.######",
        "team": "TXXXXXXXX",
        "user_team": "TXXXXXXXX",
        "source_team": "TXXXXXXXX",
        "user_profile": { ... },
        "blocks": [ ... ],
        "reactions": [
            {
                "name": "hankey",
                "users": [ ... ],
                "count": 1
            },
            ...
        ]
    },
    ...
]

といった感じで conversations.history より情報が多め。ちょっと余談だけど、情報多めな割にこの JSON にチャンネル名が(ID も)含まれていない。ファイルパスに入っているからそれでわかるだろうという一種の正規化なのかもしれないけど、このおかげで面倒なシェルスクリプトを書くことになった。メタ情報による正規化はあまりうれしくないことがわかる。

さて、この reactions というデータが興味深い。誰がどんなリアクションをつけたか、がわかる(API ならいちいち reactions.get することで得られるデータ)。

そういうわけで、今回はこのエクスポートされた zip を BigQuery にインポートしようと思います。Embulk を使うことにする。できあがりは以下のリポジトリ。

GitHub - motemen/example-slack-logs-ingest-bigquery

README にあるとおり、

  • ./data にエクスポートした zip を置いて、
  • ./config/_out.yml.liquid を書いて、
  • docker compose run --rm embulk bash -c 'embulk run /config/embulk.yml.liquid'

で BigQuery へのインポートが行える。

できたテーブルに以下のようなクエリを叩くと、リアクションランキングなどが得られる。おもしろいですね。まあ text 本文などを置くのははばかられると思うので、転送しないほうがよいかも。

WITH messages_flat_reactions AS (
SELECT
  *,
  JSON_VALUE(reaction_item, "$.name") AS reaction_name,
  JSON_VALUE(reaction_item, "$.count") AS reaction_count
FROM
  `xxx.slack_messages`
LEFT JOIN
  UNNEST(JSON_QUERY_ARRAY(reactions)) AS reaction_item
WHERE
  reactions IS NOT NULL
)

SELECT
  timestamp, channel, text, reaction_name, reaction_count
FROM messages_flat_reactions
ORDER BY
  reaction_count DESC
LIMIT 10

Embulk について

Embulk を真面目に使ってみたのは初めてだったけど、いくつかハマりポイントがあった。

  • embulk の jar ファイルはシェルスクリプトとしても解釈できるように工夫されているので、公式サイトでは jar を chmod +x して PATH に入れるように指示されている。手元ではこれで動くが、Docker で動かすときに直接 ENTRYPOINT にしてしまうと動かない。bash などを噛ませて動かす必要がある。(何も考えずに java -jar を指定するとメモリ不足になりがち)
  • embulk-output-bigquery は依存ライブラリが Ruby >= 2.6 を求めがち(https://github.com/embulk/embulk-output-bigquery/issues/144)な一方 embulk 同梱の JRuby はちょっと古いので、ひとつひとつ pin しておく必要がある。これプラグイン側でなんとかできないかなあ。Embulk v0.11 では JRuby のバージョンを自分で選べる らしいので、それ待ちなのかもしれない。

はてなで一緒に働きませんか?