Artículo
· 16 jun, 2025 Lectura de 8 min

Configurando OpenTelemetry en IRIS

¡Hola, estimados miembros de nuestra comunidad de desarrolladores!

En el artículo de hoy vamos a echar un vistazo a una de las últimas funcionalidades de telemonitorización de nuestras instancias de IRIS que se han añadido al producto. Estoy hablando de la compatibilidad con OpenTelemetry.

¿Qué es OpenTelemetry?

OpenTelemetry es un framework open source que proporciona las herramientas necesarias como SDKs y estándares para implementar la observabilidad en sistemas y aplicaciones.

Esta observabilidad se extiende a tres tipos de datos:

  1. Trazas: control del flujo de la información que fluye a lo largo de las soluciones mediante la inclusión de trazas que permitan identificar por donde están pasando y en qué condiciones.
  2. Métricas: situación del sistema, rendimiento del mismo, latencias en las respuestas, uso de recursos, etc.
  3. Logs: incluidos en los sistemas para una mejor comprensión de los eventos que ocurren.

OpenTelemetry hace uso del estándar abierto OTLP que define como se debe serializar y transportar toda la telemetría anteriormente definida, el envío de esta telemetría puede realizarse mediante HTTP o gRPC.

Open Telemetry con IRIS

InterSystems IRIS aprovecha las funcionalidades disponibles por OpenTelemetry SDK para permitir la exportación de toda la telemetría que genera la instancia configurada. ¿De donde procede dicha telemetría? 

  1. Métricas: proceden de la información que tenemos disponible desde la API REST /api/monitor (aquí podéis ver la documentación oficial de dicha API).
  2. Logs: mensajes que se registran en el archivo messages.log e información que se almacena en la base de datos de auditoría (si está activada).
  3. Trazas: trazas definidas por el usuario dentro de las aplicaciones desarrolladas en la instancia.

Pues bien veamos como procederíamos a configurar OpenTelemetry en una instancia de IRIS

Configurando IRIS con OpenTelemetry

Para nuestro ejemplo de configuración he utilizado un proyecto que tengo subido en un github que corre en Docker, pero no seria muy complicado configurarlo en una instancia instalada on-premise. Tenéis dicho proyecto subido en OpenExchange asociado a este artículo.

Antes de mostrar las distintas configuraciones vamos a explicar que elementos van a formar parte de nuestro "ecosistema de monitorización":

InterSystems IRIS

La instancia de IRIS será la encargada de generar los datos de telemetría que necesitamos monitorizar.

OpenTelemetry Collector

Es una herramienta proporcionada por OpenTelemetry encargada de recopilar datos telemétricos de diferentes orígenes, en nuestro ejemplo sólo será IRIS, pero podríamos añadir tantos como necesitáramos.

Prometheus

Herramienta open-source utilizada para la monitorización de sistemas y generación de alertas. Esta herramienta será la responsable de la recepción de las métricas acumuladas por OpenTelemetry Collector.

Jaeger

Plataforma open-source para la gestión y monitorización de trazas de sistemas basados en microservicios.

Configuración en Docker

Como he comentado anteriormente, he usado un despliegue en Docker para simplificar el ejemplo lo máximo posible. Analicemos el fichero docker-compose.yml por partes para su mejor comprensión.

Imagen de IRIS

  iris:
    init: true
    container_name: iris
    build:
      context: .
      dockerfile: iris/Dockerfile
    ports:
      - 52774:52773
      - 51774:1972
    volumes:
    - ./iris/shared:/iris-shared
    environment:
    - ISC_DATA_DIRECTORY=/iris-shared/durable
    - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
    command: --check-caps false --ISCAgent false

Como véis estoy definiendo la imagen a usar en un fichero Dockerfile que no tiene mayor interés y por lo tanto no me molestaré en explicarlo. El punto interesante de esta configuración será la definición de una variable de entorno llamada OTEL_EXPORTER_OTLP_ENDPOINT que será la URL donde nuestro OpenTelemetry Collector estará esperando que IRIS le envíe todas las métricas, trazas y logs de los que dispone.

Una vez que despleguemos nuestra instancia de IRIS tendremos que configurarla para que emita las métricas y los logs de forma regular, para ello accederemos desde el portal de gestión a la configuración de Monitor:

Como podéis ver podemos habilitar tanto el envío de Métricas como el de Logs, en el caso de las trazas estas no se envían en intervalos, sino que se enviarán en cuanto se invoque el método de "End" de la instancia de la clase %Trace.Provider, no entraré más en detalle, pero podéis revisar aquí la documentación oficial.

Imagen de OpenTelemetry Collector

otel-collector:
    build:
      context: .
      dockerfile: open-telemetry/Dockerfile
    container_name: otel-collector
    command: ["--config=/otel-local-config.yml"]
    volumes:
      - ./open-telemetry/otel-collector-config.yml:/otel-local-config.yml
    ports:
      - 4317:4317      # OTLP gRPC receiver
      - 4318:4318    # OTLP HTTP receiver
      - 9464:9464      # Metrics
    depends_on:
      - iris

Aquí tenemos la imagen de OpenTelemetry Collector, nuevamente he definido un Dockerfile para definir de donde obtener la imagen (no sería necesario). Como véis estamos haciendo accesibles 3 puertos:

  • 4317: puerto para la recepción de métricas, trazas y logs vía gRPC.
  • 4318: puerto para la recepción de métricas, trazas y logs vía HTTP.
  • 9464: puerto abierto para que terceras herramientas consulten la información recibida por OpenTelemetry Collector.

