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 TABLEetMODIFYsur 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-1us-east-2us-west-2eu-central-1ap-southeast-1ap-southeast-2ap-northeast-1ca-central-1eu-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.
-
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.Pythonimport 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 eLe niveau de journalisation racine est défini sur
WARNING. Consultez Dépannage pour modifier le niveau de journalisation. -
(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.
Exemple : métriques personnalisées, étendues et journalisation des modèles avec OpenTelemetry
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.
%%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())
-
Consignez et ajoutez le modèle au registre.
Pythonimport 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à.
- 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.
- New endpoint
- Existing endpoint
Pour activer la télémétrie dans l'UI :
- Accédez à Serving dans la barre latérale gauche.
- Cliquez sur Créer un Endpoint de service .
- 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**.
- Emplacement Unity Catalog : Sélectionnez le catalogue et le schéma de destination préparés à l'étape 2.
- (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_spanset<prefix>_otel_metrics. - 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 : Activer la télémétrie via l'API
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"
}
}
}'
La mise à jour déclenche un nouveau déploiement. Les modifications prennent effet une fois le déploiement terminé.
Pour activer la télémétrie dans l'UI :
- Depuis la page d'affichage de l'endpoint, dans la section AI Gateway , cliquez sur Modifier AI Gateway , puis sélectionnez Activer les tables d'inférence et la télémétrie .
- Emplacement Unity Catalog : Sélectionnez le catalogue et le schéma de destination préparés à l'étape 2.
- (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_spanset<prefix>_otel_metrics. - Cliquez sur Mettre à jour .
É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.
-
Accédez à l'**Explorateur de catalogues** ou à l'**Éditeur SQL**.
-
Localisez la table nommée
<prefix>_otel_logsdans votre schéma configuré. -
Exécutez une query pour vérifier que les données circulent :
SQLSELECT * 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 :
DESCRIBE TABLE <catalog>.<schema>.<prefix>_otel_logs;
Utilisez ces colonnes pour filtrer et corréler les données de télémétrie :
timestampseverity_textbodytrace_idspan_idattributes— une carte qui contient des métadonnées spécifiques à l'événement.
Vérifier les erreurs au cours de la dernière heure
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 :
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.