Slackboard〜Slackプロキシサーバ in Go〜

# Slackboard

https://github.com/cubicdaiya/slackboard

昨年末の話だけどSlackへの通知をプロキシするサーバをGoで書きました。如何せん1〜2時間で書いたので一部洗練されてない箇所があるかもしれませんが、 今年のはじめからすでに実運用をはじめています。

# Slackboardの役割 

SlackboardはSlackへのプロキシサーバである`slackboard`とそのためのクライアントである`slackboard-cli`の2つから構成されています。↓の図のようにSlackへの通知をクライアントが行うのではなく、クライアントからのリクエストを受け取ったプロキシサーバである`slackboard`が行うという仕組みです。

![image](https://qiita-image-store.s3.amazonaws.com/0/1608/59f9caa7-cadb-c6f4-aa46-30706372fbea.png)

このようにSlackへの通知を直接ではなくプロキシを介して行うのには以下のメリットがあります。

 * Slackへの通知設定をプロキシサーバで一元管理できる
 * Slackへの通知リクエストをロギングできる
 * 各サーバに散らばったSlackへの通知プログラムを一本化できる
  * そのための`slackboard-cli`

具体的にはSlackのAPIエンドポイントやチャンネルの情報を記述した設定ファイル(`slackboard.toml`)を用意して`slackboard`を起動します。

```bash
[10.0.0.2] $ slackboard -c slackboard.toml
```

そして別のホストから`slackboard`に対して`slackboard-cli`でメッセージを送るというわけです。

```bash
[10.0.0.3] $ echo "notify" | slackboard-cli -s 10.0.0.2:29800 -t random
```

これにより各所にバラバラに散ったSlackへの通知メカニズムを一元化できるというわけです。

## Slackboardのダウンロードとインストール

`go get`でできます。

```bash
go get -u github.com/cubicdaiya/slackboard/...
```

完了すると`slackboard`(プロキシサーバ)と`slackboard-cli`(クライアント)が利用出来ます。

## Slackboardの設定ファイル

Slackboardはプロキシサーバ(`slackboard`)の設定ファイルをTOMLで記述します。

```toml:slackboard.toml
[core]
port = "29800"
slack_url = "https://hooks.slack.com/services/..."

[[tags]]
tag = "general"
channel = "#general"

[[tags]]
tag = "random"
channel = "#random"
username = "slackboard"
icon_emoji = ":clipboard:"
parse = "full"

[log]
access_log = "stdout"
error_log = "stderr"
level = "error"

[ui]
root = "/var/www/slackboard/ui"
```

各パラメータの解説は[slackboard/CONFIGURATION.md](https://github.com/cubicdaiya/slackboard/blob/master/CONFIGURATION.md)にまとめているので、ここでは主要なパラメータについてのみ解説します。

### core.port

`slackboard`がListenするポート番号です。UnixドメインソケットでもListenできるようにするために文字列型で指定します。

```toml
[core]
port = "29800"
# port = "unix:/tmp/slackboard.sock"
```

### core.slack_url

`core.slack_url`にはSlackのAPIエンドポイントURLを指定します。

```toml
[core]
port = "29800"
slack_url = "https://hooks.slack.com/services/..."
```

### Slackのチャンネルにタグ付け

`slackboard.toml`中に出てくる``tags``のセクション一覧は実在するSlackのチャンネルに関連づけられたタグの配列です。`slackboard`がSlackのチャンネルへ通知を送るのに対して`slackboard-cli`は`slackboard`の関連づけられたタグに対してメッセージを送るというわけです。

## slackboardのWeb UI

`slackboard`には非常に簡素なWeb UIが付属しています。Web UIのドキュメントルートは設定ファイルで指定します。(↓の${slackboard-src-dir}を適切なパスに直してください)

```
[ui]
root = "${slackboard-src-dir}/ui"
```

![image](https://qiita-image-store.s3.amazonaws.com/0/1608/e4b0eecf-83a0-22c1-58fb-f10faa65db70.png)

## slackboardのHTTP API

通常`slackboard`との通信は`slackboard-cli`を使って行うのでその詳細について意識する必要はありません。しかし、リクエストの実態はただのJSONボディなので自分で`slackboard`と通信するクライアントを書くこともできます。APIの仕様は[slackboard/SPEC.md](https://github.com/cubicdaiya/slackboard/blob/master/SPEC.md)にまとめてあります。

## slackboard-cliを同期/非同期に実行する

`slackboard-cli`はつい昨日まで同期的に実行されるように実装されていました。しかし、隣の隣に座っている人から「同期だと遅いから非同期にして」と[リクエストが来た](https://github.com/cubicdaiya/slackboard/issues/2)ので速攻で対応してデフォルトだと非同期で通知するように変更しています。なお、`slackboard-cli`から`slackboard`への通知を同期的に行うには`-sync`オプションを指定します。

```bash
[10.0.0.3] $ echo "notify" | slackboard-cli -s 10.0.0.2:29800 -t random -sync
```

Slackへの通知が完了するまでレスポンスが返ってこないので数百msecから数秒単位の遅延が発生しますが、非同期で行う場合と違ってSlackへの通知が失敗したかどうかを`slackboard-cli`側で検知できるというメリットがあります。

# まとめ

Slackboardは、

 * `slackboard`(プロキシサーバ)と`slackboard-cli`(クライアント)の二つで構成
 * Slackへの通知設定をプロキシサーバで一元管理できる
 * Slackへの通知リクエストをロギングできる
 * 各サーバに散らばったSlackへの通知プログラムを一本化できる
 
といった特徴を持つプロダクトです。メルカリの中でも利用しています。詳しくは[こちら](http://tech.mercari.com/entry/2015/07/06/141056)。