Aller au contenu principal

Interroger les traces OpenTelemetry stockées dans Unity Catalog

En stockant les données de trace au format OpenTelemetry dans Unity Catalog, vous pouvez query les traces à l'aide du SDK Python MLflow ou via Databricks SQL en utilisant les tables et vues Unity Catalog.

Prérequis

Interroger les traces à l'aide du SDK Python MLflow

Utilisez le MLflow Python SDK pour rechercher et charger des objets de trace.

Python
import os
import mlflow
from mlflow.entities.trace_location import UnityCatalog

# Specify the name of a catalog and schema containing traces
catalog_name = "<UC_CATALOG>"
schema_name = "<UC_SCHEMA>"
table_prefix = "<UC_TABLE_PREFIX>"

mlflow.set_tracking_uri("databricks")
mlflow.set_experiment(
experiment_name="...",
trace_location=UnityCatalog(
catalog_name=catalog_name,
schema_name=schema_name,
table_prefix=table_prefix,
), # optional for existing experiments
)

# Specify the ID of a Databricks SQL warehouse for executing search queries
os.environ["MLFLOW_TRACING_SQL_WAREHOUSE_ID"] = "<SQL_WAREHOUSE_ID>"

traces = mlflow.search_traces(
filter_string="trace.status = 'OK'",
order_by=["timestamp_ms DESC"],
include_spans=False,
)
print(traces)

Pour charger la trace trouvée :

Python
import os
import mlflow

mlflow.set_tracking_uri("databricks")

# Specify the name of a catalog and schema containing traces
catalog_name = "<UC_CATALOG>"
schema_name = "<UC_SCHEMA>"
table_prefix = "<UC_TABLE_PREFIX>"
# Specify the trace UUID (example: "13ffa97d571048d69d21da12240d5863")
trace_uuid = "<TRACE_UUID>"

# Specify the ID of a Databricks SQL warehouse for executing search queries
os.environ["MLFLOW_TRACING_SQL_WAREHOUSE_ID"] = "<SQL_WAREHOUSE_ID>"

trace = mlflow.get_trace(
trace_id=f"trace:/{catalog_name}.{schema_name}.{table_prefix}/{trace_uuid}"
)
print(trace)

Tracez les queries à l'aide de Databricks SQL

Alors que les données sous-jacentes sont stockées dans des formats de table conformes à OpenTelemetry, le service MLflow crée automatiquement des vues Databricks SQL à côté d'elles. Ces vues transforment les données OpenTelemetry au format MLflow.

Pour de grands volumes de traces, les performances de la query sur ces vues peuvent se dégrader. Pour maintenir les performances, créez une vue matérialisée sur celles-ci et mettez à jour la vue matérialisée de manière incrémentielle. Pour de meilleures performances sur les données récentes, utilisez l'API pour interroger les traces.

Databricks recommande d'interroger les vues ou d'utiliser l'API plutôt que de s'appuyer sur les tables sous-jacentes, car les schémas de ces tables peuvent changer au fil du temps.

{table_prefix}_trace_unified

Cette vue offre un aperçu unifié de toutes les données de trace regroupées par identifiant de trace. Chaque ligne contient les données brutes de span et les métadonnées d'informations de trace. Les métadonnées comprennent les tags MLflow, les métadonnées et les évaluations.

Schéma

Python
trace_id: STRING
client_request_id: STRING
request_time: TIMESTAMP
state: STRING
execution_duration_ms: DECIMAL(30,9)
request: STRING
response: STRING
trace_metadata: MAP<STRING, STRING>
tags: MAP<STRING, STRING>
spans: LIST<STRUCT>
trace_id: STRING
span_id: STRING
trace_state: STRING
parent_span_id: STRING
flags: INT
name: STRING
kind: STRING
start_time_unix_nano: BIGINT
end_time_unix_nano: BIGINT
attributes: MAP<STRING, STRING>
dropped_attributes_count: INT
events: LIST<STRUCT>
time_unix_nano: BIGINT
name: STRING
attributes: MAP<STRING, STRING>
dropped_attributes_count: INT
dropped_events_count: INT
links: LIST<STRUCT>
trace_id: STRING
span_id: STRING
trace_state: STRING
attributes: MAP<STRING, STRING>
dropped_attributes_count: INT
flags: INT
dropped_links_count: INT
status: STRUCT
message: STRING
code: STRING
resource: STRUCT
attributes: MAP<STRING, STRING>
dropped_attributes_count: INT
resource_schema_url: STRING
instrumentation_scope: STRUCT
name: STRING
version: STRING
attributes: MAP<STRING, STRING>
dropped_attributes_count: INT
span_schema_url: STRING
assessments: LIST<STRUCT>
assessment_id: STRING
trace_id: STRING
assessment_name: STRING
source: STRUCT
source_id: STRING
source_type: STRING
create_time: TIMESTAMP
last_update_time: TIMESTAMP
expectation: STRUCT
value: STRING
serialized_value: STRUCT
serialization_format: STRING
value: STRING
stack_trace: STRING
feedback: STRUCT
value: STRING
error: STRUCT
error_code: STRING
error_message: STRING
stack_trace: STRING
rationale: STRING
metadata: MAP<STRING, STRING>
span_id: STRING
overrides: STRING
valid: STRING

{table_prefix}_trace_metadata

