动态表的事件表监控和警报

本主题讨论如何查询提供刷新状态信息的事件表,以及如何针对事件表中的新数据设置警报。

查询事件表以监控刷新

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.

您可以查询此活动事件表中记录的事件以监控动态表刷新。

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:

SELECT
    timestamp,
    resource_attributes:"snow.executable.name"::VARCHAR AS dt_name,
    resource_attributes:"snow.query.id"::VARCHAR AS query_id,
    value:message::VARCHAR AS error
  FROM my_event_table
  WHERE
    resource_attributes:"snow.executable.type" = 'DYNAMIC_TABLE' AND
    resource_attributes:"snow.database.name" = 'MY_DB' AND
    value:state = 'FAILED'
  ORDER BY timestamp DESC;
+-------------------------+------------------+--------------------------------------+---------------------------------------------------------------------------------+
| TIMESTAMP               | DT_NAME          | QUERY_ID                             | ERROR                                                                           |
|-------------------------+------------------+--------------------------------------+---------------------------------------------------------------------------------|
| 2025-02-17 21:40:45.444 | MY_DYNAMIC_TABLE | 01ba7614-0107-e56c-0000-a995024f304a | SQL compilation error:                                                          |
|                         |                  |                                      | Failure during expansion of view 'MY_DYNAMIC_TABLE': SQL compilation error:     |
|                         |                  |                                      | Object 'MY_DB.MY_SCHEMA.MY_BASE_TABLE' does not exist or not authorized.        |
+-------------------------+------------------+--------------------------------------+---------------------------------------------------------------------------------+

The following example retrieves all columns for upstream errors with dynamic tables in the schema my_schema:

SELECT *
  FROM my_event_table
  WHERE
    resource_attributes:"snow.executable.type" = 'DYNAMIC_TABLE' AND
    resource_attributes:"snow.schema.name" = 'MY_SCHEMA' AND
    value:state = 'UPSTREAM_FAILURE'
  ORDER BY timestamp DESC;
