如何在浏览器中实现专业级3D模型查看?Online3DViewer完全免费指南
2026/7/24 22:35:02
PHP 日志格式 ≠ JSON 格式—— 二者是可选关系,而非等同关系。
error_log、Monolog 默认格式)是否使用 JSON 取决于日志消费场景(如 ELK、Splunk 需要结构化数据)。
| 特性 | 传统文本日志 | JSON 日志 |
|---|---|---|
| 格式 | 人类可读的字符串 | 机器可解析的 JSON 对象 |
| 示例 | [2026-01-27 10:00:00] production.ERROR: User login failed | {"time":"2026-01-27T10:00:00Z","level":"ERROR","message":"User login failed","context":{"user_id":123}} |
| 解析难度 | 需正则提取字段 | 直接解析为对象 |
| 适用场景 | 本地调试、简单部署 | 集中式日志系统(ELK、Loki) |
💡核心认知:
JSON 日志 = 为机器优化的结构化格式,文本日志 = 为人类优化的可读格式
// config/logging.php'channels'=>['stack'=>['driver'=>'stack','channels'=>['single'],],'single'=>['driver'=>'single','path'=>storage_path('logs/laravel.log'),'level'=>'debug',],],[2026-01-27 10:00:00] local.ERROR: Failed to connect to database {"userId":123}// config/logging.php'single_json'=>['driver'=>'single','path'=>storage_path('logs/laravel.json'),'level'=>'debug','formatter'=>\Monolog\Formatter\JsonFormatter::class,],{"message":"Failed to connect to database","context":{"userId":123},"level":400,"level_name":"ERROR","channel":"local","datetime":"2026-01-27T10:00:00.000000Z","extra":[]}error_log():始终为文本格式php-fpm.log:文本格式(无法直接改为 JSON)user_id、request_id聚合日志tail -f laravel.log)// config/logging.php'channels'=>[// 本地保留文本日志(方便调试)'daily'=>['driver'=>'daily','path'=>storage_path('logs/laravel.log'),'level'=>'debug','days'=>14,],// 同时输出 JSON 到标准输出(供 Docker/Logstash 捕获)'stderr'=>['driver'=>'monolog','handler'=>StreamHandler::class,'with'=>['stream'=>'php://stderr',],'formatter'=>JsonFormatter::class,],],| 陷阱 | 破局方案 |
|---|---|
| 盲目全量 JSON | 本地开发保留文本日志,生产环境输出 JSON 到 stderr |
| 忽略上下文字段 | 在 JSON 日志中添加request_id、user_id等关键字段 |
| 未处理多行异常 | 使用JsonFormatter的batchMode避免异常堆栈破坏 JSON 结构 |
**“日志不是记录,
而是观测的透镜——
- 当你用文本,
你在服务人类;- 当你用 JSON,
你在赋能机器;- 当你混合输出,
你在平衡两端。真正的可观测性,
始于对消费端的敬畏,
成于对细节的精控。”
从今天起:
因为最好的日志,
不是格式之争,
而是精准匹配消费场景的每一比特。