Как стать автором
Обновить

Grafana, InfluxDB, два тега и одна сумма. Или как посчитать сумму подгрупп?

Время на прочтение 12 мин
Количество просмотров 32K
Всего голосов 24: ↑24 и ↓0 +24
Комментарии 11

Комментарии 11

Я тоже занимаюсь тестированием производительности и тоже использую jMeter + TICK stack.
Есть такая проблема, в конфигурации Telegraf есть глобальный тег ip с адресом машины на котором запущен Telegraf, и в графане хочу рядом hostname показывать этот ip. Может и вы сталкивались с этим?
Пока не сталкивался. Но если задача — вывод hostname и ip в наименовании серии, то можно сделать группировку метрик по двум тегам сразу:

USE telegraf;
SELECT mean("usage")
FROM "cpu"
WHERE
    hostname =~ /^${hostname:regex}$/ AND
    $timeFilter
GROUP BY
    "hostname", "ip", time($granularity)

А в поле ALIAS BY написать:
$tag_hostname ($tag_ip) mean cpu


Это как в самом первом запросе статьи в разделе «Как всё начиналось», только теги называться будут не Type и name, а hostname и ip.

Чтобы вывести в ALIAS BY переменную, можно использовать $tag_{Имя тега} (только такого тега, по которому есть группировка) или $col — имя поля. И ради вывода значения тега в подписи к серии, просто добавляем группировку значений по этому тегу: hostname, а если по два тега нужно вывести, то группируем по двум тегам: hostname и ip.

Верно понял задачу? Или нужно выводить ip в другом месте: в выпадающем списке, таблице?

Спасибо за ответ. Мне нужно вывести ip в дропдауне серверов дешборда (в переменных дешборда есть переменная server).

Понял — задача со звёздочкой.
Вариант 1
Вывести в выпадающем списке комбинацию hostname (ip), и по выбранным значениям успешно фильтровать метрики по полям hostname или ip.


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


Чтобы выражение вида


performanceAgent (10.11.100.111)*

применилось к списку серверов:


performanceAgent
databaseServer
applicationServer
moniringServer

И оставался только один результат: performanceAgent


Да, такое можно попробовать сделать. Ещё не пробовал.


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


Документация на такой способ есть в самом интерфейсе Grafana:



Specify an URL (relative or absolute)
Use special variables to specify cell values:
${__cell} refers to current cell value
${__cell_n} refers to Nth column value in current row. Column indexes are started from 0. For instance,
${__cell_1} refers to second column's value.
${__cell:raw} syntax. By default values are URI encoded. If the value is a complete URL you can disable all encoding using


Пример такой фильтрации подготовил в докладе для Heisenbug, конференцию пока перенесли. Если достаточно одного слайда, то он такой:

Конкретно для случая server, ip пример можно подготовить, но позже.

Вариант 3 (не рабочий)
Посмотрел ещё на постпроцессоры telegraf, среди них не нашел такого, который бы ещё на этапе записи метрик в InfluxDB объединил бы hostname и ip_address в одно поле.


Вот все постпроцессоры:
https://github.com/influxdata/telegraf#processor-plugins


Вариант 4 (рабочий)
Но есть вариант решения, через переменные окружения и небольшое изменение в файле конфигурации telegraf.conf. Решение в обход, ещё один пример ненормального программирования с InfluxDB.


Можно:


  • периодически обновлять переменную окружения hostname_with_ip: export hostname_with_ip="hostname(hostname -I | awk '{print $1}')"
  • в файле telegraf.conf настроить сохранение переменной окружения hostname_with_ip в тег hostname_with_ip:
  • фильтровать метрики по готовому тегу

Можно сделать так:


# Global tags can be specified here in key="value" format.
[global_tags]
  # dc = "us-east-1" # will tag all metrics with dc=us-east-1
  # rack = "1a"
  ## Environment variables can be used as tags, and throughout the config file
  # user = "$USER"
  hostname_with_ip = "$hostname_with_ip"

[[inputs.exec]]
  commands = ["sh /opt/telegraf_update_hostname_with_ip.sh"]
  timeout = "60s"
  data_format = "influx"

Можно выполнение export hostname_with_ip="hostname(hostname -I | awk '{print $1}')" поместить куда-нибудь в /etc/profile.d/telegraf_update_hostname_with_ip.sh
тогда не надо будет делать секцию [[inputs.exec]]


И просто фильтруем по готовой переменной.

В influx уже давно завезли вложенные query. Вы можете сделать так:


select a+b from (select ... as a from ..; select ... as b from ..) group by time(1m).

В многоточии — ваши обычные запросы.

Да, подзапросы есть. Да, за счёт подзапросов можно преобразовать теги в поля. Но у hostname и ip тип — String, а операция + не работает для строк в InfluxDB.

