Linux下Golang日志记录哪些关键信息
导读:Linux下Golang日志应记录的关键信息 一 核心字段清单 基础标识:时间戳(ISO8601 或 Unix 纳秒)、日志级别(DEBUG/INFO/WARN/ERROR/FATAL)、进程ID、线程/协程ID(如 runtime.Go...
Linux下Golang日志应记录的关键信息
一 核心字段清单
- 基础标识:时间戳(ISO8601 或 Unix 纳秒)、日志级别(DEBUG/INFO/WARN/ERROR/FATAL)、进程ID、线程/协程ID(如 runtime.Goid)、主机名/实例ID、服务名/模块名。
- 请求与上下文:一次请求的唯一ID(trace_id / request_id)、上游/下游服务、调用链信息(span/parent span)、用户ID/会话ID、客户端IP/User-Agent、认证与租户标识(如 tenant_id)。
- 代码位置:文件名、函数名、行号(便于定位)。
- 事件与错误:事件/操作名、错误对象(error)、错误堆栈(stack trace)、重试次数/超时/截止时间、输入/输出关键字段(脱敏后)。
- 性能指标:耗时/延迟(ms/µs)、内存/CPU占用、队列长度、缓存命中率、外部依赖响应时间(DB/Redis/HTTP)。
- 审计与合规:关键业务操作(创建/修改/删除)、操作者、变更前后摘要、来源IP与UA、访问资源标识。
- 安全与隐私:避免记录密码、密钥、令牌、银行卡号等敏感信息;必要时进行脱敏/哈希;控制可检索范围与保留周期。
- 输出与运维:输出目标(stdout/stderr、文件、syslog、远程聚合)、日志格式(文本或JSON)、采样策略(防止日志洪泛)、运行时可调级别。
以上字段能覆盖故障排查、性能分析、审计合规与安全要求,并与常用日志库(如 logrus、zap、zerolog)的结构化输出良好匹配。
二 不同场景的必记信息
| 场景 | 必记字段 | 建议级别 | 备注 |
|---|---|---|---|
| HTTP 请求 | trace_id、method、uri、status、latency_ms、client_ip、ua、err | INFO/ERROR | 在中间件记录入口/出口,统一错误返回 |
| 数据库/缓存 | query/hash、args(脱敏)、rows、duration_ms、err | DEBUG/ERROR | 记录慢查询阈值与错误 |
| 消息队列 | topic/queue、msg_id、group、partition/offset、duration_ms、err | INFO/ERROR | 便于重放与回溯 |
| 外部 HTTP 调用 | url、method、status、duration_ms、err、trace_id | INFO/ERROR | 传递/继承 trace_id |
| 定时任务/批处理 | job_name、task_id、shard、start/end、duration_ms、records、err | INFO/WARN/ERROR | 记录批次边界与影响面 |
| Goroutine/Worker | goroutine_id、job_type、queue_size、err | DEBUG/WARN | 便于定位并发问题 |
| 启动/关闭/配置变更 | version、build_time、config_key、old→new、err | INFO/WARN | 支持回滚与审计 |
| 安全事件 | user_id、ip、action、resource、result、reason | WARN/ERROR | 触发告警与风控 |
| 性能退化 | p95/p99 延迟、错误率、队列积压、饱和指标 | WARN/ERROR | 结合监控阈值 |
| 审计关键操作 | operator、tenant_id、resource_id、before/after摘要 | INFO/AUDIT | 满足合规要求 |
| 这些场景覆盖了常见后端服务的全链路,便于在 ELK/Graylog 或集中式系统中检索与聚合分析。 |
三 日志格式与输出建议
- 使用结构化日志(JSON),字段名统一(如 timestamp、level、msg、trace_id、span_id、caller、user_id、ip、method、uri、status、latency_ms、err、stack),便于检索与聚合。
- 统一时间格式(推荐 RFC3339Nano 或 Unix 纳秒),保证跨系统可比性。
- 区分stdout/stderr:常规日志走 stdout,错误与告警走 stderr,便于容器编排与系统日志收集。
- 输出目的地:本地文件用于落盘与审计,必要时同时输出到 syslog 或远程聚合系统(如 ELK)。
- 日志轮转与保留:按大小/时间切分,设置保留天数与压缩归档,避免磁盘被占满。
- 采样与降级:高并发下对 DEBUG/TRACE 进行采样,防止日志洪泛影响性能。
- 运行时可调级别:支持通过配置中心或信号量动态调整日志级别,减少重启。
上述做法与 logrus、zap 等库的最佳实践一致,并便于与 logrotate 或库自带轮转方案协同。
四 最小可行示例(zap + 关键字段)
package main
import (
"errors"
"fmt"
"net/http"
"os"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var logger *zap.Logger
func init() {
cfg := zap.NewProductionConfig()
cfg.EncoderConfig.TimeKey = "ts"
cfg.EncoderConfig.EncodeTime = zapcore.RFC3339NanoTimeEncoder
cfg.OutputPaths = []string{
"stdout", "/var/log/myapp.log"}
var err error
logger, err = cfg.Build()
if err != nil {
panic(err)
}
}
func handle(w http.ResponseWriter, r *http.Request) {
start := time.Now()
traceID := r.Header.Get("X-Trace-Id")
if traceID == "" {
traceID = fmt.Sprintf("%d", time.Now().UnixNano())
}
defer func() {
latency := time.Since(start).Milliseconds()
logger.Info("http request completed",
zap.String("trace_id", traceID),
zap.String("method", r.Method),
zap.String("uri", r.URL.Path),
zap.Int("status", http.StatusOK),
zap.Int64("latency_ms", latency),
zap.String("ip", r.RemoteAddr),
zap.String("ua", r.UserAgent()),
)
}
()
// 模拟业务错误
if r.URL.Path == "/error" {
err := errors.New("something went wrong")
logger.Error("business error occurred",
zap.String("trace_id", traceID),
zap.String("error", err.Error()),
zap.Stack("stack"),
)
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "ok\n")
}
func main() {
http.HandleFunc("/", handle)
if err := http.ListenAndServe(":8080", nil);
err != nil {
logger.Fatal("server failed", zap.Error(err))
}
}
要点:在入口/出口记录trace_id、method、uri、status、latency_ms、ip、ua;错误时记录error + stack;统一 JSON 输出到 stdout 与文件,便于容器与本地分析。
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Linux下Golang日志记录哪些关键信息
本文地址: https://pptw.com/jishu/753957.html
