Journalisation et traçage pour Streamlit in Snowflake¶
Streamlit in Snowflake prend en charge la journalisation pour les runtimes des entrepôts et des conteneurs. Les runtimes d’entrepôt utilisent le cadre de télémétrie Snowflake pour capturer les messages du journal et les événements de trace dans une table d’événements. Les runtimes de conteneurs capturent les journaux que votre application émet en sortie standard et en erreur standard, les stockent dans la table d’événements du compte et fournissent à la fois les journaux de la console en direct et les vues des journaux historiques dans Snowsight.
Les deux runtimes stockent les journaux dans la table des événements au niveau du compte. Un administrateur de compte doit installer et configurer cette table d’événements avant de pouvoir capturer des journaux. Pour obtenir des instructions, voir Aperçu de la table d’événements.
Pour trouver la table d’événements configurée pour votre compte, exécutez :
SHOW PARAMETERS LIKE 'event_table' IN ACCOUNT;
Le tableau suivant compare la prise en charge de la journalisation et du traçage par runtime :
Fonctionnalité |
Runtime d’entrepôt |
Runtime de conteneur (prévisualisation) |
|---|---|---|
Journalisation de la table d’événements |
Pris en charge |
Pris en charge |
Traçage |
Pris en charge |
Non pris en charge |
Journaux de console en direct dans Snowsight |
Non pris en charge |
Pris en charge |
Journaux historiques dans Snowsight |
Non pris en charge |
Pris en charge |
Journalisation du runtime de conteneur¶
Les applications Streamlit en mode conteneur s’exécutent dans un conteneur Snowpark Container Services. Snowflake capture automatiquement tout ce que votre application émet en sortie standard et en erreur standard, et le stocke dans la table d’événements du compte. Vous pouvez voir ces journaux sur Snowsight ou les interroger avecSQL.
Module de journalisation de Python¶
Utilisez le module logging intégré de Python pour émettre des messages de journal à partir de votre application. L’exemple suivant configure un journaliseur qui écrit les messages de niveau INFO et supérieur vers la sortie standard :
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")
Par ordre croissant de gravité, Python dispose des niveaux de journalisation suivants :
DEBUG
INFO
WARNING
ERROR
Définir le niveau sur INFO capture les messages INFO,WARNING et ERROR, mais pas les messages DEBUG.
Note
Par défaut, le module logging de Python écrit dans la sortie d’erreur standard (sys.stderr). Snowflake capture à la fois la sortie standard et les erreurs standard, de sorte que vos journaux sont capturés quel que soit le flux que vous utilisez. Le définition du flux sur sys.stdout est facultative mais recommandée, car l’erreur standard est classiquement réservée à la sortie d’erreur.
Après avoir configuré le journaliseur, vous pouvez l’utiliser pour enregistrer des messages dans le code de votre application. Il est courant de définir un journaliseur dans un module distinct et de l’importer ensuite dans le code de votre application :
source_directory/
├── my_logger.py
├── pyproject.toml
└── streamlit_app.py
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)
Journaux en direct dans Snowsight¶
Lorsque vous modifiez une application de runtime de conteneur dans Snowsight, un volet de journaux apparaît sous l’éditeur. Ce volet diffuse les messages du journal en temps réel au fur et à mesure que votre application les émet. Un bref historique des journaux les plus récents s’affiche lors de la première connexion.
Chaque entrée du journal affiche les informations suivantes :
Colonne |
Description |
|---|---|
|
|
|
Le niveau de gravité du message du journal (DEBUG, INFO, WARNING, ERROR). |
|
Contenu du message du journal. |
Actions de journalisation en direct disponibles¶
Dans le coin supérieur droit du volet des journaux, vous pouvez rechercher et filtrer les journaux pour vous aider à trouver les informations dont vous avez besoin. Cela inclut la recherche de texte, le filtrage par source et le filtrage par niveau de gravité. Dans le menu à trois points, vous pouvez télécharger les journaux actuels, accéder aux journaux historiques ou effacer le volet de journalisation en direct. Lorsque vous videz le volet, les journaux actuels sont supprimés de votre vue actuelle mais pas de la table d’événements. Le rechargement immédiat de la page restaure les journaux les plus récents.
Comprendre les sources du journal¶
Les journaux des runtimes de conteneurs ont l’une des deux sources suivantes :
MANAGER: Le processus système à l’intérieur du conteneur qui prépare et exécute votre application. Les journaux du gestionnaire contiennent des messages concernant le téléchargement des fichiers de votre application depuis la zone de préparation, l’installation des dépendances Python et le démarrage du processus du serveur Streamlit. Si vous mettez à jour les fichiers de dépendances de votre application pendant que celle-ci est en cours d’exécution, le processus du gestionnaire réinstalle les dépendances et produit des journaux de gestionnaire supplémentaires.APP: Journaux du processus du serveur Streamlit en cours d’exécution. Cela inclut les messages de vos journaliseurs Python configurés par l’utilisateur, du journaliseur intégré de Streamlit et de toute autre sortie que votre application écrit sur la sortie standard ou l’erreur standard.
La limite entre les sources est la commande streamlit run. Tout ce que fait le conteneur avant de démarrer le processus Streamlit produit des journaux MANAGER. Après le démarrage du processus Streamlit, la sortie de ce processus produit des journaux APP.
Afficher les journaux historiques dans Snowsight¶
Les étapes suivantes ne s’appliquent qu’aux applications de runtime de conteneur. Les applications de runtime d’entrepôt n’ont pas de volet de journaux.
Connectez-vous à Snowsight.
Dans le menu de navigation, sélectionnez Projects » Streamlit, puis sélectionnez votre application.
Dans le coin supérieur droit de la page, sélectionnez Edit.
Dans le coin supérieur droit du volet des journaux, sélectionnez le menu à trois points (Other actions) » Historical logs.
Cela ouvre la page de surveillance Snowpark Container Services du service qui s’exécute derrière votre application. La table des journaux affiche les colonnes suivantes :
Colonne |
Description |
|---|---|
Horodatage |
L’horodatage du message du journal. |
Instance ID |
L’identificateur de l’instance de conteneur. C’est toujours |
Conteneur |
L’identificateur de l’instance de conteneur. |
Flux |
Si le journal a été émis sur la sortie standard ( |
Valeur |
Le message de journal au format JSON qui comprend les champs |
Pour plus d’informations sur la page de surveillance, voir Snowpark Container Services : services de surveillance.
Journaux de requêtes avec SQL¶
Vous pouvez interroger directement la table des événements pour analyser les journaux de votre application runtime de conteneur. La requête suivante récupère les journaux d’une application Streamlit spécifique :
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;
Remplacez <event_table> avec le nom de la table d’événements renvoyée par la commande SHOW PARAMETERS, et remplacez <database_name>, <schema_name> et <app_name> avec les valeurs de votre application Streamlit.
Astuce
Incluez un filtre TIMESTAMP dans vos requêtes de tables d’événements pour améliorer les performances. Les tables d’événements peuvent contenir un grand volume de données provenant de divers composants Snowflake.
Pour plus d’informations sur les colonnes de la table d’événements, voir Colonnes de table d’événements.
Journalisation du runtime d’entrepôt¶
Pour les applications Streamlit qui utilisent les runtimes d’entrepôt, vous pouvez capturer les messages de journal et suivre les événements de votre code d’application Streamlit au fur et à mesure de son exécution, puis analyser les résultats avec SQL, par exemple, pour analyser les erreurs. Pour plus d’informations, voir Journalisation, traçage et métriques.
Les runtimes d’entrepôt nécessitent que les niveaux de journalisation et de trace soient définis sur la base de données contenant votre application :
-- 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;
Exemple : Journalisation à partir d’une application de runtime d’entrepôt¶
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)
Traçage (runtimes d’entrepôt uniquement)¶
Le traçage est pris en charge pour les runtimes d’entrepôt uniquement. Vous pouvez émettre des événements de trace à partir de votre application Streamlit, puis interroger la table des événements pour les analyser.
Note
L’exemple suivant nécessite l’installation du paquet snowflake-telemetry-python. Pour plus d’informations, voir Ajout d’une prise en charge du paquet de télémétrie.
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)