比特币核心 v31.0 有一批只在排障时才用到的日志装饰参数:-logtimestamps、-logtimemicros、-logthreadnames、-logsourcelocations。它们控制每行日志的前缀长什么样,回答两类高频问题:这条日志是谁打的、两行日志隔了多久。本文把默认值、输出格式、以及两件事的常见误解按 src/logging.h、src/logging.cpp、src/init/common.cpp 和发布说明核对一遍。
默认值与拼装顺序
logging.h 里写得明确:DEFAULT_LOGTIMESTAMPS 为真,其余三个为假。也就是说时间戳默认就在,微秒、线程名、源码位置默认都不在。每行日志的前缀按固定顺序拼装:先是时间戳,然后是线程名(开启时形如方括号包住的线程名),再是源码位置(开启时形如文件名冒号行号加方括号包住的函数名),最后才是正文。没注册名字的线程会打成 unknown,所以看到大量 unknown 前缀不是坏了,而是那些线程本来就没走命名注册。

时间戳的格式细节
时间戳由 LogTimestampStr 生成:先按整秒截断再格式化成 ISO 8601 风格的 UTC 串;只有开了 -logtimemicros 才把结尾的 Z 替换成点加六位微秒加 Z。两个实用推论:同一秒内多行日志要分先后,必须开微秒;这个参数挂了 DEBUG_ONLY 标签,帮助页默认折叠。跑了 mocktime 的测试节点上,时间戳后面还会追加一段括号附注标明 mock 时间——这是分辨”被拨过时钟的测试节点”与真实节点最快的办法。
v31 改动的源码位置输出
线程名开关的产出见上文方括号段;源码位置开关则给出文件、行号与函数。v31 发布说明里有一条专门记录:开启 -logsourcelocations 后,输出只带函数名而不再是完整函数签名(#34088)。模板参数多的行可读性明显改善,代价是跨版本对比日志样本时这列格式对不上。
两个容易搞错的地方
第一,运行时热开关的边界。logging RPC 能改的是 debug 分类(include/exclude 两组数组参数,支持 all 与 1 这两个特殊名字),v31 的该 RPC 参数表里没有线程名或源码位置的开关——这四个装饰参数是启动期的,想开就改配置文件重启。把别处抄来的 logging 热开关写法直接套到 v31 上会报不认识的参数。第二,日志回收的真相。-shrinkdebugfile 只在启动时执行一次:文件超过约 11MB 时收缩到只保留末尾约 10MB;默认值是”没有开 debug 分类时才收缩”。运行中的节点不做轮转,长期运行的磁盘占用要靠外部日志轮转方案。另一道兜底是日志限速(-logratelimit,默认开):按调用来源(文件与行号)统计,每个来源在一小时窗口内超过 1MB 后,该来源写盘的日志会被抑制并打一条警告,控制台输出不受影响;抑制生效期间,其余仍写出的行会带 [*] 前缀提示存在被抑制的来源。
该开哪一档
排查事件顺序与竞态:-logtimemicros 配合对应 debug 分类;怀疑子系统卡住或线程饥饿:-logthreadnames(线程名册与各自职责可查源码里的线程创建点,常见名字有 msghand、net、scheduler、http 等);定位代码路径:-logsourcelocations。生产节点默认面保持现状即可,装饰开关都增加行宽和写入量。顺带说清前缀里另一对常见方括号:分类与级别标签形如 [net]、[rpc:warning]——有分类且级别是 debug 时省略级别(debug 是隐含默认),没分类时 info 级别整段前缀都不出现,只有非 debug 级别才单列。另外日志文件打开前的早期消息先进内存缓冲,启动完成后一次性落盘;缓冲溢出时会在落盘第一条提示丢弃了多少行。
分类与级别:前缀里的另一半
日志行的分类标签与上面四个开关无关,由 -debug、-debugexclude 与 logging RPC 控制。v31 源码里的分类表相当长:net、rpc、validation、mempool、blockstorage、txpackages、kernel、privatebroadcast 等几十个,all 与 1 是代表全部分类的特殊名字。logging RPC 的参数是 include/exclude 两组数组,先加后删:同时出现在两组里的分类最终被关闭。无分类且级别为 info 的行不带方括号前缀,非 debug 级别才在分类后加冒号拼级别名,这套规则决定了为什么不同来源的行前缀长相不一。
以上行为均以 Bitcoin Core v31.0 源码与随附发布说明为准,不构成任何投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。