En entornos complejos, los equipos de operaciones se enfrentan a un problema recurrente: el exceso de alertas. Muchas son notificaciones irrelevantes, redundantes o directamente falsas. Este ruido provoca fatiga operativa y retrasa la respuesta ante incidentes críticos.
La Dynatrace Query Language (DQL) es una herramienta diseñada para filtrar, correlacionar y transformar datos observables —logs, métricas, trazas y eventos— directamente desde la plataforma Dynatrace. Con ella es posible diseñar consultas que identifican patrones reales y reducen los falsos positivos en las alertas.
En este artículo se explica qué es DQL y en qué se diferencia de un filtro convencional, cómo consultar logs y métricas con sintaxis correcta y actual, ejemplos prácticos para reducir el ruido de alertas, y buenas prácticas y recomendaciones finales.
Nota sobre compatibilidad: DQL con los comandos timeseries y makeTimeseries está disponible en Dynatrace SaaS (plataforma con Grail). En entornos Managed, la disponibilidad de estos comandos depende de la versión instalada. Si trabajas sobre un Managed, verifica qué versión tienes antes de aplicar las consultas de series temporales.
Qué es DQL y por qué importa
DQL es un lenguaje declarativo pensado para datos observacionales. Si conoces SQL o el SPL de Splunk, los conceptos son familiares, aunque DQL está optimizado para el modelo de datos de Dynatrace. Permite consultar logs, métricas y eventos, realizar agregaciones en tiempo real sobre ventanas temporales, correlacionar señales de distintas fuentes, y aplicar funciones de enriquecimiento y transformación.
La diferencia respecto a un filtro clásico de panel o alerta es relevante. Un filtro convencional simplemente incluye o excluye datos según condiciones básicas (por ejemplo, status=error). DQL permite aplicar lógica condicional, agregaciones por ventana temporal y cálculos que ayudan a determinar si un patrón representa realmente un incidente o es ruido pasajero.
Por ejemplo: un pico puntual de errores 500 que desaparece en diez segundos probablemente no merece una alerta. Un aumento sostenido de latencia en dos servicios correlacionados durante varios minutos sí puede indicar un problema real.
Consultando logs con DQL
Estructura básica
Una consulta típica sobre logs sigue una estructura de pipeline donde cada comando transforma el resultado del anterior:
fetch logs
| filter loglevel == "ERROR" and contains(content, "timeout")
| summarize count() by bin(timestamp, 1m)
El comando fetch logs carga el conjunto de datos de logs del rango temporal activo en la interfaz, o del especificado en la propia consulta. El comando filter aplica condiciones sobre campos del log — el campo de contenido en Dynatrace es content. El comando summarize count() by bin(timestamp, 1m) agrega los resultados en intervalos de un minuto, lo que permite detectar si el volumen de errores es puntual o sostenido.
Reducir falsos positivos con umbral temporal
Los falsos positivos más habituales provienen de errores transitorios. Se pueden filtrar añadiendo un umbral sobre la agregación:
fetch logs
| filter loglevel == "ERROR" and contains(content, "timeout")
| summarize errors_per_min = count() by bin(timestamp, 1m)
| filter errors_per_min > 5
Solo se considerará incidente si se registran más de 5 errores por minuto. Un error aislado no activará la alerta.
Correlación entre servicios
Cuando dos servicios fallan en cascada, una consulta puede detectar el patrón conjunto:
fetch logs
| filter (service.name == "checkout" or service.name == "payment")
| filter loglevel == "ERROR"
| summarize total_errors = count() by service.name, bin(timestamp, 1m)
| filter total_errors > 10
Esta consulta alerta solo cuando alguno de los dos servicios supera 10 errores por minuto, no ante un error puntual aislado.
Nota sobre service.name: este campo está disponible en logs solo si el proceso que los genera está instrumentado con OneAgent o si el atributo se enriquece explícitamente durante la ingesta mediante reglas de procesamiento. Si tus logs no muestran este campo, puedes usar dt.entity.service o el campo por el que identifiques el servicio en tu entorno.
Consultando métricas con DQL
El comando timeseries
Para métricas, DQL utiliza el comando timeseries, que carga, filtra y agrega datos en una sola expresión. A diferencia de fetch, timeseries es siempre el comando inicial del pipeline y no puede encadenarse después de otros comandos.
La sintaxis correcta para obtener la latencia media del servicio checkout con resolución de un minuto es:
timeseries avg_latency = avg(dt.service.request.response_time),
filter: { service.name == "checkout" },
interval: 1m
Los parámetros filter: e interval: van al nivel del comando timeseries, no dentro de la función de agregación. Puedes ajustar el intervalo (5m, 30s, 1h) según la granularidad que necesites. Intervalos más amplios suavizan picos puntuales y reducen los falsos positivos.
Convertir logs en series temporales con makeTimeseries
El comando makeTimeseries permite transformar datos de logs en una serie temporal, de forma equivalente a lo que timeseries hace con métricas:
fetch logs
| filter loglevel == "ERROR" and service.name == "checkout"
| makeTimeseries errors = count(), interval: 1m
Cada punto de la serie representa el número de errores por minuto del servicio checkout. El resultado se puede visualizar directamente como gráfico de líneas en un Notebook de Dynatrace.
Correlacionando logs y métricas
Correlacionar logs con métricas en una sola consulta DQL es posible, aunque requiere un enfoque diferente al que se podría esperar si vienes de otros lenguajes de consulta.
timeseries es un comando de inicio de pipeline y no puede anidarse directamente como subquery de un join después de un fetch logs. La forma más práctica de combinar ambas fuentes es usar dos secciones DQL en un mismo Notebook de Dynatrace, con el mismo rango temporal e intervalo, de modo que las dos visualizaciones queden alineadas y la correlación sea evidente.
Sección 1 — errores por minuto (logs):
fetch logs
| filter loglevel == "ERROR" and service.name == "checkout"
| makeTimeseries error_count = count(), interval: 1m
Sección 2 — latencia media por minuto (métricas):
timeseries avg_latency = avg(dt.service.request.response_time),
filter: { service.name == "checkout" },
interval: 1m
Colocando ambas visualizaciones en el mismo Notebook con el mismo rango temporal, se detectan los minutos en los que coinciden picos de errores y degradación de latencia. Ese solapamiento es exactamente lo que buscamos para reducir el ruido: alertar solo cuando las dos señales confluyen.
Buenas prácticas con DQL
Usar agregaciones en ventanas temporales
Las condiciones basadas en recuentos por minuto o promedios evitan alertas por picos breves. Ajusta la ventana según el comportamiento normal de tu aplicación: un servicio batch tolera intervalos más largos que una API de pagos.
Correlacionar múltiples señales
Una sola señal raras veces es suficiente para determinar un incidente real. Combinar errores en logs con degradación de latencia o con métricas de saturación aumenta la fiabilidad de la alerta y reduce los falsos positivos de forma significativa.
Filtrar en la consulta, no en el panel
Evita acumular lógica compleja en los paneles o en los umbrales de alerta. Cuanto más clara y precisa sea la consulta DQL, menor será la ambigüedad aguas abajo y más fácil será mantener la consulta en el tiempo.
Documentar y versionar las consultas
Trata las consultas DQL como código: anota el objetivo de cada una, los umbrales elegidos y el razonamiento detrás de ellos. Guárdalas en un repositorio o en una wiki interna. Una consulta sin contexto es difícil de ajustar meses después.
Validar con datos históricos antes de automatizar
Antes de convertir una consulta en una alerta automática, pruébala sobre periodos históricos conocidos, incluyendo periodos con incidentes reales y periodos estables, para verificar que discrimina bien el ruido.
Tener cuidado con samplingRatio en alertas
DQL permite usar samplingRatio para mejorar el rendimiento en queries exploratorias, pero en consultas destinadas a alertas conviene no samplear: un muestreo del 10% puede hacer que un incidente real quede por debajo del umbral y no se detecte.
Ejemplo práctico: detección de errores sostenidos en checkout
Un equipo quiere evitar alertas cada vez que un usuario experimenta un error puntual al completar una compra. El objetivo es alertar solo si hay un patrón sostenido de fallos de pago.
fetch logs
| filter service.name == "checkout"
and loglevel == "ERROR"
and contains(content, "payment failed")
| summarize error_count = count() by bin(timestamp, 1m)
| filter error_count > 20
Con esta consulta, si hay uno o dos errores aislados se ignoran. Si hay más de 20 errores en un mismo minuto, la condición se activa y puede configurarse como alerta en Dynatrace. El resultado práctico es menos ruido, más foco en incidentes reales y menos desgaste del equipo respondiendo a alertas que no requieren acción.
Resumiendo
Reducir falsos positivos no depende únicamente de ajustar umbrales: requiere inteligencia en cómo se consultan los datos. DQL permite construir condiciones sofisticadas que capturan patrones significativos y filtran el ruido operativo.
Esto se traduce en mayor confiabilidad en las alertas, menor tiempo de respuesta ante incidentes reales y menos fatiga en los equipos de operaciones y SRE.
Si aún no estás usando DQL activamente, un buen punto de partida es identificar las alertas con más falsos positivos en tu entorno y construir una consulta que las refine. Unas pocas líneas bien escritas pueden cambiar completamente cómo el equipo percibe y responde a las alertas.