//! \~\file pisystemmonitor.h
//! \~\ingroup Application
//! \brief
//! \~english System resources monitoring
//! \~russian Мониторинг ресурсов системы
/*
PIP - Platform Independent Primitives
Process resource monitor
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see .
*/
#ifndef PISYSTEMMONITOR_H
#define PISYSTEMMONITOR_H
#include "pifile.h"
#include "pithread.h"
//! \~\ingroup Application
//! \~\brief
//! \~english Process and thread resource monitoring.
//! \~russian Мониторинг ресурсов процесса и его потоков.
//! \details
//! \~english This module provides process and system resource monitoring capabilities including CPU usage, memory consumption, and thread
//! statistics. It supports cross-platform monitoring on Linux, Windows, macOS, and ESP platforms.
//! \~russian Этот модуль предоставляет возможности мониторинга ресурсов процессов и системы, включая использование CPU, потребление памяти
//! и статистику потоков. Поддерживается кроссплатформенный мониторинг на Linux, Windows, macOS и ESP платформах.
class PIP_EXPORT PISystemMonitor: public PIThread {
PIOBJECT_SUBCLASS(PISystemMonitor, PIThread);
friend class PIIntrospectionServer;
public:
//! \~english Constructs unassigned %PISystemMonitor.
//! \~russian Создает непривязанный %PISystemMonitor.
PISystemMonitor();
//! \~english Stops monitoring and detaches from the current process target.
//! \~russian Останавливает мониторинг и отсоединяет объект от текущей цели.
~PISystemMonitor();
#pragma pack(push, 1)
//! \~\ingroup Application
//! \~\brief
//! \~english Process statistics (fixed-size fields).
//! \~russian Статистика процесса (фиксированные поля).
struct PIP_EXPORT ProcessStatsFixed {
//! \~english PID
//! \~russian PID
int ID = 0;
//! \~english Parent PID
//! \~russian PID родителя
int parent_ID = 0;
//! \~english Group ID
//! \~russian ID группы
int group_ID = 0;
//! \~english Session ID
//! \~russian ID сессии
int session_ID = 0;
//! \~english Priority
//! \~russian Приоритет
int priority = 0;
//! \~english Threads count
//! \~russian Количество потоков
int threads = 0;
//! \~english Physical memory in bytes
//! \~russian Физическая память в байтах
ullong physical_memsize = 0;
//! \~english Resident memory in bytes
//! \~russian Резидентная память в байтах
ullong resident_memsize = 0;
//! \~english Share memory in bytes
//! \~russian Разделяемая память в байтах
ullong share_memsize = 0;
//! \~english Virtual memory in bytes
//! \~russian Виртуальная память в байтах
ullong virtual_memsize = 0;
//! \~english Data memory in bytes
//! \~russian Память данных в байтах
ullong data_memsize = 0;
//! \~english Total RAM in bytes.
//! \~russian Общий объем RAM в байтах.
ullong ram_total = 0;
//! \~english Free RAM in bytes.
//! \~russian Свободный объем RAM в байтах.
ullong ram_free = 0;
//! \~english Used RAM in bytes.
//! \~russian Используемый объем RAM в байтах.
ullong ram_used = 0;
//! \~english CPU load in kernel space
//! \~russian Загрузка CPU в пространстве ядра
float cpu_load_system = 0.f;
//! \~english CPU load in user space
//! \~russian Загрузка CPU в пространстве пользователя
float cpu_load_user = 0.f;
};
//! \~\ingroup Application
//! \~\brief
//! \~english Thread statistics (fixed-size fields).
//! \~russian Статистика потока (фиксированные поля).
struct PIP_EXPORT ThreadStatsFixed {
//! \~english TID
//! \~russian TID
llong id = 0;
//! \~english Overall live time
//! \~russian Полное время жизни
PISystemTime work_time;
//! \~english Busy time in kernel space
//! \~russian Время работы в пространстве ядра
PISystemTime kernel_time;
//! \~english Busy time in user space
//! \~russian Время работы в пространстве пользователя
PISystemTime user_time;
//! \~english CPU load in kernel space
//! \~russian Загрузка CPU в пространстве ядра
float cpu_load_kernel = -1.f;
//! \~english CPU load in user space
//! \~russian Загрузка CPU в пространстве пользователя
float cpu_load_user = -1.f;
//! \~english Date and time of creation
//! \~russian Дата и время создания
PIDateTime created;
};
#pragma pack(pop)
//! \~\ingroup Application
//! \~\brief
//! \~english Process statistics.
//! \~russian Статистика процесса.
struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
//! \~english Fills human-readable memory size fields.
//! \~russian Заполняет поля с человекочитаемыми размерами памяти.
void makeStrings();
//! \~english Execution command
//! \~russian Команда запуска
PIString exec_name;
//! \~english State
//! \~russian Состояние
PIString state;
//! \~english Human-readable physical memory
//! \~russian Физическая память в читаемом виде
PIString physical_memsize_readable;
//! \~english Human-readable resident memory
//! \~russian Резидентная память в читаемом виде
PIString resident_memsize_readable;
//! \~english Human-readable share memory
//! \~russian Разделяемая память в читаемом виде
PIString share_memsize_readable;
//! \~english Human-readable virtual memory
//! \~russian Виртуальная память в читаемом виде
PIString virtual_memsize_readable;
//! \~english Human-readable data memory
//! \~russian Память данных в читаемом виде
PIString data_memsize_readable;
};
//! \~\ingroup Application
//! \~\brief
//! \~english Thread statistics.
//! \~russian Статистика потока.
struct PIP_EXPORT ThreadStats: ThreadStatsFixed {
//! \~english Name
//! \~russian Имя
PIString name;
};
#ifndef MICRO_PIP
//! \~english Starts monitoring the process with PID "pID" using the given update interval.
//! \~russian Запускает мониторинг процесса с PID "pID" с указанным интервалом обновления.
bool startOnProcess(int pID, PISystemTime interval = PISystemTime::fromSeconds(1.));
#endif
//! \~english Starts monitoring the current application process.
//! \~russian Запускает мониторинг текущего процесса приложения.
bool startOnSelf(PISystemTime interval = PISystemTime::fromSeconds(1.));
//! \~english Stops monitoring.
//! \~russian Останавливает мониторинг.
void stop();
//! \~english Returns PID of the monitored process.
//! \~russian Возвращает PID наблюдаемого процесса.
int pID() const { return pID_; }
//! \~english Returns latest process statistics snapshot.
//! \~russian Возвращает последний снимок статистики процесса.
ProcessStats statistic() const;
//! \~english Returns latest per-thread statistics snapshot.
//! \~russian Возвращает последний снимок статистики по потокам.
PIVector threadsStatistic() const;
//! \~english Replaces current process statistics with external data.
//! \~russian Заменяет текущую статистику процесса внешними данными.
void setStatistic(const ProcessStats & s);
//! \~english Returns total RAM in bytes on supported platforms.
//! \~russian Возвращает общий объем RAM в байтах на поддерживаемых платформах.
static ullong totalRAM();
//! \~english Returns free RAM in bytes on supported platforms.
//! \~russian Возвращает свободный объем RAM в байтах на поддерживаемых платформах.
static ullong freeRAM();
//! \~english Returns used RAM in bytes on supported platforms.
//! \~russian Возвращает используемый объем RAM в байтах на поддерживаемых платформах.
static ullong usedRAM();
//! \~\events
//! \~\{
//! \~\fn void measured()
//! \~english Raised after a new statistics snapshot is measured.
//! \~russian Вызывается после измерения нового снимка статисти
EVENT(measured);
//! \~\}
private:
void run() override;
void gatherThread(llong id);
float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old);
ProcessStats stat;
PIVector cur_ts;
PIMap last_tm, cur_tm;
PIMap tbid;
mutable PIMutex stat_mutex;
int pID_, page_size, cpu_count, cycle;
#ifndef MICRO_PIP
PRIVATE_DECLARATION(PIP_EXPORT)
#endif
class PIP_EXPORT Pool {
friend class PISystemMonitor;
public:
static Pool * instance();
PISystemMonitor * getByPID(int pID);
private:
void add(PISystemMonitor * sm);
void remove(PISystemMonitor * sm);
PIMap sysmons;
PIMutex mutex;
};
};
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator<<(PICout s, const PISystemMonitor::ThreadStats & v) {
s.saveAndSetControls(0);
s << "ThreadInfo(\"" << v.name << "\", created " << v.created << ", work " << v.work_time.toMilliseconds() << " ms"
<< ", kernel " << v.kernel_time.toMilliseconds() << " ms"
<< ", user " << v.user_time.toMilliseconds() << " ms"
<< ")\n";
s.restoreControls();
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PISystemMonitor::ProcessStats) {
s << PIMemoryBlock(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) << v.exec_name << v.state;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PISystemMonitor::ProcessStats) {
s >> PIMemoryBlock(&v, sizeof(PISystemMonitor::ProcessStatsFixed)) >> v.exec_name >> v.state;
v.makeStrings();
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PISystemMonitor::ThreadStats) {
s << PIMemoryBlock(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) << v.name;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PISystemMonitor::ThreadStats) {
s >> PIMemoryBlock(&v, sizeof(PISystemMonitor::ThreadStatsFixed)) >> v.name;
return s;
}
#endif // PISYSTEMMONITOR_H