OpenTelemetry y Azure Monitor para IA: trazas, spans, Application Insights y KQL
Volver a la ruta AI-200
AI-200Capítulo 23

Preparación para la Certificación Microsoft AI-200

OpenTelemetry y Azure Monitor para IA: trazas, spans, Application Insights y KQL

Instrumenta una canalización RAG distribuida, propaga el contexto W3C, exporta telemetría confiable, controla el muestreo y diagnostica latencia con Mapa de aplicación, detalles de transacción y KQL.

Tiempo de estudio sugerido: 125 minutos • Nivel intermedio • Reescritura original completa con versión resumida de cada tema, evaluación comentada y laboratorio Python guiado

Escudo neón Microsoft Certified AI-200 para OpenTelemetry, trazado distribuido, Azure Monitor, Application Insights y KQL

1. Escenario y objetivos de aprendizaje

Una solución RAG de soporte al cliente contiene una puerta de enlace de , un servicio de embeddings, un servicio de búsqueda vectorial y un orquestador de LLM. La mayoría de las respuestas tarda dos segundos, pero algunas superan diez. Cada servicio escribe un registro distinto, por lo que las marcas de tiempo no demuestran dónde se consumió el tiempo. El objetivo es mantener p95 por debajo de tres segundos y ver el estado de todos los servicios en un solo lugar.

  • Explicar la observabilidad y el papel de trazas, métricas y registros.
  • Instrumentar Python con la Distro de OpenTelemetry de .
  • Crear spans personalizados y correlacionados para operaciones de IA.
  • Exportar y comprobar telemetría en .
  • Usar diagnósticos visuales y KQL para localizar latencia, errores y patrones de IA.

Resumen rápido

El problema no es la falta de registros aislados, sino la ausencia de una historia correlacionada para la solicitud que atraviesa todo el RAG.

2. Observabilidad y sus tres pilares

La observabilidad permite inferir el estado interno de un sistema a partir de sus señales. En IA distribuida, la latencia, los errores o la degradación de calidad pueden originarse en el modelo, la recuperación, el acceso a datos o la orquestación.

Tres perspectivas complementarias
SeñalPregunta que respondeEjemplo de IA
Métricas¿Cambia el comportamiento con el tiempo?Volumen, tasa de error, procesados y duración p95.
Trazas distribuidas¿Dónde gastó tiempo o falló una solicitud?Ruta completa puerta de enlace → embedding → búsqueda → LLM.
Registros¿Por qué se comportó así una operación?Motivo de reintento, validación o error del modelo.

Las métricas detectan el cambio, las trazas ubican la etapa y los registros aportan detalle local. El foco es el trazado, pero el diagnóstico fiable combina las tres señales.

Resumen rápido

Las métricas detectan, las trazas localizan y los registros explican; ninguna señal sustituye a las otras.

3. OpenTelemetry como estándar neutral

OpenTelemetry es un marco abierto y neutral de observabilidad en el ecosistema de Cloud Native Computing Foundation. Las definen cómo se produce telemetría; los implementan procesamiento, lotes, muestreo y recursos; las bibliotecas instrumentan marcos comunes; y los exportadores serializan las señales para un .

  • Instrumenta la lógica una vez con estables.
  • Envía datos a , Jaeger, Prometheus, Grafana u otro destino compatible sin reescribir los spans de negocio.
  • Usa instrumentación automática para protocolos comunes y manual para la semántica de IA.
  • Mantén el modelo de telemetría independiente de un proveedor de análisis.
Trazas, métricas y registros pasan por API, SDK, instrumentación y exportadores OpenTelemetry antes de Azure Monitor Application Insights
OpenTelemetry separa la producción de señales del destino; la distribución de reúne los componentes comunes para .

Resumen rápido

OpenTelemetry estandariza la producción y el transporte de telemetría sin atar el código al .

4. Trazas, spans, jerarquía y contexto

Una traza es el registro de extremo a extremo de una operación distribuida. Cada span es una unidad de trabajo con nombre y duración. Contiene el ID común, su span ID, el ID del padre si existe, nombre, tiempos, atributos y estado.

