直接用 log 包输出杂乱,因其仅含时间戳和纯文本,缺乏颜色、结构化字段对齐与层级缩进;微服务场景下日志混杂,难以快速定位问题。

为什么直接用 log 包输出会显得杂乱?
Go 标准库的 log 包默认输出只有时间戳和纯文本,没有颜色、没有结构化字段对齐、也没有层级缩进。在微服务多实例并行运行时,不同服务的日志混在一起,光靠 grep 或肉眼很难快速定位 service-auth 的 401 错误还是 service-order 的 DB timeout。
Go-pretty 不是日志库,它负责“美化输出”,所以得先确保你已有结构化日志(比如用 zerolog 或 logrus),再把它们的字符串输出喂给 prettyprint 渲染——这点容易搞反:不是替换日志器,而是装饰终端输出。
怎么让 zerolog.ConsoleWriter 支持 Go-pretty 风格?
zerolog 的 ConsoleWriter 本身支持自定义 FormatFieldName 和 FormatFieldValue,但不内置颜色或表格。你需要拦截它的输出流,用 prettyprint 做二次渲染。最简方式是绕过 ConsoleWriter,改用 io.MultiWriter + 自定义 hook:
- 创建一个
prettyWriter,实现io.Writer接口,接收原始 JSON 日志行 - 用
json.Unmarshal解析后提取level、service、message等字段 - 调用
prettyprint.Table或prettyprint.Struct渲染成带颜色的表格(注意:别对整行 JSON 调用prettyprint.Pretty,那会破坏日志时间线) - 把
prettyWriter传给zerolog.New()的Output
示例关键片段:
立即学习“go语言免费学习笔记(深入)”;
type PrettyLogWriter struct{}
func (w *PrettyLogWriter) Write(p []byte) (n int, err error) {
var log map[string]interface{}
if err := json.Unmarshal(p, &log); err != nil {
return os.Stderr.Write(p) // fallback
}
t := tablewriter.NewWriter(os.Stdout)
t.SetHeader([]string{"LEVEL", "SERVICE", "MSG"})
level := log["level"].(string)
color := map[string]string{"error": "red", "warn": "yellow", "info": "green"}[level]
t.Append([]string{
fmt.Sprintf("<code>%s</code>", level),
fmt.Sprintf("<code>%s</code>", log["service"]),
fmt.Sprintf("<code>%s</code>", log["message"]),
})
t.Render()
return len(p), nil
}
哪些字段必须保留才能让美化有意义?
Go-pretty 的价值在于对比和筛选,如果日志里没 service、trace_id、duration_ms 这类字段,再花哨的表格也只是空壳。建议在日志中间件里强制注入:
-
service:从环境变量读取,如os.Getenv("SERVICE_NAME") -
trace_id:从 HTTP header 或 context 提取,避免用随机 UUID(否则无法跨服务串联) -
duration_ms:用time.Since(start)计算,别用fmt.Sprintf("%.2f", dur.Seconds()*1000)——浮点精度会导致排序错乱
特别注意:prettyprint.Table 对字段顺序敏感,如果你用 map[string]interface{} 解析 JSON,字段顺序不保证,得提前定义 struct 或用 json.RawMessage 手动控制键序。
生产环境要不要开 Go-pretty?
不要。Go-pretty 依赖 ANSI 转义序列,而 Kubernetes Pod 日志、ELK、Datadog 等后端系统无法渲染颜色,反而会在字段里留下乱码如 \x1b[32mINFO\x1b[0m。正确做法是按环境分流:
- 本地开发 /
docker-compose up:启用PrettyLogWriter - CI 测试 / 生产:用
zerolog.ConsoleWriter{NoColor: true}或直接输出 JSON 到 stdout - 通过
LOG_FORMAT=pretty环境变量控制开关,别硬编码
最容易被忽略的是:Go-pretty 的 Table 默认带边框和分隔线,在高频日志场景下每秒几十行,这些额外字符会显著增加 stdout 写入延迟。真要上生产级美化,优先考虑用 jq + less -R 做事后高亮,而不是实时渲染。


















