Compartir a través de


Análisis de series temporales

Se aplica a: ✅Microsoft FabricAzure Data Explorer✅Azure MonitorMicrosoft Sentinel

Los servicios en la nube y los dispositivos IoT generan datos de telemetría que se pueden usar para obtener información, como supervisar el estado del servicio, los procesos de producción físicos y las tendencias de uso. Realizar análisis de series temporales es una manera de identificar desviaciones en el patrón de estas métricas en comparación con su patrón de línea base típico.

El lenguaje de consulta Kusto (KQL) contiene compatibilidad nativa para la creación, manipulación y análisis de varias series temporales. En este artículo, aprenderá cómo se usa KQL para crear y analizar miles de series temporales en segundos, lo que permite soluciones y flujos de trabajo de supervisión casi en tiempo real.

Creación de series temporales

En esta sección, crearemos un gran conjunto de series temporales normales de forma sencilla e intuitiva con el make-series operador y rellenaremos los valores que faltan según sea necesario. El primer paso en el análisis de series temporales consiste en crear particiones y transformar la tabla de telemetría original en un conjunto de series temporales. La tabla normalmente contiene una columna de marca de tiempo, dimensiones contextuales y métricas opcionales. Las dimensiones se usan para particionar los datos. El objetivo es crear miles de series temporales por partición a intervalos de tiempo regulares.

La tabla de entrada demo_make_series1 contiene 600 000 registros de tráfico arbitrario de servicio web. Use el siguiente comando para muestrear 10 registros:

demo_make_series1 | take 10 

La tabla resultante contiene una columna de marca de tiempo, tres columnas de dimensiones contextuales y ninguna métrica:

Marca de tiempo BrowserVer OsVer País/región
2016-08-25 09:12:35.4020000 Chrome 51.0 Windows 7 Reino Unido
2016-08-25 09:12:41.1120000 Chrome 52.0 Windows 10
2016-08-25 09:12:46.2300000 Chrome 52.0 Windows 7 Reino Unido
2016-08-25 09:12:46.5100000 Chrome 52.0 Windows 10 Reino Unido
2016-08-25 09:12:46.5570000 Chrome 52.0 Windows 10 República de Lituania
2016-08-25 09:12:47.0470000 Chrome 52.0 Windows 8.1 India
2016-08-25 09:12:51.3600000 Chrome 52.0 Windows 10 Reino Unido
2016-08-25 09:12:51.6930000 Chrome 52.0 Windows 7 Países Bajos
2016-08-25 09:12:56.4240000 Chrome 52.0 Windows 10 Reino Unido
2016-08-25 09:13:08.7230000 Chrome 52.0 Windows 10 India

Dado que no hay métricas, solo se puede crear un conjunto de series temporales que represente el propio recuento de tráfico, particionado por el sistema operativo mediante la consulta siguiente:

let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| render timechart 
  • Use el make-series operador para crear un conjunto de tres series temporales, donde:
    • num=count(): serie temporal de tráfico
    • from min_t to max_t step 1h: la serie temporal se crea en períodos de 1 hora dentro del rango temporal (marcas de tiempo más antiguas y más recientes de los registros de la tabla)
    • default=0: especifique el método de relleno para los contenedores que faltan para crear series temporales normales. También puede usar series_fill_const(), series_fill_forward()series_fill_backward() y series_fill_linear() para los cambios.
    • by OsVer: partición por sistema operativo
  • La estructura de datos de serie temporal real es una matriz numérica del valor agregado por cada intervalo de tiempo. Usamos render timechart para la visualización.

En la tabla anterior, tenemos tres particiones. Podemos crear una serie temporal independiente: Windows 10 (rojo), 7 (azul) y 8.1 (verde) para cada versión del sistema operativo, tal como se muestra en el gráfico:

Partición de serie temporal.

Funciones de análisis de series temporales

En esta sección, realizaremos funciones de procesamiento de series típicas. Una vez creado un conjunto de series temporales, KQL admite una lista creciente de funciones para procesarlas y analizarlas. Describiremos algunas funciones representativas para procesar y analizar series temporales.

Filtros

El filtrado es una práctica común en el procesamiento de señales y resulta útil para las tareas de procesamiento de series temporales (por ejemplo, suavizar una señal ruidosa, detección de cambios).

  • Hay dos funciones de filtrado genéricas:
    • series_fir(): aplicación del filtro FIR. Se usa para el cálculo sencillo de la media móvil y la diferenciación de la serie temporal para la detección de cambios.
    • series_iir(): aplicación del filtro IIR. Se utiliza para el suavizado exponencial y la suma acumulativa.
  • Extend el conjunto de series temporales agregando una nueva serie media móvil de tamaño 5 cubos ( denominados ma_num) a la consulta:
let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| render timechart

Filtrado de series temporales.

Análisis de regresión

Se puede usar un análisis de regresión lineal segmentado para calcular la tendencia de la serie temporal.

  • Use series_fit_line() para ajustar la mejor línea a una serie temporal para la detección de tendencias generales.
  • Use series_fit_2lines() para detectar cambios de tendencia, en relación con la línea base, que son útiles en escenarios de supervisión.

Ejemplo de funciones series_fit_line() y series_fit_2lines() en una consulta de serie temporal:

