如何使用ThinkPHP6进行异步日志记录操作?

随着互联网的高速发展,日志记录服务成为了每个大型 web 应用必不可少的模块。为了方便错误排查、性能监控等各种需求,本文将介绍如何使用 thinkphp6 框架进行异步日志记录操作。

1. 什么是日志记录

在计算机科学领域,日志记录是指将计算机系统中发生的事件和信息记录下来。通常,这些记录都以文件或数据库的形式存储。日志记录有助于了解系统运行状况,及时发现和解决问题,进而提高系统的可靠性和稳定性。

在 web 应用中,日志记录可以帮助开发者更好地了解系统的遇到的问题和错误。依据日志记录,开发者可以清楚地了解应用的行为以及错误发生的位置和时机。

2. ThinkPHP6 异步日志记录

在应用开发过程中,日志记录是一个必不可少的模块。而且,日志记录经常是一个耗时的操作,如果同步执行的话会影响系统的性能。为此,ThinkPHP6 引入了异步日志记录的功能,让日志记录不再影响应用的响应速度。

通常在控制器或模型中记录日志,我们使用注入 PsrLogLoggerInterface 接口来实现。

立即学习“PHP免费学习笔记(深入)”;

// Controller或Model中use PsrLogLoggerInterface;public function index(LoggerInterface $logger){    $logger->info('hello world');}

简单的使用方式。使用异步日志记录,定义一个异步日志记录器:

use MonologLogger;use MonologHandlerStreamHandler;$logger=new Logger("AsyncLogger");$logger->pushHandler(new StreamHandler('runtime/log/async.log'), Logger::INFO);

日志记录器定义好后,使用队列发送日志记录信息,这里我们选择使用 RabbitMQ 当做队列服务。

如知AI笔记 如知AI笔记

如知笔记——支持markdown的在线笔记,支持ai智能写作、AI搜索,支持DeepseekR1满血大模型

如知AI笔记 27 查看详情 如知AI笔记

// Message类namespace appcommon;class Message{    /**     * 记录日志     * @param $level     * @param $message     * @param array $context     * @return bool     */    public static function log($level,$message,array $context=[]){        $data=[            'level'=>$level,            'message'=>$message,            'context'=>$context,            'channel'=>'AsyncLogger',            'datetime'=>date('Y-m-d H:i:s'),            'host'=>$_SERVER['SERVER_ADDR'] ?? '',            'uri'=>$_SERVER['REQUEST_URI'] ?? '',        ];        $producer=Queue::getConnection('AsyncLogger',true);        $producer->setExchangeOptions(['name'=>'async_logs','type'=>'topic','durable'=>true])->declareExchange();        try{            $producer->publish(json_encode($data),[                'routing_key' =>'log',                'exchange' =>'async_logs',            ]);            return true;        }catch (Exception $e){            return false;        }    }}

其中,我们使用 appcommonQueue 类来提供 rabbitmq 的连接实例;data中除了记录日志的信息外,还包含一些环境信息,比如时间、IP地址、请求的uri地址等。

队列处理程序:

// Consumer类use BunnyMessage;use PsrLogLoggerInterface;class Consumer{    /**     * @param Message $message     * @param LoggerInterface $logger     */    public function process(Message $message,LoggerInterface $logger){        $body=$message->content;        $data= json_decode($body,true);        $channel=$data['channel'] ?? 'default_logger';        $logger->notice($data['message'], $data);    }}

当然,我们还需要一个辅助处理日志的类。

// Queue类namespace appcommon;use BunnyAsyncClient;use BunnyChannel;use BunnyMessage;use BunnyProtocolMethodBasicConsumeOkFrame;use BunnyProtocolMethodChannelCloseFrame;use BunnyProtocolMethodChannelCloseOkFrame;use BunnyProtocolMethodConnectionCloseFrame;use BunnyProtocolMethodConnectionCloseOkFrame;use BunnyProtocolMethodConnectionStartFrame;use BunnyClientStateEnum;use BunnyMessage as BunnyMessage;class Queue{    /**     * @param string $queueName     * @return Client|null     */    public static function getConnection(string $routingKey, bool $persistent=false):?Client    {        $config=config('rabbitmq.async_log');        $client=new Client([            'host' => $config['host'],            'port' => $config['port'],            'user' => $config['user'],            'password' => $config['password'],            'vhost' => $config['vhost'],//注意此处改为需要的 VHOST            'concurrency' => 2,        ]);        try{            $client->connect();            $client->channel()                ->then(function (Channel $channel) use($client,$routingKey,$persistent){                    $channel->exchangeDeclare('async_logs','topic',true,true);                    $channel->queueDeclare($routingKey, $passive=false,$durable=true,$exclusive=false,$autoDelete=false,$nowait=false);                    $channel->queueBind($routingKey, 'async_logs', $routingKey);                    $channel->consume(                        function ($msg, Channel $channel, BunnyMessage $message) use($client,$routingKey){                            $className=config('rabbitmq.async_log.consumer');                            $consumer=new $className($client,$routingKey);                            $consumer->process($message,app('log.async_logger'));                            $channel->ack($msg);//处理消息                        },                        $routingKey,//队列Name                        '',//消费Tag                        false,//no_local                        false,//no_ack                        false,//exclusive                        $persistent ? ['delivery_mode'=>2] : []                    );                });        }catch (Exception $e){            return null;        }finally{            return $client;        }    }}

上面这段代码中定义了队列连接的 host、port 等,通过 $client->channel() 创建了一个 channel 对象,通过 $channel->exchangeDeclare()$channel->queueDeclare() 创建了 exchange 和 queue,并将它们进行了绑定。最后,使用 $channel->consume() 异步消费队列的消息,并将消息发送到消息处理类中。

3. 总结

本文介绍了如何使用 ThinkPHP6 框架进行异步日志记录操作,使日志记录不再影响应用的响应速度。总体来说,以下是操作步骤:

开发自己的异步日志记录器使用 RabbitMQ 进行消息队列处理编写消息处理程序

在实际项目中,我们需要根据具体的需求来优化代码和调整队列的配置。通过异步记录日志,可以有效提高 web 应用的运行效率,并提高系统的稳定性与可靠性。

以上就是如何使用ThinkPHP6进行异步日志记录操作?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/445885.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月7日 20:45:02
下一篇 2025年11月7日 20:49:34

相关推荐

发表回复

登录后才能评论
关注微信