如何在可重用的包中实现日志记录?

huangapple go评论62阅读模式
英文:

How to implement logging in reusable packages?

问题

我越来越经常将常用任务转移到我的小型库中。然而,我还没有弄清楚记录日志的最佳实践。有很多资源解释类似的东西:

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug('This is a log message.')

但是在面向重用的包中如何处理呢?我应该只导入und message,然后在导入主程序时进行一次配置吗?显然,我想在我的主应用程序中设置日志样式和级别,但不是每个单独的包。

那么如何使包“准备好记录日志”?

英文:

I'm more and more offloading frequently used tasks in small little libraries of mine. However I haven't figured out what the best practice for logging is. There are lots of resources explaining something like:

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug('This is a log message.')

But how to deal with that in packages intended for reuse? Should I just import und message, but do the config once in the main program importing? Obviously I want to set the logging style and level in my main app, but not every single package.

So how to make packages "ready for logging"?

答案1

得分: 1

你的翻译如下:

你的理解几乎完全正确。处理程序设计成在应用程序侧定义。只需将记录器添加到你的库中。使用根记录器可能很容易,但很快就会变得难以控制,所以让我们为它们命名与模块相关的名称:

# mylibA.py
import logging
logger = logging.getLogger(__name__)
logger.info('来自mylibA的问候')
# mylibB.py
import logging
logger = logging.getLogger(__name__)
logger.info('来自mylibB的问候')

使用basicConfig将会向根记录器添加处理程序以捕获所有记录器。这包括我们刚刚在你的库和第三方库中定义的记录器。你可以根据需要设置格式:

# myapp.py
import logging
logging.basicConfig(filename='myapp.log', level=logging.INFO)

想象一下,mylibA已经很成熟,你只想捕获其关键日志,并且你想忽略一个正在产生日志的第三方库。因为我们使用模块名称作为记录器名称,所以很容易关注你实际需要的内容。

# myapp.py
import logging

sh = logging.StreamHandler()
sh.setLevel(logging.CRITICAL)
logging.getLogger('mylibA').addHandler(sh)

logging.getLogger('mylibB').addHandler(logging.StreamHandler())

此外,你可以毫不费力地同时运行多个应用程序,每个应用程序都以适合其自身的方式收集、处理和格式化日志,而不会出现问题。

英文:

You're pretty much spot on. Handlers were designed to be defined on the app side. Only add the logger to your libraries. Using the root logger may be easy but quickly gets out of hand so let's give them a name related to the module:

# mylibA.py
import logging
logger = logging.getLogger(__name__)
logger.info('hello from mylibA')
# mylibB.py
import logging
logger = logging.getLogger(__name__)
logger.info('hello from mylibB')

Using basicConfig will add a handler to the root logger to capture all loggers. That includes the ones we just defined in your libraries and third party libraries. You're able to set the format as you wish:

# myapp.py
import logging
logging.basicConfig(filename='myapp.log', level=logging.INFO)

Imagine, mylibA is mature and you only want to capture critical logs for it and you want to ignore a third party library that's producing logs. Because we've used module names for logger names it's easy to focus on what you actually want.

# myapp.py
import logging

sh = logging.StreamHandler()
sh.setLevel(logging.CRITICAL)
logging.getLogger('mylibA').addHandler(sh)

logging.getLogger('mylibB').addHandler(logging.StreamHandler())

Also, you'd have no issue running multiple apps concurrently with each collecting, processing and formatting the logs in a way that's relevent for each app.

huangapple
  • 本文由 发表于 2023年4月19日 17:03:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76052646.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定