Protokollierung und Ablaufverfolgung für Streamlit in Snowflake

Streamlit in Snowflake unterstützt die Protokollierung sowohl für Warehouse- als auch für Container-Laufzeiten. Warehouse-Laufzeiten verwenden das Snowflake-Telemetrie-Framework, um Protokollmeldungen und Ablaufverfolgungsereignisse in einer Ereignistabelle zu erfassen. Container-Laufzeiten erfassen Protokolle, die Ihre Anwendung an die Standardausgabe und die Standardfehler ausgibt, speichern diese in der Ereignistabelle des Kontos und stellen sowohl Live-Konsole-Protokolle als auch historische Protokollansichten in Snowsight bereit.

Beide Laufzeitumgebungen speichern Protokolleinträge in der Ereignistabelle auf Kontoebene. Ein Kontoadministrator muss diese Ereignistabelle einrichten und konfigurieren, bevor Protokolle erfasst werden können. Eine Anweisung dazu finden Sie unter Überblick über die Ereignisse.

  • Um die für Ihr Konto konfigurierte Ereignistabelle zu finden, führen Sie Folgendes aus:

    SHOW PARAMETERS LIKE 'event_table' IN ACCOUNT;
    
    Copy

Die folgende Tabelle vergleicht die Unterstützung der Protokollierung und Ablaufverfolgung nach Laufzeit:

Feature

Warehouse-Laufzeit

Container-Laufzeit (Vorschau):

Protokollierung von Ereignistabellen

Unterstützt

Unterstützt

Ablaufverfolgung

Unterstützt

Nicht unterstützt

Live-Konsole-Protokolle in Snowsight

Nicht unterstützt

Unterstützt

Historische Protokolle in Snowsight

Nicht unterstützt

Unterstützt

Protokollierung der Container-Laufzeit

Streamlit-Apps mit Container-Laufzeit werden innerhalb eines Snowpark Container Services-Containers ausgeführt. Snowflake erfasst automatisch alles, was Ihre App an die Standardausgabe und den Standardfehler ausgibt, und speichert es in der Ereignistabelle des Kontos. Sie können diese Protokolle in Snowsight anzeigen oder sie mit SQL abfragen.

Protokollierungsmodul von Python

Verwenden Sie das in Python integrierte logging-Modul, um Protokollmeldungen von Ihrer App auszugeben. Im folgenden Beispiel wird ein Logger konfiguriert, der Meldungen auf INFO-Ebene und höher an die Standardausgabe schreibt:

import logging
import sys

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s: %(message)s",
    stream=sys.stdout,
)

LOGGER = logging.getLogger("my_app")
Copy

In der Reihenfolge vom geringsten zum höchsten Schweregrad hat Python die folgenden Protokolliergrade:

  • DEBUG

  • INFO

  • WARNING

  • ERROR

Das Einstellen des Grads auf INFO erfasst INFO-, WARNING- und ERROR-Meldungen, aber nicht DEBUG-Meldungen.

Bemerkung

Standardmäßig schreibt das logging-Modul von Python in den Standardfehler (sys.stderr). Snowflake erfasst sowohl die Standardausgabe als auch den Standardfehler, sodass Ihre Protokolle unabhängig von dem von Ihnen verwendeten Stream erfasst werden. Das Einstellen des Streams auf sys.stdout ist optional, wird aber empfohlen, da der Standardfehler derzeit für die Fehlerausgabe reserviert ist.

Nachdem Sie den Logger konfiguriert haben, können Sie ihn verwenden, um Meldungen im gesamten App-Code zu protokollieren. Es ist üblich, einen Logger in einem separaten Modul zu definieren und ihn dann in den Code Ihrer App zu importieren:

source_directory/
├── my_logger.py
├── pyproject.toml
└── streamlit_app.py
Copy
import streamlit as st
from my_logger import LOGGER

LOGGER.info("Home page loaded")
st.title("My App")

if st.button("Run analysis"):
    LOGGER.info("Analysis button clicked")
    try:
        result = run_analysis()
        LOGGER.info("Analysis completed successfully")
    except Exception as e:
        LOGGER.error("Analysis failed: %s", e)
        st.error("Analysis failed: %s", e)
Copy

Live-Protokolle in Snowsight

Wenn Sie eine Container-Laufzeit-App in Snowsight bearbeiten, wird unterhalb des Editors ein Protokollbereich angezeigt. Dieser Bereich streamt Protokollmeldungen in Echtzeit, sobald Ihre App sie ausgibt. Wenn Sie zum ersten Mal eine Verbindung herstellen, wird ein kurzer Verlauf der neuesten Protokolle angezeigt.

Jeder Protokolleintrag enthält die folgenden Informationen:

Spalte

Beschreibung

Source

APP für Protokolle Ihres Streamlit-Prozesses und benutzerkonfigurierte Logger oder MANAGER für Protokolle des Systemprozesses, der den Container verwaltet.

