메일링 예외를 위한 Python 로거 확장

로깅은 무슨 일이 일어나고 있는지 디버깅하거나 추적하는 데 도움이 되므로 생성하는 모든 애플리케이션이나 프로세스에서 가장 중요한 부분입니다. 로깅은 그 자체로 매우 방대한 주제이지만 일부 부작용을 수행하거나 출력을 다른 서비스로 리디렉션하거나 일부 부수 계산 등을 수행하려는 경우 매우 유용합니다.

설계상 고도로 구성 가능하며 사용자 정의Handlers를 사용하여 기존 로거의 확장 기능을 추가할 수 있습니다.

코드 실행 중에 발생한 예외e-mail에 대해 기존 로거의 기능을 확장하려고 합니다. 내장 라이브러리python Logger를 사용하여 logging를 생성해 보겠습니다.

import logging
logger: logging.Logger = logging.getLogger()


명시적으로 어떤 이름도 언급하지 않았기 때문에 위의 코드는 root 로거 인스턴스를 반환합니다. 명명된 logger 인스턴스를 원하는 경우 namegetLogger 함수에 전달할 수 있습니다.

이제 레코드를 처리하고 일부 부작용을 수행하는 사용자 정의Handler를 생성해 보겠습니다. logging.Handler 추상 기본 클래스에서 상속하여 사용자 지정 처리기를 만들 수 있습니다.
logging.Handler 기본 클래스는 재정의할 수 있는 여러 후크를 제공합니다. 요구 사항에 맞게 emit 후크를 재정의합니다.

import logging
class MailHandler(logging.Handler):

    def emit(self, record: logging.LogRecord) -> None:
        if record.exc_info:
            exception = "".join(traceback.format_exception(*record.exc_info))
        else:
            exception = "".join(traceback.format_exception(*sys.exc_info()))
        self._send_mail(exception)


레코드에서 예외를 가로채서 서식을 생성하는 일련의 명령문을 추가했습니다stack trace.
emit 후크는 메시지, 타임스탬프, 줄 번호, 예외 정보 등과 같은 레코드에 관한 모든 세부 정보를 포함하는 logging.LogRecord를 수신합니다. 또한 형식화된 스택 추적을 사용자에게 보내는 인스턴스 메서드_send_mail를 추가했습니다.

이제 _send_mail 기능을 완성하겠습니다. 우리는 이메일을 보내는 데 AWS SES를 사용할 것입니다. 대안으로 smtp를 사용할 수도 있습니다.

import boto3

class MailHandler(logging.Handler):

    def _send_mail(self, message):
        self.client = boto3.client('ses')
        ses_arn = os.getenv('SES_ARN')
        source = os.getenv('SES_SOURCE')
        html = f"""
        <p>Exception occurred while execution. Please check. </p>
        <pre>{message}</pre>
        """
        self.client.send_email(
            Source=source,
            Destination={
                'ToAddresses': [
                    '[email protected]',
                ],
            },
            Message={
                'Subject': {
                    'Data': 'Exception occurred while executing Lambda. Please check.',
                },
                'Body': {
                    'Html': {
                        'Data': html
                    }
                }
            },
            SourceArn=ses_arn
        )


우리는 boto3에 연결하고 이메일을 보내기 위해 SES 라이브러리를 사용하고 있습니다.

환경 변수에서 ses_arnsource를 읽고 있습니다. 이는 구성된SES 레코드를 사용하여 대상 주소로 이메일을 보내는 데 필요합니다.

사용자 정의 핸들러 생성이 완료되었습니다. 이것을 로거 인스턴스에 등록하겠습니다.

import logging
logger: logging.Logger = logging.getLogger()
handler = MailHandler()
handler.setLevel(logging.ERROR)
logger.logger_.addHandler(handler)


로거 인스턴스에 사용자 정의 핸들러를 등록했습니다. 레벨을 error 로 설정했기 때문에 logging.ERROR 레코드 유형에서만 활성화됩니다. 이제 아래와 같이 사용자 지정 처리기를 테스트할 수 있습니다.

logger.error(Exception("Fake Exception"))

exception 및 스택 추적이 포함된 이메일을 수신해야 합니다.

다음은 사용자 지정 핸들러의 전체 코드입니다.

import boto3
import logging

class MailHandler(logging.Handler):
    def emit(self, record: logging.LogRecord) -> None:
        if record.exc_info:
            exception = "".join(traceback.format_exception(*record.exc_info))
        else:
            exception = "".join(traceback.format_exception(*sys.exc_info()))
        self._send_mail(exception)

    def _send_mail(self, message):
        self.client = boto3.client('ses')
        ses_arn = os.getenv('SES_ARN')
        source = os.getenv('SES_SOURCE')
        html = f"""
        <p>Exception occurred while execution. Please check. </p>
        <pre>{message}</pre>
        """
        self.client.send_email(
            Source=source,
            Destination={
                'ToAddresses': [
                    '[email protected]',
                ],
            },
            Message={
                'Subject': {
                    'Data': 'Exception occurred while executing Lambda. Please check.',
                },
                'Body': {
                    'Html': {
                        'Data': html
                    }
                }
            },
            SourceArn=ses_arn
        )

logger: logging.Logger = logging.getLogger()
handler = MailHandler()
handler.setLevel(logging.ERROR)
logger.logger_.addHandler(handler)

#raising exception
try:
    raise Exception("Fake Exception")
except Exception as e:
    logger.error(e, exc_info=True)


이제 요구 사항에 따라 로깅 핸들러를 사용자 정의할 수 있습니다.

행복한 로깅 😊.

좋은 웹페이지 즐겨찾기