+-------------------------+-----------------+-------------------------+-------+----------+-------------------------------------------------+-------+------------------+-------------+-----------------------------+-------------------+-------------------------------+-----------+
| TIMESTAMP               | START_TIMESTAMP | OBSERVED_TIMESTAMP      | TRACE | RESOURCE | RESOURCE_ATTRIBUTES                             | SCOPE | SCOPE_ATTRIBUTES | RECORD_TYPE | RECORD                      | RECORD_ATTRIBUTES | VALUE                         | EXEMPLARS |
|-------------------------+-----------------+-------------------------+-------+----------+-------------------------------------------------+-------+------------------+-------------+-----------------------------+-------------------+-------------------------------+-----------|
| 2025-02-17 21:40:45.486 | NULL            | 2025-02-17 21:40:45.486 | NULL  | NULL     | {                                               | NULL  | NULL             | EVENT       | {                           | NULL              | {                             | NULL      |
|                         |                 |                         |       |          |   "snow.database.id": 49,                       |       |                  |             |   "name": "refresh.status", |                   |   "state": "UPSTREAM_FAILURE" |           |
|                         |                 |                         |       |          |   "snow.database.name": "MY_DB",                |       |                  |             |   "severity_text": "WARN"   |                   | }                             |           |
|                         |                 |                         |       |          |   "snow.executable.id": 487426,                 |       |                  |             | }                           |                   |                               |           |
|                         |                 |                         |       |          |   "snow.executable.name": "MY_DYNAMIC_TABLE_2", |       |                  |             |                             |                   |                               |           |
|                         |                 |                         |       |          |   "snow.executable.type": "DYNAMIC_TABLE",      |       |                  |             |                             |                   |                               |           |
|                         |                 |                         |       |          |   "snow.owner.id": 2601,                        |       |                  |             |                             |                   |                               |           |
|                         |                 |                         |       |          |   "snow.owner.name": "DATA_ADMIN",              |       |                  |             |                             |                   |                               |           |
|                         |                 |                         |       |          |   "snow.owner.type": "ROLE",                    |       |                  |             |                             |                   |                               |           |
|                         |                 |                         |       |          |   "snow.schema.id": 411,                        |       |                  |             |                             |                   |                               |           |
|                         |                 |                         |       |          |   "snow.schema.name": "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 设置新数据警报.

设置新数据警报以监控刷新情况

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.

以下部分介绍如何设置事件日志记录以捕获事件、如何设置警报,以及如何解释事件表中记录的事件:

Note

Logging events for dynamic tables incurs costs. See Costs of telemetry data collection.

设置要捕获的事件的严重性级别

Note

如果您未设置严重性级别,则不会捕获任何事件。

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:

  • 账户中的所有对象。
  • 数据库或架构中的所有对象。
  • 特定的动态表。

例如:

  • To capture ERROR-level dynamic table events for all supported objects in the account, execute ALTER ACCOUNT SET LOG_EVENT_LEVEL:

    ALTER ACCOUNT SET LOG_EVENT_LEVEL = ERROR;

    Setting LOG_EVENT_LEVEL at 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:

    ALTER DATABASE my_db SET LOG_EVENT_LEVEL = INFO;

与在账户上设置级别的情况类似,在数据库上设置级别会影响数据库内受支持对象类型的日志事件。

  • To capture WARN-level events for the dynamic table my_dynamic_table, execute ALTER DYNAMIC TABLE … SET LOG_EVENT_LEVEL:
    ALTER DYNAMIC TABLE my_dynamic_table SET LOG_EVENT_LEVEL = WARN;

设置新数据警报

设置日志记录事件的严重性级别后,您可以设置新数据警报,以监控事件表中是否有指示动态表刷新失败的新事件。在事件表中插入新行并满足警报中指定的条件时,将触发新数据警报。

Note

要创建新数据警报,您必须使用已被授予查询事件表所需权限的角色。

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 为动态表事件记录的信息.

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:

timestamp > DATEADD('minute', -5, CONVERT_TIMEZONE('UTC', CURRENT_TIMESTAMP()))

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:

CREATE ALERT my_alert_on_dt_refreshes
  IF( EXISTS(
    SELECT * FROM SNOWFLAKE.TELEMETRY.EVENT_TABLE
      WHERE resource_attributes:"snow.executable.type" = 'dynamic_table'
        AND resource_attributes:"snow.database.name" = 'my_db'
        AND record:"name" = 'refresh.status'
        AND record:"severity_text" = 'ERROR'
        AND value:"state" = 'FAILED'))
  THEN
    BEGIN
      LET result_str VARCHAR;
      (SELECT ARRAY_TO_STRING(ARRAY_AGG(name)::ARRAY, ',') INTO :result_str
         FROM (
           SELECT resource_attributes:"snow.executable.name"::VARCHAR name
             FROM TABLE(RESULT_SCAN(SNOWFLAKE.ALERT.GET_CONDITION_QUERY_UUID()))
             LIMIT 10
         )
      );
      CALL SYSTEM$SEND_SNOWFLAKE_NOTIFICATION(
        SNOWFLAKE.NOTIFICATION.TEXT_PLAIN(:result_str),
        '{"my_slack_integration": {}}'
      );
    END;

为动态表事件记录的信息

当动态表刷新时,事件将记录到事件表中。以下各章节介绍表示事件的事件表行:

事件表列值

当动态表刷新时,将向事件表中插入具有以下值的行。

Note

如果列未在下面列出,则事件的列值为 NULL。

数据类型描述
timestampTIMESTAMP_NTZ事件创建时的 UTC 时间戳。
observed_timestampTIMESTAMP_NTZA UTC time used for logs. Currently, this is the same value that is in the timestamp column.
resource_attributesOBJECTAttributes that identify the dynamic table that was refreshed.
record_typeSTRINGThe event type, which is EVENT for dynamic table refreshes.
recordOBJECTDetails about the status of the dynamic table refresh.
valueVARIANTThe 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:

属性名称属性类型描述示例
snow.database.idINTEGER包含动态表的数据库的内部/系统生成的标识符。12345
snow.database.nameVARCHAR包含动态表的数据库的名称。MY_DATABASE
snow.executable.idINTEGER已刷新的动态表的内部/系统生成的标识符。12345
snow.executable.nameVARCHAR已刷新的动态表的名称。MY_DYNAMIC_TABLE
snow.executable.typeVARCHARThe type of the object. The value is DYNAMIC_TABLE for dynamic table events.DYNAMIC_TABLE
snow.owner.idINTEGER具有动态表 OWNERSHIP 权限的角色的内部/系统生成的标识符。12345
snow.owner.nameVARCHAR具有动态表 OWNERSHIP 权限的角色的名称。MY_ROLE
snow.owner.typeVARCHAR

The type of role that owns the object, for example ROLE.
If a Snowflake Native App owns the object, the value is APPLICATION.
Snowflake returns NULL if you delete the object because a deleted object does not have an owner role.

ROLE
snow.query.idVARCHAR刷新动态表的查询的 ID。01ba7614-0107-e56c-0000-a995024f304a
snow.schema.idINTEGER包含动态表的架构的内部/系统生成的标识符。12345
snow.schema.nameVARCHAR包含动态表的架构的名称。MY_SCHEMA
snow.warehouse.idINTEGER用于刷新动态表的仓库的内部/系统生成的标识符。12345
snow.warehouse.nameVARCHAR用于刷新动态表的仓库的名称。MY_WAREHOUSE

Key-value pairs in the record column

The record column contains an OBJECT value with the following key-value pairs:

KeyTypeDescriptionExample
nameVARCHARThe name of the event. The value is refresh.status for dynamic table refreshes.refresh.status
severity_textVARCHAR

事件的严重性级别,为以下值之一:

  • INFO: The refresh succeeded.
  • ERROR: The refresh failed.
  • WARN: The refresh of an upstream dynamic table failed.
INFO

Key-value pairs in the value column

The value column contains an VARIANT value with the following key-value pairs:

KeyTypeDescriptionExample
stateVARCHAR

刷新状态,为以下值之一:

  • SUCCEEDED: The refresh succeeded.
  • FAILED: The refresh failed.
  • UPSTREAM_FAILURE: The refresh failed due to a failure to refresh a dynamic table that this dynamic table depends on.
SUCCEEDED
messageVARCHARIf the value in state is FAILED, this column includes the error message.SQL compilation error:\nFailure during expansion of view 'MY_DYNAMIC_TABLE': SQL compilation error:\nObject 'MY_DB.MY_SCHEMA.MY_BASE_TABLE' does not exist or not authorized.

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:

ALTER SCHEMA my_db.my_schema SET TRACE_LEVEL = 'ALWAYS';

You can also set this at the database level to capture spans for all dynamic tables in the database:

ALTER DATABASE my_db SET TRACE_LEVEL = 'ALWAYS';

Query span data

To query pipeline spans for dynamic table refreshes, filter for rows where record_type = 'SPAN' and record:"name" = 'table_refresh':

SELECT
    resource_attributes:"snow.executable.name"::STRING AS dt_name,
    record_attributes:"snow.dynamic_table.state"::STRING AS state,
    record_attributes:"snow.dynamic_table.state_reason"::STRING AS state_reason,
    record_attributes:"snow.dynamic_table.data_timestamp"::STRING AS data_timestamp,
    trace:"trace_id"::STRING AS trace_id,
    trace:"span_id"::STRING AS span_id,
    record:"status":"code"::STRING AS status_code
  FROM my_event_table
  WHERE record_type = 'SPAN'
    AND record:"name" = 'table_refresh'
  ORDER BY start_timestamp ASC;

Span attributes (record_attributes)

Each span row includes the following attributes in the record_attributes column, specific to dynamic table refreshes:

Attribute nameTypeDescription
snow.dynamic_table.stateSTRINGThe state of the refresh: SUCCEEDED, FAILED, or SKIPPED.
snow.dynamic_table.state_reasonSTRING

Why the dynamic table was skipped or failed. NULL on success. Possible values:

  • QUERY_FAILURE: The refresh query failed.
  • UPSTREAM_FAILURE: An upstream dynamic table failed to refresh.
  • UPSTREAM_SKIP: An upstream dynamic table was skipped.
  • NOT_EFFECTIVE_TICK_TO_REFRESH: The pipeline is already running behind schedule, skipping this refresh operation to minimize the lag of this dynamic table and its consumers.
snow.dynamic_table.data_timestampSTRING

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.

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:

SELECT
    resource_attributes:"snow.executable.name"::STRING AS dt_name,
    record_attributes:"snow.dynamic_table.state"::STRING AS state,
    record:"links" AS upstream_links
  FROM my_event_table
  WHERE record_type = 'SPAN'
    AND record:"name" = 'table_refresh'
    AND trace:"trace_id" = '<trace_id>'
  ORDER BY start_timestamp;

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:

DT1 --> DT2 --> DT3 --> DT4

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:

SELECT
    trace:"span_id"::STRING AS span_id,
    trace:"trace_id"::STRING AS trace_id,
    resource_attributes:"snow.executable.name"::STRING AS dt_name,
    record_attributes:"snow.dynamic_table.data_timestamp"::STRING AS data_timestamp,
    record_attributes:"snow.dynamic_table.state"::STRING AS state,
    record_attributes:"snow.dynamic_table.state_reason"::STRING AS state_reason,
    resource_attributes:"snow.query.id"::STRING AS query_id,
    start_timestamp,
    timestamp AS end_timestamp
  FROM my_event_table
  WHERE record_type = 'SPAN'
    AND record:"name" = 'table_refresh'
    AND resource_attributes:"snow.database.name" = 'MY_DB'
    AND resource_attributes:"snow.schema.name" = 'MY_SCHEMA'
    AND resource_attributes:"snow.executable.name" = 'DT3'
  ORDER BY start_timestamp DESC
  LIMIT 5;
+----------+------------------+---------+-------------------------+-----------+--------------+--------------------------------------+-------------------------+-------------------------+
| SPAN_ID  | TRACE_ID         | DT_NAME | DATA_TIMESTAMP          | STATE     | STATE_REASON | QUERY_ID                             | START_TIMESTAMP          | END_TIMESTAMP           |
|----------+------------------+---------+-------------------------+-----------+--------------+--------------------------------------+-------------------------+-------------------------|
| a1b2c3d4 | 4f3e2d1c0b9a8877 | DT3     | 2026-02-13T10:00:00.000 | FAILED    | QUERY_FAILURE| 01ba7614-0107-e56c-0000-a995024f304a | 2026-02-13 10:02:01.000 | 2026-02-13 10:02:20.000 |
| e5f6a7b8 | 7a8b9c0d1e2f3344 | DT3     | 2026-02-13T09:55:00.000 | SUCCEEDED | NULL         | 01ba7614-0107-e56c-0000-a995024f2f9b | 2026-02-13 09:57:01.000 | 2026-02-13 09:57:18.000 |
+----------+------------------+---------+-------------------------+-----------+--------------+--------------------------------------+-------------------------+-------------------------+

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:

SELECT
    trace:"span_id"::STRING AS span_id,
    trace:"trace_id"::STRING AS trace_id,
    resource_attributes:"snow.executable.name"::STRING AS dt_name,
    record_attributes:"snow.dynamic_table.state"::STRING AS state,
    record_attributes:"snow.dynamic_table.state_reason"::STRING AS state_reason,
    resource_attributes:"snow.query.id"::STRING AS query_id,
    start_timestamp,
    timestamp AS end_timestamp,
    DATEDIFF('second', start_timestamp, timestamp) AS duration_sec,
    record:"links" AS upstream_links
  FROM my_event_table
  WHERE record_type = 'SPAN'
    AND record:"name" = 'table_refresh'
    AND trace:"trace_id" = '4f3e2d1c0b9a8877'
  ORDER BY start_timestamp ASC;
+----------+------------------+---------+-----------+-----------------+--------------------------------------+-------------------------+-------------------------+--------------+---------------------------------------------+
| SPAN_ID  | TRACE_ID         | DT_NAME | STATE     | STATE_REASON    | QUERY_ID                             | START_TIMESTAMP          | END_TIMESTAMP           | DURATION_SEC | UPSTREAM_LINKS                              |
|----------+------------------+---------+-----------+-----------------+--------------------------------------+-------------------------+-------------------------+--------------+---------------------------------------------|
| f1e2d3c4 | 4f3e2d1c0b9a8877 | DT1     | SUCCEEDED | NULL            | 01ba7614-0107-e56c-0000-a995024f3001 | 2026-02-13 10:01:00.000 | 2026-02-13 10:01:30.000 |           30 | []                                          |
| b5a6c7d8 | 4f3e2d1c0b9a8877 | DT2     | SUCCEEDED | NULL            | 01ba7614-0107-e56c-0000-a995024f3002 | 2026-02-13 10:01:31.000 | 2026-02-13 10:02:00.000 |           29 | [{"span_id": "f1e2d3c4", ...}]              |
| a1b2c3d4 | 4f3e2d1c0b9a8877 | DT3     | FAILED    | QUERY_FAILURE   | 01ba7614-0107-e56c-0000-a995024f304a | 2026-02-13 10:02:01.000 | 2026-02-13 10:02:20.000 |           19 | [{"span_id": "b5a6c7d8", ...}]              |
| c9d0e1f2 | 4f3e2d1c0b9a8877 | DT4     | SKIPPED   | UPSTREAM_FAILURE| NULL                                 | 2026-02-13 10:02:20.000 | 2026-02-13 10:02:20.000 |            0 | [{"span_id": "a1b2c3d4", ...}]              |
+----------+------------------+---------+-----------+-----------------+--------------------------------------+-------------------------+-------------------------+--------------+---------------------------------------------+

From this result, you can see the full picture of the refresh cycle:

  • DT1 and DT2 succeeded (30 and 29 seconds respectively).
  • DT3 failed after 19 seconds due to a query failure.
  • DT4 was skipped immediately (represented by a zero-duration span) because its upstream dependency failed.
  • The UPSTREAM_LINKS column shows each dynamic table’s direct dependencies by span_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:

WITH pipeline AS (
  SELECT
    trace:"span_id"::STRING AS span_id,
    resource_attributes:"snow.executable.name"::STRING AS dt_name,
    record_attributes:"snow.dynamic_table.state"::STRING AS state,
    record_attributes:"snow.dynamic_table.state_reason"::STRING AS state_reason,
    resource_attributes:"snow.query.id"::STRING AS query_id,
    record:"links" AS upstream_links
  FROM my_event_table
  WHERE record_type = 'SPAN'
    AND record:"name" = 'table_refresh'
    AND record_attributes:"snow.dynamic_table.data_timestamp" = '2026-02-13T10:00:00.000'
),
target_links AS (
  SELECT f.value:"span_id"::STRING AS upstream_span_id
  FROM pipeline,
  LATERAL FLATTEN(input => upstream_links) f
  WHERE dt_name = 'DT4'
)
SELECT
  p.dt_name AS upstream_dt,
  p.state AS upstream_state,
  p.state_reason AS upstream_reason,
  p.query_id AS upstream_query_id
FROM target_links tl
JOIN pipeline p ON tl.upstream_span_id = p.span_id;
+-------------+----------------+-----------------+--------------------------------------+
| UPSTREAM_DT | UPSTREAM_STATE | UPSTREAM_REASON | UPSTREAM_QUERY_ID                    |
|-------------+----------------+-----------------+--------------------------------------|
| DT3         | FAILED         | QUERY_FAILURE   | 01ba7614-0107-e56c-0000-a995024f304a |
+-------------+----------------+-----------------+--------------------------------------+

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:

WITH pipeline AS (
  SELECT
    trace:"span_id"::STRING AS span_id,
    resource_attributes:"snow.executable.name"::STRING AS dt_name,
    record_attributes:"snow.dynamic_table.state"::STRING AS state,
    record_attributes:"snow.dynamic_table.state_reason"::STRING AS state_reason,
    record:"links" AS upstream_links
  FROM my_event_table
  WHERE record_type = 'SPAN'
    AND record:"name" = 'table_refresh'
    AND record_attributes:"snow.dynamic_table.data_timestamp" = '2026-02-13T10:00:00.000'
)
SELECT p.dt_name, p.state, p.state_reason
FROM pipeline p,
LATERAL FLATTEN(input => p.upstream_links) f
WHERE f.value:"span_id"::STRING = 'a1b2c3d4';
+---------+---------+-----------------+
| DT_NAME | STATE   | STATE_REASON    |
|---------+---------+-----------------|
| DT4     | SKIPPED | UPSTREAM_FAILURE|
+---------+---------+-----------------+

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.