日志级别与通道

本篇是参考文档:说明 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()sqlSQL 执行记录数据库查询与写入日志
Log::task()task异步任务记录任务投递、执行结果

PSR-3 其余级别

PSR-3 定义的 emergency(系统不可用)、critical(临界)、notice(需关注的正常但重要事件)没有独立方法,通过 mixed() 记录:

php
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),级别以第一个参数指定:

php
Log::write('error', '支付回调验签失败,立即落盘', ['order_id' => $orderId]);

级别使用建议

级别选择的核心是「严重程度」而非「代码位置」。以下给出各级别的典型用法,供团队统一口径参考:

alert —— 触发紧急通知

适合需要立即人工介入、通常会对接告警渠道的问题:

php
$freeSpace = disk_free_space('/');
if ($freeSpace < 1024 * 1024 * 1024) { // 磁盘可用空间小于 1GB
    Log::alert('磁盘空间不足', ['free_bytes' => $freeSpace]);
}

error —— 需要监控的运行时错误

php
try {
    $response = $this->http->post($url, $data);
} catch (\Throwable $e) {
    Log::error('外部服务请求失败', [
        'url' => $url,
        'exception' => get_class($e),
        'message' => $e->getMessage(),
    ]);
}

warning —— 值得关注但非故障

php
if ($duration > 5.0) {
    Log::warning('接口响应时间过长', [
        'endpoint' => '/api/orders',
        'duration' => "{$duration}s",
    ]);
}

info / debug —— 业务节点与调试数据

php
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 将它们单独归档:

php
Log::sql('INSERT 订单', ['sql' => $sql, 'affected_rows' => 1]);
Log::task('任务执行完成', ['topic' => 'email.send', 'duration' => '0.5s']);

上下文即检索维度

每条日志的第二个参数 $context 会被结构化存储(File 驱动下为 JSON 字段),把 order_iduidtrace_id 这类检索键放进上下文而非拼进消息文本,是日志可检索的前提。

级别到通道映射(type_channel)

log.type_channel级别名将日志路由到指定通道,未命中的级别写入 log.default 通道:

php
// 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' 不会连带 criticalalert;需要同级处理请逐级配置
  • 优先级type_channel 命中 > default 默认通道
  • 多通道:值为数组时,同一条日志依次写入每个通道
  • 启动校验type_channel 引用了未注册的通道时,启动即抛出 LogException,避免运行期静默丢日志
  • trace_source 全局生效:来源追踪在路由之前注入,各通道拿到的日志结构一致

典型用法

生产环境把 error 级别路由到独立通道并设置更长的保留天数(如 90 天),应用主日志保持 7-14 天,既降低存储成本又方便错误监控采集。

控制台输出

log.console 开启后,日志在实际写入时(协程聚合批次落盘那一刻)同步输出到控制台,并按级别着色:

级别颜色
emergency / alert / critical粗体红色
error红色
warning / task黄色
notice蓝色
sql绿色
debug灰色
其他(info 等)默认
php
// config/log.php
'console' => true,  // 开发环境开启;生产环境务必关闭

仅开发环境开启

控制台输出走标准输出(stdout),生产环境建议关闭,避免污染进程日志与影响性能;框架默认配置中该值为 false

echo_log 助手函数

echo_log() 是独立的控制台输出助手,不经过日志管线(不落盘、不受 console 配置控制),适合脚本与调试场景:

php
// 签名: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 转义序列。

下一步