Аналитика временных рядов

Облачные службы и устройства Интернета вещей создают данные телеметрии, которые можно использовать для получения аналитических сведений, таких как мониторинг работоспособности служб, физические производственные процессы и тенденции использования. Анализ временных рядов — это один из способов выявления отклонений в шаблоне этих метрик по сравнению с типичной базовой моделью.

язык запросов Kusto (KQL) содержит встроенную поддержку для создания, обработки и анализа нескольких временных рядов. Из этой статьи вы узнаете, как KQL используется для создания и анализа тысяч временных рядов в секундах, что позволяет выполнять мониторинг решений и рабочих процессов практически в реальном времени.

Создание временных рядов

В этом разделе мы создадим большой набор обычных временных рядов простым и интуитивно понятным способом — с помощью оператора make-series — и заполним недостающие значения по необходимости. Первый этап анализа временных рядов — секционировать и преобразовать исходную таблицу данных телеметрии в набор временных рядов. В этой таблице обычно содержатся столбец меток времени, контекстно-зависимые измерения и необязательные метрики. Измерения используются для секционирования данных. Цель — создание тысяч временных рядов в каждой секции через регулярные интервалы времени.

Входная таблица demo_make_series1 содержит 600 тысяч записей произвольного трафика веб-служб. Используйте следующую команду для примера 10 записей:

demo_make_series1 | take 10 

Результатом будет таблица со столбцом меток времени, тремя столбцами контекстно-зависимых измерений и без метрик:

TimeStamp BrowserVer (версия браузера) OsVer (версия ОС) Страна или регион
2016-08-25 09:12:35.4020000 Chrome 51.0 Windows 7 Соединенное Королевство
2016-08-25 09:12:41.1120000 Chrome 52.0 Windows 10
2016-08-25 09:12:46.2300000 Chrome 52.0 Windows 7 Соединенное Королевство
2016-08-25 09:12:46.5100000 Chrome 52.0 Windows 10 Соединенное Королевство
2016-08-25 09:12:46.5570000 Chrome 52.0 Windows 10 Литовская Республика
2016-08-25 09:12:47.0470000 Chrome 52.0 Windows 8.1 Индия
2016-08-25 09:12:51.3600000 Chrome 52.0 Windows 10 Соединенное Королевство
2016-08-25 09:12:51.6930000 Chrome 52.0 Windows 7 Нидерланды
2016-08-25 09:12:56.4240000 Chrome 52.0 Windows 10 Соединенное Королевство
2016-08-25 09:13:08.7230000 Chrome 52.0 Windows 10 Индия

Из-за отсутствия метрик мы можем сформировать только набор временных рядов, представляющий сам объем трафика и секционированный по ОС, выполнив следующий запрос:

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 
  • С помощью оператора make-series создайте набор из трех временных рядов, где:
    • num=count(): временной ряд трафика.
    • from min_t to max_t step 1h: временной ряд создается по 1-часовым ячейкам в указанном диапазоне времени (самые старые и самые новые метки времени записей таблицы).
    • default=0: укажите метод заполнения отсутствующих ячеек для создания регулярных временных рядов. Также можно использовать series_fill_const(), series_fill_forward(), series_fill_backward() и series_fill_linear() для изменений.
    • by OsVer: секционирование по ОС.
  • Фактическая структура данных во временных рядах представляет собой числовой массив агрегированных значений по каждой ячейке времени. Мы используем render timechart для визуализации.

В приведенной выше таблице есть три секции. Мы можем создать отдельные временные ряды для каждой версии операционной системы — Windows 10 (красный), 7 (синий) и 8.1 (зеленый), как показано на графике:

Секция временных рядов.

Функции анализа временных рядов

В этом разделе мы выполним типичные функции обработки рядов. После создания набора временных рядов KQL поддерживает растущий список функций для их обработки и анализа. Мы рассмотрим несколько репрезентативных функций для обработки и анализа временных рядов.

Фильтрация

Фильтрация — это распространенная практика при обработке сигналов, которая полезна в задачах обработки временных рядов (например, для сглаживания сигнала с шумами, обнаружения изменений).

  • Существует две универсальные функции фильтрации.
    • series_fir(): Применение фильтра FIR. Используется для простого вычисления скользящего среднего и дифференциации временных рядов для обнаружения изменений.
    • series_iir(): Применение фильтра IIR. Используется для экспоненциального сглаживания и вычисления кумулятивной суммы.
  • Можно расширить временной ряд функцией Extend путем добавления в запрос нового ряда скользящих средних с размером в 5 ячеек (с именем ma_num):
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

