使用 python 记录 AWS Lambda

Using python Logging with AWS Lambda

正如 AWS 文档所建议的那样:

import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def my_logging_handler(event, context):
    logger.info('got event{}'.format(event))
    logger.error('something went wrong')

现在我做了:

import logging
logging.basicConfig(level = logging.INFO)
logging.info("Hello World!")

第一段代码打印在 Cloud Watch 控制台,但第二段没有。

我没有发现任何区别,因为这两个片段使用的是根记录器。

实际上可能没有引用同一个记录器。 在第一个片段中,记录 return of: logging.Logger.manager.loggerDict

它将return dict 个记录器初始化。

此外,来自 logging 文档,关于 logging.basicConfig 的重要说明:

Does basic configuration for the logging system by creating a StreamHandler with a default Formatter and adding it to the root logger. The functions debug(), info(), warning(), error() and critical() will call basicConfig() automatically if no handlers are defined for the root logger.

This function does nothing if the root logger already has handlers configured for it.

来源:https://docs.python.org/2/library/logging.html#logging.basicConfig

我遇到了类似的问题,我怀疑 lambda 容器正在调用 logging.basicConfig 以在导入 lambda 代码之前添加处理程序。这似乎是错误的形式...

解决方法是查看是否配置了根记录器处理程序,如果是,则删除它们,添加我的格式化程序和所需的日志级别(使用 basicConfig),然后恢复处理程序。

查看这篇文章Python logging before you run logging.basicConfig?

直接从@StevenBohrer 的问题答案链接中的顶部答案复制到(这对我有用,用我自己的配置替换了最后一行):

root = logging.getLogger()
if root.handlers:
    for handler in root.handlers:
        root.removeHandler(handler)
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)

本质上,需要以非常特殊的方式处理 AWS 日志猴子补丁,其中:

  1. 日志级别从脚本的 TOP 级别设置(例如,在导入时)
  2. 您感兴趣的日志语句是从 lambda 函数中调用的

由于通常认为不在 Python 模块导入中 运行 任意代码是一种很好的形式,因此您通常应该能够重组代码,以便仅在 lambda 函数内部进行繁重的工作。

日志记录似乎不起作用的原因是因为 AWS Lambda Python 运行时 pre-configures a logging handler 根据所选运行时的版本,它可能会修改记录的消息格式,如果可用,还可能向记录中添加一些元数据。 not 预配置的是 log-level。这意味着无论您尝试发送 log-message 的类型,它都不会实际打印。

As AWS documents themselves,要在 AWS Lambda 上下文中正确使用 logging 库,您只需为 root-logger 设置 log-level:

import logging
logging.getLogger().setLevel(logging.INFO)

如果您希望 Python-script 既可在 AWS Lambda 上执行,又可在本地 Python 解释器中执行,您可以检查是否配置了处理程序,然后回退到 basicConfig(创建默认值 stderr-handler)否则:

if len(logging.getLogger().handlers) > 0:
    # The Lambda environment pre-configures a handler logging to stderr. If a handler is already configured,
    # `.basicConfig` does not execute. Thus we set the level directly.
    logging.getLogger().setLevel(logging.INFO)
else:
    logging.basicConfig(level=logging.INFO)

我一直在努力解决这个确切的问题。在本地和 AWS CloudWatch 上都适用的解决方案是像这样设置您的日志记录:

import logging

# Initialize you log configuration using the base class
logging.basicConfig(level = logging.INFO)

# Retrieve the logger instance
logger = logging.getLogger()

# Log your output to the retrieved logger instance
logger.info("Python for the win!")

    LOGGER = logging.getLogger()
    HANDLER = LOGGER.handlers[0]
    HANDLER.setFormatter(
        logging.Formatter(“[%(asctime)s] %(levelname)s:%(name)s:%(message)s”, “%Y-%m-%d %H:%M:%S”)
    )

我建议使用 aws python lambda powertools. The logging doc is here。代码示例:

from aws_lambda_powertools import Logger
logger = Logger() # Sets service via env var
# OR logger = Logger(service="example")

它对我来说在本地和 CloudWatch 上都有效。

这取决于aws lambda python version

如果python版本3.8和以上

import os
import logging

default_log_args = {
    "level": logging.DEBUG if os.environ.get("DEBUG", False) else logging.INFO,
    "format": "%(asctime)s [%(levelname)s] %(name)s - %(message)s",
    "datefmt": "%d-%b-%y %H:%M",
    "force": True,
}


logging.basicConfig(**default_log_args)
log = logging.getLogger("Run-Lambda")

log.info("I m here too)

如果python版本3.7和以下

import os
import logging

root = logging.getLogger()
if root.handlers:
    for handler in root.handlers:
        root.removeHandler(handler)

default_log_args = {
    "level": logging.DEBUG if os.environ.get("DEBUG", False) else logging.INFO,
    "format": "%(asctime)s [%(levelname)s] %(name)s - %(message)s",
    "datefmt": "%d-%b-%y %H:%M"
}

logging.basicConfig(**default_log_args)
log = logging.getLogger("Run-Lambda")

log.info("Iam here")