RabbitMQのログを検索する

# やりたいこと

- RabbitMQで生成されるログを検索したいが、以下のような問題がある
- ログの形式がSASL形式(後述)で、この形式のログを効率的に検索するようなツールもなさそう
- ログレベルを絞っていないのでINFO〜CRITICALまで記録されており、そのままでは探すのが大変
- Elasticsearch等の外部ツールも利用していない
- そのため、 `grep` 等のコマンドを工夫して使用し、検索する必要がある

# 検証環境

- Ubuntu 16.04
    - 古い
    - 参考: https://ubuntu.com/about/release-cycle
- RabbitMQ 3.6.6
    - 古い
    - 参考: https://www.rabbitmq.com/release-information

# 用語整理

### RabbitMQ

- メッセージキューを実現するためのメッセージブローカ
- Erlang製
- 詳細は [ここ](https://qiita.com/h_tyokinuhata/items/1097a3a0ad018366ecec#%E6%A6%82%E8%A6%81) にまとめている

### Erlang

- 1980年代後半に開発
- 元々はスウェーデンの通信機器メーカーのエリクソンが開発
- 並行処理、高可用性、分散処理が要求されるシステム向けの言語
- ちなみに由来は呼量(単位時間あたりの通信回線の占有量)を表す単位の「アーラン」らしい

### OTP

- Open Telecom Platformの略称
- Erlangを基盤として開発されたライブラリ、ツールセット
- リポジトリ: https://github.com/erlang/otp

### SASL

- System Architecture Support Librariesの略称
- OTPの一部
- 主にロギング等の機能を提供している

### SASL形式

- SASLによって生成されたログのフォーマットのことを便宜上そう呼ぶ

```:SASL形式のログの例
=INFO REPORT==== 29-Aug-2024::13:42:19 ===
<ここから本文>
```

# 手順

### ログの場所を確認

- RabbitMQのログは `/var/log/rabbitmq` 配下に保存されている

```bash
$ ls -1 /var/log/rabbitmq/
rabbit@rabbitmq-01.log
rabbit@rabbitmq-01.log.1
rabbit@rabbitmq-01.log.10.gz
rabbit@rabbitmq-01.log.11.gz
rabbit@rabbitmq-01.log.12.gz
rabbit@rabbitmq-01.log.13.gz
rabbit@rabbitmq-01.log.14.gz
rabbit@rabbitmq-01.log.15.gz
rabbit@rabbitmq-01.log.16.gz
rabbit@rabbitmq-01.log.17.gz
rabbit@rabbitmq-01.log.18.gz
rabbit@rabbitmq-01.log.19.gz
rabbit@rabbitmq-01.log.20.gz
rabbit@rabbitmq-01.log.2.gz
rabbit@rabbitmq-01.log.3.gz
rabbit@rabbitmq-01.log.4.gz
rabbit@rabbitmq-01.log.5.gz
rabbit@rabbitmq-01.log.6.gz
rabbit@rabbitmq-01.log.7.gz
rabbit@rabbitmq-01.log.8.gz
rabbit@rabbitmq-01.log.9.gz
rabbit@rabbitmq-01-sasl.log
rabbit@rabbitmq-01-sasl.log.1
rabbit@rabbitmq-01-sasl.log.2.gz
```

- 新しいログはテキスト形式で保存されており、古いログはgzipで圧縮されてから保存されている
- ファイル名の数字が大きいほど古いログとなっている
- ファイル名に `-sasl` が付与されているログはSASLログで、付与されていないログは標準ログとなっている
- 標準ログは日常の動作やイベントの記録がなされている(警告やエラーの概要も含む)
- SASLログは詳細なエラーやクラッシュ情報の記録がなされている
- どちらもフォーマット自体は先述したSASL形式となっている

### 圧縮されていないログを検索する

- 以下は標準ログで検証しているが、SASLログの場合でも基本的には同様

```bash
$ tail -n 1000 <ファイル名> | grep -n -A 2 -E "WARNING REPORT|ERROR REPORT"
38:=WARNING REPORT==== 29-Aug-2024::13:42:21 ===
39-memory resource limit alarm cleared on node 'rabbit@rabbitmq-01'
40-
41:=WARNING REPORT==== 29-Aug-2024::13:42:21 ===
42-memory resource limit alarm cleared across the cluster
43-
--
50:=WARNING REPORT==== 29-Aug-2024::13:50:09 ===
51-memory resource limit alarm set on node 'rabbit@rabbitmq-02'.
52-
--
57:=WARNING REPORT==== 29-Aug-2024::13:50:11 ===
58-memory resource limit alarm set on node 'rabbit@rabbitmq-01'.
59-
--
64:=WARNING REPORT==== 29-Aug-2024::13:50:23 ===
65-memory resource limit alarm cleared on node 'rabbit@rabbitmq-02'
66-
```

- `tail -n 1000`
    - ログファイルの最後の1000行(つまり最新のログから1000行分)を対象とするようにしている
    - ログファイルの先頭から見たい場合は `head` を使うと良い
    - 行数が少ない場合は `tail` や `head` で絞る必要もなさそう
- `grep -n -A 2 -E "WARNING REPORT|ERROR REPORT"`
    - `-n`
        - 行番号を表示するようにしている
    - `-A 2`
        - マッチした行から追加で2行表示しているようにしてる
        - ログの本文が長い場合はここを増やしても良い
    - `-E`
        - 拡張正規表現を指定できるオプション
        - `WARNING REPORT` か `ERROR REPORT` にマッチする行に絞り込んでいる

### 圧縮されたログを検索する

```bash
$ zcat <ファイル名> | tail -n 1000 | grep -n -A 2 -E "WARNING REPORT|ERROR REPORT"
8:=WARNING REPORT==== 20-Aug-2024::17:22:43 ===
9-disk resource limit alarm cleared for dead node 'rabbit@rabbitmq-02'
10-
11:=WARNING REPORT==== 20-Aug-2024::17:22:43 ===
12-disk resource limit alarm cleared across the cluster
13-
--
20:=WARNING REPORT==== 20-Aug-2024::17:23:06 ===
21-memory resource limit alarm cleared on node 'rabbit@rabbitmq-01'
22-
23:=WARNING REPORT==== 20-Aug-2024::17:23:06 ===
24-memory resource limit alarm cleared across the cluster
25-
26:=WARNING REPORT==== 20-Aug-2024::17:23:29 ===
27-memory resource limit alarm set on node 'rabbit@rabbitmq-01'.
28-
```

- `zcat`
    - gzipで圧縮されたログファイルはそのままでは見れないので解凍してから標準出力に表示する
- `tail -n 1000`
    - 先述の通り
    - ただし、 `zcat` で一度ログファイルを全て読み取るようになっているので、ログファイルが大きい場合は一度 `tail` で解凍してからログファイルを読み込んでも良いかもしれない
- その他は「圧縮されていないログを検索する」場合と同様

# 所感

- RabbitMQのログをsyslogやElasticsearchに保存する方法も存在するので、あらかじめそういう設計にしておくのも手かもしれない
- 不要なログレベルのログをそもそも記録しないように設定を変えておいても良いかもしれない

# 関連記事(手前味噌)

- [Docker Composeで立てたRabbitMQにpikaで接続してみる](https://qiita.com/h_tyokinuhata/items/1097a3a0ad018366ecec)
- [RabbitMQ + PostgreSQL + Celeryで非同期タスク処理をしてみる](https://qiita.com/h_tyokinuhata/items/f24fc078e0f750bb788b)