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

本文涉及的产品
函数计算FC,每月15万CU 3个月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介:

python 调试篇

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

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

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

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

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

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

def bar(c):
    x = [1,2,3,4]
    return x[c]

def foo(a, b):
    c = a + b
    bar(c)

def test():
    try:
        foo(2, 5)
    except:
        print "traceback"

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

使用范例:

  • 我们先创建代码目录:
mkdir ~/sandbox/fc/traceback/python
  • 复制粘贴以下代码到 ~/sandbox/fc/traceback/python/main.py
import tracebackturbo as traceback

def bar(c):
    x = [1,2,3,4]
    return x[c]

def foo(a, b):
    c = a + b
    bar(c)

def handler(event, context):
    try:
        foo(5, 2)
    except:
        print traceback.format_exc(with_vars=True)

if __name__ == '__main__':
    handler(None, None)
  • 然后切换到 ~/sandbox/fc/traceback 目录
  • 执行 shell 命令: fcli shell,关于 fcli
  • 执行下述命令,其中 -d python 指的是当前代码所在目录 python ,而 python2.7python2.7 runtime
sbox -d python -t python2.7
pip install --target=$(pwd) tracebackturbo
  • 本地可以先做一下测试:
python main.py

测试结果:

Traceback Turbo (most recent call last):
  File "main.py", line 13, in test
    Local variables:
    foo(5, 2)
  File "main.py", line 9, in foo
    Local variables:
      a = 5
      b = 2
      c = 7
    bar(c)
  File "main.py", line 5, in bar
    Local variables:
      c = 7
      x = [1, 2, 3, 4]
    return x[c]
IndexError: list index out of range

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

比较

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

  • 全日志

    • 优点

      • 可以隐藏敏感信息
      • 对于无报错,无异常抛出的代码也可以做有效记录
    • 缺点

      • 日志可能记录不全,线上问题调查很困难
      • 需要记录大量日志,太多的日志会导致性能低下
  • traceback 日志

    • 优点

      • 报错时可以拿到整个栈的信息,分析问题可以非常全面
      • 日志简洁,在没有报错的时候,不会有其他信息干扰
      • 由于只在报错才有日志,正常情况下只有try的开销,相对来说性能更高
    • 缺点

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

实现原理简介

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

栈结构

stack top
frame 0 (bar)
frame 1 (foo)
frame 2 (...)
...
frame n()

frame 的结构

name comment
function proto 函数信息地址
frame base frame 基地址
args 函数参数地址
ret 函数返回地址
var1 第一个局部变量的空间
var2 第二个局部变量的空间
... ...
varN 第N个局部变量空间

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

function proto 结构

name comment
filename 实现文件名
line start, end 函数实现具体行
local variables 局部变量信息

每个变量包含

  • 声明行
  • 相对于frame 基地址偏移
  • 局部变量声明周期对应指令集

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

相关链接

相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
2月前
|
存储 JSON 监控
告别Print,使用IceCream进行高效的Python调试
本文将介绍**IceCream**库,这个专门用于调试的工具显著提升了调试效率,使整个过程更加系统化和规范化。
91 2
告别Print,使用IceCream进行高效的Python调试
|
1月前
|
存储 Prometheus 监控
Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行
本文深入探讨了在Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行。
65 5
|
2月前
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
70 8
|
3月前
|
存储 运维 监控
Elasticsearch Serverless 高性价比智能日志分析关键技术解读
本文解析了Elasticsearch Serverless在智能日志分析领域的关键技术、优势及应用价值。
137 8
Elasticsearch Serverless 高性价比智能日志分析关键技术解读
|
3月前
|
Java 程序员 应用服务中间件
「测试线排查的一些经验-中篇」&& 调试日志实战
「测试线排查的一些经验-中篇」&& 调试日志实战
39 1
「测试线排查的一些经验-中篇」&& 调试日志实战
|
4月前
|
监控 Python Windows
python知识点100篇系列-pysnooper用于调试
PySnooper是一个便捷的Python调试工具,用于监控代码执行过程及局部变量的变化,替代繁琐的打印语句。作为GitHub上的热门开源项目,它通过装饰器自动记录代码执行细节。安装简便,支持多种平台,可通过pip安装。使用时,只需在目标函数上添加装饰器即可实时查看变量变化或将其记录至日志文件。此外,还支持使用with块对特定代码段进行调试。更多详细信息可参阅其官方使用文档。
python知识点100篇系列-pysnooper用于调试
|
5月前
|
运维 Serverless 测试技术
函数计算产品使用问题之怎么使用python读取csv文件
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
5月前
|
JavaScript 前端开发 Serverless
函数计算产品使用问题之打印日志时间与实际时间相差8小时,是什么原因
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
5月前
|
SQL 数据库 Java
Hibernate 日志记录竟藏着这些秘密?快来一探究竟,解锁调试与监控最佳实践
【8月更文挑战第31天】在软件开发中,日志记录对调试和监控至关重要。使用持久化框架 Hibernate 时,合理配置日志可帮助理解其内部机制并优化性能。首先,需选择合适的日志框架,如 Log4j 或 Logback,并配置日志级别;理解 Hibernate 的多级日志,如 DEBUG 和 ERROR,以适应不同开发阶段需求;利用 Hibernate 统计功能监测数据库交互情况;记录自定义日志以跟踪业务逻辑;定期审查和清理日志避免占用过多磁盘空间。综上,有效日志记录能显著提升 Hibernate 应用的性能和稳定性。
60 0
|
5月前
|
存储 JSON 监控
FastAPI日志之谜:如何揭开Web应用监控与调试的面纱?
【8月更文挑战第31天】在现代Web开发中,日志记录对于监控应用状态、诊断问题和了解用户行为至关重要。FastAPI框架提供了强大的日志功能,使开发者能轻松集成日志记录。本文将详细介绍如何在FastAPI中设置和利用日志,包括基础配置、请求响应日志、错误处理和结构化日志等内容,帮助提升应用的可维护性和性能。
226 0

相关产品

  • 函数计算