Las relaciones padre-hijo forman un árbol. La solicitud de la puerta de enlace es la raíz; embedding, búsqueda y modelo son descendientes. OpenTelemetry transporta esta relación mediante TraceContext. traceparent tiene versión--id-parent-span-id-, por ejemplo 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01. El 01 final indica muestreo.

traceparent W3C conecta spans RAG entre puerta de enlace, embedding, búsqueda vectorial y LLM
Cada servicio conserva el ID, crea un span ID y registra al llamador como padre para reconstruir la cascada.

Resumen rápido

El ID correlaciona el recorrido, los ID de span preservan causalidad y traceparent lleva el contexto entre servicios.

5. Correspondencia con

Terminología y almacenamiento
OpenTelemetryPython
Tracer.get_tracer("nombre")Fuente de instrumentación; no genera una fila por sí mismo.
Span SERVER o CONSUMERSpanKind.SERVER o CONSUMERSolicitud: en el esquema clásico o AppRequests en el área de trabajo.
Span , INTERNAL o PRODUCERSpanKind correspondienteDependencia: dependencies o AppDependencies.
IDspan.get_span_context().trace_idoperation_Id / OperationId.
Span ID y padrespan_id y contexto padreid y operation_ParentId.
Atributosspan.set_attribute()customDimensions / Properties.
Registros, excepciones y métricas, record_exception y Meter/AppTraces, exceptions/AppExceptions y customMetrics/AppMetrics.

Las consultas abiertas desde un recurso de suelen usar los nombres clásicos de los ejemplos. Las transformaciones del área de trabajo usan tablas App*. operation_Id correlaciona las tablas clásicas.

Resumen rápido

El tipo de span decide solicitud o dependencia y operation_Id une todos los elementos de la transacción.

6. Instrumentación automática o basada en código

Enfoques
EnfoqueCuándo usarloCompensación
Instrumentación automática del hostCargas compatibles en , Functions o máquinas virtuales que necesitan una base sin cambiar código.Esfuerzo bajo, pero menor control del contexto de negocio.
Distro dentro de la aplicaciónServicios de IA que deben mostrar embedding, recuperación, prompt, o modelo.Requiere código y gobierno, pero permite spans, atributos y muestreo personalizados.

La Distro de OpenTelemetry de reúne el de Python, exportadores, detectores e instrumentaciones compatibles. Los spans manuales complementan —no duplican— la telemetría , de marcos, bases de datos, y .

Resumen rápido

Usa automatización como base y la Distro incorporada cuando la traza deba expresar operaciones propias de IA.

7. Instala y conecta la Distro de Python

Instala -monitor-opentelemetry y llama configure_azure_monitor() una vez al iniciar. Configura proveedores globales de trazas, métricas y registros. En producción, guarda la cadena en APPLICATIONINSIGHTS_CONNECTION_STRING y no en el repositorio.

pip install azure-monitor-opentelemetry

from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace

# Read APPLICATIONINSIGHTS_CONNECTION_STRING from the environment.
configure_azure_monitor()
tracer = trace.get_tracer("rag-api")

La cadena identifica el punto de ingesta y el recurso. Un argumento connection_string explícito prevalece sobre la variable equivalente; las variables de muestreo son una excepción documentada y prevalecen sobre sus argumentos. No registres la cadena.

Resumen rápido

Una llamada inicial establece la canalización; la cadena pertenece a la configuración de implementación.

8. Comprende la recopilación automática

Cobertura común de Python
OrigenTelemetría recopilada
Flask, Django y FastAPIRutas entrantes como solicitudes, duración, estado y, en integraciones compatibles, excepciones no controladas.
, urllib y urllib3Dependencias salientes.
psycopg2Operaciones y tiempo de PostgreSQL.
Bibliotecas cliente del de Llamadas a servicios compatibles de .
de PythonRegistros conectados a OpenTelemetry.