В комментарии выше всё же описал Вариант 1. Там предположил, что подобная конструкция будет работать. Позже прочел ваш amarao комментарий, про сложение, и понял, что Вариант 1 не получится реализовать. Строки не комбинируются в InfluxDB 1.7, в InfluxDB 2.0, возможно комбинируются.

Про $granularity не очень понятно. Это переменная dashboard-ы со списком, чтобы вручную выбирать интервал группировки? А чем не подходит GROUP BY ($__interval)?

Хороший вопрос, спасибо.


Да, $granularity — список констант, с интервалом времени.


Сделан для ускорения отображения большого количества графиков, чтобы показать меньше точек. Чтобы можно было задать группировку по минутам, и получить на графике 100 точек вместо 1900 точек (при ширине монитора 1980 точек).


Также для отладки неудачных запросов. И для возможности предсказания ожидаемого количества точек => для наличия критериев соответствия результата запроса настройкам.


Причина — не самое производительное оборудование для станций мониторинга.


И для обратной ситуации, чтобы иногда показать больше точек, чем поддерживает монитор. Показать на отдельном графике три месяца, но с группировкой по минутам. Это используется, чтобы найти на графике отдельный кратковременный запуск теста. Или метрики по отдельному процессу, который фиксировался однажды в момент тестирования, ссылки на временной интервал не сохранилось, и теперь надо его визуально найти. Представьте, что вы выполняли когда-то в этом году тестирование длительностью 30 минут, и вот сейчас отображаете последние 6 месяцев на графике. В этом случае для разрешения 1900 точек получается, что в каждой точке будет 6×30×24×60÷1900=136,42 минут, примерно с такой группировкой выполнится запрос при настройке auto. А если все метрики собирались всего 30 минут, и на графике отображается одна точка, то точку не видно. Некоторые графики для отображения нуждаются в двух точках, и при группировке превышающей весь набор сбора метрик вообще график не получить. Например, функции NON_NEGATIVE_DERIVATIVE(), DERIVATIVE(), NON_NEGATIVE_DIFFERENCE(), DIFFERENCE(),… в таком случае не вернут числовой результат им нужно две точки минимум.


Причина почему из 6 месяцев сбора метрик бывает нужно найти только интервал в 30 минут — нерегулярные запуски тестов, нерегулярный сбор метрик из-за переключений между проектами. Стенд может собраться, тесты будут выполнены (30 минут). А следующий запуск тестов, через недели три, а может через месяц.


Кстати эту проблему уже решил, на связке Grafana + InfluxDB можно сделать ссылки на конкретные участки временного ряда, и кликом по гиперссылке получить нужный интервал времени. Это интересная и полезная задача. Расскажу скоро и о ней.


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


Если отдавать разработанную доску во внешний мир, то можно в $granularity оставить одно значение = auto, а саму переменную скрыть. Тогда у пользователей всегда будет одно значение, основанное на количестве пикселей в графике. Но пока идёт разработка, параметр $granularity полезен с разными значениями.


The $__interval Variable


Цитата
The $__interval is calculated using the time range and the width of the graph (the number of pixels).

Approximate Calculation: (from - to) / resolution

For example, when the time range is 1 hour and the graph is full screen, then the interval might be calculated to 2m — points are grouped in 2 minute intervals. If the time range is 6 months and the graph is full screen, then the interval might be 1d (1 day) — points are grouped by day.

Спасибо за развёрнутый ответ! У меня опыт с Prometheus и я как-то предположил, что тамошние операции с указанием интервала это примерно тоже самое что и GROUP BY ($__interval) в Influx. Там есть семейство операций *_over_time и вот они как раз умеют работать с $__interval с учётом данных во всех промежуточных точках, которые есть в базе.


Чтобы не пропустить редкие случаи проблем и при этом не запрашивать много точек, помогают min_over_time/max_over_time/count_over_time, но можно пойти дальше и сократить количество запрашиваемых точек, т.к. важен только факт присутствия какого-то статуса в промежутке времени. Собственно так и появился плагин grafana-statusmap, с ним количество запрашиваемых точек выходит меньше, чем для $__interval, но при этом всё равно можно видеть редкие проблемы. Т.е. в вашем случае на доске с тестами я бы сделал отдельный график «Запуск тестов» или «Статус тестов» с этим плагином и показывал бы на нём наличие метрик по тестам или метрику успешности тестов. При этом на графиках с DERIVATIVE() может быть пусто, но в «Статус тестов» будут квадратики — значит в то время был неуспешный тест, значит можно уточнить time range, $__interval уменьшиться и на графиках что-то появится.
Если есть желание попробовать, можно в личке обсудить, я бы потом утащил в README как пример использования для influx.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий