Snowflake

Snowflake Event Tables: Centralizing Logs, Traces, and Audit Data

2026-03-26
更新: 2026-03-27
NicheeLab Editorial Team

Event Tables are dedicated Snowflake tables for collecting log, trace, and metric events emitted by UDFs, stored procedures, Streamlit apps, and similar workloads. They turn what used to be hard-to-debug function execution into structured event data you can analyze with SQL, providing an observability foundation for Snowflake.

Creating and Enabling an Event Table

-- Event Tableの作成
CREATE OR REPLACE EVENT TABLE observability_db.events.app_events;

-- アカウントレベルでEvent Tableを有効化(ACCOUNTADMIN必須)
ALTER ACCOUNT SET EVENT_TABLE = 'observability_db.events.app_events';

-- データベースレベルでログレベルを設定
ALTER DATABASE my_app_db SET LOG_LEVEL = 'INFO';

-- スキーマレベルでログレベルを設定(より細かい制御)
ALTER SCHEMA my_app_db.analytics SET LOG_LEVEL = 'DEBUG';

-- 特定のUDF/プロシージャだけログレベルを変更
ALTER FUNCTION my_app_db.public.process_data(VARCHAR)
  SET LOG_LEVEL = 'TRACE';

-- トレースレベルの設定
ALTER DATABASE my_app_db SET TRACE_LEVEL = 'ON_EVENT';

LOG_LEVEL Hierarchy and Inheritance

LevelEvents RecordedUse Case
OFFNoneDisable log collection entirely
FATALFatal errors onlyDetect critical failures
ERRORFATAL + errorsError monitoring
WARNERROR + warningsEarly problem detection
INFOWARN + informationalMonitoring under normal operations (recommended default)
DEBUGINFO + debugDebugging in dev and test environments
TRACEAll eventsDetailed tracing (note: expensive)

LOG_LEVEL can be overridden in the order Account → Database → Schema → Object (function/procedure). If not set, the value is inherited from the next level up.

TRACE_LEVEL Configuration

TRACE_LEVELBehavior
OFFDo not record trace events
ON_EVENTRecord only when SYSTEM$ADD_TRACE() is called
ALWAYSAutomatically record every function execution as a span

Emitting Events from UDFs and Stored Procedures

-- Python UDFからログを出力
CREATE OR REPLACE FUNCTION process_order(order_json VARIANT)
RETURNS VARIANT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.10'
HANDLER = 'run'
AS $
import logging
logger = logging.getLogger('order_processor')

def run(order_json):
    logger.info(f"Processing order: {order_json['order_id']}")
    try:
        total = sum(item['price'] * item['qty'] for item in order_json['items'])
        logger.info(f"Order total calculated: {total}")
        return {"order_id": order_json['order_id'], "total": total, "status": "success"}
    except Exception as e:
        logger.error(f"Failed to process order: {str(e)}")
        raise
$;

-- JavaScriptプロシージャからログを出力
CREATE OR REPLACE PROCEDURE sync_inventory()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS $
  snowflake.log("info", "Starting inventory sync");
  var rs = snowflake.execute({sqlText: "SELECT COUNT(*) FROM inventory"});
  rs.next();
  var count = rs.getColumnValue(1);
  snowflake.log("info", "Inventory records: " + count);
  return "Synced " + count + " records";
$;

-- SQLスクリプトからログを出力
CALL SYSTEM$LOG('INFO', 'Data pipeline started');

-- トレースイベントの出力
CALL SYSTEM$ADD_TRACE('pipeline_run', '{"stage": "transform", "rows": 50000}');

Key Columns of an Event Table

ColumnTypeDescription
TIMESTAMPTIMESTAMP_NTZWhen the event occurred
RESOURCE_ATTRIBUTESVARIANTExecution context (database name, schema name, function name, etc.)
RECORD_TYPEVARCHAREvent type (LOG / SPAN / SPAN_EVENT)
RECORDVARIANTEvent details (log message, severity, etc.)
RECORD_ATTRIBUTESVARIANTCustom attributes (data attached via SYSTEM$ADD_TRACE)
SCOPEVARIANTScope information (logger name, span name, etc.)

Querying the Event Table

-- 直近1時間のエラーログを取得
SELECT
  timestamp,
  resource_attributes['snow.database.name']::VARCHAR AS db_name,
  resource_attributes['snow.schema.name']::VARCHAR AS schema_name,
  resource_attributes['snow.executable.name']::VARCHAR AS function_name,
  record['severity_text']::VARCHAR AS severity,
  record['body']['text']::VARCHAR AS message
FROM observability_db.events.app_events
WHERE record_type = 'LOG'
  AND record['severity_text']::VARCHAR IN ('ERROR', 'FATAL')
  AND timestamp >= DATEADD(HOUR, -1, CURRENT_TIMESTAMP())
