日志级别与通道
本篇是参考文档:说明 Viswoole 日志的级别体系、级别到通道(Channel)的路由规则 type_channel,以及控制台输出的行为。
级别体系
框架提供 7 个内置级别快捷方法,语义遵循 PSR-3 日志规范(PSR-3):
| 方法 | 级别 | 语义 | 典型场景 |
|---|---|---|---|
Log::alert() | alert | 必须立即采取行动 | 整站不可用、数据库不可达,应触发短信等紧急通知 |
Log::error() | error | 运行时错误 | 业务异常、外部服务调用失败,需监控但无需立即处理 |
Log::warning() | warning | 非错误的异常情况 | 响应超时、调用了弃用 API |
Log::info() | info | 普通业务信息 | 用户登录、订单状态变更 |
Log::debug() | debug | 详细调试信息 | 开发调试,生产环境建议关闭 |
Log::sql() | sql | SQL 执行记录 | 数据库查询与写入日志 |
Log::task() | task | 异步任务记录 | 任务投递、执行结果 |
PSR-3 其余级别
PSR-3 定义的 emergency(系统不可用)、critical(临界)、notice(需关注的正常但重要事件)没有独立方法,通过 mixed() 记录:
use Viswoole\Log\Facade\Log;
Log::mixed('emergency', '数据库连接池耗尽,无法获取连接', ['pool_size' => 64]);
Log::mixed('critical', '短信服务不可用', ['provider' => 'aliyun']);
Log::mixed('notice', '用户完成首次实名认证', ['uid' => 1001]);mixed() 的第一个参数是任意级别名,因此也可用于业务自定义级别(如 audit),自定义级别同样参与 type_channel 路由。
写入模式与级别无关
Log::info() 等快捷方法默认走协程聚合写入;需要立即落盘时使用 Log::write($level, $message, $context),级别以第一个参数指定:
Log::write('error', '支付回调验签失败,立即落盘', ['order_id' => $orderId]);级别使用建议
级别选择的核心是「严重程度」而非「代码位置」。以下给出各级别的典型用法,供团队统一口径参考:
alert —— 触发紧急通知
适合需要立即人工介入、通常会对接告警渠道的问题:
$freeSpace = disk_free_space('/');
if ($freeSpace < 1024 * 1024 * 1024) { // 磁盘可用空间小于 1GB
Log::alert('磁盘空间不足', ['free_bytes' => $freeSpace]);
}error —— 需要监控的运行时错误
try {
$response = $this->http->post($url, $data);
} catch (\Throwable $e) {
Log::error('外部服务请求失败', [
'url' => $url,
'exception' => get_class($e),
'message' => $e->getMessage(),
]);
}warning —— 值得关注但非故障
if ($duration > 5.0) {
Log::warning('接口响应时间过长', [
'endpoint' => '/api/orders',
'duration' => "{$duration}s",
]);
}info / debug —— 业务节点与调试数据
use Viswoole\HttpServer\Facade\Request;
// info:有业务意义的流程节点,生产环境保留
Log::info('订单状态变更', ['order_id' => $orderId, 'from' => 'pending', 'to' => 'paid']);
// debug:详细过程数据,生产环境可通过独立通道关闭或降保留期
Log::debug('请求处理开始', ['params' => Request::params()]);sql / task —— 业务专用级别
数据库组件与任务组件内部会使用这两个级别记录执行情况;业务代码在自研 SQL 封装或任务处理器中也可复用,配合 type_channel 将它们单独归档:
Log::sql('INSERT 订单', ['sql' => $sql, 'affected_rows' => 1]);
Log::task('任务执行完成', ['topic' => 'email.send', 'duration' => '0.5s']);上下文即检索维度
每条日志的第二个参数 $context 会被结构化存储(File 驱动下为 JSON 字段),把 order_id、uid、trace_id 这类检索键放进上下文而非拼进消息文本,是日志可检索的前提。
级别到通道映射(type_channel)
log.type_channel 按级别名将日志路由到指定通道,未命中的级别写入 log.default 通道:
// config/log.php
use Viswoole\Log\Drives\File;
return [
'default' => 'app',
// 键:级别名;值:通道名(字符串)或通道名列表(同一条日志写多个通道)
'type_channel' => [
'error' => 'error', // error 单独入错误通道
'critical' => ['error', 'alert'], // critical 同时写两个通道
'sql' => 'sql', // SQL 日志单独归档
],
'channels' => [
'app' => File::class,
'error' => [
'driver' => File::class,
'options' => [
'log_dir' => BASE_PATH . '/runtime/error_logs',
'storageDays' => 90,
],
],
'sql' => [
'driver' => File::class,
'options' => ['log_dir' => BASE_PATH . '/runtime/sql_logs'],
],
],
];路由规则要点:
- 精确匹配:路由键是精确的级别名,
'error' => 'error'不会连带critical、alert;需要同级处理请逐级配置 - 优先级:
type_channel命中 >default默认通道 - 多通道:值为数组时,同一条日志依次写入每个通道
- 启动校验:
type_channel引用了未注册的通道时,启动即抛出LogException,避免运行期静默丢日志 trace_source全局生效:来源追踪在路由之前注入,各通道拿到的日志结构一致
典型用法
生产环境把 error 级别路由到独立通道并设置更长的保留天数(如 90 天),应用主日志保持 7-14 天,既降低存储成本又方便错误监控采集。
控制台输出
log.console 开启后,日志在实际写入时(协程聚合批次落盘那一刻)同步输出到控制台,并按级别着色:
| 级别 | 颜色 |
|---|---|
| emergency / alert / critical | 粗体红色 |
| error | 红色 |
| warning / task | 黄色 |
| notice | 蓝色 |
| sql | 绿色 |
| debug | 灰色 |
| 其他(info 等) | 默认 |
// config/log.php
'console' => true, // 开发环境开启;生产环境务必关闭仅开发环境开启
控制台输出走标准输出(stdout),生产环境建议关闭,避免污染进程日志与影响性能;框架默认配置中该值为 false。
echo_log 助手函数
echo_log() 是独立的控制台输出助手,不经过日志管线(不落盘、不受 console 配置控制),适合脚本与调试场景:
// 签名:echo_log(string|int $message, string $label = 'SUCCESS', ?string $color = null, int $backtrace = 1)
echo_log('配置加载完成'); // 默认 SUCCESS 标签
echo_log('参数缺失', 'WARNING'); // 自定义标签,按标签自动着色
echo_log('高亮', 'INFO', 'red'); // 指定颜色名
echo_log('无调用源', 'INFO', null, 0); // backtrace 为 0 时不输出调用位置输出格式为 [时间][标签]: 消息 - 调用源,标签自动转大写;$color 支持颜色名或 ANSI 转义序列。