Level

Der Schweregrad der Protokollmeldung (DEBUG, INFO, WARNING, ERROR).

Message

Der Inhalt der Protokollmeldung.

Verfügbare Live-Protokoll-Aktionen

In der rechten oberen Ecke des Protokollbereichs können Sie die Protokolle durchsuchen und filtern, um die benötigten Informationen zu finden. Dazu gehören die Textsuche, das Filtern nach Quelle und das Filtern nach Schweregrad. Im Drei-Punkte-Menü können Sie die aktuellen Protokolle herunterladen, zu den historischen Protokollen navigieren oder den Bereich für die Live-Protokollierung löschen. Wenn Sie den Bereich löschen, werden die aktuellen Protokolleinträge aus Ihrer aktuellen Ansicht gelöscht, jedoch nicht aus der Ereignistabelle. Beim sofortigen Neuladen der Seite werden die jüngsten Protokolleinträge wiederhergestellt.

Erläuterungen zu Protokollquellen

Protokolle von Container-Laufzeit-Apps haben eine von zwei Quellen:

  • MANAGER: Der Systemprozess innerhalb des Containers, der Ihre App vorbereitet und ausführt. Die Manager-Protokolle enthalten Meldungen zum Herunterladen Ihrer App-Dateien aus dem Stagingbereich, zum Installieren von Python-Abhängigkeiten und zum Starten des Streamlit-Serverprozesses. Wenn Sie die Abhängigkeitsdateien Ihrer App aktualisieren, während die App ausgeführt wird, installiert der Manager-Prozess die Abhängigkeiten neu und erstellt zusätzliche Manager-Protokolle.

  • APP: Protokolle des laufenden Streamlit-Serverprozesses. Dazu gehören Meldungen von Ihren benutzerkonfigurierten Python-Loggern, dem integrierten Streamlit-Logger und allen anderen Ausgaben, die Ihre App auf die Standardausgabe oder den Standardfehler schreibt.

Die Grenze zwischen den Quellen ist der streamlit run-Befehl. Alles, was der Container vor dem Start des Streamlit-Prozesses ausführt, erzeugt MANAGER-Protokolle. Nachdem der Streamlit-Prozess gestartet ist, erzeugt die Ausgabe dieses Prozesses APP-Protokolle.

Historische Protokolle in Snowsight anzeigen

Die folgenden Schritte gelten nur für Container-Laufzeit-Apps. Warehouse-Laufzeit-Apps haben keinen Protokollbereich.

  1. Melden Sie sich bei Snowsight an.

  2. Wählen Sie im Navigationsmenü die Option Projects » Streamlit und dann Ihre App aus.

  3. Wählen Sie in der rechten oberen Ecke der Seite die Option Edit aus.

  4. Wählen Sie in der rechten oberen Ecke des Protokollbereichs das Drei-Punkte-Menü aus (Other actions) » Historical logs.

Dadurch wird die Snowpark Container Services-Überwachungsseite für den Dienst geöffnet, der im Hintergrund Ihrer App ausgeführt wird. Die Tabelle der Protokolle enthält die folgenden Spalten:

Spalte

Beschreibung

Zeitstempel

Der Zeitstempel der Protokollmeldung.

Instanz-ID

Der Bezeichner für die Container-Instanz. Dies ist immer 0 für Streamlit-Apps.

Container

Der Bezeichner für die Container-Instanz.

Stream

Ob das Protokoll an die Standardausgabe (stdout) oder den Standardfehler (stderr) ausgegeben wurde.

Wert

Die JSON-formatierte Protokollmeldung, die "level"-, "message"-, "source"- und "timestamp"-Felder enthält.

Weitere Informationen zur Überwachungsseite finden Sie unter Snowpark Container Services: Überwachen von Diensten.

Abfrageprotokolle mit SQL

Sie können die Ereignistabelle direkt abfragen, um die Protokolle Ihrer Container-Laufzeit-App zu analysieren. Die folgende Abfrage ruft Protokolle von einer bestimmten Streamlit-App ab:

SELECT
    TIMESTAMP,
    RECORD['severity_text']::VARCHAR AS level,
    VALUE::VARCHAR AS message,
    RESOURCE_ATTRIBUTES['snow.database.name']::VARCHAR AS database_name,
    RESOURCE_ATTRIBUTES['snow.schema.name']::VARCHAR AS schema_name,
    RESOURCE_ATTRIBUTES['snow.executable.name']::VARCHAR AS app_name,
    RECORD_ATTRIBUTES['log.iostream']::VARCHAR AS stream
FROM <event_table>
WHERE RESOURCE_ATTRIBUTES['snow.database.name'] = '<database_name>'
  AND RESOURCE_ATTRIBUTES['snow.schema.name'] = '<schema_name>'
  AND RESOURCE_ATTRIBUTES['snow.executable.name'] = '<app_name>'
  AND RECORD_TYPE = 'LOG'
  AND TIMESTAMP > DATEADD(hour, -1, CURRENT_TIMESTAMP())