ORDER BY timestamp DESC;

-- 関数別の実行回数とエラー率を集計
SELECT
  resource_attributes['snow.executable.name']::VARCHAR AS function_name,
  COUNT(*) AS total_events,
  COUNT_IF(record['severity_text']::VARCHAR = 'ERROR') AS error_count,
  ROUND(error_count / total_events * 100, 2) AS error_rate_pct
FROM observability_db.events.app_events
WHERE record_type = 'LOG'
  AND timestamp >= DATEADD(DAY, -7, CURRENT_TIMESTAMP())
GROUP BY function_name
ORDER BY error_rate_pct DESC;

-- トレーススパンの実行時間を分析
SELECT
  scope['name']::VARCHAR AS span_name,
  record_attributes,
  DATEDIFF('millisecond',
    record['start_time']::TIMESTAMP_NTZ,
    timestamp
  ) AS duration_ms
FROM observability_db.events.app_events
WHERE record_type = 'SPAN'
ORDER BY duration_ms DESC
LIMIT 20;

Operational Best Practices

  • INFO in production, DEBUG in development: Switch LOG_LEVEL per database to keep log volume and cost down in production
  • Copy to regular tables for long-term storage: Keep the Event Table retention short and periodically migrate the logs you need into regular tables
  • Avoid TRACE_LEVEL = ALWAYS: It records every function call as a span and generates a huge number of events. Use ON_EVENT to record only where you need it
  • Integrate with alerts: Set up alerts (ALTER ALERT) against the Event Table to automatically detect spikes in error rate
  • Use structured logging: Include context in your log messages as JSON so you can later search them via VARIANT path access

Check Your Understanding

Observability

問題 1

You want logger.info() output from a Python UDF to be recorded in an Event Table for debugging. Which combination is the minimum required configuration?

  1. Specify the Event Table with ALTER ACCOUNT SET EVENT_TABLE and set ALTER DATABASE SET LOG_LEVEL = 'INFO'
  2. Setting only ALTER ACCOUNT SET LOG_LEVEL = 'DEBUG' will automatically create an Event Table
  3. After CREATE EVENT TABLE, set ALTER DATABASE SET TRACE_LEVEL = 'ALWAYS'
  4. Setting only ALTER FUNCTION SET LOG_LEVEL = 'INFO' is enough to start writing to the Event Table

正解: A

Recording logs in an Event Table requires three steps: (1) create the table with CREATE EVENT TABLE, (2) designate the account's Event Table with ALTER ACCOUNT SET EVENT_TABLE, and (3) configure LOG_LEVEL on the target database or object. Setting LOG_LEVEL alone is not enough if no Event Table is designated. TRACE_LEVEL is for trace spans; log messages are controlled by LOG_LEVEL.

Frequently Asked Questions

Can I change the data retention period for Event Tables?

Yes. You can change the retention period with the ALTER DATABASE SET EVENT_RETENTION_TIME_IN_DAYS parameter. The default is 1 day. Increase this value when you need long-term log analysis, but storage costs grow with the retention period. For long-term storage, also consider periodically copying or inserting Event Table data into regular tables for persistence.

What kinds of events can be written to Event Tables?

Event Tables capture three main kinds of events: (1) LOG messages — custom logs emitted from UDFs/stored procedures via system.log() or SYSTEM$LOG(); (2) TRACE events — function execution traces and span information recorded via SYSTEM$ADD_TRACE(); and (3) METRIC data — measurements such as execution time and row counts. The LOG_LEVEL parameter (OFF/FATAL/ERROR/WARN/INFO/DEBUG/TRACE) controls which severity levels are recorded.

How many Event Tables can be enabled per account?

Only one Event Table can be active per account. The single Event Table specified with ALTER ACCOUNT SET EVENT_TABLE = db.schema.my_events becomes the destination for events from every database and schema. You can create multiple Event Tables, but only one can be enabled as the event collection target at a time.

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Snowflake

Snowflake Certifications: All 11 Exams Explained (2026)

Every SnowPro certification — Associate, Core, Specialty, Ad...

Snowflake

Snowflake Exam Difficulty Ranking: All 11 Certs Compared (2026)

All 11 SnowPro exams ranked by difficulty with study-time es...

Snowflake

Snowflake Study Guide: Fastest Pass Route by Exam (2026)

How to pass SnowPro certifications efficiently — official ma...

Snowflake

SnowPro Core (COF-C03): Complete Exam Guide (2026)

Pass the SnowPro Core exam — six domains, scope, sample ques...

Snowflake

SnowPro Associate Platform (SOL-C01): Complete Guide (2026)

The entry-level SnowPro Associate exam — scope, weighting, s...

Browse all Snowflake articles (103)
© 2026 NicheeLab All rights reserved.