Python에서 메시지 로깅하기

Python 표준 라이브러리의 로깅 모듈인 로깅 을 사용하여 Python으로 작성된 함수 또는 프로시저 처리기의 메시지를 로깅할 수 있습니다. 로그 항목을 저장하도록 이벤트 테이블을 설정하면 Snowflake가 처리기 코드에서 생성된 로그 항목을 테이블에 저장합니다.

Python에서 지원하는 로깅 수준에 대한 자세한 내용은 로깅 수준 설명서 를 참조하십시오. Snowflake는 다음과 같이 Python 로깅 수준 중 두 가지를 특정한 방식으로 처리합니다.

  • Python CRITICAL 수준은 FATAL로 처리됩니다.

  • Python NOTSET 수준은 TRACE로 처리됩니다.

Snowflake에서 로깅 설정 및 메시지 검색에 대한 일반적인 정보는 함수 및 프로시저의 메시지 로깅하기 섹션을 참조하십시오.

코드에서 로깅하기 전에 다음을 수행해야 합니다.

Python으로 로그 임계값 수준 재정의하기

Python 처리기 코드를 사용하여 SQL로 설정된 로그 수준 이었던 로그 임계값 수준을 재정의할 수 있습니다. Python으로 로그 수준을 설정하면 로그 항목은 Python에서 정의한 로깅 수준 을 사용합니다.

Python에서 로그 수준을 설정하면 다음을 수행할 수 있습니다.

  • Snowflake 세션이나 프로시저 또는 UDF와 같은 오브젝트에 대해 설정된 임계값을 재정의할 수 있습니다.

  • 지정된 Python 패키지로 범위가 지정된 임계값을 설정할 수 있습니다.

    예를 들어 설정하고 이벤트 테이블 에 저장된 로거 이름을 사용하여 Python으로 해당 로거에 대한 임계값을 설정할 수 있습니다.

다음 예제의 Python 코드는 Snowpark session 패키지의 로그 수준을 DEBUG로 설정합니다.

session_logger = logging.getLogger('snowflake.snowpark.session')
session_logger.setLevel(logging.DEBUG)
Copy

로거 이름을 사용하여 로깅 수준 설정하기

이벤트 테이블에 기록된 로거 이름을 사용하여 해당 로거의 로그 항목에 대한 임계값을 설정할 수 있습니다. 이는 특정 수준 이상의 불필요한 로그 항목을 필터링하도록 로거의 임계값을 설정하려는 경우 유용할 수 있습니다.

이를 수행하려면 먼저 이벤트 테이블을 쿼리하여 다른 로깅 수준을 캡처하려는 항목과 연관된 로거 이름을 검색해야 합니다. 그런 다음 해당 로거 이름을 사용하여 로그 수준을 원하는 임계값으로 설정합니다.

다음 예제의 코드는 반환된 데이터의 로거 이름을 포함하여 로그 항목을 쿼리합니다. 범위 열 의 값으로 이름을 얻을 수 있습니다.

SET event_table_name='my_db.public.my_event_table';

SELECT
  TIMESTAMP as time,
  RECORD['severity_text'] as log_level,
  SCOPE['name'] as logger_name,
  VALUE as message
FROM
  IDENTIFIER($event_table_name)
WHERE
  RECORD_TYPE = 'LOG';
Copy

이 쿼리는 여러 로거에서 많은 항목을 반환할 수 있습니다. 결과를 살펴본 후 numpy 로거에서 원하지 않는 많은 INFO 메시지를 받고 있다고 판단할 경우 Python을 사용하여 해당 로거의 임계값을 설정하여 ERROR 수준 이상에서 로그 항목을 캡처할 수 있습니다.

numpy_logger = logging.getLogger('numpy_logs')
numpy_logger.setLevel(logging.ERROR)
Copy

이벤트 테이블 쿼리에 대한 자세한 내용은 로그 메시지 보기 섹션을 참조하십시오.

사용자 지정 특성 추가하기

로그 항목을 생성할 때 키-값 페어로 사용자 고유의 특성을 추가할 수 있습니다. Snowflake는 이러한 사용자 지정 특성을 이벤트 테이블의 RECORD_ATTRIBUTES 열 에 저장합니다.

logger.info, logger.error 등 로깅 수준 함수 중 하나를 호출할 때 사용자 지정 특성을 추가하려면 extra 키워드 인자를 추가하여 인자의 값을 키-값 페어로 설정하여 사용자 지정 특성으로 기록합니다.

