Как сделать временные ряды с несколькими графиками на Grafana с Kusto

Ну и хочу сделать так: https://grafana.com/docs/grafana/v9.0/basics/timeseries-dimensions/, но на Кусто.

Проблема в том, что я не знаю, где я терплю неудачу, уникальный момент в том, что у меня есть следующее предупреждение:

Обнаружен длинный отформатированный временной ряд, но не удалось преобразовать его из длинного кадр: длинные серии должны быть отсортированы по возрастанию для преобразования.

Дело в том, что мой запрос возвращает следующее:

let test = datatable (Timestamp: datetime, Id: string, Value: dynamic)
[
  datetime(2022-11-09 11:39:25), "machineA", "True",
  datetime(2022-11-09 11:39:30), "machineA", "True",
  datetime(2022-11-09 11:39:35), "machineA", "False",
  datetime(2022-11-09 11:39:36), "machineA", "False",
  datetime(2022-11-09 11:40:03), "machineA", "True",
  datetime(2022-11-09 11:40:03), "machineA", "True",
  datetime(2022-11-09 11:40:04), "machineA", "True",
  datetime(2022-11-09 11:40:05), "machineA", "True",
  datetime(2022-11-09 11:40:25), "machineA", "False",
  datetime(2022-11-09 11:40:25), "machineA", "False",
  datetime(2022-11-09 11:40:26), "machineA", "False",
  datetime(2022-11-09 11:40:27), "machineA", "False",
  datetime(2022-11-09 11:40:37), "machineA", "True",
  datetime(2022-11-09 11:40:47), "machineA", "False",
  datetime(2022-11-09 11:40:57), "machineA", "True",
  datetime(2022-11-09 11:40:59), "machineA", "True",
  datetime(2022-11-09 11:40:25), "machineB", "True",
  datetime(2022-11-09 11:40:30), "machineB", "True",
  datetime(2022-11-09 11:40:35), "machineB", "False",
  datetime(2022-11-09 11:40:36), "machineB", "False",
  datetime(2022-11-09 11:41:03), "machineB", "True",
  datetime(2022-11-09 11:41:03), "machineB", "True",
  datetime(2022-11-09 11:41:04), "machineB", "True",
  datetime(2022-11-09 11:41:05), "machineB", "True",
  datetime(2022-11-09 11:41:25), "machineB", "False",
  datetime(2022-11-09 11:41:25), "machineB", "False",
  datetime(2022-11-09 11:41:26), "machineB", "False",
  datetime(2022-11-09 11:41:27), "machineB", "False",
  datetime(2022-11-09 11:41:37), "machineB", "True",
  datetime(2022-11-09 11:41:47), "machineB", "False",
  datetime(2022-11-09 11:41:57), "machineB", "True",
  datetime(2022-11-09 11:41:59), "machineB", "True",
  datetime(2022-11-09 11:42:25), "machineC", "True",
  datetime(2022-11-09 11:42:30), "machineC", "True",
  datetime(2022-11-09 11:42:35), "machineC", "False",
  datetime(2022-11-09 11:42:36), "machineC", "False",
  datetime(2022-11-09 11:43:03), "machineC", "True",
  datetime(2022-11-09 11:43:03), "machineC", "True",
  datetime(2022-11-09 11:43:04), "machineC", "True",
  datetime(2022-11-09 11:43:05), "machineC", "True",
  datetime(2022-11-09 11:43:25), "machineC", "False",
  datetime(2022-11-09 11:43:25), "machineC", "False",
  datetime(2022-11-09 11:43:26), "machineC", "False",
  datetime(2022-11-09 11:43:27), "machineC", "False",
  datetime(2022-11-09 11:43:37), "machineC", "True",
  datetime(2022-11-09 11:43:47), "machineC", "False",
  datetime(2022-11-09 11:43:57), "machineC", "False",
  datetime(2022-11-09 11:43:59), "machineC", "False",
];
let tiemposCicloBruto = test
    | where Timestamp > ago(100d)
    | partition hint.strategy=native by Id
    (
        order by Timestamp asc // ordenamos ascendentemente
        | extend prev_Timestamp = prev(Timestamp) // extendemos la fecha previa
        | extend prev_Value = prev(Value) // extendemos el valor previo
        | extend duration = 
        iif ( // Condicion ternaria
            prev_Value == "True" and Value == "False" // Si anteriormente estaba en funcion y el valor actual es parado, cuenta como tiempo de ciclo
            or prev_Value == "True" and Value == "True", // Si el valor anterior era funcionando y el actual tambien, la maquina sigue funcionando
            Timestamp - prev_Timestamp, // Para ese caso restamos la diferencia de tiempo
            time(null) // Para el caso contrario, devolvemos nulo
        )
        | project Id, Timestamp, duration, Value, prev_Value
    );