ORDER BY TIMESTAMP DESC
LIMIT 100;
Copy

Ersetzen Sie <event_table> mit dem Namen der Ereignistabelle, die vom SHOW PARAMETERS-Befehl zurückgegeben wird, und ersetzen Sie <database_name>, <schema_name> und <app_name> mit den Werten für Ihre Streamlit-App.

Tipp

Fügen Sie einen TIMESTAMP-Filter in Ihren Ereignistabellenabfragen hinzu, um die Leistung zu verbessern. Ereignistabellen können eine große Datenmenge aus verschiedenen Snowflake-Komponenten enthalten.

Weitere Informationen zu den Spalten der Ereignistabelle finden Sie unter Spalten von Ereignistabellen.

Protokollierung der Warehouse-Laufzeit

Bei Streamlit-Apps mit Warehouse-Laufzeiten können Sie die Meldungen und Ereignisse Ihrer Streamlit-App während der Ausführung aufzeichnen und dann die Ergebnisse mit SQL analysieren, um z. B. Fehler zu analysieren. Weitere Informationen dazu finden Sie unter Protokollierung, Ablaufverfolgung und Metriken.

Für die Laufzeit von Warehouses müssen in der Datenbank, die Ihre App enthält, Protokoll- und Ablaufverfolgungsstufen eingestellt werden:

-- Set the log level for the database containing your app
ALTER DATABASE <database_name> SET LOG_LEVEL = INFO;

-- Set the trace level for the database containing your app
ALTER DATABASE <database_name> SET TRACE_LEVEL = ON_EVENT;
Copy

Beispiel: Protokollierung von einer Warehouse-Laufzeit-App

import logging
import streamlit as st

logger = logging.getLogger("simple_logger")

# Write directly to the app
st.title("Simple Logging Example")

# Get the current credentials
session = st.connection('snowflake').session()

def get_log_messages_query() -> str:
    return """
            SELECT
                TIMESTAMP,
                RECORD:"severity_text"::VARCHAR AS SEVERITY,
                RESOURCE_ATTRIBUTES:"db.user"::VARCHAR AS USER,
                VALUE::VARCHAR AS VALUE
            FROM
                SAMPLE_EVENTS
            WHERE
                SCOPE:"name" = 'simple_logger'
            ORDER BY
                TIMESTAMP DESC;
            """

button = st.button("Log a message")

if button:
    try:
        logger.info("Logging an info message through Streamlit App.")
        st.success('Logged a message')
    except Exception as e:
        logger.error("Logging an error message through Streamlit App: %s",e)
        st.error('Logged an error')

sql = get_log_messages_query()

df = session.sql(sql).to_pandas()

with st.expander("**Show All Messages**"):
     st.dataframe(df, use_container_width=True)
Copy

Ablaufverfolgung (nur Warehouse-Laufzeiten)

Die Ablaufverfolgung wird nur für Warehouse-Laufzeiten unterstützt. Sie können Ablaufverfolgungsereignisse von Ihrer Streamlit-App ausgeben und dann die Ereignistabelle abfragen, um sie zu analysieren.

Bemerkung

Das folgende Beispiel erfordert die Installation des snowflake-telemetry-python-Pakets. Weitere Informationen dazu finden Sie unter Hinzufügen von Unterstützung für das Telemetrie-Paket.

import streamlit as st
import time
import random
from snowflake import telemetry

def sleep_function() -> int:
    random_time = random.randint(1, 10)
    time.sleep(random_time)
    return random_time

def get_trace_messages_query() -> str:
    return """
            SELECT
                TIMESTAMP,
                RESOURCE_ATTRIBUTES :"db.user" :: VARCHAR AS USER,
                RECORD_TYPE,
                RECORD_ATTRIBUTES
            FROM
                SAMPLE_EVENTS
            WHERE
                RECORD :"name" :: VARCHAR = 'tracing_some_data'
                OR RECORD_ATTRIBUTES :"logging_demo.tracing" :: VARCHAR = 'begin_span'
            ORDER BY
                TIMESTAMP DESC;
            """

def trace_message() -> None:
    execution_time = sleep_function()
    telemetry.set_span_attribute("logging_demo.tracing", "begin_span")
    telemetry.add_event(
        "tracing_some_data",
        {"function_name": "sleep_function", "execution_time": execution_time},
    )

# Write directly to the app
st.title("Simple Tracing Example")

# Get the current credentials
session = st.connection('snowflake').session()

button = st.button("Add trace event")

if button:
    with st.spinner("Executing function..."):
        trace_message()
        st.toast("Successfully log a trace message!", icon="✅")

sql = get_trace_messages_query()

df = session.sql(sql).to_pandas()

with st.expander("**Show All Trace Messages**"):
     st.dataframe(df, use_container_width=True)
Copy