一、 问题描述
开发k8s插件,使用klog作为日志工具,开发完成发现在设置将日志打印到文件后,Error级别的日志信息仍然会输出到命令行,过多日志打印会使后期将服务部署于docker有卡死的风险(docker的bug,日志输出过快会卡顿)
二、解决思路
1. 先看命令行参数
可以看到klog的配置还是很灵活的,根据提示尝试了以下启动参数:
1. go run main.go -log_dir=logs -logtostderr=false
2. go run main.go -log_dir=logs -logtostderr=false -alsologtostderr=false
3. go run main.go -log_dir=logs -logtostderr=false -alsologtostderr=true -stderrthreshold=5
4. go run main.go -log_dir=logs -logtostderr=false -alsologtostderr=true -stderrthreshold=0
5. go run main.go -log_dir=logs -logtostderr=false -v=0
6. go run main.go -log_dir=logs -logtostderr=false -v=5
不管根据flag参数怎么调试,Error日志始终会打印到命令行,于是怀疑logtostderr或alsologtostderr参数在klog项目中应该存在bug;
2. 查找bug
先查看alsologtostderr,
发现这里有个if,在这个条件下如果alsoToStderr或l.alsoToStderr为true或s >= l.stderrThreshold.get()都会出现把日志打印到命令行的问题:
- 那我们把alsoToStderr设置为false,
- 再加上一句输出看看参数:
fmt.Printf("666666 %v : %v : %v : %v", alsoToStderr, l.alsoToStderr, s ,l.stderrThreshold.get())
- 执行
go run main.go -log_dir=logs -logtostderr=false -alsologtostderr=false
- 输出为
666666 false : false : 2 : 2
, - 这样看那应该是
s >= l.stderrThreshold.get()
导致的error日志输出到命令行,这里不知道s为啥为2,我们尝试把stderrThreshold设置>2, - 执行
go run main.go -log_dir=logs -logtostderr=false -alsologtostderr=false -stderrthreshold=3
- 打印
666666 false : false : 2 : 3
,同时error日志也不再打印到命令行,并且日志文件里是有error日志的
3. 追查原因
为什么s一直2?向上追查代码调用发现:
这次水落石出了,stderrthreshold默认为2,而Error日志的值为2,正常情况下logLevel >= stderrthreshold的都会被输出,即默认情况下Errorlog以上的等级都会被输出,这就是为啥Infolog不会被输出到命令行,error会的原因
4. 问题原因
真正导致我们一直走弯路的是官方的文档和代码中的参数注解:
"stderrthreshold" : "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false ")
从官方给的解释来看,要stderrthreshold
生效就必须让logtostderr=false
且alsologtostderr=true
,因此我们上面的flag参数尝试一直保持这种设置,但是代码里的实现确是:要想stderrthreshold
生效就必须让logtostderr=false
且alsologtostderr=false
才行,这里官方的alsologtostderr与stderrthreshold意义冲突了,应该是个bug
三、总结
被官方坑了一道,浪费了不少时间
总之,要想让klog日志输出到日志文件,且不输出到命令行的,参数配置为:
go run main.go -log_dir=logs -logtostderr=false -alsologtostderr=false -stderrthreshold=3
其中-stderrthreshold
的大小看你自己的需求设定
想要全部都不输出,就设定为4即可
参考资料:
- https://pkg.go.dev/k8s.io/klog
- https://github.com/kubernetes/klog