ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

线上报错只有一行堆栈,如何定位到真正的根因

线上报错只有一行堆栈,如何定位到真正的根因 目录一、先把堆栈丢进去让它顺着调用链往回找二、日志贴进去做时序比自己 grep 快三、改完之后确认没有别的地方有同样的假设四、几个它帮不上忙的地方五、什么时候我不用这套流程小结前段时间处理过一个线上问题服务半夜 panic 了一次日志里只留下一行堆栈指向某个工具函数里的一次 map 读取。去看那个函数二十行逻辑简单得一眼能看完怎么看都不该 panic。这种情况的难点不在于看懂那二十行而在于它只是触发点不是原因。真正的问题在上游——是谁传了那个值进来为什么会传成那样。往回倒的过程才是排查耗时的地方。下面的例子是 Go但这个问题跟语言没关系。Java 的空指针、Python 的 AttributeError、前端的 undefined堆栈指向的都是崩的那一行而不是错的那一行。排查思路是一样的。记一下我现在的排查顺序。一、先把堆栈丢进去让它顺着调用链往回找在用 wescode 之前我拿到堆栈的第一件事是搜函数名然后一层层往上翻调用方。项目里二十八个包翻到第三层基本就晕了尤其是中间隔着接口的时候——静态跳转跳不过去只能猜。现在我直接把堆栈贴进 wescode 的 Chat让它结合调用关系往回倒。区别在于它不是只读那个函数而是能顺着调用图看到上游有哪些路径能走到这里。这次它给出来的是三条可能的调用路径其中两条我自己翻的时候根本没想到——有一条是通过接口分派进来的函数名跟堆栈里那个完全不沾边。最后问题出在那条我没想到的路径上上游有个分支在特定条件下会传空 map 进来而那个工具函数假设了 map 一定初始化过。这里省下的时间不是「分析代码」是「找到该看哪些代码」。二十行的函数本身谁都看得懂难的是知道要去看上游哪一个分支。二、日志贴进去做时序比自己 grep 快排查过程中我习惯把相关时段的日志也一起给它看。我们的日志是 JSON 结构化的一次故障前后几百行人眼扫容易漏掉关联。我一般在 wescode 的 Chat 里直接引用日志文件logs/app.log 这段时间的错误有没有关联按时间线理一下它能做两件我自己做起来比较烦的事。一是按 request id 把散落的日志串起来。一次请求的日志可能分散在几十行里中间夹杂其他请求的输出手动 grep 要来回切。二是区分因果。比如连接池耗尽那种情况日志里最扎眼的是一堆 timeout 错误但真正的起点往往是更早的一条慢查询——它占着连接不放后面的请求才开始排队超时。这种「最响的报错不是根因」的情况按时间线理一遍就清楚了。三、改完之后确认没有别的地方有同样的假设找到原因之后还有一步我以前经常省略后来吃过亏。那个工具函数假设了入参 map 一定初始化过。改法有两种在函数里加判断或者让上游保证。不管选哪种都该问一句——项目里还有没有别的地方做了同样的假设这个我会用 wescode 的调用图去查看看还有谁在调这个函数以及有没有结构类似的其他函数。这次查下来又发现两处同样的写法虽然当前的调用路径还没触发但属于同一类隐患。一次 panic 修三个地方比修一个然后下个月再 panic 一次划算。四、几个它帮不上忙的地方这部分比前面更重要因为知道边界才不会浪费时间。它看不到运行时状态变量当时是什么值、并发时序是怎么交错的、goroutine 当时卡在哪——这些运行期信息不在代码里wescode 看不到。涉及竞态、死锁这类问题还是得上 debugger、pprof、trace。我的分工是静态结构上的问题交给它运行时状态自己抓。日志不全的时候它会猜这一条要特别小心。如果你给的日志缺了关键片段它不会说「信息不足」而是会基于已有的部分给出一个听起来很合理的推断。我被这样带偏过一次日志里缺了上游服务的返回它推断是本地逻辑问题我按着查了半小时最后发现是上游返回了非预期的状态码。所以现在我的习惯是它的结论当假设不当结果。说是 A 导致的我会去找 A 确实发生过的证据而不是直接开始改代码。偶发问题还是得靠复现那种几天出一次、没有稳定复现路径的问题静态分析能做的有限。该加日志加日志该上监控上监控。wescode 能帮的是决定日志该加在哪几个位置剩下的还是得等它复现。五、什么时候我不用这套流程报错信息已经很明确的时候。编译错误、明显的空指针、一眼能定位的问题直接改比问一轮快。小项目。文件就那么几个调用关系在脑子里翻上游不费劲。纯前端的视觉问题。样式不对、布局错位看效果比看代码有用。这套流程的价值在于调用链长、有接口分派、涉及的包比较多。这时候「找到该看哪儿」的成本高才值得借助调用图。小结排查线上问题真正花时间的从来不是读代码是确定该读哪段代码。堆栈给的是触发点从触发点往回倒到根因中间可能隔着好几层调用和几个接口。这段路以前靠经验和耐心现在可以让工具把候选路径先列出来我再逐个验证。但有一点始终没变工具给的是线索不是结论。它说问题在 A我还是会去找 A 发生过的证据。被它带偏过一次之后这个习惯就养成了。文中用到的调用链回溯和日志时序分析都是在 wescode 里做的官网是 weisyn.com。你们排查线上问题时有什么提效的办法欢迎评论区交流。
返回列表