Возникла передо мной такая задача: сделать мониторинг Raspberry PI. И требования:
- самодостаточность. Возможность показывать статус и исторические данные без доступа в интернет;
- работа в Java Embedded compact1 profile. Это всё по следам Java и без 16Gb памяти?.
Анализ требований
Здесь и далее под мониторингом системы я буду понимать сбор time series данных. Например, JVM heap size или количество обработанных сообщений за интервал.
Самодостаточность автоматически означает, что данные надо хранить локально. Отображать их надо в браузере, потому что уже есть вэб-админка для этого. Итак, что мы имеем из современного:
-
InfluxDB. Специальная база для хранения time series данных. Умеет делать аггрегации и data retention. Opensource версия не поддерживает кластеризацию, но для Raspberry PI и не нужно. Проблема с системными требованиями: CPU 2-4 ядра и RAM 2-4 Gb. Не подходит.
- Graphite. Хранит данные в базе данных whisper, который, как уверяется, немного лучше RRD. В зависимостях Python 2.7 и Django. Имеет свой собственный интерфейс, который надо бы ещё интегрировать в существующую админку. Ну можно конечно же взять… Но когда на сервере сплошная Java, стоит ли тащить весь мир Python? Опять же запущенные WSGI процессы будут занимать дополнительную память.
Все остальные варианты найденные на просторах, не подошли либо потому, что надо вручную делать data retention, либо требовательны к ресурсам, либо уж совсем наколеночные.
А что если продолжить мысль про RRD и Java? Получается RRD4J. Эта библиотека на Java, которая полностью поддерживает все операции и возможности оригинального rrdtool. Единственное отличие — это несовместимость баз данных между rrdtool и RRD4J. Но с другой стороны это даже лучше. Базы, созданные оригинальным rrdtool, бинарно несовместимы между различными архитектурами.
Итак, RRD. Он идеально подходит для Raspberry PI:
- файлы баз данных фиксированного размера. Можно легко посчитать размер на диске. Очень удобно для embedded систем, которые надо один раз настроить и забыть;
- один раз открытый файл обновляется через RandomAccessFile. Оригинальный rrdtool каждый раз открывает файл, записывает данные и закрывает файл.
Но и не без проблем.
-
Не совместим с compact1 профайлом. RRD4J написан, похоже, в лихие 2000-е, когда шаблон visitor был очень модным, поэтому базовые классы зависят от org.w3c.*. Оказывается одной из фич оригинального rrdtool была возможность писать в XML вместо бинарного файла. И эту фичу RRD4J гордо скопировал. Решается просто: делается hard fork и удаляется все ненужное. Грязно, но работает.
- Создание графиков. С самой генерацией проблем нет. Графики действительно получаются красивые. Но вот шаблоны создания никуда не годятся. В те же лихие 2000-е, когда RRD был на пике популярности, вполне нормальным считалось добавление команды rrdgraph в crontab и выполнение с периодом в 5 минут. Заставлять генерировать .png графики на Raspberry PI — дело неблагородное. Слишком много ресурсов будет тратиться. А если учесть специфику проекта (вэб-админка, которая используется в лучшем случае раз в год), то видимо нужно придумать более хитрую схему.
RRD4J-js
И тут мне в голову приходит осознание. Мы же в 2017 году! Время, когда у нас есть стандарты на передачу бинарных файлов в браузер и разные мощные javascript библиотеки для рисования графиков. Что если передавать скачивать RRD базу с сервера как есть, вытаскивать из неё данные и рисовать уже какой-нибудь готовой и проверенной временем Javascript библиотекой?
Посидев несколько ночей в попытке понять как писать на Javascript и создать плагин для Jquery (а на нём ещё модно писать?), я создал rrd4j-js.
Суть проекта достаточно проста: скачивать RRD, парсить и передавать данные для отрисовки во flot. А уже плагинами flot добивать нужные стили и интерактив. В итоге, решение оказалось даже лучше, чем стандартные графики rrdgraph:
- по наведению мышки в подсказке можно отображать значение точки в момент времени
- растягивать, сжимать и изменять размер графика в зависимости от разрешения экрана
- форматировать данные в зависимости от типа. Например, с помощью jquery.flot.byte можно форматировать данные в килобайты, мегабайты и гигабайты.
Библиотека получилась достаточно простая. Больше всего времени конечно заняло выяснение конвенций по оформлению кода, созданию классов (sic!) в javascript и попытке поделиться проектом с миром.
Я с самого начала решил сделать самодостаточную библиотеку, которую можно загрузить в npm. После нескольких попыток это сделать, у меня, конечно же, всё получилось. Но тут же выяснилось, что npm используется только для server-side разработки на nodejs. И нельзя просто так зарелизить библиотеку в правильный репозиторий. Да что тут стесняться: нельзя понять какой из репозиториев правильный. В итоге я остановился на npm. Может кто-нибудь сведущий подскажет как правильно?
Послесловие
С получившимся инструментом, уже можно было начинать творить. А именно периодически сохранять метрики в RRD4J. Обвязка в виде достаточно распространённых metrics работающая в compact1 — приятное дополнение. В итоге пришлось написать достаточно простой RRD4JReporter, который расширяет com.codahale.metrics.ScheduledReporter и пользоваться в удовольствие.
Автор: dernasherbrezon