beego默认日志为纯文本,无法被elk/loki直接解析;必须使用logs.adapterfile或logs.adapterconn并显式配置"json":true(字符串值),禁用enablefunccalldepth,通过命名logger分离日志通道,并在logstash中用codec=>json配合filter转换level字段。

Beego 默认日志输出无法直接被 ELK 或 Loki 等分析系统解析,必须显式配置为结构化格式(如 JSON),否则 Logstash / Fluent Bit 会把整行当字符串切分,字段提取失败。
Beego 日志必须用 logs.AdapterFile 或 logs.AdapterConn 并启用 JSON 编码
Beego 的 logs 模块默认输出是纯文本(含颜色、时间前缀、调用位置等),不满足结构化日志要求。想对接 ELK、Loki 或 Datadog,得放弃 logs.AdapterConsole,改用支持序列化的适配器:
-
logs.AdapterFile:配合"json":true配置项,写入 JSON 格式到文件 -
logs.AdapterConn:直连 Logstash/TCP 端口,同样需开启"json":true - 别用
logs.AdapterMultifile—— 它不支持 JSON 输出,文档未说明但实测会忽略json:true
示例配置(写入文件):
logs.SetLogger(logs.AdapterFile, `{"filename":"app.log","json":true,"level":7,"daily":true,"maxdays":7}`)
注意:"json":true 必须是字符串 "true",不是布尔值 true(Beego v2.1+ 的 JSON 解析器只认字符串)。
logs.EnableFuncCallDepth(true) 会破坏 JSON 结构,上线前务必关闭
开启 logs.EnableFuncCallDepth(true) 后,日志会插入 "file":"/path/to/file.go:123" 字段,看似有用,但实际导致两个问题:
- Logstash 的
json过滤器可能因路径含冒号或反斜杠而解析失败(报JSON parse error) - Loki 的 Promtail 默认
docker模式不识别该字段,造成 label 提取混乱 - 更隐蔽的是:如果代码封装了日志调用(比如封装成
util.LogInfo()),EnableFuncCallDepth会记录封装层而非业务层,失去调试价值
正确做法是:关掉它,改用 logs.SetLogFuncCallDepth(2)(跳过 2 层封装),且仅在开发环境启用。
自定义日志字段必须通过 logs.GetLogger("xxx") + SetLevel 分离通道
ELK 场景下,你通常需要区分 access log、error log、biz log。Beego 不支持单 logger 多 level 输出到不同目标,必须用命名 logger:
- 定义 access 日志:
accessLog := logs.GetLogger("access"),再accessLog.SetLogger(...)指向 TCP 或文件 - 定义 biz 日志:
bizLog := logs.GetLogger("biz"),可单独设level和format - 所有命名 logger 共享同一底层 writer,但
SetLevel可独立控制是否输出(例如让access输出 info,biz只输出 warn+)
关键限制:不能对同一 logs.Logger 实例多次调用 SetLogger 切换输出目标;每个命名 logger 对应唯一 writer。
Logstash input tcp 需配 codec => json,且 Beego 的 AdapterConn 必须禁用换行
若用 logs.AdapterConn 直连 Logstash 的 TCP input,常见错误是日志在 Logstash 里变成多行或解析为空:
- Beego 默认每条日志末尾加
\n,但codec => json要求单行 JSON;必须在 Beego 配置中加"separator":""(空字符串)禁用自动换行 - Logstash 配置必须明确指定
codec => json,不能只靠json过滤器 —— 否则 TCP 流会被按行切分,首行 JSON 解析失败就丢弃整条 - Beego 的
AdapterConn不支持 keep-alive,短连接频繁重连;生产建议改用AdapterFile+ Filebeat 收集
Beego 端配置示例(TCP 输出):
logs.SetLogger(logs.AdapterConn, `{"net":"tcp","addr":":5000","json":true,"separator":""}`)
Logstash input 示例:
input { tcp { port => 5000 codec => json } }
真正难的不是接通,而是字段语义对齐——比如 Beego 的 "level" 是数字(7=Info),而 ELK 习惯用字符串("info"),这个转换必须在 Logstash filter 里做,不能指望 Beego 自动映射。











