更多日志!结构化日志记录和异常处理

mo-logs的Python项目详细描述


更多日志-结构化日志记录和异常处理

<表><广告>分支 状态< /广告><正文>大师级构建状态 DEV构建状态coverage status<

此库提供两个主要功能

  • 结构化日志记录-输出全部为json(带有序列化为人类文本的选项)
  • 编织在中的异常处理-良好的日志必须表示发生了什么, 如果日志库不熟悉 采取的(异常)代码路径。

动机

异常处理和日志记录是不可否认的联系在一起的。有很多例子 出现异常且必须记录的地方,以及包含 系统可以完全处理异常,不应发出日志。例外 处理语义很好,因为它们将原因与解决方案分离, 但这可能与清洁伐木不符,清洁伐木是夫妻饲养和捕获的 对要向日志中发送的内容做出适当的决定。

这个日志模块还负责引发异常, 收集跟踪和上下文,然后推断它是否必须被记录,或者 如果它可以被忽略,因为有些东西可以处理它。

基本用法

使用log.note()进行所有日志记录
Log.note("Hello, World!")

不需要创建记录器对象。日志模块将跟踪 每次通话的时间、地点和地点。

使用命名参数

所有日志记录调用都接受带有命名参数的字符串模板。关键字参数 可以添加到调用中以提供值。模板和参数不是 它们在调用时组合在一起,而不是保存在 结构化日志记录。只有当日志为人类序列化时,模板才会展开。

Log.note("Hello, {{name}}!",name="World!")

不要使用python的字符串格式功能:

使用其中任何一个都将在调用时展开字符串模板,这是一个解析 日志分析工具的噩梦。

参数参数

所有的日志函数都接受一个默认参数作为第二个参数,如下所示:

Log.note("Hello, {{name}}!",{"name":"World!"})

这是针对您的代码已经具有捆绑结构的情况 希望用作参数源。如果使用关键字参数,则 将覆盖默认值。发送全部数据时要小心 结构,它们将被记录!

格式化参数

有多种格式化程序,可以使用e 管道()符号。

在本例中,我们将名称转换为大写

Log.note("Hello, {{name|upper}}!",name="World!")

一些格式化程序接受参数:

Log.note("pi is {{pi|round(places=3)}}!",pi=3.14159265)

您可以查看字符串模块以查看可用的格式化程序。

请不要使用locals()

defworker(value):name="tout le monde!"password="123"Log.note("Hello, {{name}}",locals())# DO NOT DO THIS!