Фильтрация временных рядов.

Регрессионный анализ

Azure Data Explorer поддерживает сегментированную линейную регрессию для оценки тенденции временных рядов.

  • Функция series_fit_line() позволяет подобрать оптимальную линию для временного ряда с целью определения общей тенденции.
  • Функция series_fit_2lines() позволяет обнаруживать изменения тенденций относительно базовой линии, которые важны в сценариях мониторинга.

Пример использования функций series_fit_line() и series_fit_2lines() в запросе по временному ряду:

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

Регрессия временных рядов.

  • Синий: исходный временной ряд
  • Зеленый: подобранная линия
  • Красный: две подобранные линии

Примечание

Функция точно обнаружила точку перехода (изменения уровня).

Обнаружение сезонности

Многие метрики следуют сезонным (периодическим) закономерностям. Пользовательский трафик облачных служб обычно подчиняется ежедневным и еженедельным закономерностям с максимальными значениями в середине рабочего дня и минимальными — ночью и в выходные. Датчики Интернета вещей выполняют измерения с периодическими интервалами. Физические измерения, например температура, давление или влажность, также могут иметь сезонный характер.

В следующем примере применяется обнаружение сезонности к трафику веб-службы за один месяц (с 2-часовыми ячейками):

demo_series3
| render timechart 

Сезонность временных рядов.

  • Функция series_periods_detect() позволяет автоматически обнаружить периоды во временных рядах.
  • Функция series_periods_validate() полезна, если мы знаем, что метрика должна иметь определенные отличительные периоды, и хотим убедиться, что они существуют.

Примечание

Если определенных отличительных периодов нет, это аномалия.

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
periods scores (баллы) days
84 0,820622786055595 7
12 0,764601405803502 1

Функция обнаруживает ежедневную и еженедельную сезонность. Ежедневный показатель меньше еженедельного, так как выходные дни отличаются от будних.

Функции с учетом элементов

Над временным рядом можно выполнять арифметические и логические операции. С помощью функции series_subtract() мы можем вычислить остаточный временной ряд, то есть разность между исходной необработанной метрикой и сглаженной метрикой, и поискать аномалии в остаточном сигнале:

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 in 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

Операции над временными рядами.

  • Синий: исходный временной ряд
  • Красный: сглаженный временной ряд
  • Зеленый: остаточный временной ряд

Масштабирование рабочего процесса с временными рядами

В приведенном ниже примере показано, как описанные функции могут выполняться в масштабе тысяч временных рядов за секунды для обнаружения аномалий. Чтобы просмотреть несколько примеров записей данных телеметрии для метрики количества операций чтения службы баз данных, выполните следующий запрос:

demo_many_series1
| take 4 
timestamp Loc Оператор 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

И простая статистика:

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

Построение временного ряда с 1-часовыми ячейками метрики операций чтения (всего четыре дня * 24 часа = 96 баллов) приводит к обычному колебанию закономерности:

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) 

Временные ряды в большом масштабе.

Указанное выше поведение может ввести в заблуждение, так как один обычный временной ряд агрегируется из тысяч различных экземпляров, в которых возможны аномальные закономерности. Поэтому мы создаем по временному ряду на каждый экземпляр. Экземпляр определяется Loc (расположение), Операция (операция) и База данных (конкретный компьютер).

Сколько временных рядов мы можем создать?

demo_many_series1
| summarize by Loc, Op, DB
| count
Счетчик
18 339

Теперь мы создадим набор из 18 339 временных рядов метрики количества операций чтения. Добавим предложение by в оператор make-series, применим линейную регрессию, а также выберем два верхних временных ряда, в которых возникла наиболее значительная тенденция уменьшения:

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)')

Первые два временных ряда.

Отобразим экземпляры:

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 Оператор DB slope
Loc 15 37 1151 -102743.910227889
Loc 13 37 1249 -86303.2334644601

Менее чем за две минуты было проанализировано около 20 000 временных рядов и обнаружены два аномальных временных ряда, в которых число операций чтения внезапно упало.

Эти расширенные возможности в сочетании с высокой производительностью предоставляют уникальное и мощное решение для анализа временных рядов.