También hemos declarado un archivo de configuración otel-local-config.yml (el nombre es modificable). Echemos un vistazo a su interior:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"
      http:
        endpoint: "0.0.0.0:4318"
exporters:
  otlp:
    endpoint: jaeger:4317
    tls:
      insecure: true
  prometheus:
    endpoint: "0.0.0.0:9464"
  debug: {}
service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [otlp]
    metrics:
      receivers: [otlp]
      exporters: [prometheus]
    logs:
      receivers: [otlp]
      exporters: [debug]

¿Qué estamos viendo aquí? Muy sencillo, tenemos las siguiente secciones: 

  • Receptores de datos, en nuestro caso lo hemos llamado otlp, en el que configuramos la IP y los puertos en los que nuestro receptor va a esperar la información de terceros sistemas.
  • Exportadores de datos, a donde vamos a enviar o quién va a extraer los datos que sean recibidos en el OpenTelemetry Collector. Para nuestro ejemplo hemos usado un exporter ya incluido en OpenTelemetry como es prometheus que se encargará de obtener las métricas en la instancia local del OpenTelemetry Collector en el puerto 9464. Para el caso de jaeger estamos usando directamente la capacidad de OpenTelemetry de remitir datos directamente a una IP (jaeger es el nombre de la instancia dentro de la red montada por Docker) que corresponderá con nuestra instancia de jaeger.
  • Servicios, donde indicaremos quienes de los componentes que hemos configurado como receptores y exportadores se van a hacer cargo de la recepción y emisión de métricas, trazas y logs. Cómo podéis ver en nuestro caso, el OpenTelemetry Collector será el receptor que usaremos para todo, Prometheus será el receptor de las métricas y Jaeger, mediante OpenTelemetry Collector, será el receptor de las trazas.

Imagen de Prometheus

Echemos un vistazo a su configuración en Docker:

prometheus:
    build:
      context: .
      dockerfile: prometheus/Dockerfile
    container_name: prometheus
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - 9090:9090

Cómo podéis observar es muy sencillo, tenemos nuestra imagen definida nuevamente en un archivo Dockerfile que únicamente hace referencia al nombre de la imagen, un puerto 9090 donde se desplegará la interfaz web a la que podremos acceder y finalmente un archivo de configuración llamado prometheus.yml 

Veamos que nos cuenta ese archivo prometheus.yml:

global:
  scrape_interval: 15s
scrape_configs:
  - job_name: 'otel-collector'
    static_configs:
      - targets: ['otel-collector:9464']

Tenemos la siguiente configuración:

  • Scrape interval: con el intervalo de tiempo entre consulta y consulta al OpenTelemetry Collector.
  • Scrape configs: donde damos un nombre a la tarea que realizará la búsqueda y la IP y el puerto al que se conectará para dicha búsqueda.

Imagen de Jaeger

Para la imagen de Jaeger he cogido directamente un ejemplo disponible en nuestro querido chatGPT:

jaeger:
    image: jaegertracing/all-in-one:latest
    container_name: jaeger
    environment:
      - COLLECTOR_OTLP_ENABLED=true
    ports:
      - 16686:16686    # Jaeger UI
      - 14250:14250    # OTLP gRPC receiver

El punto más relevante, a parte del puerto 16689 que es el que usaremos para acceder a la interfaz web, es la variable de entorno COLLECTOR_OTLP_ENABLED, la cual nos habilitará los puertos por defecto de Jaeger para permitir las conexiones HTTP desde OpenTelemetry Collector. Aquí podéis ver la lista de puertos que usa, pero ya os adelanto que es 4317 para la transmisión gRCP y el 4318 para la HTTP, como habéis visto en la configuración de OpenTelemetry Collector, vamos a hacer uso de la conexión vía gRCP.

Pues bien, con todo preparado, veámoslo en funcionamiento arrancando el proyecto.

Emitiendo métricas, recepción en Prometheus

Ya tenemos nuestras instancias configuradas y arrancadas, accedamos a la la interfaz web que nos proporciona Prometheus, en nuestro ejemplo lo hemos mapeado a http://localhost:9090 , por defecto se nos mostrará donde podemos lanzar consultas sobre las métricas disponibles.

Si hemos configurado correctamente la conexión entre IRIS - OpenTelemetry Collector - Prometheus, desde la pantalla de consultas de Prometheus tendremos acceso a todas las métricas estándar disponibles de IRIS como podéis ver en el siguiente pantallazo buscando por "iris_"

Si seleccionamos cualquiera de ellas podremos ver un gráfico a lo largo del tiempo:

Enviando trazas a Jaeger

Para comprobar el funcionamiento del envío de trazas vamos a usar el recurso más sencillo que nos pone a disposición IRIS, que es el método TestTraces() de la clase SYS.Monitor.OTel que podéis consultar aquí, si tenéis algún interés particular en verlo más en detalle comentádmelo en los comentarios y estaré encantado de escribir un artículo al respecto.

Nos limitamos a ejecutar por consola el comando desde el namespace SYS:

%SYS>do ##class(SYS.Monitor.OTel).TestTraces()

Esto nos remitirá una traza que deberá haber llegado a Jaeger, comprobémoslo desde su interfaz gráfica desplegada en http://localhost:16686

En los filtros del menú de la izquierda podemos ver que tenemos un servicio llamado irisotel, este servicio es el usado por IRIS para probar el envío de trazas de prueba, de ahí el nombre de la traza recibida test_trace.

¡Pues ya estaría! Ya tenemos nuestra instancia preparada para el envío de todos los datos de métricas y trazas que deseamos. Estoy a vuestra disposición si queréis profundizar más en el tema.

Comentarios (2)1
Inicie sesión o regístrese para continuar