source

AWS Lambda에서 파이썬 로깅 사용

nicesource 2023. 7. 23. 14:21
반응형

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콘솔, 하지만 두 번째 콘솔은 아닙니다.

저는 두 스니펫이 루트 로거를 사용하고 있기 때문에 차이점을 보지 못했습니다.

로깅이 작동하지 않는 이유는 AWS Lambda Python 런타임이 선택한 런타임 버전에 따라 로깅된 메시지의 형식을 수정하고 사용 가능한 경우 일부 메타데이터를 레코드에 추가할 수 있는 로깅 핸들러를 미리 구성하기 때문입니다.그러나 사전 구성되지 않은 것은 로그 수준입니다.즉, 어떤 유형의 로그 메시지를 보내도 실제로는 인쇄되지 않습니다.

AWS 자체가 문서화되어 있듯이 올바른 사용 방법은loggingAWS Lambda 컨텍스트의 라이브러리에서는 루트 로거에 대한 로그 수준만 설정하면 됩니다.

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

Python 스크립트를 AWS Lambda에서 실행할 수 있고 로컬 Python 인터프리터에서도 실행할 수 있도록 하려면 핸들러 구성 여부를 확인하고 다음으로 이동할 수 있습니다.basicConfig(기본 stderr-module을 생성함) 그렇지 않은 경우:

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)

질문 @Steven Boherrer의 답변 링크의 맨 위에서 바로 복사됨(마지막 줄을 내 구성으로 교체하는 것이 나에게 유용했습니다):

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 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!")

저도 비슷한 문제가 있었는데, 람다 컨테이너가 logging.basicConfig를 호출하여 람다 코드를 가져오기 전에 핸들러를 추가하는 것 같습니다.이것은 나쁜 형태인 것 같습니다...

해결 방법은 루트 로거 처리기가 구성되어 있는지 확인하고, 구성된 경우 제거하고, 포맷터와 원하는 로그 수준(basicConfig 사용)을 추가하고, 처리기를 복원하는 것이었습니다.

logging.basicConfig를 실행하기 전에 이 문서 Python 로깅을 참조하십시오.

그것은 그것에 달려 있습니다.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")

아마 같은 로거를 참조하지 않았을 겁니다첫 번째 스니펫에서 다음의 반환을 기록합니다.logging.Logger.manager.loggerDict

다음을 반환합니다.dict로거가 이미 초기화되었습니다.

그리고 또.logging에 대한 중요한 메모인 문서logging.basicConfig:

기본 포맷터를 사용하여 StreamHandler를 만들고 루트 로거에 추가하여 로깅 시스템에 대한 기본 구성을 수행합니다.루트 로거에 대해 정의된 핸들러가 없는 경우 debug(), info(), warning(), error() 및 critical() 함수는 basicConfig()를 자동으로 호출합니다.

루트 로거에 이미 구성된 핸들러가 있는 경우 이 기능은 아무 동작도 하지 않습니다.

출처: https://docs.python.org/2/library/logging.html#logging.basicConfig

저는 aws python lambda 파워 툴을 사용하는 것을 제안합니다.기록 문서가 여기 있습니다.코드 예:

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

로컬 및 CloudWatch에서 모두 작동합니다.

기본적으로 AWS 로깅 원숭이 패치는 다음과 같은 매우 특별한 방식으로 처리되어야 합니다.

  1. 로그 수준은 스크립트의 TOP 수준에서 설정됩니다(예: 가져오기 시).
  2. 관심 있는 로그 문은 람다 함수 내에서 호출됩니다.

Python 모듈 가져오기에서 임의 코드를 실행하지 않는 것이 일반적으로 좋은 형태로 간주되기 때문에 일반적으로 무거운 리프팅이 람다 함수 내부에서만 발생하도록 코드를 재구성할 수 있습니다.

로깅에 로컬 및 on aws에 대한 변경이 필요 없도록 이 문제도 해결했습니다.다음은 샘플 코드입니다.

def set_default_logger():
    if "LOG_LEVEL" in os.environ:
        # For Lambda
        log_level = os.environ["LOG_LEVEL"] 
    else:
        log_level = DEFAULT_LOG_LEVEL # Set default log level for local

    root = logging.getLogger()
    if len(logging.getLogger().handlers) > 0:
        # For Lambda
        for handler in root.handlers:
            root.removeHandler(handler)
            logging.basicConfig(level=log_level,
                                format='[%(asctime)s.%(msecs)03d] [%(levelname)s] [%(module)s] [%(funcName)s] [L%(lineno)d] [P%(process)d] [T%(thread)d] %(message)s',
                                datefmt='%Y-%m-%d %H:%M:%S')
    else:
        # For Local
        l_name = os.getcwd()+'/'+'count_mac_module.log'
        logging.basicConfig(filename=l_name, level=log_level,
                            format='[%(asctime)s.%(msecs)03d] [%(levelname)s] [%(module)s] [%(funcName)s] [L%(lineno)d] [P%(process)d] [T%(thread)d] %(message)s',
                            datefmt='%Y-%m-%d %H:%M:%S')  
    
    logger = logging.getLogger(__name__)
    logger.debug(f"************* logging set for Lambda {os.getenv('AWS_LAMBDA_FUNCTION_NAME') } *************")
    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”)
    )
import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    logger.info('## ENVIRONMENT VARIABLES')
    logger.info(os.environ)
    logger.info('## EVENT')
    logger.info(event)`enter code here`

언급URL : https://stackoverflow.com/questions/37703609/using-python-logging-with-aws-lambda

반응형