La automatización elimina código repetitivo, pero no sabe que una función crea un prompt o que result_count mide recuperación. Agrega spans manuales con valor operativo y evita duplicar o base de datos.

Resumen rápido

La colección automática aporta estructura; los spans personalizados aportan significado de IA.

9. Identifica servicios con atributos de recurso

Cuando varios servicios informan al mismo , service.name proporciona un nombre de rol en la nube. service. agrupa la solución y service.instance.id distingue réplicas. Sin nombres estables, componentes distintos se mezclan en un nodo.

from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry.sdk.resources import Resource

resource = Resource.create({
    "service.name": "embedding-service",
    "service.namespace": "support-rag",
    "service.instance.id": "embedding-01",
})

configure_azure_monitor(resource=resource)

El nombre de rol combina service. y service.name si existen ambos; de lo contrario usa service.name. OTEL_SERVICE_NAME y OTEL_RESOURCE_ATTRIBUTES son alternativas. Puerta de enlace, embedding, búsqueda y orquestador necesitan nombres únicos y un común.

Resumen rápido

Los atributos de recurso describen al emisor y hacen fiable la topología del Mapa de aplicación.

10. Crea spans, atributos, estado y excepciones

.get_tracer() obtiene una fuente. start_as_current_span() inicia, activa y cierra el span al salir de with. Usa atributos con : embedding.model, embedding.token_count, search.top_k, search.result_count, llm.prompt_tokens y llm.response_tokens. Evita prompts sensibles, datos personales y nombres genéricos.

from opentelemetry import trace
from opentelemetry.trace import SpanKind, Status, StatusCode

tracer = trace.get_tracer("rag-pipeline")

with tracer.start_as_current_span("SearchVectorIndex") as span:
    span.set_attribute("search.index_name", "support-docs")
    span.set_attribute("search.top_k", 5)
    try:
        results = search_index(embedding, top_k=5)
        span.set_attribute("search.result_count", len(results))
    except Exception as error:
        span.record_exception(error)
        span.set_status(Status(StatusCode.ERROR, "Vector search failed"))
        raise

with tracer.start_as_current_span("CallLlmApi", kind=SpanKind.CLIENT) as span:
    span.set_attribute("gen_ai.request.model", model_name)
    response = call_model(prompt)

Una excepción no controlada que sale del contexto se registra y marca error. Si el código la captura, record_exception() y set_status() conservan la evidencia. SERVER y CONSUMER son entrada; y PRODUCER son salida; INTERNAL es trabajo local y el valor predeterminado.

Resumen rápido

Los spans nombran el trabajo, los atributos lo contextualizan, kind clasifica la dirección y el estado conserva el error.

11. Modela una solicitud RAG con spans anidados

Iniciar un span mientras otro está activo crea automáticamente la relación padre-hijo mediante variables de contexto de Python. No hace falta pasar el padre para trabajo síncrono anidado.

with tracer.start_as_current_span("ProcessQuery", kind=SpanKind.SERVER):
    with tracer.start_as_current_span("GenerateEmbedding") as embedding_span:
        embedding_span.set_attribute("embedding.token_count", token_count)
        embedding = create_embedding(query)

    with tracer.start_as_current_span("SearchVectorIndex") as search_span:
        documents = search(embedding, top_k=5)
        search_span.set_attribute("search.result_count", len(documents))

    with tracer.start_as_current_span("CallLlm", kind=SpanKind.CLIENT) as llm_span:
        llm_span.set_attribute("llm.prompt_tokens", prompt_tokens)
        answer = generate_answer(query, documents)
        llm_span.set_attribute("llm.response_tokens", answer_tokens)

La cascada muestra ProcessQuery como raíz y embedding, búsqueda y LLM como hijos. Ocho segundos en CallLlm dentro de diez totales hacen visible el cuello de botella. En , clientes instrumentados inyectan traceparent y servidores instrumentados lo extraen.

Resumen rápido

Los contextos anidados expresan causalidad local y la propagación extiende la misma traza a otros procesos.

12. Exporta directamente o mediante Collector

