日志级别
Viswoole 日志系统参考 PSR-3 规范定义日志级别。框架内置 5 个标准级别(alert、error、warning、info、debug)并扩展了 sql、task 业务专用级别,同时提供 mixed 方法记录任意自定义级别。
级别列表
| 级别 | 方法 | 严重程度 | 说明 |
|---|---|---|---|
| ALERT | Log::alert() | 🔴 高 | 必须立即采取行动 |
| ERROR | Log::error() | 🟠 中 | 运行时错误,不需要立即处理但需监控 |
| WARNING | Log::warning() | 🟡 低 | 异常情况,非错误 |
| INFO | Log::info() | 🟢 正常 | 一般业务信息 |
| DEBUG | Log::debug() | ⚪ 最低 | 调试详细信息 |
PSR-3 中的 emergency、critical、notice 级别框架未提供独立方法,可通过
Log::mixed('emergency', ...)、Log::mixed('critical', ...)、Log::mixed('notice', ...)记录。
扩展级别
除标准级别外,框架还提供两个业务专用级别:
| 级别 | 方法 | 说明 |
|---|---|---|
| SQL | Log::sql() | 数据库 SQL 执行记录 |
| TASK | Log::task() | 异步任务执行记录 |
级别使用指南
自定义级别(emergency / critical / notice 等)
PSR-3 中的 emergency、critical、notice 等级别未内置独立方法,请使用 Log::mixed() 记录:
php
// 系统不可用(emergency)
Log::mixed('emergency', '数据库连接池耗尽,无法获取连接', [
'pool_size' => 64,
'active_connections' => 64,
'waiting' => 128,
]);
// 严重情况(critical)
try {
$smsClient->send($phone, $code);
} catch (ServiceUnavailableException $e) {
Log::mixed('critical', '短信服务不可用', [
'provider' => 'aliyun',
'error' => $e->getMessage(),
]);
}ALERT - 必须立即行动
需要立即人工介入的问题:
php
// 磁盘空间不足
$freeSpace = disk_free_space('/');
if ($freeSpace < 1024 * 1024 * 1024) { // 小于 1GB
Log::alert('磁盘空间不足', [
'free_bytes' => $freeSpace,
'path' => '/',
]);
}
// 支付回调签名验证失败
Log::alert('支付回调验签失败', [
'order_id' => $orderId,
'expected_sign' => $expectedSign,
'received_sign' => $receivedSign,
]);ERROR - 运行时错误
常规运行时错误,应被监控和追踪:
php
// 业务逻辑异常
catch (ValidationException $e) {
Log::error('数据验证失败', [
'field' => $e->getField(),
'value' => $e->getValue(),
'rule' => $e->getRule(),
]);
}
// 外部 API 调用失败
$response = $httpClient->post($url, $data);
if ($response->getStatusCode() >= 400) {
Log::error('外部API请求失败', [
'url' => $url,
'status' => $response->getStatusCode(),
'body' => $response->getBody(),
]);
}WARNING - 警告情况
非错误的异常情况,值得关注:
php
// 性能警告
$duration = $endTime - $startTime;
if ($duration > 5.0) {
Log::warning('接口响应时间过长', [
'endpoint' => '/api/orders',
'duration' => "{$duration}s",
'threshold' => '5s',
]);
}
// 弃用的功能调用
Log::warning('使用了已弃用的API', [
'old_method' => 'getOldData()',
'suggestion' => '请使用 getNewData() 替代',
]);INFO - 一般信息
记录有意义的业务流程节点:
php
// 用户行为
Log::info('用户登录成功', [
'user_id' => $userId,
'login_method' => 'password',
]);
// 关键业务流程
Log::info('订单状态变更', [
'order_id' => $orderId,
'from' => 'pending',
'to' => 'paid',
'operator' => 'system',
]);DEBUG - 调试信息
详细的调试数据,生产环境建议关闭:
php
// 请求详情
Log::debug('请求处理开始', [
'headers' => request()->getHeaders(),
'params' => request()->getQueryParams(),
'body' => request()->getBody(),
]);
// 变量状态
Log::debug('处理前数据', [
'input' => $rawData,
'processed' => $processedData,
'result' => $result,
]);SQL - 数据库查询
专门用于记录 SQL 执行情况:
php
// 查询记录
Log::sql('SELECT查询', [
'sql' => 'SELECT * FROM users WHERE id = ?',
'bindings' => [100],
'time' => '2.34ms',
'rows' => 1,
]);
// 写入记录
Log::sql('INSERT插入', [
'sql' => 'INSERT INTO orders (...) VALUES (...)',
'insert_id' => 10001,
'affected_rows' => 1,
]);TASK - 异步任务
记录异步任务的执行状态:
php
// 任务投递
Log::task('任务已投递', [
'topic' => 'sms.send',
'queue_id' => $queueId,
'data' => ['phone' => '138****8888'],
]);
// 任务完成
Log::task('任务执行完成', [
'topic' => 'sms.send',
'result' => 'success',
'duration' => '0.5s',
]);控制台颜色映射
各日志级别在控制台输出的预设颜色:
| 级别 | ANSI 颜色码 | 显示效果 |
|---|---|---|
| emergency / alert / critical | \033[1;31m | 粗体红色 |
| error | \033[0;31m | 红色 |
| warning / task | \033[0;33m | 黄色 |
| notice | \033[0;34m | 蓝色 |
| sql | \033[0;32m | 绿色 |
| debug | \033[0;37m | 灰色 |
| 其他 | \033[0m | 默认颜色 |
最佳实践
生产环境配置建议
php
// config/log.php - 生产环境
return [
'default' => 'file',
// 只记录 warning 及以上级别到独立通道
'type_channel' => [
'error' => 'file', // error/critical/alert/emergency
],
'trace_source' => true,
'console' => false, // 生产环境关闭控制台输出
'channels' => [
'file' => [
'driver' => File::class,
'options' => [
'storageDays' => 30, // 保留30天
'maxFiles' => 50,
'fileSize' => 10 * 1024 * 1024,
]
],
],
];开发环境配置建议
php
// config/log.php - 开发环境
return [
'default' => 'file',
'trace_source' => true,
'console' => true, // 开发环境开启控制台输出
'channels' => [
'file' => [
'driver' => File::class,
'options' => [
'storageDays' => 7,
'json' => true,
]
],
],
];