Adoptar OpenTelemetry sin parar al equipo un trimestre

OpenTelemetry no está igual de maduro en trazas, métricas y logs, y los planes de adopción que fracasan son los que lo tratan como una sola migración. Este es el orden que funciona y de dónde salen los meses de factura doble.

La versión cara de una migración a OpenTelemetry es esta: un equipo de plataforma declara un futuro neutral respecto al proveedor, arranca la instrumentación de cuarenta servicios y seis meses después sigue ejecutando el agente antiguo junto al nuevo pipeline porque tres equipos nunca terminaron. Has pagado dos plataformas de observabilidad durante medio año y los paneles están peor que al empezar.

La versión barata trata OpenTelemetry como tres adopciones separadas en tres calendarios separados, empieza por el colector y no por los SDK, y nunca tiene más de unas pocas semanas de solape en una señal concreta.

Las tres señales no están en el mismo punto de madurez

Esto es lo más útil que puedes interiorizar antes de planificar nada.

Las trazas son la parte madura. El trazado es aquello alrededor de lo que se diseñó OpenTelemetry: la API y el SDK son estables en todos los lenguajes importantes, las librerías de instrumentación automática cubren los frameworks habituales y el protocolo lo acepta cualquier backend comercial que merezca la pena. Si solo vas a adoptar una señal, adopta esta.

Las métricas son estables pero la migración es engorrosa. La API y el SDK son estables y OTLP de métricas se acepta ampliamente, pero es casi seguro que vienes de Prometheus, que tiene su propio modelo de recogida, sus propias convenciones de nombres y una década de paneles y reglas de alerta construidos sobre ellas. Traducir entre ambos es mecánico pero no es gratis, y ahí es donde muerden las colisiones de nombres. En la práctica la mayoría de equipos mantienen el scraping de Prometheus como vía de métricas durante mucho tiempo y usan OpenTelemetry primero para trazas y logs. Es un estado final legítimo, no un fracaso.

Los logs son lo más nuevo. La especificación de logs se estabilizó más tarde que las otras, y el patrón dominante no es "instrumenta tu logger con un SDK" sino "sigue escribiendo logs estructurados y que el colector los recoja, los correlacione y los reenvíe". Está bien así. Y además es mucho menos trabajo.

Planifica en consecuencia: trazas ahora, logs por el colector después, métricas cuando haya una razón concreta.

La instrumentación automática es el primer paso y tiene un techo

Los agentes de lenguaje y las librerías de instrumentación te dan tramos para servidores y clientes HTTP, drivers de base de datos, brókers de mensajes y gRPC sin tocar una línea de código. En la JVM y en .NET es literalmente una opción en el arranque del proceso. En Python y Node se le acerca. En Go escribes más a mano, porque no hay un runtime al que engancharse.

Actívala en toda una capa de servicios en una tarde y tendrás un grafo de llamadas que antes no tenías. Esa es la victoria, y conviene cobrarla antes de hacer nada más sofisticado.

El techo llega pronto. La instrumentación automática conoce la frontera del framework y nada de tu dominio. No puede decirte qué inquilino, qué nivel de plan, qué trabajo por lotes ni cuál de los cuatro caminos de código dentro del manejador tomaste de verdad. Eso son atributos de tramo puestos a mano, y son lo que convierte una traza de una foto en un índice de búsqueda. Presupuesta esa pasada manual para los tres o cuatro servicios que importan, no para todos.

El colector es el punto de control, y es la razón de fondo para hacer esto

Si te llevas una sola decisión de arquitectura: no envíes telemetría desde las aplicaciones directamente a un proveedor. Envíala a un colector que operas tú, y deja que el colector decida qué pasa después.

Operar tu propia capa de colector te da cuatro cosas difíciles de conseguir de otra forma:

  • Filtrar antes de pagarlo. Descarta tramos de health check, atributos de depuración de alta cardinalidad y los endpoints internos ruidosos en el colector, no en el contador de ingesta del proveedor.
  • Enriquecer. Adjunta pod, namespace, deployment y nodo de Kubernetes, nombre de clúster, región y entorno de forma centralizada, para que ninguna aplicación tenga que saberlo.
  • Reencaminar sin volver a desplegar nada. Cambio de backend, doble escritura durante una migración, una copia de los errores a un archivo barato: todo eso es configuración del colector.
  • Un búfer. Agrupación y reintento entre tus servicios y un backend que está teniendo un mal día.

