Pythonでのメッセージのログ

Pythonの標準ライブラリのログモジュールである ログ を使用すると、Pythonで記述された関数またはプロシージャハンドラーからのメッセージをログできます。ログエントリを格納するイベントテーブルを設定すると、Snowflakeはハンドラーコードによって生成されたログエントリをテーブルに格納します。

Pythonでサポートされているログレベルの詳細については、 ログレベルのドキュメント をご参照ください。Snowflakeは、2つの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.infologger.error などのログレベル関数を呼び出す際にカスタム属性を追加するには、 extra キーワード引数を追加し、引数の値をカスタム属性として記録するキーと値のペアに設定します。

以下の例のコードは、イベント・テーブルの VALUE 列に「Logging with attributes」というメッセージを記録する。また、 RECORD_ATTRIBUTES 列に2つのカスタム属性を追加します。

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