Об этом проекте
vitals — это системный монитор для Mac с Apple Silicon под управлением macOS 14 или более поздних версий. Один бинарный файл на Rust собирает данные о CPU, GPU, памяти, питании и тепловом состоянии непосредственно в процессе: он не вызывает powermetrics, не требует sudo и не запускает никаких подпроцессов. Вывод представляет собой структурированный JSON, который могут считывать скрипты, агенты или пользователи. Тот же бинарный файл, запущенный без аргументов, работает как элемент меню-бара с опциональным локальным дашбордом.
Командные глаголы
snapshot выводит один полный сэмпл SoC: количество чипов и ядер хоста, общую загрузку CPU, данные по каждому ядру с указанием типа (эффективное или производительное), частоту и загрузку, загрузку и частоту GPU, общие объемы и использование памяти и swap, давление на память ядра, показатели питания для CPU, GPU, ANE, RAM и системы, температуру CPU и GPU, скорость вентиляторов с максимумами, среднюю нагрузку (load average), время работы (uptime) и тепловое состояние. Опция интервала изменяет окно выборки, по которому интегрируются показатели CPU, GPU и энергопотребления.
top ранжирует процессы по CPU и по памяти независимо и с настраиваемым количеством строк, поэтому один и тот же процесс может появиться в обоих списках. Процент CPU считается на процесс, а не на всю систему, и может превышать 100% при многопоточной работе, как в ps.
pressure возвращает вердикт вместо необработанных чисел: состояние, флаг наличия доступной истории, список причин с кодами и степенью серьезности, список подозрительных процессов с указанием причины их пометки и однострочное резюме. По определению, программа завершается с кодом 0 при сообщении о плохом состоянии, так как само сообщение не является ошибкой. Флаг кода выхода переносит серьезность вердикта в статус (0 — номинал, 3 — предупреждение, 4 — критическое), в то время как сбой выполнения возвращает 1, а некорректный вызов — 2.
watch — единственный глагол, который не завершается самостоятельно. Он выводит один компактный JSON-объект на строку, сбрасывая буфер после каждой строки, и работает до прерывания или до вывода запрошенного количества сэмплов. Интервал задает как частоту, так и окно выборки. Поскольку вывод сбрасывается построчно, потребитель, который считывает одну строку и закрывает конвейер, получает корректное завершение. Вывод всегда представляет собой JSON с разделителем в виде новой строки и отклоняет флаг JSON.
JSON является форматом по умолчанию для snapshot, top и pressure; каждый из них также поддерживает человекочитаемый текстовый формат для терминалов, а флаг JSON в этом случае игнорируется. Каждый ответ содержит версию схемы. Единицы измерения указаны в именах ключей (память в МБ, питание в ваттах, температура в градусах Цельсия), а отсутствующие опциональные поля опускаются, а не выводятся как null.
Приложение в меню-баре и дашборд
Запущенный без аргументов, vitals работает как иконка в меню-баре с живым текстом и кастомным выпадающим списком, охватывающим CPU (спарклайн плюс одна полоса на ядро, эффективные и производительные ядра окрашены по-разному), GPU, память (оцениваемую по сигналу давления ядра) и питание. Главные значения меняют цвет при достижении порогов, перерисовка не происходит, пока список закрыт, а частота опроса снижается, когда дисплей находится в спящем режиме.
Приложение объявляет себя аксессуаром, поэтому у него нет иконки в Dock и записи в переключателе приложений, пока не будет запрошено окно. Дашборд можно открыть из выпадающего списка или повторным запуском работающего приложения; он открывается в нативном окне на базе web view как отдельный процесс. Пока он открыт, у него есть плитка в Dock и меню приложения; при закрытии этот процесс завершается, что сводит затраты ресурсов закрытого дашборда к нулю. Если трей завершает работу или аварийно завершается, окно замечает это через отслеживание файлового дескриптора и оперативно закрывается. HTTP-сервер работает внутри процесса трея и запускается по требованию, поэтому трей, у которого никогда не запрашивали дашборд, не имеет слушателя и второго сэмплера.
Страница дашборда построена для чтения сверху вниз: тот же вердикт, что выдает глагол pressure, четыре плитки для CPU, GPU, памяти и питания с главным показателем, индикатором статуса, контекстной строкой и трендом, переключатель диапазона (2, 5 или 15 минут), который определяет область действия всего, что находится ниже, графики CPU и GPU во времени с перекрестием и подсказками, одна полоса на ядро с подписью позиции и тактовой частотой при наведении, измерители памяти и swap, заполнение которых следует за сигналом давления ядра, и список топовых процессов с встроенными полосами. Каждый график имеет переключатель «график или таблица» для тех же данных, опрос прекращается, когда страница скрыта, последний успешный рендер остается на экране в приглушенном виде, если сервер исчез, а светлая или темная тема следует за системной.
Установка и упаковка
Существует два независимых пути установки, результатом которых становится наличие vitals в PATH. Сборка с последующей установкой создает симлинк на релизный бинарный файл в директории bin префикса (префикс можно переопределить, чтобы избежать sudo, а цель uninstall удаляет симлинк). Путь установки приложения собирает, упаковывает и копирует приложение в папку Applications, устанавливает пользовательского launch-агента для автозапуска трея при каждом входе в систему и перенаправляет тот же симлинк на копию в бандле; соответствующая цель uninstall отменяет все эти действия. Бандл подписан ad-hoc, а не нотариально заверен, чего достаточно для выполнения launch-агента; открытие приложения через Finder может потребовать однократного открытия через правый клик или одобрения в Системных настройках.
Разработка
Для сборки, тестирования, проверки clippy (с предупреждениями как ошибками) и форматирования существуют make-цели. Дашборд представляет собой приложение на Vite и React, чей результат production-сборки встраивается в бинарный файл во время компиляции, поэтому после изменений на странице бинарный файл необходимо пересобрать. Dev-сервер с горячей перезагрузкой проксирует API-запросы на локальный порт, поэтому он работает с любым запущенным экземпляром, включая тот, что находится в трее.
Вклад в проект осуществляется через отчеты об ошибках, измерения и pull-реквесты, с отдельным каналом для уязвимостей. Проект распространяется под лицензией MIT.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.