Aller au contenu principal

Conserver les données de service de modèle personnalisées dans Unity Catalog

Cette page montre comment configurer la télémétrie d'endpoint pour faire persister les logs, les traces et les métriques OpenTelemetry de vos endpoints de diffusion de modèles personnalisés dans des tables Unity Catalog. Utilisez les données de télémétrie persistantes pour effectuer une analyse des causes fondamentales, surveiller la santé des Endpoint et répondre aux exigences de conformité avec des requêtes SQL standard.

Exigences

  • Votre Workspace doit être activé pour Unity Catalog. Le stockage default (Arclight) n'est pas pris en charge.

  • Vous devez disposer des autorisations USE CATALOG, USE SCHEMA, CREATE TABLE et MODIFY sur le catalogue et le schéma Unity Catalog de destination où les Logs sont stockés.

  • Un Endpoint de service de modèle personnalisé existant ou un Endpoint de service d'agent, ou les autorisations pour en créer un.

  • Votre workspace doit se trouver dans une région prise en charge :

    • us-east-1
    • us-east-2
    • us-west-2
    • eu-central-1
    • ap-southeast-1
    • ap-southeast-2
    • ap-northeast-1
    • ca-central-1
    • eu-west-1

Étape 1 : Instrumentez votre code de modèle

Ajoutez une instrumentation à votre code de modèle pour capturer les données de télémétrie.

  1. Ajoutez la journalisation des applications à votre modèle. La télémétrie d'endpoint capture automatiquement la sortie standard Python logging. Aucune instrumentation du SDK OpenTelemetry n'est requise pour la journalisation de base.

    Python
    import logging

    class MyCustomModel(mlflow.pyfunc.PythonModel):
    def predict(self, context, model_input):
    # This log will be persisted to the <prefix>_otel_logs table
    logging.warning("Received inference request")

    try:
    # Your model logic here
    result = model_input * 2
    return result
    except Exception as e:
    # Error logs are also captured with severity 'ERROR'
    logging.error(f"Inference failed: {e}")
    raise e

    Le niveau de journalisation racine est défini sur WARNING. Consultez Dépannage pour modifier le niveau de journalisation.

  2. (Facultatif) Instrumentez des métriques et des traces personnalisées avec OpenTelemetry. Pour capturer des métriques et des traces personnalisées au-delà de la journalisation de base, ajoutez l'instrumentation du SDK OpenTelemetry à votre modèle. Développez la section suivante pour un exemple complet qui montre comment créer des compteurs, enregistrer des étendues et attacher des attributs personnalisés.

Icône de crochets carré. Exemple : métriques personnalisées, étendues et journalisation des modèles avec OpenTelemetry

remarque

Due to limitations in model serialization, you must write your model to a separate file before logging to avoid errors, as shown below using %%writefile return_input_model.py.

Python
%%writefile return_input_model.py
import os

import mlflow
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.metrics import get_meter, set_meter_provider
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.trace import get_tracer, set_tracer_provider

# ---- OTel initialization (per-worker) ----
resource = Resource.create({
"worker.pid": str(os.getpid()),
})

otlp_trace_exporter = OTLPSpanExporter()
tracer_provider = TracerProvider(resource=resource)
tracer_provider.add_span_processor(BatchSpanProcessor(otlp_trace_exporter))
set_tracer_provider(tracer_provider)

otlp_metric_exporter = OTLPMetricExporter()
metric_reader = PeriodicExportingMetricReader(otlp_metric_exporter)
meter_provider = MeterProvider(metric_readers=[metric_reader], resource=resource)
set_meter_provider(meter_provider)

_tracer = get_tracer(__name__)
_meter = get_meter(__name__)
_prediction_counter = _meter.create_counter(
name="prediction_count",
description="Number of predictions made",
unit="1"
)


class ReturnInputModel(mlflow.pyfunc.PythonModel):
def load_context(self, context):
self.tracer = _tracer
self.prediction_counter = _prediction_counter

def predict(self, context, model_input):
with self.tracer.start_as_current_span("ReturnInputModel.predict") as span:
span.set_attribute("input_shape", str(model_input.shape))
span.set_attribute("input_columns", str(list(model_input.columns)))
self.prediction_counter.add(1)
return model_input

mlflow.models.set_model(ReturnInputModel())
  1. Consignez et ajoutez le modèle au registre.

    Python
    import pandas as pd
    import mlflow
    from mlflow.models import infer_signature

    # Prepare tabular input/output for signature (pyfunc expects DataFrame)
    input_df = pd.DataFrame({"inputs": ["hello world"]})
    output_df = input_df.copy() # model returns input unchanged

    # Log the model with OpenTelemetry dependencies (using code-based logging to avoid serialization issues)
    with mlflow.start_run():
    signature = infer_signature(input_df, output_df)

    model_info = mlflow.pyfunc.log_model(
    name="model",
    python_model="return_input_model.py",
    signature=signature,
    input_example=input_df,
    pip_requirements=[
    "mlflow==3.1",
    "opentelemetry-sdk",
    "opentelemetry-exporter-otlp-proto-http",
    ],
    )

    # Register with express deployment environment packing
    # Use Unity Catalog name: catalog.schema.model_name
    registered = mlflow.register_model(
    model_info.model_uri,
    MODEL_NAME,
    env_pack="databricks_model_serving"
    )

