laravelのログをslackに送信する(production環境でのログ管理)
時間がなくて適当なログ設定にしてる人への記事
開発モードのログなんて適当な時しか見ないんだろうけど、インフラ屋はアプリログを制す必要あり。要するに開発時のログとproductionとしてデプロイしたもののログは性質が異なる。開発時に見落されているエラーログを素早く受けとる手法は何かしら残しておく必要がある。筆者もいくつかアプリケーションを運用してきたが、これらのログの受信はメール送信でもいいのだが今日日やはりslack送信が便利であると思ったので、ここに紹介する。そもそも、まともに色々できないで適当に設定するようなアプリはテストが甘く単純なエラーも見落とされているものだ。デプロイメントに関してもとりわけステージング環境などは雑に設定しやすいので、ある程度ログ設定には気配りして欲しい。
ディフォルトのログ設定
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
おそらくこれが通常のログ設定で、ほとんど深掘りしなくても動作するのではあるが、これはdebugを含む全部のログをシングルファイルに送信している。以下にエラーレベルを記述するが
-
debug
- 詳細なデバッグ情報 -
info
- 一般的な情報 -
notice
- 重要な通知 -
warning
- 潜在的な問題 -
error
- 一般的なエラー -
critical
- 致命的なエラー -
alert
- 即対応が必要なエラー -
emergency
- システム全体が使用不能
このようになっており、debugが指定されているため実質全てのログが送信されている。
自分でログを送信する以前のレベルの話
上記で諸々ログレベルを記述したが、一番重要なのはerror
というレベルであり、たとえば以下のような例
syntax error
これは、アプリケーションのコードが解析・実行される前に PHP エンジンによって検出されており、スクリプトが動作していないのでこのようなエラーは確実に拾い上げる必要がある。まあそのテストが甘いものなどはこれが隠されている事もあるので少なくともerror
以上は確実にproduction環境においては拾い上げる必要があるのと、debug、infoとかをどうするという問題は多少ある。多少あるもののerror以上はかなり重大なのでslackに通知してもほとんどの場合損は無い。逆に言うと、アプリケーション作成者はその辺を意識してログレベルを決定する必要があるが、割と適当に
logger('moge'); // debugレベル
とかやりがちなのでまあその辺はerror
以上に送るかどうかを気をつけて開発してもらうとして...
defaultの設定の上にslackを加える
プロダクション環境でこのディフォルトを適用したdebugかつsingleファイルがいいとは思えないが、先述の通り、その辺を雑に記録してもとりあえずerror以上を受けとれるようにしておけば割と何とかはなる、ということでdefaultの上にslackで受信する設定を加えてみよう。
config/logging.phpをみる
// <snip...>
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => explode(',', env('LOG_STACK', 'single')),
'ignore_exceptions' => false,
],
// <snip...>
このように、stack
においてはLOG_STACK
の設定によりカンマ区切りで複数のchannelを待ち受ける事を想定している。現在 .env を再度貼り付けると
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
のようにLOG_STACK=single
なっているので何だかんだsingleログにしか記録されていないのであるが、singleかつslackにするには以下のようにセットすればいいことが理解できる。
LOG_CHANNEL=stack
LOG_STACK=single,slack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
この設定だとdebug以上がsingleとslackに記録されるので、非常にうるさいわけだが、これで適当に
Route::get('/demo', function () {
logger("test"); // debugレベルの簡易ログ送信ヘルパー
});
などして/demoにアクセスすると、slackのエラーもまとめて記録される
[2025-02-10 20:00:04] laravel.EMERGENCY: Unable to create configured logger. Using emergency logger. {"exception":"[object] (TypeError(code: 0): Monolog\\Handler\\SlackWebhookHandler::__construct(): Argument #1 ($webhookUrl) must be of type string, null given, called in /var/www/html/vendor/laravel/framework/src/Illuminate/Log/LogManager.php on line 346 at /var/www/html/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php:50)
[stacktrace]
まあこれはslackの設定を何もしてないので当然ではある。
slackの設定
https://api.slack.com/apps などで適切にアプリケーションを作成する。slackアプリケーションの作成に関しては本稿では取り上げないので、どうにかして適切にwebhookのurlを取得する事。必要なのはincoming webhookだけというのがslackの楽なところだろう。
configでslack関連の設定を確認する
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
このようになっており、 .env に適切な値をセットすればそれが利用される。少なくとも LOG_SLACK_WEBHOOK_URL
だけは絶対に必要なので、この値を .env に適切にセットする。
特に特殊な設定を施さずとも、この段階でslackにログが転送されるはずだ。
debugを記録するのは流石にうるさ過ぎる
これに関してはslackののconfig arrayのlevelを変更するといい。ただ
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
// 'level' => env('LOG_LEVEL', 'critical'),
'level' => 'error',
'replace_placeholders' => true,
],
としてもokなんだけど、
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('SLACK_LOG_LEVEL', 'error'),
'replace_placeholders' => true,
],
のように .env のエントリーを新設するのが個人的には好みである。ただconfigに変更かかっちゃうけど、まあそれはそれとして。
テスト
この段階で
Route::get('/demo', function () {
logger("test"); // debugレベルの簡易ログ送信ヘルパー
});
としたとき、storage/logs/laravel.logのみにtestが書かれ、slackの通知はこなくなる
Route::get('/demo', function () {
logger()->error("This is an error log via logger()!");
});
に変更すると、slackに通知されなおかつログにも記録されるはずだ。
まとめ
slackのincoming webhookはurlさえゲットできれは非常に手軽にログ送信できるので、書いておくのはおすすめ。production環境でたとえばerror以上のログのみファイルにもslackにも記録したいというような場合はconfig/logger.phpの変更すら不要で
LOG_CHANNEL=stack
LOG_STACK=single,slack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=error
LOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/****/****
と雑に設定しておいても割とお得な事が多い。
あとがき
結構雑にデプロイしたステージングサーバーなどでも、流石にsingle
ファイルじゃなくてdaily
にしておくといいかもしれないですね。まああとstagingであっても.envにセンシティブな設定が残ってる場合はdebug設定から露出しないように注意(かつては露出してたんだよなあ...)
Discussion