Event table monitoring and alerts for dynamic tables¶
This topic discusses how to query an event table that provides information about your refresh status and how to set up alerts on new data in an event table.
Query an event table to monitor refreshes¶
When a dynamic table is refreshed, you can configure Snowflake to record an event that provides information about the status of the refresh operation. The event is recorded in the active event table associated with the dynamic table.
For example, suppose that you have associated an event table with a database. When a dynamic table in that database is refreshed, Snowflake records an event to that event table.
You can query the events logged in this active event table to monitor your dynamic table refreshes.
For example, to get the timestamp, dynamic table name, query ID, and error message for errors with dynamic tables in the database my_db,
do the following:
The following example retrieves all columns for upstream errors with dynamic tables in the schema my_schema:
For information about the role that you need to use to query the event table and the conditions that you can use to filter the results, see Set up an alert on new data.
Set up alerts on new data to monitor refreshes¶
As mentioned earlier, when a dynamic table is refreshed, an event is logged in the event table to indicate whether the refresh succeeded or failed. You can set up an alert on new data to monitor the event table. You can configure the alert to send a notification when a refresh fails.
The next sections explain how to set up the event logging to capture the events, how to set up the alert, and how to interpret the events recorded in the event table:
Note
Logging events for dynamic tables incurs costs. See Costs of telemetry data collection.
Set the severity level of the events to capture¶
Note
If you do not set the severity level, no events will be captured.
To set up dynamic table events to be recorded to the event table, set the severity level of events that you want captured in the event table. Events are captured at the following levels:
ERROR: Refresh failure events.WARN: Failures to refresh upstream dynamic tables and refresh failure events.INFO: Successful refresh events, failures to refresh upstream dynamic tables, and refresh failure events.
To set the level, set the LOG_EVENT_LEVEL parameter for the account or object. You can set the level for:
All objects in the account.
All objects in a database or schema.
A specific dynamic table.
For example:
To capture ERROR-level dynamic table events for all supported objects in the account, execute ALTER ACCOUNT SET LOG_EVENT_LEVEL:
Setting
LOG_EVENT_LEVELat the account level applies to log events (record type EVENT) for supported workloads in the account, including dynamic tables. It does not replace LOG_LEVEL for log messages from logging APIs. For more information, see Parameters.To capture INFO-level events for all supported objects in the database
my_db, execute ALTER DATABASE … SET LOG_EVENT_LEVEL:Similar to the case of setting the level on the account, setting the level on the database affects log events for supported object types in the database.
To capture WARN-level events for the dynamic table
my_dynamic_table, execute ALTER DYNAMIC TABLE … SET LOG_EVENT_LEVEL:
Set up an alert on new data¶
After you set the severity level for logging events, you can set up an alert on new data to monitor the event table for new events that indicate a failure in a dynamic table refresh. An alert on new data is triggered when new rows in the event table are inserted and meet the condition specified in the alert.
Note
To create the alert on new data, you must use a role that has been granted the required privileges to query the event table.
If the alert condition queries the default event table (SNOWFLAKE.TELEMETRY.EVENTS) or the predefined view (SNOWFLAKE.TELEMETRY.EVENTS_VIEW view), see Roles for access to the default event table and EVENTS_VIEW.
To manage access to the EVENTS_VIEW view, see Manage access to the EVENTS_VIEW view.
If the alert condition queries a custom event table, see Access control privileges for event tables.
To manage access to a custom event table, see Managing access to event table data.
In the alert condition, to query for dynamic table events, select rows where
resource_attributes:"snow.executable.type" = 'DYNAMIC_TABLE'. To narrow down the list of events, you can filter on the
following columns:
To restrict the results to dynamic tables in a specific database, use
resource_attributes:"snow.database.name".To return events where the refresh failed due to an error with the dynamic table, use
value:state = 'FAILED'.To return events where the refresh failed due to an error with an upstream dynamic table, use
value:state = 'UPSTREAM_FAILURE'.
For information on the values logged for a dynamic table event, see Information logged for dynamic table events.
Note
The timestamp column in the event table stores values in UTC. If you use a scheduled alert with a timestamp filter
(for example, timestamp > DATEADD('minute', -5, CURRENT_TIMESTAMP())), convert the current timestamp to UTC to ensure
accurate comparisons:
For example, the following statement creates an alert on new data that performs an action when refreshes fail for dynamic tables
in the database my_db. The example assumes that:
Your active event table is the default event table (SNOWFLAKE.TELEMETRY.EVENTS).
You have set up a webhook notification integration for that Slack channel.
Information logged for dynamic table events¶
When a dynamic table refreshes, an event is logged to the event table. The following sections describe the event table row that represents the event:
Event table column values¶
When a dynamic table refreshes, a row with the following values is inserted into the event table.
Note
If a column is not listed below, the column value is NULL for the event.
Column |
Data type |
Description |
|---|---|---|
|
TIMESTAMP_NTZ |
The UTC timestamp when an event was created. |
|
TIMESTAMP_NTZ |
A UTC time used for logs. Currently, this is the same value that is in the |
|
OBJECT |
Attributes that identify the dynamic table that was refreshed. |
|
STRING |
The event type, which is |
|
OBJECT |
Details about the status of the dynamic table refresh. |
|
VARIANT |
The status of the dynamic table refresh and, if the refresh failed, the error message for the failure. |
Key-value pairs in the resource_attributes column¶
The resource_attributes column contains an OBJECT value with the following key-value pairs:
Attribute name |
Attribute type |
Description |
Example |
|---|---|---|---|
|
INTEGER |
The internal/system-generated identifier of the database containing the dynamic table. |
|
|
VARCHAR |
The name of the database containing the dynamic table. |
|
|
INTEGER |
The internal/system-generated identifier of the dynamic table that was refreshed. |
|
|
VARCHAR |
The name of the dynamic table that was refreshed. |
|
|
VARCHAR |
The type of the object. The value is |
|
|
INTEGER |
The internal/system-generated identifier of the role with the OWNERSHIP privilege on the dynamic table. |
|
|
VARCHAR |
The name of the role with the OWNERSHIP privilege on the dynamic table. |
|
|
VARCHAR |
The type of role that owns the object, for example |
|
|
VARCHAR |
ID of the query that refreshed the dynamic table. |
|
|
INTEGER |
The internal/system-generated identifier of the schema containing the dynamic table. |
|
|
VARCHAR |
The name of the schema containing the dynamic table. |
|
|
INTEGER |
The internal/system-generated identifier of the warehouse used to refresh the dynamic table. |
|
|
VARCHAR |
The name of the warehouse used to refresh the dynamic table. |
|
Key-value pairs in the record column¶
The record column contains an OBJECT value with the following key-value pairs:
Key |
Type |
Description |
Example |
|---|---|---|---|
|
VARCHAR |
The name of the event. The value is |
|
|
VARCHAR |
The severity level of the event, which is one of the following values:
|
|
Key-value pairs in the value column¶
The value column contains an VARIANT value with the following key-value pairs:
Key |
Type |
Description |
Example |
|---|---|---|---|
|
VARCHAR |
The state of the refresh, which can be one of the following values:
|
|
|
VARCHAR |
If the value in |
|
Query pipeline spans to trace refreshes¶
In addition to events, Snowflake can record pipeline spans for dynamic table refreshes. Events and spans are two separate observability mechanisms:
Events (controlled by LOG_LEVEL) provide logs per-dynamic-table refresh, indicating whether each refresh succeeded or failed.
Spans (controlled by TRACE_LEVEL) provide richer pipeline-level observability, including correlated trace IDs across a pipeline, skip reasons, and dependency topology.
Spans capture additional states for which events are not emitted, including SKIPPED refreshes due to upstream
skips or refresh cycles where the scheduler skipped refreshing to minimize the lag of the dynamic table and
its consumers.
Note
Recording spans for dynamic tables incurs costs. See Costs of telemetry data collection.
Enable pipeline spans¶
To enable pipeline spans for dynamic table refreshes, set the TRACE_LEVEL parameter to ALWAYS at the
database or schema level:
You can also set this at the database level to capture spans for all dynamic tables in the database:
Query span data¶
To query pipeline spans for dynamic table refreshes, filter for rows where record_type = 'SPAN' and
record:"name" = 'table_refresh':
Span attributes (record_attributes )¶
Each span row includes the following attributes in the record_attributes column, specific to dynamic
table refreshes:
Attribute name |
Type |
Description |
|---|---|---|
|
STRING |
The state of the refresh: |
|
STRING |
Why the dynamic table was skipped or failed. NULL on success. Possible values:
|
|
STRING |
The transactional timestamp when the refresh was evaluated. (This might be slightly before the actual time of the refresh.) All data in base objects that arrived before this timestamp is included in the dynamic table. |
Note
Spans cover SKIPPED states (with reasons UPSTREAM_SKIP and NOT_EFFECTIVE_TICK_TO_REFRESH)
for which events are not emitted. If you need visibility into skipped refreshes, use spans instead of events.
Pipeline correlation with trace IDs and span links¶
A unique capability of spans is pipeline-level correlation. When a refresh cycle includes refresh operations
for multiple dynamic tables, all the resulting spans share the same trace:"trace_id". This lets you
reconstruct the full set of refresh operations that occurred in a single refresh cycle.
Each span also includes a record:"links" array that lists the span_id of each upstream dependency.
For example, if DT_B depends on DT_A, then DT_A’s span_id appears in DT_B’s
record:"links".
The record:"status":"code" field is STATUS_CODE_OK for successes and skips, and
STATUS_CODE_ERROR for failures.
For example, to correlate all dynamic table refresh operations in a single refresh cycle, query for spans
with the same trace_id:
Trace a pipeline refresh¶
This section walks through how to use pipeline spans to trace a refresh cycle end to end: finding the relevant spans, retrieving the full pipeline, and diagnosing failures or skips.
Example pipeline scenario¶
Consider a linear pipeline of four dynamic tables:
In this example, DT1 and DT2 refresh successfully, but DT3 fails due to a query error. Because
DT3 failed, DT4 is automatically skipped with the reason UPSTREAM_FAILURE.
The following steps show how to retrieve and interpret the pipeline spans for this scenario.
Step 1: Find the span for a dynamic table¶
To investigate a specific dynamic table’s refresh, query the event table for its most recent span. Filter by database, schema, and dynamic table name to ensure you match the correct object:
The trace_id value identifies the refresh cycle. All dynamic table spans within a single pipeline refresh
share the same trace_id. Use this value in the next step to retrieve
all spans from the same refresh cycle.
Step 2: Retrieve the full pipeline¶
Query all spans that share the same trace_id to see every dynamic table in the refresh cycle.
Include record:"links" to capture the dependency graph and DATEDIFF to compute the duration of each
refresh operation:
From this result, you can see the full picture of the refresh cycle:
DT1andDT2succeeded (30 and 29 seconds respectively).DT3failed after 19 seconds due to a query failure.DT4was skipped immediately (represented by a zero-duration span) because its upstream dependency failed.The
UPSTREAM_LINKScolumn shows each dynamic table’s direct dependencies byspan_id.
Step 3: Identify the root cause of a failure or skip¶
When a dynamic table is skipped or fails, you can trace its upstream dependencies through the span links to find the root cause. This query resolves the span links for a specific dynamic table back to the other spans in the pipeline:
In this example, DT4 was skipped because its upstream dependency DT3 failed with
QUERY_FAILURE. You can use the query_id to investigate the failed query further (for example,
by calling GET_QUERY_OPERATOR_STATS or
checking the query history).
For longer dependency chains, repeat the same pattern: replace the target dynamic table name to walk
further upstream until you reach a span with state = 'FAILED' and state_reason = 'QUERY_FAILURE',
which is the root cause.
Find downstream impact of a failure¶
To find which dynamic tables were affected by a specific failure, reverse the span link lookup. This query
finds all dynamic tables whose record:"links" reference the failed dynamic table’s span_id:
This returns the direct dependents of the failed dynamic table. To find all transitively affected dynamic
tables, repeat the query with each dependent’s span_id to walk further downstream.
Use OpenTelemetry-compatible tools¶
Dynamic table pipeline spans follow the standard OpenTelemetry data model. Because all spans in a refresh
cycle share the same trace:"trace_id", you can export them from the event table into
OpenTelemetry-compatible tools for visualization.
These tools can render the pipeline as a trace timeline, showing the duration and status of each dynamic table’s refresh operation and the dependency relationships encoded in the span links.