代码之家  ›  专栏  ›  技术社区  ›  Remotec

在AWS lambda函数中获取两次日志

  •  5
  • Remotec  · 技术社区  · 6 年前

    main.py

    import logging
    
    logging.debug("test1")
    

    cloudwatch logs

    12:28:42 [DEBUG]-main.py:38,test1
    

    loghelper.py

    def setup_logging(name):
    
        formatter = logging.Formatter("%(name)s, %(asctime)s, %(message)s")
    
        handler = logging.StreamHandler(sys.stdout)
        handler.setFormatter(formatter)
    
        logger = logging.getLogger(name)
    
        if logger.handlers:
            for handler in logger.handlers:
                logger.removeHandler(handler)
    
        logger.setLevel(logging.DEBUG)
        logger.addHandler(handler)
        return logger
    

    import logging
    
    logger = loghelper.setup_logging('main.test_function')
    
    def test_function():
        logger.debug("test function log statement")
    
    test_function()
    

    当lambda函数现在运行时,我在云监视日志中收到两次调试消息,如下所示:

    以下内容:

    12:22:53 [DEBUG]-main.py:5, test function log statement
    12:22:53 [INFO]-__init__.py:880,main.test_function,2018-06-18 12:22:53,099, test function log statement
    

    参考文献:

    1. How to define a logger in python once for the whole program?

    2. Using python Logging with AWS Lambda

    3. Python: logging module - globally

    2 回复  |  直到 6 年前
        1
  •  8
  •   Martijn Pieters    6 年前

    AWS lambda还在根记录器上设置了一个处理程序, 任何写的东西 stdout INFO .因此,您的日志消息被捕获两次:

    (asctime) [(levelname)]-(module):(lineno), 信息;根日志记录器被配置为以该格式输出消息,而写入stdout的信息只是另一种格式。 %(message)

    由AWS发送的消息;在后一种情况下,您自己的格式化程序可以包括 levelname

    可以使用禁用日志传播 logger.propagate = False 你的

    this excellent reverse engineering blog post 根记录器配置为:

    logging.Formatter.converter = time.gmtime
    logger = logging.getLogger()
    logger_handler = LambdaLoggerHandler()
    logger_handler.setFormatter(logging.Formatter(
        '[%(levelname)s]\t%(asctime)s.%(msecs)dZ\t%(aws_request_id)s\t%(message)s\n',
        '%Y-%m-%dT%H:%M:%S'
    ))
    logger_handler.addFilter(LambdaLoggerFilter())
    logger.addHandler(logger_handler)
    

    time.localtime logging.Formatter time.gmtime aws_request_id

    handler.formatter

    for handler in logging.getLogger().handlers:
        formatter = handler.formatter
        if formatter is not None and 'aws_request_id' in formatter._fmt:
            # this is the AWS Lambda formatter
            # formatter.datefmt => '%Y-%m-%dT%H:%M:%S'
            # formatter._style._fmt => 
            #    '[%(levelname)s]\t%(asctime)s.%(msecs)dZ'
            #    '\t%(aws_request_id)s\t%(message)s\n'
    

    然后完全放下自己的记录器处理程序。您一定要小心这一点;AWS lambda基础结构很可能依赖于正在使用的特定格式。您在问题中显示的输出不包括日期组件 %Y-%m-%dT formatter.datefmt

        2
  •  1
  •   Florian Brucker    6 年前

    root 上面的记录器和下面的其他记录器。在记录器名称中,一个点( .

    logger = logging.getLogger('some_module.some_function`)
    

    The root logger (`logging.getLogger()`)
        A logger at module level (`logging.getLogger('some_module'))
            A logger at function level (`logging.getLogger('some_module.some_function'))
    

    this flowchart

    main 记录器以某种方式以附加的一些处理程序结束,这会导致重复的消息。为了避免这种情况,你可以设置 propagate False

    推荐文章