断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇

云栖君导读:本文将介绍一种结合函数堆栈,捕获栈中local变量的方式来达到快速定位bug的目的。


Python 调试篇


很多初学者喜欢使用断点调试,方便之处是可以查到运行期各种栈内的变量值,来帮助debug。
但这一点如果脱离了IDE,其实是非常困难的。在服务器的执行过程中,更需要使用attach的方式才可能做到这点。


对于一些生产环境的错误定位,用断点调试几乎是完全不可能的。


而使用日志来做错误定位,对于一些脚本语言,尤其弱类型的语言,当你将一个变量经过多个函数传递的过程中,如果传递过程中不小心有拼写错误,只有最后使用到这个变量的地方才报出错误来,使用日志的方式要定位什么地方写错了非常困难,对于生产环境中多分支调用链极长的逻辑,更是难上加难。


本文将介绍一种结合函数堆栈,捕获栈中local变量的方式来达到快速定位bug的目的。


相对于其他runtime,python可以获取到很多运行时信息。通常来说,通过异常捕获,python 默认的traceback 给出的栈和错误信息已经能帮助开发者调试了。但时常来说,这并不是万能的,偶尔会遇到一些问题,必须加日志才能解决。但如果开发者日志加得不够细,生产环境中也很难立即重现,此时有什么好办法呢?


下面我们通过一个简单的例子来讲解如何在断点调试和日志调试中找一个平衡点定位python脚本中的bug。


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


假设 bar 中数组访问越界,实际的bug在c = a + b 那行,其实本应该是c = a - b,我们没有日志,此时如何定位到这个bug?


使用范例:


  • 我们先创建代码目录:


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


  • 复制粘贴以下代码到 ~/sandbox/fc/traceback/python/main.py


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


  • 然后切换到 ~/sandbox/fc/traceback 目录

  • 执行 shell 命令: fcli shell,关于 fcli

  • 执行下述命令,其中 -d python 指的是当前代码所在目录 python ,而 python2.7 指 python2.7 runtime


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


  • 接下来我们使用 pip 安装 tracebackturbo 这个库


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


  • 本地可以先做一下测试:


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


测试结果:


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


我们可以看到栈中每个local变量都已经被print了出来,在生产环境中,我们可以在 service 上设置 logstore,将这部分错误信息输出到日志服务。


比较


我们可以比较全日志 及 traceback 日志的优缺点:


  • 全日志

优点

可以隐藏敏感信息

对于无报错,无异常抛出的代码也可以做有效记录

缺点

日志可能记录不全,线上问题调查很困难

需要记录大量日志,太多的日志会导致性能低下


  • traceback 日志

优点

报错时可以拿到整个栈的信息,分析问题可以非常全面

日志简洁,在没有报错的时候,不会有其他信息干扰

由于只在报错才有日志,正常情况下只有try的开销,相对来说性能更高

缺点

局部变量中含有敏感信息,可能会暴露给日志查看人员


实现原理简介


接下来我们了解一下这个库的实现原理,简要提一下计算机系统运行时栈的结构:


栈结构


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


frame 的结构


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


通常来说,各类计算机语言的 runtime 实现(实现细节及名称可能各不相同)都会包含上述信息。


function proto 结构


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


每个变量包含

  • 声明行

  • 相对于frame 基地址偏移

  • 局部变量声明周期对应指令集


对于任何一个未 return 的函数,如果我们拿到了这个栈,就可以获取到栈顶的若干 frame ,找到function proto,就可以找到各个局部变量的偏移,通过 frame 基地址相加,我们就可以得到每个局部变量的地址,获取到每个变量的内容。


相关链接


  • lua traceback

    https://github.com/rocaltair/ltrace

  • lua 调用动态链接库 crash

    https://github.com/rocaltair/lua-coredump


断点调试和日志调试之间的平衡点 --- 函数计算调试之Python篇


end

大繁至简,首度揭秘阿里云飞天洛神系统

blink测试技术介绍

阿里资深技术专家行易:我所理解的工程师文化

一文速读阿里云ET大脑 ——阿里云机器智能首席科学家闵万里详解数字驱动的智能之路

更多精彩