Exec плагин
Среди всего разнообразия плагинов в collectd есть один особенный: если из-за какой-нибудь техногенной катастрофы у collectd останется только Exec, то им вполне можно заменить все остальные.
Как следует из названия, Exec запускает стороннее приложение или скрипт и интерпретирует её вывод в качестве данных для себя. Если быть точным, то он ищет строки вроде таких:
1 2 |
PUTVAL myhost/cpu-0/cpu-system interval=10 N:51 PUTVAL hostname/vm_count/gauge 1484012951:U |
Что самое прекрасное, Exec абсолютно по барабану, на каком языке написан скормленный ему скрипт. Хоть на JavaScript. В принципе, в некоторых сценариях использовать JavaScript было бы очень хорошей затеей. Например, когда приходится иметь дело с RESTful сервисом возвращающим JSON.
Но прежде чем мы попробуем скормить collectd данные из JavaScript приложения, стоит присмотреться поближе к формату PUTVAL-строк.
Аргументы для PUTVAL
Формат PUTVAL строк очень многое позаимствовал из rrdtool. Он использует те же типы данных, те же временные метки, даже синтаксис, и тот очень похож. Обобщённый формат выглядит так:
1 |
PUTVAL hostname/source-instance/datatype-instance [Interval=seconds] timestamp:value[:value..] |
Первый аргумент — строка вида hostname/source-instance/datatype-instance , может быть чем угодно, если она однозначно идентифицирует источник данных. -instance-компонент, кстати, опционален. Правда, у datatype есть некоторые ограничения.
datatype задаёт, какого типа данные мы пытаемся скормить collectd, и как он должен их хранить. У rrdtool есть две группы типов: счётчикоподобные (COUNTER и компания), для сохранения не самого значения, а скорости, с которой оно меняется, и обычные, численные (GAUGE), которые сохраняются как есть. PUTVAL понимает эти типы, и мы можем использовать, например, тот же gauge для хранения чисел между 0 и 232.
Кроме них у collectd есть собственные типы, которые он определяет в /usr/share/collectd/types.db . Например, там есть temperature (тот же gauge, но от минус до плюс бесконечности), count (gauge, от нуля до бесконечности), и уйма других. Эти тоже можно использовать, или даже добавить свой.
Вторым аргументом в PUTVAL подаётся interval в секундах. Он опционален и показывает, как часто мы планируем подавать новые значения.
Наконец, в конце идут разделенные двоеточием timestamp и value. timestamp , временная метка, может быть либо юниксовым временем в секундах, либо N в качестве «сейчас». А value — просто число, либо U для «undefined«.
Подаём данные из JavaScript в collectd
Предположим, у нас есть очень полезное JavaScript приложение sensor.js , которое собирает данные мониторинга чего-то (количество пользователей онлайн, например), и мы хотим их передавать в collectd.
1 2 3 4 5 |
const readSensor = () => Math.floor(Math.random() * 1000); const currentReading = readSensor(); console.log(currentReading); // profit? |
С чего начинать?
1. Делаем sensor.js исполняемым
Во-первых, нужно, чтобы скрипт запускался. А чтобы скрипт запускался, ему нужно дать пермишен ‘execute’ (линукс же вокруг), а так же шебанг, чтобы никса знала, как именно его исполнять. chmod +x sensor.js исправит первый недостаток, а node.js в шебанге разберется с запуском:
1 2 3 4 |
#!/usr/local/bin/node const readSensor = () => Math.floor(Math.random() * 1000); ... |
Теперь, если запустить скрипт из шелла, на выход подастся очень полезное число:
1 2 |
$ ./sensor.js # 245 |
Следующем шагом будет офорить эту полезность в формат, понятный collectd.
2. Форматируем вывод для collectd
Для этого нужно собрать PUTVAL строку. Думаю, для начала вполне сойдёт что-то вроде этого:
1 2 3 4 |
... const currentReading = readSensor(); console.log(`PUTVAL hostname/mysensor/gauge N:${currentReading}`); |
Мы используем gauge тип («храни числа как есть») и «сейчас» ( N) в качестве временной метки. Опциональный Interval параметр так и остался опциональным.
Правда, у нас жёстко прошито имя хоста ( hostname/ ), да и данные-то предполагалось подавать регулярно, а не раз в вечность.
Но это можно исправить.
3. Используем имя и интервал прямиком из collectd
Когда collectd запускает скрипт, он так же создаёт две переменные окружения: COLLECTD_HOSTNAME и COLLECTD_INTERVAL, которые мы вполне можем использовать. Ну и так как данные будут подаваться регулярно, Interval параметр всё-таки стоит указывать. Вот, в итоге, что у нас получилось:
1 2 3 4 5 6 7 8 9 10 11 |
#!/usr/local/bin/node const hostname = process.env.COLLECTD_HOSTNAME || 'localhost'; const interval = process.env.COLLECTD_INTERVAL || 15; const readSensor = () => Math.floor(Math.random() * 1000); setInterval(function () { const currentReading = readSensor(); console.log(`PUTVAL ${hostname}/mysensor/gauge Interval=${interval} N:${currentReading}`); }, interval * 1000); |
И если запустить его руками:
1 2 3 4 |
$ ./sensor.js PUTVAL localhost/mysensor/gauge Interval=15 N:942 PUTVAL localhost/mysensor/gauge Interval=15 N:207 .... |
То, что нужно. Но запускать его руками не было частью плана. Будем аутсорсить привилегию в collectd.
4. Подключаем sensor.js к collectd
Это, кстати, очень просто сделать. Раскомментируем строки Exec плагина в файле настроек — /etc/collectd/collectd.conf , и укажем в нём, где лежит sensor.js:
1 2 3 4 |
LoadPlugin exec <Plugin exec> Exec someuser "/home/someuser/sensor.js" </Plugin> |
Кстати, использовать root пользователя в конфигурации Exec нельзя. Он не простит.
4.1 Пробный запуск
Теперь, если мы перезапустим collectd, первым знаком, что всё хорошо, будет отсутствие ошибок со словом ‘exec’ в них:
1 2 3 4 5 6 |
$ service collectd restart #[....] Restarting statistics collection and monitoring daemon: collectdcollectd[5126]: Exiting normally. #... #. ok #collectd[5183]: Initialization complete, entering read-loop. #collectd[5183]: rrdtool plugin: Adjusting "RandomTimeout" to 0.000 seconds. |
Пока хорошо. Правда, отсутствие ошибок не значит, что всё хорошо, так что стоит проверить, сохранил ли collectd хоть что-нибудь. По умолчанию, он хранит все свои данные в RRD файлах по этому адресу /var/lib/collectd/rrd . Если там есть что-то от mysensor (название, которое мы указали в PUTVAL), то это вин:
1 2 3 |
$ ls -R /var/lib/collectd/rrd | grep mysensor #mysensor #/var/lib/collectd/rrd/e6015696c686/mysensor: |
Да, тотальный вин.
Итак
Как оказалось, использовать JavaScript для подачи данных в collectd — очень просто. И кроме «У-у-у, теперь я сделал это и на JavaScript!», существуют и разумные для того причины. В наши суровые времена очень много полезных с точки зрения мониторинга данных берутся из RESTful сервисов в JSON формате. Использовать JavaScript для работы с ними — сам Айк велел.
Я использовал связку JavaScript (node.js) + collectd + Graphite для мониторинга continuous integration серверов и остался очень доволен. GitLab и Google Compute Engine идут в комплекте с прекрасным JSON API, поэтому получать данные о количестве виртуальных машин, билдов и тестируемых веток — одно удовольствие. Всего за несколько часов, включая время на кофе и Гугл, получилась вот такая полезная красота:
Всем привет.
Автору на заметку.
Инструмента очень много и когда в наших руках есть стандартная популярная Ось или хотябы «полу-Ось» задача сводится к личным вкусам 🙂
Я вот недавно столкнулся с задачей мониторить нестандартные коробочки (их есть в моём Зоопарке).
самое простое это всякие фрукты ягоды : Raspberry-PI, Orange-PI итд «ARM» ( Хвала изготовителю ) Малинка и прочие фрукты работают с Debian -Ubuntu. и хоть кактой то софт можно прикрутить. Но вот есть еще «embedded » — коробочки PFsense ( FreeBSD ) а также DD-WRT Open WRT .
вот с них собирать метрики хочется но всегда куча проблем с поиском либо пакета либо зависимостей.
Попался в руки старый PFsense ( FreeBSD ) — хотел я установить Telegraff и отправлять метрики в InfluxDB.
установить не получилось (обновлять памяти и места мало как обычно в этих коробочках).
Вообщем пихать данные в InfluxDB оказалось очень просто 🙂
описание метрик может быть больше и другие ()
главное База и таблица
——- пример ——-
curl -u ‘user:pass’ -i -XPOST ‘http://10.10.1.68:8086/write?db=telegraf’ —data-binary ‘APC,host=LCBO_123,region=Missisauga LINEV=122.0’
curl -u ‘user:pass’ -i -XPOST ‘http://10.10.1.68:8086/write?db=telegraf’ —data-binary ‘APC,host=LCBO_123,region=Missisauga LOADPCT=36.0’
curl -u ‘user:pass’ -i -XPOST ‘http://10.10.1.68:8086/write?db=telegraf’ —data-binary ‘APC,host=LCBO_123,region=Missisauga TIMELEFT=5.1’
curl -u ‘user:pass’ -i -XPOST ‘http://10.10.1.68:8086/write?db=telegraf’ —data-binary ‘APC,host=LCBO_123,region=Missisauga BATTV=26.4’
curl -u ‘user:pass’ -i -XPOST ‘http://10.10.1.68:8086/write?db=telegraf’ —data-binary ‘APC,host=LCBO_123,region=Missisauga TONBATT=0’
curl -u ‘user:pass’ -i -XPOST ‘http://10.10.1.68:8086/write?db=telegraf’ —data-binary ‘APC,host=LCBO_123,region=Missisauga NOMINV=120’
curl -u ‘user:pass’ -i -XPOST ‘http://10.10.1.68:8086/write?db=telegraf’ —data-binary ‘APC,host=LCBO_123,region=Missisauga NOMBATTV=24.0’
———
написал скрипт, и наступило мне счастье 🙂
Grafana рисует графики.