다음 예제의 코드는 이벤트 테이블의 VALUE 열에 “특성 포함 기록” 메시지를 기록합니다. 또한 2개의 RECORD_ATTRIBUTES 열에 사용자 지정 특성도 추가합니다.

CREATE OR REPLACE PROCEDURE do_logging_python()
RETURNS VARCHAR
LANGUAGE PYTHON
PACKAGES = ('snowflake-snowpark-python')
RUNTIME_VERSION = 3.9
HANDLER = 'do_things'
AS $$
import logging

logger = logging.getLogger("python_logger")

def do_things(session):

  logger.info("Logging with attributes in SP", extra = {'custom1': 'value1', 'custom2': 'value2'})

  return "SUCCESS"
$$;
Copy

logger.info 호출의 출력은 이벤트 테이블에 다음과 같이 표시됩니다. RECORD_ATTRIBUTES 열에는 Snowflake가 자동으로 추가하는 특성이 포함됩니다.

---------------------------------------------------------------------
| VALUE                        | RECORD_ATTRIBUTES                  |
---------------------------------------------------------------------
| "Logging with attributes in" | {                                  |
|                              |   "code.filepath": "_udf_code.py", |
|                              |   "code.function": "do_things",    |
|                              |   "code.lineno": 10,               |
|                              |   "custom1": "value1",             |
|                              |   "custom2": "value2"              |
|                              | }                                  |
---------------------------------------------------------------------

Python 예제

다음 섹션에서는 Python 코드에서 로깅에 대한 지원을 추가하는 방법에 대한 예제를 제공합니다.

저장 프로시저 예제

다음 예제의 코드는 logging 모듈을 가져오고, 로거를 가져오고, INFO 수준에서 메시지를 로깅합니다.

Python에서 지원하는 로깅 수준에 대한 자세한 내용은 로깅 수준 설명서 를 참조하십시오.

CREATE OR REPLACE PROCEDURE do_logging()
RETURNS VARCHAR
LANGUAGE PYTHON
PACKAGES=('snowflake-snowpark-python')
RUNTIME_VERSION = 3.9
HANDLER='do_things'
AS $$
import logging

logger = logging.getLogger("python_logger")
logger.info("Logging from Python module.")

def do_things(session):
  logger.info("Logging from Python function start.")

  try:
    throw_exception()
  except Exception:
    logger.error("Logging an error from Python handler: ")
    return "ERROR"

  return "SUCCESS"

def throw_exception():
  raise Exception("Something went wrong.")

$$;
Copy

이벤트 테이블에서 SELECT 명령을 실행하여 로그 메시지에 액세스할 수 있습니다. 자세한 내용은 로그 메시지 보기 섹션을 참조하십시오.

다음 예제의 코드는 로그 메시지가 저장된 이벤트 테이블을 쿼리합니다. 이 쿼리는 처리기 클래스에서 각 로그 항목의 심각도와 메시지에 대해 보고합니다.

SET event_table_name='my_db.public.my_event_table';

SELECT
  RECORD['severity_text'] AS SEVERITY,
  VALUE AS MESSAGE
FROM
  IDENTIFIER($event_table_name)
WHERE
  SCOPE['name'] = 'python_logger'
  AND RECORD_TYPE = 'LOG';
Copy

앞의 예제에서는 다음 출력을 생성합니다.

---------------------------------------------------------------------------
| SEVERITY | MESSAGE                                                      |
---------------------------------------------------------------------------
| "INFO"   | "Logging from Python module."                                |
---------------------------------------------------------------------------
| "INFO"   | "Logging from Python function start."                        |
---------------------------------------------------------------------------
| "ERROR"  | "Logging an error from Python handler."                      |
---------------------------------------------------------------------------

Streamlit 예

다음 예제의 코드는 logging 모듈을 가져오고, 로거를 가져오고, INFO 수준에서 메시지를 로깅합니다.

Python에서 지원하는 로깅 수준에 대한 자세한 내용은 로깅 수준 설명서 를 참조하십시오.

import streamlit as st
import logging

logger = logging.getLogger('app_logger')

st.title("Streamlit logging example")

hifives_val = st.slider("Number of high-fives", min_value=0, max_value=90, value=60)

if st.button("Submit"):
    logger.info(f"Submitted with high-fives: {hifives_val}")
Copy