Despliégalo como DaemonSet para el enriquecimiento de host y pod más un gateway para los procesadores pesados y las decisiones de muestreo por cola. El gateway es donde vive la política interesante, y es lo que hace posible el muestreo por cola en trazas distribuidas, porque el muestreador necesita ver todos los tramos de una traza en el mismo sitio.

Las convenciones semánticas importan más de lo que parecen

Las convenciones semánticas son los nombres de atributo acordados: http.request.method, server.address, db.system.name, service.name. Suenan a burocracia y son la diferencia entre telemetría que funciona y telemetría que es un montón de cadenas de texto.

Dos razones concretas. Primera, todos los paneles, mapas de servicio y vistas de métricas RED que cualquier backend te da de fábrica están construidos sobre esos nombres. Desvíate y obtienes un panel vacío y un ticket de soporte. Segunda, las convenciones son lo que hace posible la correlación: una traza, una línea de log y una serie de métrica que llevan el mismo service.name y el mismo deployment.environment.name se pueden unir; tres grafías distintas no.

La trampa es que algunos grupos de convenciones han cambiado al estabilizarse, y la instrumentación antigua emite los nombres anteriores. Comprueba qué versión de las convenciones emite tu instrumentación y, si estás a caballo de un renombrado, normaliza en el colector con un procesador de transformación en lugar de pedir a todos los equipos que actualicen el mismo día.

Migrar de un agente propietario sin pagar dos veces durante seis meses

El patrón que mantiene el solape corto:

  1. Despliega el colector junto al agente existente. Para las aplicaciones no cambia nada todavía.
  2. Apunta el colector a tu backend actual usando su endpoint OTLP o un exportador. Casi todos los proveedores comerciales aceptan OTLP hoy. Ya tienes el pipeline nuevo probado contra el backend viejo, con riesgo de migración cero.
  3. Pasa una capa de servicios a instrumentación de OpenTelemetry, exportando todavía al mismo backend. Compara paneles en paralelo durante una semana.
  4. Solo entonces, si de verdad vas a cambiar de proveedor, exporta a los dos desde el colector durante una ventana definida. Dos semanas, con fecha.
  5. Apaga el agente antiguo servicio a servicio según se verifica, no todos de golpe al final.

Los meses de coste doble salen de que el paso 4 no tenga fecha de fin. Pon el corte en el ticket.

Lo que se olvida

  • Los atributos de recurso se ponen una vez y quedan mal para siempre. service.name, service.version y deployment.environment.name son las claves primarias de toda tu telemetría. Ponlos desde el despliegue, no desde un valor por defecto que deja media flota llamándose unknown_service.
  • La propagación de contexto a través de colas. La instrumentación automática propaga el contexto de traza por HTTP y gRPC. Por SQS, Kafka o una tabla de trabajos en base de datos normalmente no, salvo que la librería lo soporte explícitamente. Ahí es donde las trazas se parten en dos en silencio.
  • El muestreo configurado en el SDK es difícil de deshacer. Si las aplicaciones descartan tramos antes de exportarlos, el colector no los puede recuperar. Muestrea en el colector, donde puedes cambiar de opinión.
  • El colector hay que monitorizarlo como todo lo demás. Vigila longitud de cola, tramos rechazados y fallos del exportador. Un colector que descarta datos en silencio es peor que no tener colector.
  • La portabilidad es real pero parcial. OTLP significa que tu instrumentación se mueve entre backends sin tocar código de aplicación, y eso sí cambia tu posición negociadora. Los paneles, las reglas de alerta y las consultas guardadas no se mueven. Valora el cambio con honestidad.

Adoptar esto suelen ser unas semanas de trabajo de plataforma más un toque ligero por equipo, y es una de las piezas que montamos pronto en un proyecto cloud porque todo lo demás se discute mejor cuando los datos son neutrales.

Qué hacer esta semana

Despliega un colector en un clúster de preproducción con el procesador de atributos de Kubernetes y un exportador OTLP apuntando al backend que ya pagas, y activa la instrumentación automática en un solo servicio. Tendrás una traza completa funcionando en menos de una hora, y algo concreto que enseñar a los equipos que tendrán que hacer el resto.

ConsultorIA

¿Quieres esto en tu nube?

El diagnóstico de diez días en solo lectura es gratuito, y con Skyline puedes ver tu entorno en un mapa antes de escribirnos.

Artículos relacionados

Módulos que la gente reutiliza en vez de copiar

Los dos fracasos son un módulo que envuelve un recurso y no aporta nada, y un módulo que lo hace todo y que nadie se atreve a cambiar. Una interfaz mínima, valores por defecto seguros y un versionado honesto son lo que los separa.