View logs
This guide explains how to find and use RelationalAI Native App logs in Snowflake, including how to share filtered logs with RelationalAI support when deeper diagnostics are needed for a specific incident or time window.
- The RAI Native App is installed in your Snowflake account.
- You can create and run Snowflake Notebooks in Snowsight.
- You can use the
ACCOUNTADMINrole in Snowflake for the log-sharing workflow.
Where logs are written
Section titled “Where logs are written”The RAI Native App writes information to different Snowflake surfaces:
| Location | What it is used for |
|---|---|
| Active Snowflake Event Table | Continuous app telemetry and observability metrics. This is the main source for routine monitoring. |
RELATIONALAI.LOGGING.LOGS | Internal application log records. This table gives you direct access to recent log entries, but it is not intended for end-user consumption and should be treated as potentially sensitive operational data. |
RELATIONALAI.APP_STATE.CLIENT_LOG_STAGE | Filtered support-share files used when RelationalAI asks for deeper diagnostics. See Share logs with RelationalAI support for details. |
You do not need to query these surfaces directly for routine monitoring or troubleshooting. Refer to the following resources for observability and monitoring guidance.
What information is collected in logs
Section titled “What information is collected in logs”The Native App collects different kinds of operational data for different purposes: Event Table telemetry gives you high-level health and usage signals for monitoring, LOGGING.LOGS contains raw internal log messages and metadata for deeper diagnosis, and the support-share workflow produces a filtered subset of engine and optional control-plane logs for a specific incident or time window.
Share logs with RelationalAI support
Section titled “Share logs with RelationalAI support”Use on-demand logs when RelationalAI asks for deeper diagnostics for a specific time window, engine, or incident. This workflow shares a filtered set of staged logs instead of exposing your full telemetry history.
Do the following to create the secure share and copy the requested logs:
-
Download and import the notebook into Snowflake
Download the on-demand logs notebook.
In Snowsight, choose + Create Projects > Notebook > Import .ipynb File, then upload the notebook. If you want to inspect the workflow before importing it, use the embedded preview below.
View a preview of the notebook.
Sharing On-Demand Logs with RAI
Overview
This notebook creates and shares a secure-share view with RAI to provide access to on-demand logs. It’s designed to run as a Snowflake Notebook, but it can be adapted to run as a local Jupyter notebook by replacing the call to
get_active_session()with code to generate aSessionobject locally. See Snowflake’s documentation for details.from datetime import datetime, timedelta, datedef get_date_range(start_date, end_date):start = datetime.strptime(start_date, "%Y-%m-%d")end = datetime.strptime(end_date, "%Y-%m-%d")dates = [(start + timedelta(days=i)).strftime("%Y-%m-%d")for i in range((end - start).days + 1)]return "|".join(dates)Edit this cell with your specific values:
# Override this to the date you want to get logs starting from in the format YYYY-MM-DD:start_date = date.today().strftime("%Y-%m-%d")# Override this to the date you want to get logs until in the format YYYY-MM-DDend_date = date.today().strftime("%Y-%m-%d")date_range = get_date_range(start_date, end_date)# Override this to True if you want to share spcs_control_plane logsinclude_erps_logs = False# Override this to the engine name (ex, 'testEngine') or leave it as it is if you want to get logs for all enginesengine_name = ".*"warehouse = ""# Override this to a unique id and share it with RAIid = ""# The account you want to share the logs with -- it should be in the format org.account_nameevent_sharing_account = ""# Your native app name (usually relationalai)native_app_name = "relationalai"engine_file_pattern = f'{engine_name}/clientlogs-.*({date_range}).*\\.json|{engine_name}/clientlogs-engine.json'erp_file_pattern = f'|clientlogs-cp-({date_range}).*\\.json|.*clientlogs-cp.json'if include_erps_logs:file_pattern = f'.*({engine_file_pattern}{erp_file_pattern}).*'else:file_pattern = f'.*({engine_file_pattern}).*'sql_query = """BEGINUSE ROLE ACCOUNTADMIN;USE WAREHOUSE &warehouse; -- Update to use another warehouse if necessary.CREATE DATABASE IF NOT EXISTS TELEMETRY_SHARING;USE DATABASE TELEMETRY_SHARING;CREATE SCHEMA IF NOT EXISTS LOGS;USE SCHEMA LOGS;--*****---- Load staged data files to temporary tables--*****--CREATE OR REPLACE TABLE TELEMETRY_SHARING.LOGS.TELEMETRY_LOAD_TABLE_&id (LOG_RECORD VARCHAR);CREATE OR REPLACE TABLE TELEMETRY_SHARING.LOGS.TELEMETRY_SHARE_TABLE_&id (TIMESTAMP TIMESTAMP,OBSERVED_TIMESTAMP TIMESTAMP,SPAN_ID VARCHAR,TRACE_ID VARCHAR,MESSAGE VARCHAR,LOG_RECORD VARCHAR);--*****---- Create secure view from table with target log records--*****--CREATE OR REPLACE SECURE VIEW TELEMETRY_SHARING.LOGS.TELEMETRY_SHARE_VIEW_&idCOMMENT = 'View containing telemetry records to share with the RAI provider account'ASSELECT *FROM TELEMETRY_SHARING.LOGS.TELEMETRY_SHARE_TABLE_&id ;--*****---- Share secure view with the RAI provider account--*****--CREATE OR REPLACE SHARE TELEMETRY_SHARE_&id;CREATE DATABASE ROLE IF NOT EXISTS TELEMETRY_SHARE_ROLE;GRANT USAGE ON DATABASE TELEMETRY_SHARING TO SHARE TELEMETRY_SHARE_&id;GRANT USAGE ON SCHEMA TELEMETRY_SHARING.LOGS TO DATABASE ROLE TELEMETRY_SHARE_ROLE;GRANT SELECT ON VIEW TELEMETRY_SHARE_VIEW_&id TO DATABASE ROLE TELEMETRY_SHARE_ROLE;GRANT DATABASE ROLE TELEMETRY_SHARE_ROLE TO SHARE TELEMETRY_SHARE_&id;ALTER SHARE TELEMETRY_SHARE_&id ADD ACCOUNTS = &event_sharing_account;COPY INTO TELEMETRY_SHARING.LOGS.TELEMETRY_LOAD_TABLE_&idFROM (SELECT$1 AS log_recordFROM @&native_app_name.app_state.client_log_stage)PATTERN = '&file_pattern'FILE_FORMAT = (TYPE = JSON)ON_ERROR = CONTINUE; -- This will skip any log records that are invalid JSON.-- The output of the query will indicate if any records were skipped due to errors.-- Copy from TELEMETRY_LOAD_TABLE_&id into TELEMETRY_SHARE_TABLE_&id and remove safe logsINSERT INTO TELEMETRY_SHARING.LOGS.TELEMETRY_SHARE_TABLE_&idSELECTto_timestamp(timeUnixNano) as timestamp,to_timestamp(observedTimeUnixNano) as observed_timestamp,spanId,traceId,a.value:value:stringValue as message,log_recordFROM (SELECTvalue:timeUnixNano as timeUnixNano,value:observedTimeUnixNano as observedTimeUnixNano,value:spanId as spanId,value:traceId as traceId,value as log_recordFROM TELEMETRY_SHARING.LOGS.TELEMETRY_LOAD_TABLE_&id, LATERAL FLATTEN( INPUT => TRY_PARSE_JSON($1):resourceLogs[0]:scopeLogs[0]:logRecords, OUTER => TRUE )),LATERAL FLATTEN( INPUT => log_record:body:kvlistValue:values, OUTER => TRUE) a, LATERAL FLATTEN( INPUT => log_record:attributes, OUTER => TRUE) bWHERE a.VALUE:key = 'message'and(( -- engine unsafe logsb.value:key = 'log.file.name'and b.value:value:stringValue ='engine-unsafe.log')or(-- erps unsafe logslog_record not like '%___safe_to_log%'and log_record not like '%engine-safe.log%'and log_record like '%spcs_control_plane%'));END;"""sql_query = (sql_query.replace('&warehouse', warehouse).replace('&id', id).replace('&event_sharing_account', event_sharing_account).replace('&date_range', date_range).replace('&native_app_name', native_app_name).replace('&file_pattern', file_pattern))# if running as a Snowflake notebook:session = get_active_session()# # if running as a local Jupyter notebook:# from snowflake.snowpark import Session## connection_parameters = {# "account": "<your snowflake account>",# "user": "<your snowflake user>",# "password": "<your snowflake password>",# "role": "<your snowflake role>", # optional# "warehouse": "<your snowflake warehouse>", # optional# "database": "<your snowflake database>", # optional# "schema": "<your snowflake schema>", # optional# }## session = Session.builder.configs(connection_parameters).create()session.sql(sql_query).collect()Run the following cell to confirm that the logs are copied to the secure share:
session.sql("USE ROLE ACCOUNTADMIN").collect()session.sql(f"USE WAREHOUSE {warehouse}").collect()query = f"SELECT * FROM TELEMETRY_SHARING.LOGS.TELEMETRY_SHARE_TABLE_{id} LIMIT 5"session.sql(query).collect() -
Set the notebook inputs
Before you update the configuration cell, gather the values that control which logs are copied and where the secure share is sent:
Input What to decide start_dateandend_dateThe date range to include in the log share. engine_nameA specific engine (i.e., reasoner) name, or .*if RelationalAI asked for logs across all engines.include_erps_logsWhether to include spcs_control_planelogs in addition to engine logs.warehouseThe Snowflake warehouse the notebook should use while building the share. idA unique identifier for this share so the created tables, view, and share do not collide with another run. event_sharing_accountThe target Snowflake account name that RelationalAI gives you for the secure share. native_app_nameThe installed app name, which is usually relationalai.Then update the configuration cell with the scope and sharing details you prepared:
start_date = "YYYY-MM-DD"end_date = "YYYY-MM-DD"include_erps_logs = Falseengine_name = ".*"warehouse = "<warehouse_name>"id = "<unique_share_id>"event_sharing_account = "<org.account_name>"native_app_name = "relationalai" -
Run the notebook to create the secure share
Run the notebook cells in order. The workflow computes the file pattern for your requested date range, creates the
TELEMETRY_SHARING.LOGSobjects, copies matching files from the app stage, filters the records, and grants the resulting secure share to the target account. -
Verify that the share contains the requested logs
Run the verification cell at the end of the notebook, or run the equivalent query below:
session.sql("USE ROLE ACCOUNTADMIN").collect()session.sql(f"USE WAREHOUSE {warehouse}").collect()query = f"SELECT * FROM TELEMETRY_SHARING.LOGS.TELEMETRY_SHARE_TABLE_{id} LIMIT 5"session.sql(query).collect()If the query returns rows, the filtered logs were copied into the share table and the secure share is populated.