核心优势 #
1. 机器可读性 #
JSON日志最大的优势是原生机器可读,无需复杂的解析规则。
传统文本日志
2025-09-07 00:46:36 ERROR [mail_server/Imap_save.go:66] Failed to connect: timeout after 30s, user=admin@example.com
JSON日志
{
"ts": "2025-09-07T00:46:36.261+0800",
"level": "error",
"caller": "mail_server/Imap_save.go:66",
"msg": "Failed to connect",
"error": "timeout after 30s",
"user": "admin@example.com",
"duration": 30000
}
2. 查询分析 #
使用 jq 进行日志分析:
# 统计错误数量
cat log.json | jq 'select(.level=="error")' | wc -l
# 查找特定用户的错误
cat log.json | jq 'select(.user=="admin@example.com" and .level=="error")'
# 找出最慢的10个请求
cat log.json | jq -s 'sort_by(.duration_ms) | reverse | .[0:10]'
# 按错误类型分组统计
cat log.json | jq 'select(.level=="error") | .error' | sort | uniq -c
3. 日志聚合平台 #
ELK Stack 配置 #
# Logstash 无需解析规则
input {
file {
path => "/logs/app.json"
codec => "json" # 直接解析
}
}
CloudWatch Insights 查询 #
fields @timestamp, level, msg, error
| filter level = "error"
| stats count() by error
4. 结构化数据 #
JSON可以优雅地表达复杂数据结构:
{
"ts": "2025-09-07T00:46:36.261+0800",
"level": "info",
"msg": "Bill imported",
"import_stats": {
"total": 1000,
"success": 980,
"failed": 20,
"duration_ms": 1523
},
"failed_items": [
{"line": 10, "reason": "invalid amount"},
{"line": 45, "reason": "duplicate entry"}
]
}
成本对比 #
| 方面 | 文本日志 | JSON日志 |
|---|---|---|
| 存储空间 | 基准 | +20-30% |
| 解析性能 | 慢(正则) | 快(原生JSON) |
| 维护成本 | 高(解析规则) | 低(自描述) |
| 工具支持 | 需要自定义 | 原生支持 |
Go实现示例 (Zap) #
// 分离控制台和文件输出
func createLogger() {
// JSON编码器(文件)
jsonEncoder := zapcore.NewJSONEncoder(encoderConfig)
// Console编码器(控制台)
consoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
// 文件输出JSON
fileCore := zapcore.NewCore(
jsonEncoder,
zapcore.AddSync(&lumberjackLogger),
level,
)
// 控制台输出可读格式
consoleCore := zapcore.NewCore(
consoleEncoder,
zapcore.AddSync(os.Stdout),
level,
)
// 合并输出
core := zapcore.NewTee(fileCore, consoleCore)
}
最佳实践 #
适用场景 #
- 微服务架构
- 需要日志分析的生产环境
- 分布式追踪
- 审计合规要求
不适用场景 #
- 嵌入式系统(存储受限)
- 简单的开发调试
- 日志量极小的应用
实际应用 #
故障排查 #
# 查找最近1小时的慢查询
cat log.json | jq 'select(.duration_ms > 1000 and .ts > (now - 3600 | todate))'
安全审计 #
# 统计每个IP的失败登录次数
cat log.json | jq 'select(.event=="login_failed") | .ip' | sort | uniq -c | sort -rn
GDPR合规 #
# 快速定位敏感信息
cat log.json | jq 'select(has("email") or has("phone"))'
# 批量脱敏
cat log.json | jq '.email = (.email | split("@")[1] // "***")'