如何在单个 Python 应用程序中分离 Google Cloud Logging 中的日志?

How can I separate logs in Google Cloud Logging within a single Python application?

我已经编写了一个 Python 3.8.6 包来编排和 运行 Compute Engine 实例上的几个任务,分为几个子包。

    package/
        __init__.py
        subpackage1
        subpackage2
        subpackage3

我设置日志记录以将日志提交到 Cloud Logging 并导入子包 类 以在包含入口点 (package/__init__.py) 的文件中完成它们的工作。

import logging as pylogging
from google.cloud import logging
from google.cloud.logging.handlers import CloudLoggingHandler

from package.subpackage1.script1 import Class1
from package.subpackage2.script2 import Class2
from package.subpackage3.script3 import Class3

pylogging.basicConfig(level=20)
LOGGER = pylogging.getLogger()


def main():
    log_client = logging.Client()
    handler = CloudLoggingHandler(log_client, name="package")
    LOGGER.addHandler(handler)

    LOGGER.info("Starting work")

    Class1()
    Class2()
    Class3()

    LOGGER.info("Finished work")


if __name__ == '__main__':
    main()

为了从我导入的子包中记录日志,并以类似的方式设置日志记录。

import logging as pylogging

pylogging.basicConfig(level=20)
LOGGER = pylogging.getLogger()


class Class1:

    def __init__(self):
        LOGGER.info("Work Class1")

日志以相同的日志名称“package”提交到 Cloud Logging,see here。一些子包会提交很多日志,所以一般情况下很难把握全局运行。

我必须如何设置我的代码来分隔 Cloud Logging 中的日志,例如,分成不同的日志名称?

今天折腾了一段时间,终于找到了答案。

在主文件中(package/__init__.py)我需要为记录器设置一个特定的名称,否则,将使用根记录器。我还添加了一些调试消息来演示和尝试不同的日志级别。主文件现在看起来像这样:

import logging as pylogging
from google.cloud import logging
from google.cloud.logging.handlers import CloudLoggingHandler

from package.subpackage1.script1 import Class1
from package.subpackage2.script2 import Class2
from package.subpackage3.script3 import Class3

pylogging.basicConfig(level=20)
LOGGER = pylogging.getLogger("package")


def main():
    log_client = logging.Client()
    handler = CloudLoggingHandler(log_client, name="package")
    LOGGER.addHandler(handler)

    LOGGER.info("Starting work")

    LOGGER.debug("Class 1")
    Class1()
    LOGGER.debug("Class 2")
    Class2()
    LOGGER.debug("Class 3")
    Class3()

    LOGGER.info("Finished work")


if __name__ == '__main__':
    main()

在子模块中,我不必一遍又一遍地设置 basicConfig,因为在这里更改它会导致不必要的副作用。此外,我必须使用与 package/__init__.py 中设置的相同的记录器名称来使用相同的设置并通过定义的处理程序将日志发送到 Google Cloud Logging。 package/subpackage1/script1.py 现在看起来像这样:

import logging as pylogging

LOGGER = pylogging.getLogger("package")


class Class1:

    def __init__(self):
        LOGGER.debug("Inside Class1")
        LOGGER.info("Work Class1")

现在,我想将日志(例如,不同级别的日志)发送到单独的处理程序以 Google 云日志记录。为此,我必须创建一个具有不同名称的单独记录器,并为其附加一个新的处理程序。值得注意的是 python 日志记录支持以句点分隔的层次结构。这意味着如果我通过将其命名为 package/subpackage2 在 script2 中创建 package 记录器的子记录器,日志将被传递给两个处理程序,因此导致重复提交给 Google云日志。但是,在某些情况下,对子项应用适当的过滤器可能是有意义的。在我的例子中,package/subpackage2/script2.py 看起来像这样:

import logging as pylogging
from google.cloud import logging
from google.cloud.logging.handlers import CloudLoggingHandler

LOGGER = pylogging.getLogger("subpackage2")
LOGGER.setLevel(10)
log_client = logging.Client()
handler = CloudLoggingHandler(log_client, name="subpackage2")
LOGGER.addHandler(handler)

class Class2:

    def __init__(self):
        LOGGER.debug("Inside Class2")
        LOGGER.info("Work Class2")

这会通过不同的处理程序将日志发送到 Google 云日志中的不同日志名称,即使在这种情况下修改了日志级别。 This is how it looks in Google Cloud Logging.

这个 Python logging documentation 非常有帮助。