unifreak / qlog
可配置的记录器,可以将日志记录到Redis队列以持久化或记录到stashed进行调试
Requires
- monolog/monolog: ~1.0
Requires (Dev)
- phpunit/phpunit: ^5.7
- predis/predis: ^1.1
This package is auto-updated.
Last update: 2024-09-20 22:23:06 UTC
README
中文用户请见 https://github.com/UniFreak/QLog/blob/master/README.cn.md
QLog
包装了 Monolog
包,并添加了一些自定义的处理器/处理器/格式化器,以提供以下功能
- 根据配置将日志记录到stash区域(用于后续输出和调试)或Redis队列
- 提供一些预定义的日志通道和相应的日志方法
- 所有记录都有额外的字段,提供关于耗时和内存使用的详细信息。请参阅一些概念
- 为每条记录自动生成一个会话键。请参阅一些概念
- 使用
_id
标识符标记记录 - 搜索stashed记录
目前,QLog
的两个主要用例是
- 在API响应中打印stashed记录,用于实时调试
- 异步处理Redis队列中的记录,将它们聚合到一个地方(如ES)进行搜索或可视化
安装
只需运行 composer require unifreak/qlog
用法
一些概念
QLog
以预定义的结构将日志记录作为数组,如下所示
[ "message" => "api call to api.example.com", "context" => [ "method" => "GET", "params" => [ "id" => 12345, "name" => "John", ], ], "level" => 200, "level_name" => "INFO", "channel" => "app", "datetime" => "2019:03:28 18:53:19.587777", "time" => "15 ms", "time_total" => "15 ms", "session" => "15a1c8220475f41990cc389ad5f6b495", "mem" => "3 MB", ]
-
message
:日志消息 -
context
:日志上下文 -
level
&level_name
日志级别,支持的级别有
DEBUG
、INFO
、NOTICE
、WARNING
、ERROR
、CRITICAL
、ALERT
、EMERGENCY
。您可以通过调用相应的日志方法来指定级别。请参阅日志 -
channel
日志通道。每条日志都位于一个指定的通道中,以指示此日志可能与哪个应用程序事件相关。
QLog有几个预定义的通道
QLogger::CHANNEL_APP = 'app'; // Applicatoin QLogger::CHANNEL_SQL = 'sql'; // SQL QLogger::CHANNEL_API = 'api'; // Api call QLogger::CHANNEL_REQ = 'req'; // Request QLogger::CHANNEL_RESP = 'resp'; // Response
您可以通过调用不同的
in
方法将记录记录到预定义的通道或自定义通道。请参阅指定通道 -
datetime
:日志日期时间 -
time
/time_total
/mem
:自上次日志记录以来消耗的时间 / 自首次日志记录以来消耗的时间 / 消耗的内存 -
session
:日志记录的会话键。此会话键可以用于将不同请求中的日志链接在一起,这些请求可能跨越多个应用程序。例如,对应用程序A的API调用
A:api/a
A:api/a --> B:api/b --> C:api/c
如果A、B和C中的所有日志都共享相同的会话键,则我们可以搜索整个跨应用程序日志链。
QLogger的会话键是随机字符串。QLogger会从
QLOG_SESSION
cookie中读取以初始化会话键,如果没有QLOG_SESSION
cookie,则将生成一个新的会话键。之后,所有日志记录都将具有相同的会话键。但是请注意:您必须手动维护
QLOG_SESSION
cookie以链接记录。 -
_id
:id如果我们只有会话键,这将是一个问题:因为会话键是随机的,我们在搜索记录链之前不知道它,所以我们如何知道这个会话键?
这就是
id
字段的作用。默认日志记录结构中没有
_id
字段,但您可以通过调用idBy()
方法指定多个_id
字段。请参阅指定ID。id
的主要目的是首先进行搜索以定位一个感兴趣的记录,然后使用此记录的会话密钥来搜索整个日志记录链。
初始化
QLog 构造函数需要两个参数:一个 \Predis\Client
/\Reids
实例和一个配置数组。如下所示
use Unifreak\QLog\QLogger; $redis = new \Predis\Client(['host' => '127.0.0.1', 'port' => 6379]); $config = [ 'default_channel' => QLogger::CHANNEL_APP, 'queue_name' => 'qlog:example.com', 'size' => 3000, 'log_to' => QLogger::LOG_REDIS, ]; $log = new QLogger($redis, $config);
配置选项:$config
-
queue_name
:必需,指定 QLog 要记录的 Redis 队列
-
default_channel
:指定默认通道。默认为
app
-
size
:Redis 队列的最大大小。默认为 3000 -
log_to
:记录记录的位置。支持三个值0
:仅记录到存储区1
:默认值。仅记录到 Redis 队列2
:记录到存储区和 Redis 队列
日志
您可以通过调用不同的日志方法来记录不同级别的记录,传递日志消息(必需)和日志上下文(可选)
$message = 'log message'; $context = ['some' => 'context']; $log->info($message, $context); $log->notice($message, $context); $log->warn($message, $context); $log->error($message, $context); $log->critical($message, $context); $log->alert($message, $context); $log->emergency($message, $context);
指定通道
您可以通过调用这些方法来指定预定义的通道
$log->inApp()->info($message, $context); // Specify channel: app $log->inSql()->info($message, $context); // Specify channel: sql $log->inApi()->info($message, $context); // Specify channel: api $log->inReq()->info($message, $context); // Specify channel: req $log->inResp()->info($message, $context); // Specify channel: resp
此外,您还可以通过调用 in()
方法来指定自定义通道
$log->in('custom_channel')->info($message, $context); // Specify channel: custom_channel
指定 ID
您可以通过调用 idBy()
方法来指定多个 id 名称/值对。**注意**:id 名称必须以 _id
结尾。
$log->idBy('car_id', 123)->idBy('user_id', 321)->info($message, $context);
然后记录将具有额外的两个 id 字段
[ 'car_id' => 123, 'user_id' => 321 ]
**注意**:
- 如果您多次使用相同的名称调用
idBy()
,则后者将覆盖前者 - Id 是 sticky,这意味着所有后续日志都将自动保留指定的 id 名称/值。
过滤存储的日志
您可以通过调用这些方法来过滤存储的日志
$log->shift(); // get the first record $log->pop(); // get the last record $log->stashed(); // get all records $log->stashed(function($record) { // filter for specific records // like: filter for records that have car_id and level greater than warning return !empty($record['car_id']) && $record['level'] > QLogger::WARN; }); $log->clean(); // clear all records
**注意**:如果 QLog
配置为不记录到存储区(log_to
配置选项),则存储区将为空,因此上述所有方法将返回空数组
Laravel & Lumen
QLog 为 laravel
/lumen
提供了一个外观类和服务提供者类
- 外观:
Unifreak\QLog\QLogFacade
- 服务提供者:
Unifreak\QLog\QLogServiceProvider
在注册外观和服务提供者之后,您可以使用 QLog
来访问 QLogger
,如下所示
use QLog; QLog::in('my_channel')->idBy('car_id', 123)->warning('somthing went wrong'); dump(QLog::stashed());
QLogServiceProvider
还启用了自动记录 SQL 查询和 GuzzleHttp
请求。您可以使用以下查询参数来控制 QLog
的日志行为
-
qlog_debug
:非零值等同于传递
qlog_autolog=2
和qlog_log_to=0
,启用自动记录GuzzleHttp
请求和 SQL 查询,并且仅记录到存储区。见下文 -
qlog_autolog
:控制自动记录行为1
:默认值。自动记录GuzzleHttp
请求2
:自动记录GuzzleHttp
请求和 SQL 查询
-
qlog_log_to
:控制日志区域0
:仅记录到存储区1
:仅记录到 Redis 队列2
:同时记录到存储区和 Redis 队列
注册外观和服务提供者
- 添加一个新的配置文件
config/qlog.php
return [ // Disable QLog: // - If disabled, all log methods call will simply be ignored // - But if there is `qlog_debug` query parameter present, QLog will be auto-enabled 'disable' => false, // redis connection config 'redis' => [ 'host' => $redisHost, 'port' => $redisPort ], // qlog config 'queue_name' => 'qlog:example.com', 'size' => 2000, ];
- 将以下代码添加到
bootstrap/app.php
if (!class_exists('QLog')) { class_alias(Unifreak\QLog\QLogFacade::class, 'QLog'); } $app->configure('qlog'); $app->register(Unifreak\QLog\QLogServiceProvider::class);
**注意**:确保在 $app->withEloquent()
之后注册服务提供者,否则 SQL 查询自动记录功能将无法正常工作
有关更多信息,请参阅 laravel
/lumen
的官方文档
TODO
- 在
QLogServiceProvider
中自动记录异常 - 当记录达到配置的级别时,自动发送邮件