用钉钉提醒 Laravel 11 异常:一个简单的实现

受到这篇帖子启发,联想到自己也有 Error Tracking 的需求。我的项目目前只有 laravel.log 日志,不能主动提醒出错。之前调查过 Sentry、Laravel Flare 这样的专业服务,但最终没有使用。受上述帖子的启发,相比完全没有,自己实现一个简陋的解决方案总比没有强。

注册异常报告

  • 使用 dispatch()->afterResponse() 可以在当前请求结束之后,再通知钉钉。
  • 虽然是 dispatch,但这儿没有队列任务,并不需要队列运行。
// bootstrap/app.php
->withExceptions(function (Exceptions $exceptions) {
    if (App::environment('production')) {
        $exceptions->report(function (Exception $e) {
            // 等当前请求结束后,再发送到钉钉
            $message = Dingtalk::message($e);
            dispatch(function () use ($message) {
                Dingtalk::send($message);
            })->afterResponse();
        });
    }
})

发送消息到钉钉

  • 使用钉钉的机器人 API 发送消息
  • 消息支持 Markdown 格式
// app/Dingtalk.php
class Dingtalk
{
    public static function sendException(Exception $e): void
    {
        static::send(static::message($e));
    }

    public static function message(Exception $e): array
    {
        return [
            'msgtype' => 'markdown',
            'markdown' => [
                'title' => 'Exception️',
                'text' => sprintf(
                    "# Exception: %s\n\n## File\n%s:%d\n\n## Trace\n%s",
                    $e->getMessage(),
                    $e->getFile(),
                    $e->getLine(),
                    Str::limit($e->getTraceAsString(), 200),
                ),
            ],
        ];
    }

    public static function send(array $message): void
    {
        $token = config('services.dingtalk.access_token');
        if (!$token) {
            throw new Exception('Dingtalk access token is not set');
        }

        $response = Http::post('https://oapi.dingtalk.com/robot/send?access_token=' . $token, $message);

        if ($response->failed()) {
            throw new Exception('Dingtalk message failed to send with status ' . $response->status());
        }

        if ($response->json('errcode') !== 0) {
            throw new Exception('Dingtalk message failed to send with error ' . $response->body());
        }
    }
}

别忘了配置钉钉 Token:

// config/services.php
'dingtalk' => [
    'access_token' => env('DINGTALK_ACCESS_TOKEN'),
],

测试效果

运行一个随机命令,比如:

$ php artisan xxx

   ERROR  Command "xxx" is not defined.

这是得到的结果:

用钉钉跟踪 Laravel 11 异常

本帖已被设为精华帖!
本帖由 MArtian 于 2个月前 加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 8
Dcatplus-杨光

很早之前就已经用上了系统异常,通知钉钉,企业微信。

2个月前 评论

这里可以考虑使用UDP做个专门的队列上报服务。直接嵌在业务底层代码中的话,日后容易形成瓶颈。特别是队列中如果出现报错的话,短时间会有大量的http请求,造成网络阻塞。

2个月前 评论
快乐的皮拉夫 (作者) 2个月前
快乐的皮拉夫 (作者) 2个月前
xuchunyang (楼主) 2个月前
xuchunyang (楼主) 2个月前

方案是灵活的,解耦的话,可以配置es-filebeat从日志采集,写入日志服务器,然后从日志服务器再发送消息。

1个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!