Cette vue contient uniquement les tags, métadonnées et évaluations MLflow regroupés par ID de trace et est plus performante que la vue unifiée pour la récupération des données MLflow.

Schéma

Python
trace_id: STRING
client_request_id: STRING
tags: MAP<STRING, STRING>
trace_metadata: MAP<STRING, STRING>
assessments: LIST<STRUCT>
assessment_id: STRING
trace_id: STRING
assessment_name: STRING
source: STRUCT
source_id: STRING
source_type: STRING
create_time: TIMESTAMP
last_update_time: TIMESTAMP
expectation: STRUCT
value: STRING
serialized_value: STRUCT
serialization_format: STRING
value: STRING
stack_trace: STRING
feedback: STRUCT
value: STRING
error: STRUCT
error_code: STRING
error_message: STRING
stack_trace: STRING
rationale: STRING
metadata: MAP<STRING, STRING>
span_id: STRING
overrides: STRING
valid: STRING

Formats de données d'annotation MLflow

Les données des entités de suivi MLflow telles que les métadonnées, les balises, les évaluations et les Link vers les exécutions sont stockées dans la table {table_prefix}_otel_annotations. Chaque entité est stockée sous forme de ligne unique avec un annotation_type typé, et ses champs sont répartis entre les colonnes de niveau supérieur (name, value, comment, metadata). La table d'annotations est en ajout uniquement avec des suppressions logicielles, vous devez donc dédupliquer lors de la récupération en prenant la dernière ligne par annotation_id (en triant par updated_at de manière décroissante) et en filtrant les lignes où deleted_at est défini. Les colonnes value et metadata sont VARIANT (JSON).

La table comporte les colonnes suivantes :

Python
annotation_id: STRING
target_type: STRING ("TRACE" or "SPAN")
target_id: STRING ("{trace_id}" for TRACE, "{trace_id}:{span_id}" for SPAN)
annotation_type: STRING ("METADATA", "TAG", "FEEDBACK", "EXPECTATION", "RUN_LINK")
name: STRING
value: VARIANT
comment: STRING
metadata: VARIANT
created_at: TIMESTAMP
created_by: STRING
updated_at: TIMESTAMP
updated_by: STRING
deleted_at: TIMESTAMP
deleted_by: STRING

Métadonnées MLflow

Une seule de ces lignes existe par trace. La colonne value est une structure JSON contenant l'ID de requête client de la trace, la carte de métadonnées et des aperçus de requête/réponse.

Python
annotation_type: "METADATA"
target_type: "TRACE"
name: "metadata"
value: VARIANT (includes `client_request_id`, `trace_metadata`, `request_preview`, `response_preview`)

Balises MLflow

Chaque tag est stocké comme une ligne distincte. Vous pouvez les dédoublonner au sein de chaque trace en utilisant l'attribut annotation_id, qui est dérivé de manière déterministe de l'ID de trace et de la clé de balise.

Python
annotation_type: "TAG"
target_type: "TRACE"
name: STRING (the tag key)
value: STRING (the tag value)

Évaluations MLflow

Chaque évaluation est stockée sous forme de FEEDBACK ou EXPECTATION ligne en fonction de son type. Vous pouvez les dédupliquer au sein de chaque trace en utilisant l'attribut annotation_id, qui correspond à l'ID d'évaluation. La justification est stockée dans la colonne comment de premier niveau. Les métadonnées d'évaluation fournies par l'utilisateur sont stockées dans la colonne metadata parallèlement aux champs gérés par MLflow internes (clés préfixées par mlflow.), que vous devez ignorer lors de la lecture des métadonnées utilisateur.

Python
annotation_type: "FEEDBACK" | "EXPECTATION"
target_type: "TRACE"
name: STRING (the assessment name)
value: VARIANT (feedback value, expectation value, or JSON-serialized expectation string)
comment: STRING (the rationale)
metadata: VARIANT (user-supplied assessment metadata)

Liens d'exécution MLflow

Chaque link entre une trace et une exécution MLflow est stocké comme une ligne distincte. Vous pouvez les dédupliquer au sein de chaque trace à l'aide de l'attribut annotation_id, qui est dérivé de manière déterministe de l'ID de trace et de l'ID d'exécution.

Python
annotation_type: "RUN_LINK"
target_type: "TRACE"
name: "run_link"
value: STRING (the run ID)

Analysez les performances de la query

Pour diagnostiquer les queries lentes, inspectez les profils de query dans l'historique des queries du SQL Warehouse :

  1. Accédez à la page Entrepôts SQL dans votre workspace Databricks.
  2. Sélectionnez votre SQL Warehouse et cliquez sur l’onglet Query history .
  3. Recherchez les requêtes dont **MLflow** est spécifié comme source.
  4. Cliquez sur une query pour afficher son profil de query.

Dans le profil de query, inspectez les éléments suivants :

  • Temps de planification : Si le temps de planification est élevé, vos queries sont en attente en raison d'une charge importante sur le warehouse. Basculez vers un autre SQL warehouse à l'aide du menu déroulant dans l'interface utilisateur MLflow, ou configurez un autre warehouse dans votre client.
  • Performances globales des queries : Pour les queries constamment lentes, utilisez un SQL Warehouse plus grand, resserrez les limites supérieures et inférieures sur trace.timestamp_ms, et supprimez d'autres prédicats de filtre si possible.