Scalaでのメッセージのログ

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

Snowflakeに含まれているSnowflakeテレメトリライブラリにある SLF4J API を使用できます。これを実行するには、関数またはプロシージャを作成するときに、値 com.snowflake:telemetry:latest を PACKAGES 句に含めます。

Mavenでコードをパッケージ化するときにテレメトリライブラリを含める方法については、 テレメトリクラスを使用するためのJavaおよびScala環境の設定 をご参照ください。

注釈

Snowflakeテレメトリライブラリを使用すると、関数またはプロシージャの実行環境に他のライブラリが追加されます。詳細については、 Snowflakeテレメトリパッケージの依存関係 をご参照ください。

注釈

SLF4J は、 FATAL レベルでのメッセージのログをサポートしていません。JavaまたはScalaで記述されたハンドラーの場合、 FATAL レベルは ERROR レベルとして扱われます。

たとえば、 LOG_LEVEL パラメーターを FATAL に設定すると、JavaまたはScalaハンドラーからの ERROR レベルのメッセージがインジェストされます。

Snowflakeでのログの設定とメッセージの取得に関する一般的な情報については、 関数とプロシージャからのメッセージのログ をご参照ください。

コードからログする前に、次を実行する必要があります。

  • ハンドラーコードからログされたメッセージを収集するイベントテーブルを設定します。

    詳細については、 イベントテーブルの概要 をご参照ください。

  • 必要なメッセージがイベントテーブルに格納されるようにログレベルが設定されていることを確認してください。

    詳細については、 ロギング、メトリクス、トレースのレベル設定 をご参照ください。

カスタム属性の追加

ログエントリーを作成する際、キーと値のペアで独自の属性を追加することができます。Snowflake は、これらのカスタム属性をイベントテーブルの RECORD_ATTRIBUTES 列 に保存します。

カスタム属性を追加するには、 Logger.atInfoLogger.atError のような slf4j フルエント API のメソッドを呼び出します。これらのメソッドを使用して、ログエントリーにキーと値のペアを設定します。それぞれは org.slf4j.spi.LoggingEventBuilder を返し、それを使ってログメッセージを設定することができます。

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

CREATE OR REPLACE PROCEDURE do_logging_scala()
RETURNS VARCHAR
LANGUAGE SCALA
RUNTIME_VERSION = '2.12'
PACKAGES=('com.snowflake:telemetry:latest', 'com.snowflake:snowpark:latest')
HANDLER = 'ScalaLoggingHandler.doThings'
AS
$$
  import org.slf4j.Logger
  import org.slf4j.LoggerFactory
  import com.snowflake.snowpark.Session

  class ScalaLoggingHandler {
    private val logger: Logger = LoggerFactory.getLogger(getClass)

    def doThings(session: Session): String = {
      logger.atInfo().addKeyValue("custom1", "value1").setMessage("Logging with attributes").log();
      return "SUCCESS"
    }
  }
$$;
Copy

この Logger.atInfo コールの出力は、以下のようにイベント・テーブルに表示されます。RECORD_ATTRIBUTES 列には、Snowflake が自動的に追加する属性が含まれることに注意してください。

------------------------------------------------------------------
| VALUE                     | RECORD_ATTRIBUTES                  |
------------------------------------------------------------------
| "Logging with attributes" | {                                  |
|                           |   "custom1": "value1",             |
|                           |   "thread.name": "Thread-5"        |
|                           | }                                  |
------------------------------------------------------------------

Scalaの例

次の例のコードは、Snowflakeテレメトリライブラリへの参照をインポートし、そこからロガーを取得します。メッセージを INFO レベルでログします。また、例外のエラーもログされます。

特定のレベルでのログに使用できるメソッドの詳細については、 SLF4J メソッド をご参照ください。

CREATE OR REPLACE PROCEDURE do_logging()
RETURNS VARCHAR
LANGUAGE SCALA
RUNTIME_VERSION = '2.12'
PACKAGES=('com.snowflake:snowpark:latest', 'com.snowflake:telemetry:latest')
HANDLER = 'ScalaLoggingHandler.doThings'
AS
$$
  import org.slf4j.Logger
  import org.slf4j.LoggerFactory
  import com.snowflake.snowpark.Session

  class ScalaLoggingHandler {
    private val logger: Logger = LoggerFactory.getLogger(getClass)

    logger.info("Logging from within the Scala constructor.")

    def doThings(session: Session): String = {
      logger.info("Logging from Scala method start.")

      try {
        throwException
      } catch {
        case e: Exception => logger.error("Logging an error from Scala handler: " + e.getMessage())
        return "ERROR"
      }
      return "SUCCESS"
    }

    // Simulate a thrown exception to catch.
    @throws(classOf[Exception])
    private def throwException = {
      throw new 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'] = 'ScalaLoggingHandler'
  AND RECORD_TYPE = 'LOG';
Copy

前述の例では、次の出力が生成されます。

---------------------------------------------------------------------------
| SEVERITY | MESSAGE                                                      |
---------------------------------------------------------------------------
| "INFO"   | "Logging from within the Scala constructor."                 |
---------------------------------------------------------------------------
| "INFO"   | "Logging from Scala method start."                           |
---------------------------------------------------------------------------
| "ERROR"  | "Logging an error from Scala handler: Something went wrong." |
---------------------------------------------------------------------------