You can log messages from a function or procedure handler written in Scala by using the SLF4J API. When you’ve
set up an event table to store log entries, Snowflake stores log
entries generated by your handler code in the table.
You can use the SLF4J API included with the Snowflake Telemetry library included on Snowflake. To do so, include the following
value in the PACKAGES clause when you create the function or procedure: com.snowflake:telemetry:latest.
Using the Snowflake Telemetry Library adds other libraries to your function or procedure’s execution environment. For more information,
see Snowflake telemetry package dependencies.
Note
SLF4J does not support logging messages at the FATAL level. For handlers written in Java or Scala, the FATAL level is
treated as the ERROR level.
For example, if you set the LOG_LEVEL parameter to FATAL, ERROR-level messages from a Java or Scala
handler are ingested.
When you create a log entry, you can add your own attributes in key-value pairs. Snowflake saves these custom attributes to the event
table’s RECORD_ATTRIBUTES column.
To add custom attributes, call methods of the slf4j fluent API, such as Logger.atInfo and Logger.atError. Use these
methods to set key-value pairs in the log entry. Each returns an org.slf4j.spi.LoggingEventBuilder, which you can use to set the
log message.
Code in the following example logs a message “Logging with attributes” to the event table’s VALUE column. It also adds a custom
attribute to the RECORD_ATTRIBUTES column.
CREATEORREPLACEPROCEDUREdo_logging_scala()RETURNSVARCHARLANGUAGESCALARUNTIME_VERSION='2.12'PACKAGES=('com.snowflake:telemetry:latest','com.snowflake:snowpark_2.12:latest')HANDLER='ScalaLoggingHandler.doThings'AS$$importorg.slf4j.Loggerimportorg.slf4j.LoggerFactoryimportcom.snowflake.snowpark.SessionclassScalaLoggingHandler{privatevallogger:Logger=LoggerFactory.getLogger(getClass)defdoThings(session:Session):String={logger.atInfo().addKeyValue("custom1","value1").setMessage("Logging with attributes").log();return"SUCCESS"}}$$;
CREATEORREPLACEPROCEDUREdo_logging_scala()RETURNSVARCHARLANGUAGESCALARUNTIME_VERSION='2.13'PACKAGES=('com.snowflake:telemetry:latest','com.snowflake:snowpark_2.13:latest')HANDLER='ScalaLoggingHandler.doThings'AS$$importorg.slf4j.Loggerimportorg.slf4j.LoggerFactoryimportcom.snowflake.snowpark.SessionclassScalaLoggingHandler{privatevallogger:Logger=LoggerFactory.getLogger(getClass)defdoThings(session:Session):String={logger.atInfo().addKeyValue("custom1","value1").setMessage("Logging with attributes").log();return"SUCCESS"}}$$;
Output of this Logger.atInfo call appears in the event table as follows. Note that the RECORD_ATTRIBUTES column will include
attributes that Snowflake adds automatically.
Code in the following example imports references the Snowflake Telemetry library and from it gets a logger. It logs a message at the
INFO level. It also logs an error for an exception.
For more information about the methods you can use to log at specific levels, see SLF4J methods.
CREATEORREPLACEPROCEDUREdo_logging()RETURNSVARCHARLANGUAGESCALARUNTIME_VERSION='2.12'PACKAGES=('com.snowflake:snowpark_2.12:latest','com.snowflake:telemetry:latest')HANDLER='ScalaLoggingHandler.doThings'AS$$importorg.slf4j.Loggerimportorg.slf4j.LoggerFactoryimportcom.snowflake.snowpark.SessionclassScalaLoggingHandler{privatevallogger:Logger=LoggerFactory.getLogger(getClass)logger.info("Logging from within the Scala constructor.")defdoThings(session:Session):String={logger.info("Logging from Scala method start.")try{throwException}catch{casee:Exception=>logger.error("Logging an error from Scala handler: "+e.getMessage())return"ERROR"}return"SUCCESS"}// Simulate a thrown exception to catch.@throws(classOf[Exception])privatedefthrowException={thrownewException("Something went wrong.")}}$$;
CREATEORREPLACEPROCEDUREdo_logging()RETURNSVARCHARLANGUAGESCALARUNTIME_VERSION='2.13'PACKAGES=('com.snowflake:snowpark_2.13:latest','com.snowflake:telemetry:latest')HANDLER='ScalaLoggingHandler.doThings'AS$$importorg.slf4j.Loggerimportorg.slf4j.LoggerFactoryimportcom.snowflake.snowpark.SessionclassScalaLoggingHandler{privatevallogger:Logger=LoggerFactory.getLogger(getClass)logger.info("Logging from within the Scala constructor.")defdoThings(session:Session):String={logger.info("Logging from Scala method start.")try{throwException}catch{casee:Exception=>logger.error("Logging an error from Scala handler: "+e.getMessage())return"ERROR"}return"SUCCESS"}// Simulate a thrown exception to catch.@throws(classOf[Exception])privatedefthrowException={thrownewException("Something went wrong.")}}$$;
You can access log messages by executing a SELECT command on the event table. For more information, see
Viewing log messages.
Code in the following example queries the event table where the log messages are stored. The query reports on the severity and message of
each log entry from the handler class.
The preceding example generates the following output.
---------------------------------------------------------------------------| 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." |---------------------------------------------------------------------------