Как написать мониторинг?

время 7 МИН
звезда звезда звезда СРЕДНЕ
Мониторинг
Домашний хостинг

Сегодня поговорим про мониторинг, зачем он нужен и зачем вообще писать свой🙂

Что такое мониторинг? Для того чтобы не было внезапных слез клиента по поводу неработающего сайта, важно иметь мониторинг систермых ресурсов. С помощть него можно заранее узнать каких ресурсов начинает не хватать чтобы их добавить. Так например если видно что CPU молотит под 100% - пора менять процесор на более мощный или добавлять еще один сервер и перераспределять между ними нагрузку, а если не осталось свободной оперативки - ну тут тоже самое, надо просто добавить оперативки. И как можно догадаться с жесткими дисками та же история, у них правда может не хватать как объема так и скорости работы, при нехватке скорости если у вас HDD - можно заменить на SSD. Вот как то так. От всех слез клиента это конено не избавит, ведь еще бывают и проблемы с Интернетом и DDoS атаки на сервер, но эти проблемы проходящие и решаемые по другому. На этом вводная часть закончился и начинаем хардкор.

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

Подумал, что минимальный и достаточный мониторинг можно написать и самому. Задача виделась несложной, на пару недель максимум. Начал, естественно, с описания требований.

Требования

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

- раз в секунду собирать интересующие параметры и результат измерений записывать в файл;

- формат файла должен быть простым и компактным, чтоб не занимать много места на диске;

- отображение графиков как в реальном времени, так и исторических;

- агрегация данных (поиск среднего, медианы и различных перцентилей за интересующие промежутки времени - минуту, час, день, неделю, месяц и т.д.);

- минимальное потребление ресурсов компьютера как для сбора, так и при генерации отчетов;

Проектируем базу данных

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

Раз решили, что минимальный интервал измерения равен одной секунде, значит для хранения времени можно использовать unix time stamp (это количество секунд с 1 января 1970 года в UTC). С тех пор уже натикало 1688397914 секунд или 0x64A2E85A в шестнадцатеричном формате, как нетрудно заметить 4 байта требуется для записи каждого измерения плюс минимум 1 байт для значения, итого минимум 5 байт должно хватить и для загрузки процессора в процентах и для температуры. Но может понадобится и больше, например, если захотим измерить трафик или размер свободной памяти, там значения могут доходить и до терабайт, а это уже надо минимум 5 байт на измерение, так одна запись может быть 9 байт. Давайте прикинем сколько данных наберется за год. Например, у ЦП 4 ядра, на каждое ядро по измерению по процент загрузки и еще 4 по частоте процессора, штук 5 датчиков температур (несколько на процессоре и на диске) итого 13 параметров. В сутках 86400 секунд, а значит 86400сек x 13параметров x 5байт x 365 дней = 2049840000 байт или 2Гигабайта данных в год. Если еще агрегацию хранить в отдельных файлах, то и еще больше.

Давайте попробуем сэкономить. Для начала не будем хранить unix time stamp, раз уж решили в файл писать каждую секунду то можно писать только значения измерений, а по смещению измерения от начала файла можно найти время в секундах, когда оно было сделано. Далее при желании можно и значения изменяемые в широких пределах сократить до 1 байта, по сути хранить процент свободного места, но не в 100% шкале, а в 255 для большей точности и чтоб байт даром не пропадал. Ну то есть 255 это 100%, 128 - 50% и т.д. А проценты можно перевести и в абсолютные величины, понятно, что точность будет хромать, но порядок значений будет понятен, иногда этого достаточно. Итого, нам на любое измерение будет достаточно байта! Если 2 Гбайта было из расчета 5 байт на измерение, то при 1 байте на измерение будет 400 Мегабайт в год, весьма неплохая экономия.

Далее подумаем, как будем отображать графики. Хочется, чтоб в браузере и чтоб обновлялись каждую секунду, прям как в мониторе ресурсов, только на удаленной машине. Допустим, на графике помещается 100 значений, значит при открытии графика надо отобразить последние 100 значений из файла, и дальше каждую секунду запрашивать не появились ли новые данные и, если появились, добавлять на график и сдвинуть его влево. Хочется все это реализовать бережно для сервера, чтоб минимально потребляло ресурсов, а самое бережное - это раздача статики каким-нибудь HTTP-сервером, можно взять Apache или Nginx. Oстановился на последнем, он современнее и лучше держит нагрузку, пусть и не наш случай, но на сервере будут и другие сервисы, так что выбор оправдан. Осталось понять, как заставить его отдавать только нужные данные, а не все файлы целиком, так и сеть можно приложить и клиента перегрузить, а нам такого не надо. В HTTP протоколе есть возможность запрашивать кусок файла, передав диапазон смещения от начала файла (Range запрос) и Nginx такое умеет из коробки, что не может не радовать.

А что с агрегацией? Сначала думал возложить это на клиента, ну чтоб брал исходные данные и сам себе все что надо вычислял, но, как сказано выше, данных может быть довольно много, а сеть ложить не хочется. Да и быстрее все необходимые агрегации просчитать заранее, благо исторические данные не меняются, просчитал раз, записал на диск и так же раздавай статикой. Так что все же мониторингу придется уметь делать агрегацию и делать ее как можно раньше, но при этом все так же бережно к ресурсам, скажем, если берем минутные интервалы, как прошла очередная минута уже можно агрегировать за эту минуту и записывать значение, аналогично для часа, дня и всего остального. Сначала думал сэкономить и данные за час агрегировать на уже агрегированных минутных данных, но с точки зрения математики вроде не одно и тоже, и придется делать по честному каждый раз брать в расчет секундные данные.

Выбираем технологический стек

Самым экономичным по ресурсам видится C или C++, но надо будет еще библиотеки затащить, которые умеют измерять температуру и прочее. Однако, привыкший к Java и NodeJS хотелось иметь пакетный менеджер. Подумалось тогда про Go или Rust. Оба современные языка, но в итоге выбор пал на Rust, там и удобная установки и пакетный менеджер и все необходимые для мониторинга библиотеки, так же подкупила его система управления памятью, что и не надо самому освобождать как в C++ и при этом без таких накладных расходов как в Java, и еще то, что они позиционируются как zero-cost abstraction и даже есть поддержка embedded систем.

Для графики чистый JavaScript и библиотека d3js, чтоб минимально и достаточно, фреймворки в виде VueJS решил не тащить, ну чего по воробьям из пушки то.

Что вышло

Собирал на Debian 12, бинарный файл вышел 4.5 Мегабайт При запуске: Потребление CPU в пределах 0.3-0.7%; оперативки порядком 1.3 Мегабайт. Агрегацию пока не реализовывал.

Вот так выглядят графики:

Исходники можно взять тут: https://github.com/mekhanikov/hardware-monitoring

Спасибо, что заглянули,
добавляйтесь в Telegram канал и будьте в курсе новинок.
Если Вам было интересно, можете поддержать автора

на главную