demo_series2
| extend series_fit_2lines(y), series_fit_line(y)
| render linechart with(xcolumn=x)

Regresión de series temporales.

  • Azul: serie temporal original
  • Verde: línea ajustada
  • Rojo: dos líneas ajustadas

Nota:

La función detectó con precisión el punto de salto (cambio de nivel).

Detección de estacionalidad

Muchas métricas siguen patrones estacionales (periódicos). El tráfico de usuarios de servicios en la nube normalmente contiene patrones diarios y semanales que son más altos alrededor del medio del día laborable y más bajo por la noche y durante el fin de semana. Los sensores de IoT miden en intervalos periódicos. Las medidas físicas, como la temperatura, la presión o la humedad, también pueden mostrar un comportamiento estacional.

En el ejemplo siguiente se aplica la detección de estacionalidad en un tráfico mensual de un servicio web (intervalos de 2 horas):

demo_series3
| render timechart 

Estacionalidad de series temporales.

  • Use series_periods_detect() para detectar automáticamente los períodos de la serie temporal, donde:
    • num: serie temporal que se va a analizar
    • 0.: la duración mínima del período en días (0 significa que no es mínimo)
    • 14d/2h: la duración máxima del período en días, que es de 14 días dividida en intervalos de 2 horas.
    • 2: el número de períodos a detectar.
  • Use series_periods_validate() si sabemos que una métrica debe tener períodos distintos específicos y queremos comprobar que existen.

Nota:

Es una anomalía si no existen períodos distintos específicos.

demo_series3
| project (periods, scores) = series_periods_detect(num, 0., 14d/2h, 2) //to detect the periods in the time series
| mv-expand periods, scores
| extend days=2h*todouble(periods)/1d
Períodos Puntuaciones Días
84 0.820622786055595 7
12 0.764601405803502 1

La función detecta estacionalidad diaria y semanal. Las puntuaciones diarias son menores que las semanales porque los días de fin de semana son diferentes a los días laborables.

Funciones orientadas a elementos

Las operaciones aritméticas y lógicas se pueden realizar en una serie temporal. Con series_subtract() podemos calcular una serie temporal residual, es decir, la diferencia entre la métrica sin procesar original y una suavizada y buscar anomalías en la señal residual:

let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| extend residual_num=series_subtract(num, ma_num) //to calculate residual time series
| where OsVer == "Windows 10"   // filter on Win 10 to visualize a cleaner chart 
| render timechart

Operaciones de serie temporal.

  • Azul: serie temporal original
  • Rojo: serie temporal suavizada
  • Verde: serie temporal residual

Flujo de trabajo de series temporales a escala

En el ejemplo siguiente se muestra cómo estas funciones se pueden ejecutar a escala en miles de series temporales en segundos para la detección de anomalías. Para ver algunos registros de telemetría de ejemplo de la métrica de recuento de lectura de un servicio de base de datos durante cuatro días, ejecute la consulta siguiente:

demo_many_series1
| take 4 
TIMESTAMP Loc Op DB DataRead
2016-09-11 21:00:00.0000000 Loc 9 5117853934049630089 262 0
2016-09-11 21:00:00.0000000 Loc 9 5117853934049630089 241 0
2016-09-11 21:00:00.0000000 Loc 9 -865998331941149874 262 279862
2016-09-11 21:00:00.0000000 Loc 9 371921734563783410 255 0

Y estadísticas simples:

demo_many_series1
| summarize num=count(), min_t=min(TIMESTAMP), max_t=max(TIMESTAMP) 
Num min_t max_t
2177472 2016-09-08 00:00:00.0000000 2016-09-11 23:00:00.0000000

La creación de una serie temporal en intervalos de 1 hora de la métrica de lectura (total de cuatro días * 24 horas = 96 puntos), da como resultado una fluctuación normal del patrón:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h
| render timechart with(ymin=0) 

Series temporales a gran escala.

El comportamiento anterior es engañoso, ya que la única serie temporal normal se agrega a partir de miles de instancias diferentes que pueden tener patrones anómalos. Por lo tanto, creamos una serie temporal para cada instancia. Una instancia se define mediante Loc (ubicación), Op (operación) y DB (máquina específica).

¿Cuántas series temporales podemos crear?

demo_many_series1
| summarize by Loc, Op, DB
| count
Contar
18339

Ahora vamos a crear un conjunto de 18339 series temporales de la métrica de recuento de lecturas. Agregamos la by cláusula a la instrucción make-series, aplicamos regresión lineal y seleccionamos las dos series temporales principales que tenían la tendencia de disminución más significativa:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc 
| render timechart with(title='Service Traffic Outage for 2 instances (out of 18339)')

Dos principales de la serie temporal.

Mostrar las instancias:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc
| project Loc, Op, DB, slope 
Loc Op DB pendiente
Loc 15 37 1151 -102743.910227889
Loc 13 37 1249 -86303.2334644601

En menos de dos minutos, se analizaron cerca de 20 000 series temporales y se detectaron dos series anómalas en las que el recuento de lecturas cayó repentinamente.

Estas funcionalidades avanzadas combinadas con un rendimiento rápido proporcionan una solución única y eficaz para el análisis de series temporales.