laravel 9+ 中 slack 日志通道开箱即用,但必须同时满足三个条件:log_channel=slack、slack_webhook_url 配置正确且为完整 https url、日志级别不低于 error;任一缺失均静默失败。

Slack 日志通道在 Laravel 9+ 中是开箱即用的,不需要装额外包,但必须同时满足三个硬性条件:LOG_CHANNEL=slack、SLACK_WEBHOOK_URL 配置正确、日志级别 ≥ error;缺一不可,否则静默失败。
LOG_CHANNEL=slack 却没消息?先查这三件事
最常见的“配置了却没反应”,其实根本没走到 Slack 发送逻辑。重点排查:
-
LOG_CHANNEL值是否真的为slack(不是stack或拼错) -
SLACK_WEBHOOK_URL是否写在.env里,且格式是完整 URL(https://hooks.slack.com/services/...),不能漏掉https:// - 触发日志的代码是否用了
error及以上级别:比如Log::error('boom')可以,Log::warning('oops')默认不会发——因为 Slack 通道默认level是error
验证方式:在 php artisan tinker 里执行 Log::channel('slack')->error('test from tinker');,比改业务代码更快定位问题。
config/logging.php 里 slack 通道的 level 和 formatter 怎么调
Slack 通道默认只推 error 级别,想连 warning 也推,得显式改配置:
'slack' => [
'driver' => 'slack',
'url' => env('SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => 'warning', // ← 改这里,不是 'error'
],
如果还想带请求上下文(比如 IP、URL、用户 ID),不能靠默认 formatter。得加自定义 formatter,在 slack 配置里加:
'formatter' => \Monolog\Formatter\LineFormatter::class, 'formatter_with_context' => true,
更进一步的话,需要自己写一个继承 LineFormatter 的类,重写 format() 方法,把 $record['context'] 里的字段塞进 Slack 消息体——因为原生 Slack handler 不解析 context 字段。
本地开发误推 Slack?用 stack + 环境判断更稳
硬编码 LOG_CHANNEL=slack 在 .env 里,很容易在本地或测试环境误发。推荐做法是保持 LOG_CHANNEL=stack,然后在 config/logging.php 的 stack.channels 数组里动态控制:
- 定义一个专用通道:
'production_slack',driver 为slack - 在
stack.channels里写:env('APP_ENV') === 'production' ? ['single', 'production_slack'] : ['single']
这样本地 APP_ENV=local 就完全不走 Slack,也不用反复改 .env。后续加 Sentry 或 DB 日志,只需往数组里追加 channel 名,不碰环境变量。
Webhook 失败不报错,curl 测试是唯一靠谱验证手段
Laravel Slack 日志通道用的是 Monolog 的 SlackWebhookHandler,它失败时只会丢弃异常,不抛出、不记录、不提示——你什么都看不到。
所以每次换 Webhook URL 或上线前,务必手动 curl 测试:
curl -X POST \
-H 'Content-type: application/json' \
--data '{"text":"test from curl"}' \
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
如果 curl 成功但 Laravel 不发,问题一定出在配置或日志级别;如果 curl 都失败,说明 Webhook URL 无效、被组织防火墙拦截,或 Slack 工作区已禁用 Incoming Webhooks。