tiemposCicloBruto // La consulta para 1d completo tarda entre 1-1.5s
| where isnotnull(duration)
| partition hint.strategy=native by Id ( // partimos por Id
    order by Timestamp asc // debe ser siempre ascendente si no pierde la logica
    | scan declare (y:timespan=time(null), x:timespan=time(null)) with ( // declaramos el scan
        step s1: true => // declaramos el paso
        x=iif (s1.Value == "True" and Value == "True", iif (isnull(s1.x), duration, s1.x)+s1.duration, time(null)), // si tenemos varios True-True consecutivos, sumamos la duracion anterior a la actual, asignandola a X
        y=iif (s1.Value= = "False" and Value= = "False", duration, // si tenemos el caso de que es False-False, partimos de la duracion
                iif (s1.Value= = "True" and Value= = "False", s1.x+duration, time(null))); // si tenemos que la maquina estaba funcionando y para, sumamos las duraciones consecutivas de mientras que estaba funcionando
    )
    | extend next_Id=next(Id)
    | extend tiempoCiclo=iif (isempty(next_Id), duration, iif (isnull(y) and prev_Value == "True" and Value= = "False", duration+prev(duration), iif (isnotnull(y), y, time(null)))) / 1s // y para aquellos cambios de maquina o para aquellos donde no hubiera valor por casuistica, asignamos la duracion o la duracion+duracion previa
    | where isnotnull(tiempoCiclo) // filtramos
    | project-away prev_Value, x, y, duration, Value, next_Id
)

Но я не вижу эти группы машин на моем графике временных рядов KQL Grafana:

По крайней мере, он должен показывать столько же, сколько машин в моей среде:

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
85
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как правило, я обнаружил, что Grafana ожидает, что несколько рядов будут отдельными столбцами, а не одним столбцом дискриминатора. Одним из вариантов может быть использование плагина pivot.

Добавление

| evaluate pivot(Id, max(tiempoCiclo))

в конец вашего запроса дает следующий набор данных:

что приводит к следующему графику grafana:

Я не соглашусь, это не причина проблемы здесь. Более того, я обнаружил, что подход со столбцом дискриминатора гораздо более распространен, потому что таким образом проще писать запросы, и Grafana может выполнять поворот самостоятельно.

greatvovan 30.11.2022 07:34

@greatvovan: Ну, мой опыт отличается. Я согласен, что столбец дискриминатора был бы лучше, но для меня это всегда случайность с графаной. Иногда это работает, иногда нет. Выделенные колонки работают всегда

ChrisWue 02.12.2022 01:28

ChrisWue не могли бы вы показать пример, когда по документации это не работает? Я создам ошибку в Grafana.

greatvovan 02.12.2022 19:20

Ответ содержится в вашем вопросе:

Обнаружены длинные отформатированные временные ряды, но не удалось преобразовать из длинного кадра: для преобразования длинные ряды должны быть отсортированы по возрастанию по времени.

Вам нужно добавить сортировку в конце вашего запроса. Это так просто.

...
| order by Timestamp asc

Также не забудьте выбрать «Временные ряды» в раскрывающемся списке «Форматировать как».

Другие вопросы по теме