Ну и хочу сделать так: 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:
По крайней мере, он должен показывать столько же, сколько машин в моей среде:
Как правило, я обнаружил, что Grafana ожидает, что несколько рядов будут отдельными столбцами, а не одним столбцом дискриминатора. Одним из вариантов может быть использование плагина pivot.
Добавление
| evaluate pivot(Id, max(tiempoCiclo))
в конец вашего запроса дает следующий набор данных:
что приводит к следующему графику grafana:
@greatvovan: Ну, мой опыт отличается. Я согласен, что столбец дискриминатора был бы лучше, но для меня это всегда случайность с графаной. Иногда это работает, иногда нет. Выделенные колонки работают всегда
ChrisWue не могли бы вы показать пример, когда по документации это не работает? Я создам ошибку в Grafana.
Ответ содержится в вашем вопросе:
Обнаружены длинные отформатированные временные ряды, но не удалось преобразовать из длинного кадра: для преобразования длинные ряды должны быть отсортированы по возрастанию по времени.
Вам нужно добавить сортировку в конце вашего запроса. Это так просто.
...
| order by Timestamp asc
Также не забудьте выбрать «Временные ряды» в раскрывающемся списке «Форматировать как».
Я не соглашусь, это не причина проблемы здесь. Более того, я обнаружил, что подход со столбцом дискриминатора гораздо более распространен, потому что таким образом проще писать запросы, и Grafana может выполнять поворот самостоятельно.