Pular para o conteúdo principal

Persistir dados do modelo personalizado no Unity Catalog

info

Beta

Este recurso está em versão Beta. Essa funcionalidade não é ativada automaticamente para todos os clientes e está sujeita a alterações. Para solicitar acesso, entre em contato com a equipe da sua account Databricks .

Aprenda como configurar a telemetria endpoint para persistir logs, rastreamentos e medições do OpenTelemetry do seu endpoint de modelo de serviço personalizado em tabelas Unity Catalog . Utilize os dados de telemetria armazenados para realizar análises de causa raiz, monitorar a integridade endpoint e atender aos requisitos compliance com consultas SQL padrão.

Requisitos

  • Seu workspace precisa estar habilitado para Unity Catalog. O armazenamento padrão (Arclight) não é compatível.

  • Você deve ter permissões USE CATALOG, USE SCHEMA, CREATE TABLE e MODIFY no catálogo e esquema de destino do Unity Catalog onde os logs são armazenados.

  • Um endpointde modelo de serviço personalizado existente ou permissões para criar um.

  • Seu workspace deve estar em uma região compatível:

    • 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

Passo 1: Instrumente seu código modelo

Adicione instrumentação ao código do seu modelo para capturar telemetria.

  1. Adicione o registro de logs da aplicação ao seu modelo. A telemetria do endpoint captura automaticamente a saída padrão do Python logging . Não é necessário nenhum instrumento do SDK OpenTelemetry para o registro básico de logs.

    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

    O nível de registro raiz está definido como WARNING. Consulte a seção Solução de problemas para alterar o nível de registro.

  2. (Opcional) Instrumente métricas e rastreamentos personalizados com o OpenTelemetry. Para capturar métricas e rastreamentos personalizados além do registro básico, adicione a instrumentação do SDK OpenTelemetry ao seu modelo. Expanda a seção a seguir para ver um exemplo completo que mostra como criar contadores, intervalos de registro e anexar atributos personalizados.

Ícone quadrado entre colchetes. Exemplo: métricas personalizadas, intervalos e registro de modelos com OpenTelemetry

nota

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. Registre e registre o modelo.

    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 serverless optimized 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"
    )

o passo 2: Prepare o destino Unity Catalog

Antes de criar seu endpoint, certifique-se de ter um catálogo e um esquema prontos para receber os dados de telemetria. O Databricks cria automaticamente as tabelas necessárias neste esquema, caso elas ainda não existam.

  1. No Explorador de Catálogo, navegue até o catálogo e esquema que deseja usar (por exemplo, my_catalog.observability).

o passo 3: Habilitar telemetria endpoint

Você pode habilitar a telemetria ao criar um novo endpoint ou adicioná-la a um já existente.

Para ativar a telemetria na interface do usuário:

  1. Navegue até "Servindo" na barra lateral esquerda.
  2. Clique em Criar endpoint de serviço .
  3. Na seção de telemetria do endpoint (marcada como Pré-visualização), expanda as opções de configuração.
  4. LocalizaçãoUnity Catalog : Selecione o catálogo e o esquema de destino preparados na etapa 2.
  5. (Opcional) Prefixo da tabela : Insira um prefixo para as tabelas geradas. Se deixado em branco, não há prefixo. As tabelas são denominadas <prefix>_otel_logs, <prefix>_otel_spans e <prefix>_otel_metrics.
  6. Conclua o restante da configuração endpoint (seleção do modelo, configurações de computação) e clique em Criar .

Para fazer isso com a API:

Ícone quadrado entre colchetes. Habilitar telemetria usando a 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"
}
}
}
}'

o passo 4: Verificar e consultar dados de telemetria

Após o endpoint receber tráfego, os dados de telemetria são transmitidos para as tabelas Unity Catalog configuradas.

  1. Acesse o Explorador de Catálogo ou o Editor SQL .

  2. Localize a tabela chamada <prefix>_otel_logs no seu esquema configurado.

  3. execução de uma consulta para verificar se os dados estão fluindo:

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

Consultar dados de telemetria

Os exemplos a seguir mostram consultas comuns.

Para view o esquema completo de qualquer tabela de telemetria, execute o seguinte comando:

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

Utilize estas colunas para filtrar e correlacionar dados de telemetria:

  • timestamp
  • severity_text
  • body
  • trace_id
  • span_id
  • attributes — um mapa que contém metadados específicos do evento.

Verifique se houve erros na última hora.

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;

Solução de problemas

Registros não aparecem na tabela : O nível de registro raiz é definido como WARNING por padrão para reduzir a sobrecarga. Para capturar logs de menor gravidade, altere o nível no código do seu modelo:

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)

Limitações

Os seguintes limites se aplicam à telemetria endpoint :

  • A evolução do esquema na tabela de destino não é suportada.

  • Somente tabelas Delta são suportadas. O armazenamento externo e o armazenamento default do Arclight não são suportados.

  • A localização da tabela deve estar na mesma região que seu workspace.

  • Somente nomes de tabelas com letras ASCII, dígitos e sublinhados são suportados.

  • A recriação de uma tabela de destino não é suportada.

  • Apenas a durabilidade de zona de disponibilidade única (single-az) é suportada.

  • A entrega é feita pelo menos uma vez. Um aviso do servidor significa que o registro é permanente e está na tabela Delta.

  • Os registros devem ter menos de 10 MB cada.

  • Cada solicitação deve ter menos de 30 MB.

  • As linhas de log devem ter menos de 1 MB cada.

  • A latência da telemetria se degrada além de 2500 QPS.

  • Os registros aparecem na tabela Unity Catalog alguns segundos após serem emitidos.