Étape 2 : Préparez la destination Unity Catalog

Avant de créer votre Endpoint, assurez-vous de disposer d'un catalogue et d'un schéma prêts à recevoir les données de télémétrie. Databricks crée automatiquement les tables nécessaires dans ce schéma si elles n'existent pas déjà.

  1. Dans Catalog Explorer, accédez au catalogue et au schéma que vous souhaitez utiliser (par exemple, my_catalog.observability).

Étape 3 : Activez la télémétrie de l’Endpoint

Vous pouvez activer la télémétrie lors de la création d'un nouvel endpoint ou l'ajouter à un endpoint existant.

Pour activer la télémétrie dans l'UI :

  1. Accédez à Serving dans la barre latérale gauche.
  2. Cliquez sur Créer un Endpoint de service .
  3. Développez **Options avancées**, accédez à la section **AI Gateway** et sélectionnez **Activer les tables d'inférence et la télémétrie**.
  4. Emplacement Unity Catalog : Sélectionnez le catalogue et le schéma de destination préparés à l'étape 2.
  5. (Facultatif) Préfixe de table : Saisissez un préfixe pour les tables générées. Si le champ est laissé vide, il n'y a pas de préfixe. Les tables sont nommées <prefix>_otel_logs, <prefix>_otel_spans et <prefix>_otel_metrics.
  6. Terminez le reste de la configuration de l'Endpoint (Sélection du modèle, paramètres de compute) et cliquez sur **Créer**.

Pour ce faire avec l'API :

Icône de crochets carré. Activer la télémétrie via l'API

Bash
curl -X POST -H "Authorization: Bearer <your-token>" \
https://<workspace-url>/api/2.0/serving-endpoints \
-d '{
"name": "my-custom-logging-endpoint",
"config": {
"served_entities": [
{
"name": "my-model",
"entity_name": "my-model",
"entity_version": "1",
"workload_size": "Small",
"scale_to_zero_enabled": true
}
]
},
"telemetry_config": {
"table_names": {
"logs_table": "my_catalog.observability.custom_endpoint_logs",
"metrics_table": "my_catalog.observability.custom_endpoint_metrics",
"traces_table": "my_catalog.observability.custom_endpoint_spans"
}
}
}'

Étape 4 : vérifier et query les données de télémétrie

Une fois que l'endpoint reçoit du trafic, les données de télémétrie sont transmises aux tables Unity Catalog configurées.

  1. Accédez à l'**Explorateur de catalogues** ou à l'**Éditeur SQL**.

  2. Localisez la table nommée <prefix>_otel_logs dans votre schéma configuré.

  3. Exécutez une query pour vérifier que les données circulent :

    SQL
    SELECT * FROM <catalog>.<schema>.<prefix>_otel_logs
    LIMIT 10;

Query des données de télémétrie

Les exemples suivants présentent des requêtes courantes.

Pour afficher le schéma complet de toute table de télémétrie, exécutez :

SQL
DESCRIBE TABLE <catalog>.<schema>.<prefix>_otel_logs;

Utilisez ces colonnes pour filtrer et corréler les données de télémétrie :

  • timestamp
  • severity_text
  • body
  • trace_id
  • span_id
  • attributes — une carte qui contient des métadonnées spécifiques à l'événement.

Vérifier les erreurs au cours de la dernière heure

SQL
SELECT
timestamp,
severity_text,
body,
attributes
FROM <catalog>.<schema>.<prefix>_otel_logs
WHERE
severity_text = 'ERROR'
AND timestamp > current_timestamp() - INTERVAL 1 HOUR
ORDER BY timestamp DESC;

Dépannage

Logs n'apparaissant pas dans la table : le niveau de journalisation racine est par default WARNING pour réduire la surcharge. Pour capturer des logs de gravité inférieure, modifiez le niveau dans votre code de modèle :

Python
class MyModel(mlflow.pyfunc.PythonModel):
def load_context(self, context):
root = logging.getLogger()
root.setLevel(logging.DEBUG)
for handler in root.handlers:
handler.setLevel(logging.DEBUG)

Limitations

Les limites suivantes s’appliquent à la télémétrie d’Endpoint :

  • L'évolution des schémas sur la table cible n'est pas prise en charge.

  • Seules les tables Delta gérées sont prises en charge. Le stockage externe et le stockage default Arclight ne sont pas pris en charge.

  • L'emplacement de la table doit être dans la même région que votre Workspace.

  • Seuls les noms de table comportant des lettres ASCII, des chiffres et des tirets bas sont pris en charge.

  • La recréation d'une table cible n'est pas prise en charge.

  • Seule la durabilité en zone de disponibilité unique (single-az) est prise en charge.

  • La livraison est au moins une fois. Une confirmation du serveur signifie que l'enregistrement est durable et se trouve dans la table Delta.

  • Les enregistrements doivent faire moins de 10 Mo chacun.

  • Les requêtes doivent être inférieures à 30 Mo chacune.

  • Les lignes de log doivent être inférieures à 1 Mo chacune.

  • La latence de la télémétrie se dégrade au-delà de 2500 QPS.

  • Les logs apparaissent dans la table Unity Catalog quelques secondes après leur émission.