daisuzz.log

notify_slackを利用してalpの集計結果をSlackで通知する

最近はISUCONの過去問を解いています。今回はnotify_slackを利用してalpの集計結果をSlackで通知する方法をまとめます。

以下の流れで説明していきます。

notify_slackを利用してテキストをSlackで通知する

notify_slackのインストール

Releases · catatsuy/notify_slack · GitHub からバイナリファイルを落としてくる

# wget https://github.com/catatsuy/notify_slack/releases/download/v0.4.8/notify_slack-linux-amd64.tar.gz

# tar zxvf notify_slack-linux-amd64.tar.gz

# ./notify_slack -version
notify_slack version v0.4.8; go1.15.6

Go1.15以上の環境があるならgit cloneしてmakeでもOK

# git clone https://github.com/catatsuy/notify_slack.git

# cd notify_slack/

# make

# ./notify_slack -version
notify_slack version v0.4.8; go1.15.6

Slackアプリの作成

notify_slackのREADMEに書かれているので、これに則ってSlackアプリを作成し、通知したいチャンネルに追加する。

https://github.com/catatsuy/notify_slack#how-to-create-a-token

github.com

notify_slackの設定ファイルの作成

https://github.com/catatsuy/notify_slack#toml-configuration-file を参考に以下のようなnotify_slack.tomlを作成する。

[slack]
url = "https://hooks.slack.com/services/**"
token = "xoxp-xxxxx"
channel = "#general"
username = "tester"
icon_emoji = ":rocket:"
interval = "1s"

各パラメータの意味は https://github.com/catatsuy/notify_slack#cli-options を参照してください。

作成した設定ファイルは以下のように実行時に-cオプションで指定するか、

# ./notify_slack -c notify_slack.toml

もしくは、以下のディレクトリに配置しておけば自動的に読み込んでくれる

  • $HOME/.notify_slack.toml
  • $HOME/etc/notify_slack.toml
  • /etc/notify_slack.toml

動作確認

# echo a | ./notify_slack -c notify_slack.toml

↑これを実行すると、Slackにテキストが投稿される。

f:id:dais39:20210218232222p:plain

alpの集計結果をhtmlファイルとして配信する

alpのインストール

Releases · tkuchiki/alp · GitHub からバイナリファイルを落としてくる

# wget https://github.com/tkuchiki/alp/releases/download/v1.0.3/alp_linux_amd64.zip
# unzip alp_linux_amd64.zip
# ./alp --version
1.0.3

ログ形式をLTSV形式に変更

alpでログを集計するために、nginxのアクセスログの形式をLTSV形式に変更する。

# vim /etc/nginx/nginx.conf

// 中略

// 以下を追加
    log_format ltsv "time:$time_local"
                "\thost:$remote_addr"
                "\tforwardedfor:$http_x_forwarded_for"
                "\treq:$request"
                "\tstatus:$status"
                "\tmethod:$request_method"
                "\turi:$request_uri"
                "\tsize:$body_bytes_sent"
                "\treferer:$http_referer"
                "\tua:$http_user_agent"
                "\treqtime:$request_time"
                "\tcache:$upstream_http_x_cache"
                "\truntime:$upstream_http_x_runtime"
                "\tapptime:$upstream_response_time"
                "\tvhost:$host";

    access_log /var/log/nginx/access.log ltsv;

// 中略

設定が完了したら、設定ファイルの文法チェック

# nginx -t 

問題がなければnginxの設定ファイルを再読み込みする

# nginx -s reload

alpでログを集計してみる

ベンチマーク実行後、アクセスログをalpで集計してみる。 今回はISUCON9予選の過去問をやっていたので、alpのオプションでエンドポイントをまとめて集計するような指定をしている。

# ./bin/benchmarker
# cat /var/log/nginx/access.log |./alp ltsv -m "/upload/[0-9a-z]+.jpg,/items/[0-9]+.json,/new_items/[0-9]+.json,/users/[0-9]+.json,/transactions/[0-9]+.png,/static/*"

+-------+-----+------+-----+-----+-----+--------+------------------------------+-------+-------+---------+-------+-------+-------+-------+--------+-----------+------------+--------------+------------+
| COUNT | 1XX | 2XX  | 3XX | 4XX | 5XX | METHOD |             URI              |  MIN  |  MAX  |   SUM   |  AVG  |  P1   |  P50  |  P99  | STDDEV | MIN(BODY) | MAX(BODY)  |  SUM(BODY)   | AVG(BODY)  |
+-------+-----+------+-----+-----+-----+--------+------------------------------+-------+-------+---------+-------+-------+-------+-------+--------+-----------+------------+--------------+------------+
|     1 |   0 |    1 |   0 |   0 |   0 | GET    | /logo.png                    | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 | 23082.000 |  23082.000 |    23082.000 |  23082.000 |
|     1 |   0 |    0 |   0 |   1 |   0 | GET    | /aaaa                        | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |    19.000 |     19.000 |       19.000 |     19.000 |
|     1 |   0 |    0 |   0 |   1 |   0 | GET    | /health                      | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |    19.000 |     19.000 |       19.000 |     19.000 |
|     1 |   0 |    1 |   0 |   0 |   0 | POST   | /register                    | 0.088 | 0.088 |   0.088 | 0.088 | 0.088 | 0.088 | 0.088 |  0.000 |    70.000 |     70.000 |       70.000 |     70.000 |
|     1 |   0 |    0 |   1 |   0 |   0 | GET    | /logs/index.html             | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |     0.000 |      0.000 |        0.000 |      0.000 |
|     2 |   0 |    2 |   0 |   0 |   0 | GET    | /reports.json                | 0.008 | 0.008 |   0.016 | 0.008 | 0.008 | 0.008 | 0.008 |  0.000 | 87837.000 | 105839.000 |   193676.000 |  96838.000 |
|     2 |   0 |    0 |   0 |   2 |   0 | GET    | /logs/test                   | 0.004 | 0.004 |   0.004 | 0.002 | 0.000 | 0.000 | 0.000 |  0.002 |    19.000 |    564.000 |      583.000 |    291.500 |
|     2 |   0 |    0 |   0 |   2 |   0 | GET    | /_status/vars                | 0.000 | 0.004 |   0.004 | 0.002 | 0.004 | 0.004 | 0.004 |  0.002 |    19.000 |     19.000 |       38.000 |     19.000 |
|     2 |   0 |    2 |   0 |   0 |   0 | POST   | /initialize                  | 6.980 | 7.300 |  14.280 | 7.140 | 6.980 | 6.980 | 6.980 |  0.160 |    31.000 |     31.000 |       62.000 |     31.000 |
|     2 |   0 |    0 |   0 |   2 |   0 | GET    | /logs/test.html              | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |    19.000 |    564.000 |      583.000 |    291.500 |
|     2 |   0 |    0 |   0 |   2 |   0 | GET    | /actuator/prometheus         | 0.000 | 0.032 |   0.032 | 0.016 | 0.032 | 0.032 | 0.032 |  0.016 |    19.000 |     19.000 |       38.000 |     19.000 |
|     2 |   0 |    0 |   0 |   2 |   0 | GET    | /manager/status              | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |    19.000 |     19.000 |       38.000 |     19.000 |
|     2 |   0 |    0 |   0 |   2 |   0 | GET    | /squid-internal-mgr/counters | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |   166.000 |    166.000 |      332.000 |    166.000 |
|     2 |   0 |    0 |   0 |   2 |   0 | -      | -                            | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |   166.000 |    166.000 |      332.000 |    166.000 |
|     4 |   0 |    0 |   0 |   4 |   0 | GET    | /metrics                     | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |    19.000 |     19.000 |       76.000 |     19.000 |
|     5 |   0 |    0 |   0 |   5 |   0 | GET    | /favicon.ico                 | 0.000 | 0.004 |   0.004 | 0.001 | 0.000 | 0.004 | 0.000 |  0.002 |    19.000 |     19.000 |       95.000 |     19.000 |
|     6 |   0 |    6 |   0 |   0 |   0 | GET    | /favicon.png                 | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |   176.000 |    176.000 |     1056.000 |    176.000 |
|     8 |   0 |    8 |   0 |   0 |   0 | GET    | /                            | 0.000 | 0.016 |   0.020 | 0.003 | 0.004 | 0.000 | 0.016 |  0.005 |  2037.000 |   2037.000 |    16296.000 |   2037.000 |
|     8 |   0 |    7 |   1 |   0 |   0 | GET    | /logs/alp.html               | 0.000 | 0.000 |   0.000 | 0.000 | 0.000 | 0.000 | 0.000 |  0.000 |     0.000 |   8517.000 |    59190.000 |   7398.750 |
|    10 |   0 |    0 |   0 |  10 |   0 | GET    | /logs                        | 0.000 | 0.004 |   0.004 | 0.000 | 0.000 | 0.000 | 0.000 |  0.001 |    19.000 |    564.000 |     2915.000 |    291.500 |
|    11 |   0 |   11 |   0 |   0 |   0 | GET    | /static/*                    | 0.008 | 0.216 |   1.032 | 0.094 | 0.004 | 0.024 | 0.008 |  0.087 |   994.000 | 508459.000 |  1802458.000 | 163859.818 |
|    17 |   0 |    6 |   0 |  11 |   0 | POST   | /items/edit                  | 0.000 | 0.024 |   0.120 | 0.007 | 0.008 | 0.020 | 0.004 |  0.008 |    58.000 |     93.000 |     1191.000 |     70.059 |
|    26 |   0 |   26 |   0 |   0 |   0 | POST   | /bump                        | 0.004 | 0.616 |   1.384 | 0.053 | 0.024 | 0.016 | 0.028 |  0.131 |    90.000 |     92.000 |     2366.000 |     91.000 |
|    40 |   0 |   39 |   0 |   1 |   0 | POST   | /complete                    | 0.004 | 0.880 |  27.613 | 0.690 | 0.024 | 0.880 | 0.808 |  0.290 |    34.000 |     34.000 |     1326.000 |     33.150 |
|    68 |   0 |   46 |   0 |  22 |   0 | GET    | /transactions/[0-9]+.png     | 0.004 | 0.024 |   0.148 | 0.002 | 0.004 | 0.000 | 0.000 |  0.004 |    33.000 |    623.000 |    29065.000 |    427.426 |
|    72 |   0 |   50 |   0 |  22 |   0 | POST   | /ship                        | 0.812 | 0.836 |  36.184 | 0.503 | 0.000 | 0.812 | 0.812 |  0.394 |    29.000 |     61.000 |     3776.000 |     52.444 |
|    79 |   0 |   45 |   0 |  34 |   0 | POST   | /ship_done                   | 0.004 | 0.860 |  39.544 | 0.501 | 0.008 | 0.808 | 0.812 |  0.391 |    29.000 |     83.000 |     3169.000 |     40.114 |
|   102 |   0 |   52 |   0 |  50 |   0 | POST   | /buy                         | 0.004 | 1.684 |  95.174 | 0.933 | 0.008 | 1.616 | 0.996 |  0.787 |     0.000 |     49.000 |     3541.000 |     34.716 |
|   103 |   0 |   67 |   0 |  36 |   0 | POST   | /sell                        | 0.020 | 0.852 |   9.632 | 0.094 | 0.000 | 0.012 | 0.000 |  0.172 |    13.000 |    106.000 |     3763.000 |     36.534 |
|   113 |   0 |  113 |   0 |   0 |   0 | GET    | /settings                    | 0.000 | 0.520 |  12.944 | 0.115 | 0.004 | 0.000 | 0.012 |  0.136 |  2799.000 |   2953.000 |   331583.000 |   2934.363 |
|   121 |   0 |  105 |   0 |  16 |   0 | POST   | /login                       | 0.068 | 0.908 |  47.844 | 0.395 | 0.472 | 0.072 | 0.084 |  0.258 |    73.000 |    107.000 |    11449.000 |     94.620 |
|   233 |   0 |    1 | 220 |  12 |   0 | GET    | /logs/                       | 0.000 | 0.004 |   0.032 | 0.000 | 0.000 | 0.000 | 0.000 |  0.001 |    13.000 |    564.000 |     4056.000 |     17.408 |
|   248 |   0 |  248 |   0 |   0 |   0 | GET    | /upload/[0-9a-z]+.jpg        | 0.000 | 0.068 |   2.260 | 0.009 | 0.004 | 0.016 | 0.000 |  0.012 | 51480.000 | 150881.000 | 19921321.000 |  80327.907 |
|   263 |   0 |  262 |   0 |   1 |   0 | GET    | /new_items.json              | 0.040 | 1.216 |  95.107 | 0.362 | 0.056 | 0.052 | 0.052 |  0.247 |     0.000 |  23728.000 |  6131659.000 |  23314.293 |
|   323 |   0 |  304 |   0 |  19 |   0 | GET    | /users/transactions.json     | 0.020 | 6.780 | 920.902 | 2.851 | 0.220 | 2.138 | 1.667 |  1.756 |     0.000 |  29240.000 |  6247445.000 |  19341.935 |
|   533 |   0 |  533 |   0 |   0 |   0 | GET    | /users/[0-9]+.json           | 0.012 | 1.800 | 104.540 | 0.196 | 0.216 | 0.080 | 0.032 |  0.175 |    94.000 |  24033.000 |  7384995.000 |  13855.525 |
|  1429 |   0 | 1429 |   0 |   0 |   0 | GET    | /new_items/[0-9]+.json       | 0.020 | 2.380 | 331.060 | 0.232 | 1.344 | 0.088 | 0.188 |  0.202 | 22666.000 |  24058.000 | 33558952.000 |  23484.221 |
|  4501 |   0 | 4501 |   0 |   0 |   0 | GET    | /items/[0-9]+.json           | 0.004 | 0.548 |  21.088 | 0.005 | 0.028 | 0.000 | 0.004 |  0.013 |  1828.000 |   4326.000 |  9918458.000 |   2203.612 |
+-------+-----+------+-----+-----+-----+--------+------------------------------+-------+-------+---------+-------+-------+-------+-------+--------+-----------+------------+--------------+------------+

集計したログのhtmlファイルを作成

アクセスログの集計結果をブラウザから見れるようにするために、htmlファイルを作成する

# mkdir -p /www/data/logs
# echo "<html><body><pre style=\"font-family: 'Courier New', Consolas\">" > /www/data/logs/alp.html
# cat /var/log/nginx/access.log | ./alp ltsv -m "/upload/[0-9a-z]+.jpg,/items/[0-9]+.json,/new_items/[0-9]+.json,/users/[0-9]+.json,/transactions/[0-9]+.png,/static/*" >> /www/data/logs/alp.html

静的ファイルの配信設定

作成したhtmlファイルをローカルのブラウザから確認できるようにするためnginxの設定を変更する。

# vim /etc/nginx/nginx/conf

// 中略
// 以下のように/logs/xxxx.htmlでアクセスできるようにしておく
    server {
        listen 8080;

        location / {
            proxy_pass http://localhost:8000;
        }

        location /logs/ {
            root /www/data;
            index alp.html;
        }
    }

// 中略

設定が完了したらnginxの設定ファイルを再読み込みする

# nginx -t 
# nginx -s reload

動作確認

ローカルのブラウザからhttp://<nginxが起動しているIPアドレス>:8080/logs/alp.htmlにアクセスすると、集計結果が表示されている。 f:id:dais39:20210218235301p:plain

notify_slackを利用してhtmlファイルをSlackに通知する

最後にnotify_slackを使ってhttp://<nginxが起動しているIPアドレス>:8080/logs/alp.htmlをslackに通知する。

# echo "http://172.28.128.3:8080/logs/alp.html" | ./notify_slack -c notify_slack.toml

f:id:dais39:20210218235654p:plain