尽管使用locals()是一个很好的日志记录快捷方式 很危险,因为它还会拾取敏感的局部变量。即使 {{name}是模板中的唯一值,整个locals()dict将 发送到结构化记录器进行记录。

异常处理

所有日志都是结构化日志;参数将包括在 原木结构。此库还希望所有参数值都是json- 可序列化,以便下游json工具可以存储/处理它们。

{//EXAMPLE STRUCTURED LOG"template":"Hello, {{name}}!","param":{"name":"World!"},"timestamp":1429721745,"thread":{"name":"Main thread"},"location":{"line":3,"file":"hello.py","method":"hello"},"machine":{"python":"CPython","os":"Windows10","name":"ekyle-win"}}

使用log.error()

Log.error("This will throw an error")

实际调用将始终引发异常,并操纵堆栈 跟踪以确保来电者受到适当指责。请随意使用 raise关键字(如raise log.error("")中所示),如果您觉得这样更好的话。

始终链接例外情况

cause参数接受异常或异常列表。 链接通常是一种很好的做法,可以帮助您找到 失败。

try:# Do something that might raise exceptionexceptExceptionase:Log.error("Describe what you were trying to do",cause=e)

在错误描述中也使用命名参数

错误日志记录接受关键字参数,就像log.note()那样

Log.note("Hello, World!")
0

无需正式键入异常

异常可以由第一个参数字符串模板唯一标识 它是给定的;使用同一模板引发的异常是同一类型的。你 不需要创建新的异常类型。

测试异常"类型"

这个库提倡尽早并且经常地链接异常,这就隐藏了 长因果链中的重要异常类型。MO日志允许您轻松地 通过使用 中的关键字:

Log.note("Hello, World!")
1

对于那些讨厌使用魔弦的人,可以随意使用常量:

Log.note("Hello, World!")
2

如果可以处理异常,则永远不会记录它

当调用方从被调用方捕获异常时,它是调用方的 处理或重新提出异常的责任。有很多 调用方可以处理异常的情况;在这种情况下 记录错误是骗人的。

Log.note("Hello, World!")
3

如果您的代码可以处理异常,但您仍然希望将其记录为问题,请使用log.warning()
Log.note("Hello, World!")
4

不要散开你的堆迹!

注意您的except子句也可以抛出异常:在 捕捉一个普通的python异常,可能会丢失它的堆栈跟踪。 要防止这种情况,请将异常包装在except对象中,该对象将捕获 你的踪迹供以后使用。从这个日志库引发的异常不需要 因为他们已经捕捉到了他们的踪迹。如果包装除外 对象,只需返回传递的对象。

Log.note("Hello, World!")
5

始终捕获所有异常

捕获所有异常优先于仅捕获您可以处理的异常 策略。首先,异常不会因为我们在链接而丢失。第二, 我们很早就捕捉到意外的异常,并用 当地法规打算做什么的描述。此批注 有效地将可能的错误(已知或未知)分组到一个类中,该类 可供呼叫者决定适当的缓解措施。

重复:当使用依赖注入时,调用方不能合理地 希望认识abo但是可能发生的故障类型 调用链。这使得方法总结所有 异常,包括已知的和未知的,因此它们的调用方拥有 就适当的行动做出更好的决定。

例如:一个抽象文档容器,在sql之上实现 数据库,不应发出任何类型的SqlException: 文档容器不需要知道如何处理SqlException(或任何 其他特定于实现的例外情况)。相反,在本例中, 应告知调用方"无法添加文档"或"无法删除 文件"。这样一来,当来电者做出合理的决定时 发生。原始原因(SqlException)在因果链中。

另一个例子涉及嵌套异常:如果捕获特定类型 对于异常,您可能会无意中捕获相同类型的异常 从呼叫链的深处。狭义异常处理是一种错觉。 广泛的异常处理将迫使您考虑各种失败 早期;迫使您考虑当一个代码块失败时它意味着什么;以及 强迫你为别人描述它。

不要制定不需要的方法

有一个论点建议你应该把代码分成方法, 而不是捕获异常:方法名将描述 失败,可以检查堆栈跟踪以作出缓解决策。 但这是一个糟糕的解决方案:

  • 更多的方法意味着更复杂;程序员必须找到方法, 记住这个方法,并想知道它是否在其他地方使用。
  • 方法可以在重构时被删除;异常可以清楚地表明 错误很重要
  • 编译器优化可能会干扰调用堆栈
  • 方法名可能很长,无法描述问题
  • 检查堆栈跟踪会导致代码混乱。
  • 堆栈跟踪不包括异常可以 捕获。

记录"级别"

mo logs模块没有日志级别的概念,预计调试 变量(以debug为前缀的变量)用于控制日志记录 输出:

Log.note("Hello, World!")
6

这些调试变量可以通过配置文件设置:

Log.note("Hello, World!")
7

日志配置

默认情况下,日志模块将登录到控制台。日志开始(设置) 将日志重定向到其他流,如设置所定义的:

  • 日志-所有日志流及其参数的列表
  • 跟踪-在每个日志行中显示更多详细信息(默认为false)
  • cprofile-用于启用内置python c-profiler(默认为false)
  • 配置文件-用于启用pylibrary的简单配置文件(默认为false) (例如使用profiler("某些说明"):)
  • 常量-将模块常量的绝对路径映射到将 被分配。主要用于设置模块中的调试常数。

当然,日志记录应该是设置的第一件事(除了消化 当然是设置)。因此,应用程序应具有以下内容 结构:

Log.note("Hello, World!")
8
Log.note("Hello, World!")
9

python日志记录的问题

python的默认日志记录模块 接近做正确的事情,但失败了:

  • 它有关键字参数,但它们在调用时被扩展,因此值将丢失在字符串中。
  • 它有额外的参数,但如果不被匹配的格式化程序使用,这些参数将丢失
  • 它甚至还具有带有exc_info参数的堆栈跟踪,但只有在处理异常时才有效。
  • python 2.x没有内置的异常链,但是python 3有>< >< > >

更多阅读

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何克服带有空值的不可空bean级验证   “此行有多个标记”的authenticateUser上的java MySQLConnection错误   java处理Jackson异常   java Netbeans编辑器如何知道文件在撤消后不会被修改?   目标C相当于Java的ArrayList   java当需要int时,可以将short传递给方法调用吗?   drawString()方法上的java MouseListener   java服务器socket是执行此操作的最佳选项   java需要单个匹配bean,但找到了2:org。springframework。网状物servlet。mvc。方法注释。RequestMappingHandlerMapping   如何在Java中执行Windows命令?   安卓应用程序的java文件主机   java将所有spring引导属性都设置在内。将yml文件转换为系统属性   Java邮件中的html内联链接在邮件客户端中不起作用   Java二进制文件的bazel版本控制   java如何在自定义ListView中使用Intent   java(Spring MVC+Hibernate 4+Test 4)自动连线DAO返回NULL   java一次add()调用可以在Solr服务器中索引多少文档?   java如何获取Avro GenericRecord大小