Con exportación directa, la instrumentación alimenta el , el exportador serializa lotes y el proceso envía al punto de ingesta. Es la opción más simple y predeterminada. OpenTelemetry Collector añade transformación central, múltiples o políticas comunes, pero es otro servicio que operar.

Servicios de IA exportan OpenTelemetry a Application Insights y se analizan con Mapa de aplicación, transacciones, Métricas en directo y KQL
La exportación directa reduce infraestructura; usa Collector cuando el procesamiento central o varios destinos lo justifiquen.

Resumen rápido

Prefiere exportación directa y adopta Collector solo por una necesidad concreta.

13. Controla volumen y coste con muestreo

El porcentaje fijo conserva una fracción representativa; el límite de velocidad restringe trazas nuevas por segundo. La Distro actual usa muestreo limitado por velocidad si no se configura una estrategia. OTEL_TRACES_SAMPLER y OTEL_TRACES_SAMPLER_ARG cambian la política sin reconstruir.

# Fixed percentage: about 10% of traces.
configure_azure_monitor(sampling_ratio=0.10)

# Or rate limited: at most about 1.5 traces per second.
configure_azure_monitor(traces_per_second=1.5)

# Equivalent environment configuration:
export OTEL_TRACES_SAMPLER="microsoft.fixed_percentage"
export OTEL_TRACES_SAMPLER_ARG="0.10"

El muestreo afecta trazas, no métricas. Los registros pueden seguir la decisión. Tasas bajas reducen precisión; usa métricas no muestreadas para alertas. Una fila puede llevar itemCount, que representa varios eventos; usa sum(itemCount), no el número bruto de filas.

Resumen rápido

Controla el coste sin ocultar errores raros y no confundas filas muestreadas con tráfico total.

14. Tolera fallos de exportación y verifica la ingesta

El exportador almacena localmente transmisiones fallidas y reintenta tras interrupciones. La ruta debe ser escribible, privada, supervisada y suficientemente persistente. disable_offline_storage elimina la protección y solo procede si una política prohíbe persistencia o existe otra garantía.

configure_azure_monitor(
    storage_directory="/var/telemetry/support-rag",
    # Keep False in production unless local persistence is prohibited.
    disable_offline_storage=False,
)
  1. Genera tráfico correcto y erróneo.
  2. Comprueba la información general tras el retraso normal.
  3. Abre Métricas en directo para solicitudes, dependencias y excepciones casi en tiempo real; viene habilitado.
  4. Consulta solicitudes recientes y roles en la nube.
  5. Abre una traza y confirma operation_Id, padres y atributos.
  6. Prueba una interrupción breve en un entorno controlado y supervisa el almacenamiento.

Resumen rápido

Verificar significa demostrar llegada, identidad, correlación, atributos y recuperación.

15. Usa Mapa de aplicación y diagnóstico de transacciones

Mapa de aplicación reconstruye la topología a partir de roles y dependencias. Los nodos son componentes y los conectores son llamadas. Duración, volumen y errores permiten acotar la investigación.

Los detalles de transacción de extremo a extremo muestran una línea temporal estilo Gantt: raíz arriba, hijos sangrados, trabajo secuencial seguido y trabajo paralelo solapado. Selecciona un evento para ver duración, código, propiedades y excepción. Se accede desde Rendimiento, Errores, búsqueda de transacciones o el mapa.

Resumen rápido

El mapa encuentra el servicio sospechoso; la transacción explica una solicitud correlacionada en el tiempo.

16. Analiza trazas distribuidas con KQL

KQL responde preguntas sobre muchas transacciones. contiene entradas, dependencies contiene trabajo descendente e interno, contiene registros y exceptions contiene fallos. operation_Id conecta las tablas clásicas.

// Slow server operations by service.
requests
| where timestamp > ago(1h) and duration > 3s
| summarize slowRequests=count(), averageDuration=avg(duration)
    by cloud_RoleName
| order by averageDuration desc

