본문으로 바로가기
728x90
반응형

목차

     

    개요 

    SQLAlchemy의 SQL log는 눈에 잘 들어오지 않는다. 어떤 설정 없이 이용할 경우 SQL에 대해 Formatting이 적용되지 않아 그런지 가로로 늘어져있는 SQL을 읽을 때마다 가독성이 떨어진다.

     

    그러한 이유로 SQLAlchemy의 SQL Log도 Formatting을 적용할 수 있는 방법이 없을지 조사했다.

     

     

    1. SQLAlchemy의 SQL Log

    SQLAlchemey의 기본 SQL Logging은 다음과 같은 형식이다.

    SQL Logging이 언뜻봐서는 어디가 SELECT인지 어디가 FROM인지 눈에 들어오지 않는다.

     

    위의 예시에서는 SELECT ~ FROM이라는 간단한 SQL을 예시로 사용했기에 금방 찾을 수 있을지 모르나 table join이나 where 절과 같은 부분이 추가된다고 생각하면 쉽게 읽히는 형식은 아니다.

     

    2.  sqlparse를 이용한 SQL Log 변경하기

    Python에서 SQL을 읽기 쉽게 변경해 주는 sqlparse를 가져다 앞서 언급한 SQL Log 형식을 변경해 보도록 하자. sqlparse를 이용하기 전 Python의 logging 모듈을 이용해 먼저 간단히 세팅해 주자.

    import logging
    
    sql_logger = logging.getLogger("sqlalchemy.engine.Engine")
    
    handler = logging.StreamHandler()
    handler.setFormatter(SQLAlchemySQLFormatter())
    
    sql_logger.addHandler(handler)

    위 코드에서 보이는 "SQLAlchemySQLFomatter"라는 class는 다음과 같이 직접 정의해서 사용하는 코드이다.

    class SQLAlchemySQLFormatter(logging.Formatter):
        def format(self, record):
            sql = sqlparse.format(
                record.getMessage(),
                keyword_case='upper',
                identifier_case='lower',
                truncate_strings=50,
                reindent=True).strip('')
            sql = '\n\t\t| '.join([l for l in sql.split('\n')])
            return sql

    이 코드를 적용하고 나면 SQLAlchemy의 SQL Log는 다음과 같이 변경된다.

     

    SQL keyword에 따라 개행이 생겼으며 이전보다는 가독성이 향상됐다. 그런데 좀 밋밋하다. SQLAlchemySQLFormatter를 다음과 같이 변경해 보자.

    class SQLAlchemySQLFormatter(logging.Formatter):
    
        def format(self, record):
        	...
    
            sql = highlight(sql, SqlLexer(), TerminalFormatter()) # 추가
    
            return f"{datetime.datetime.now()}:{sql}"

    이제 SQL Log는 다음과 같이 변경된다.

     

    3. rich를 이용한 SQL Formatting 

    이 방법은 console의 text를 다채롭게 꾸며주는 rich 라이브러리를 활용한 방법이다.

    from rich.logging import RichHandler
    
    sql_logger = logging.getLogger("sqlalchemy.engine.Engine")
    
    rich_handler = RichHandler(rich_tracebacks=True, level="INFO")
    rich_handler.setFormatter(SQLAlchemySQLFormatter())
    
    sql_logger.addHandler(rich_handler)

    그런데 개인적인 생각은 이 방법은 앞서 소개한 방법과는 별로 차이가 없다. sql handler를 rich 라이브러리에서 제공하는 Handler로 변경하고 SQLAlchemySQLFormatter 클래스의 format 함수를 조금 더 간소화시킬 뿐이다.

    class SQLAlchemySQLFormatter(logging.Formatter):
    
        def format(self, record):
            sql = sqlparse.format(
                record.getMessage(),
                keyword_case='upper',
                identifier_case='lower',
                truncate_strings=50,
                reindent=True).strip('')
            sql = '\n\t\t| '.join([l for l in sql.split('\n')])
    
            return sql

    결과는 다음과 같다.

     

    3.1 "IN" Logging

     

    3.2 "INSERT" Logging

     

     

    마치며

    SQL Log가 어떤 형식이 읽기 편한 것은 개인적인 취향에 따라 호불호가 갈릴 것 같다. 어떤 형식이 읽기 좋다고 명확히 정의하기보다는 개인적으로 읽기 편한 SQL Logging을 적용했다는 점에서 의미를 가져야겠다.

    728x90
    반응형