// Dependencies belonging to slow requests.
requests
| where timestamp > ago(1h) and duration > 5s
| project operation_Id, requestName=name, requestDuration=duration
| join kind=inner (
    dependencies
    | project operation_Id, dependencyName=name,
        dependencyDuration=duration, dependencyTarget=target,
        dependencyResult=resultCode
) on operation_Id
| order by requestDuration desc

// Embedding latency segmented by custom span attributes.
dependencies
| where name == "GenerateEmbedding"
| extend model=tostring(customDimensions["embedding.model"]),
    tokenCount=toint(customDimensions["embedding.token_count"])
| summarize averageDuration=avg(duration), p95=percentile(duration, 95),
    averageTokens=avg(tokenCount) by model

Las dimensiones personalizadas aportan contexto de IA: segmenta embedding por modelo y , búsqueda por cantidad y umbral y LLM por modelo y . No guardes prompts, texto privado recuperado ni credenciales para facilitar consultas.

Resumen rápido

Une por operation_Id, agrega duraciones y usa dimensiones seguras para probar una hipótesis.

17. Diagnostica patrones de IA y completa el laboratorio

Patrones
SeñalInvestigación
Tiempo de espera de embeddingDependencia larga o fallida; compara embedding.model.
Arranque en frío de búsquedaPrimeros spans tras inactividad lentos y después normales; compara result_count.
Limitación del LLMDependencias con 429 o reintentos largos; correlaciona .
Desbordamiento de contextoFallo cerca del límite de ; no almacenes el prompt.

Crea alertas, Libros para estado de la canalización y métricas para tendencias. El laboratorio usa Flask con Python 3.12+, una suscripción de , y la CLI de más reciente. Crea , instrumenta un proceso documental y diagnostica latencia simulada.

  1. Crea el recurso y configura la cadena en el entorno.
  2. Instala la Distro y define atributos.
  3. Agrega spans padre e hijo con seguros.
  4. Genera tráfico normal, lento y fallido.
  5. Ubica el retraso en mapa y transacción.
  6. Confirma con KQL y guarda una vista útil.
  7. Elimina el recurso y la cadena local.
export APPLICATIONINSIGHTS_CONNECTION_STRING="<application-insights-connection-string>"
az login
python -m flask --app app run

# Generate normal, slow, and failing requests, then inspect:
# Application Map -> Performance/Failures -> End-to-end transaction details -> Logs.

Resumen rápido

El laboratorio termina cuando topología, una traza y una consulta agregada sostienen el mismo diagnóstico.

18. Evaluación comentada, lista final y referencias

Decisiones
PreguntaMejor respuestaRazón
¿Cómo se propaga contexto ? TraceContext mediante traceparent.Transporta ID, padre, versión y .
¿Dónde configurar la cadena?APPLICATIONINSIGHTS_CONNECTION_STRING.Mantiene la implementación fuera del código.
¿Qué ocurre con una excepción no controlada?El la registra y marca error.El contexto captura el fallo antes de cerrar.
¿Dónde aparece ?dependencies / AppDependencies.Es una llamada saliente.
¿Qué campo correlaciona?operation_Id / OperationId.Corresponde al ID.

Lista final

  • Define service.name estable y común.
  • Verifica traceparent en cada frontera.
  • Combina automatización con pocos spans semánticos.
  • Usa atributos con baja cardinalidad y sin datos sensibles.
  • Clasifica SpanKind correctamente.
  • Documenta muestreo, almacenamiento y retención.
  • Valida mapa, transacciones, Métricas en directo, KQL, alertas y Libros.
  • Supervisa lagunas, errores de exportación, almacenamiento, coste y p95.
  1. Distro de OpenTelemetry de para Python
  2. Configurar OpenTelemetry en
  3. Recopilación automática y detectores
  4. Modelo de datos de
  5. Mapa de aplicación
  6. Errores, rendimiento y diagnóstico de transacciones
  7. Especificación Context
  8. Documentación de OpenTelemetry

Resumen rápido

Una solución de producción une instrumentación semántica, correlación , exportación controlada, muestreo consciente del coste, entrega resistente, diagnóstico visual, KQL y supervisión proactiva.