2 #define TRACE_NAME "SystemMetricCollector"
5 #include "SystemMetricCollector.hh"
6 #include "sys/sysinfo.h"
10 #define MLEVEL_PROCESS 6
13 #define MLEVEL_NETWORK 9
16 : lastProcessCPUTimes_(), lastProcessCPUTime_(0), sendProcessMetrics_(processMetrics), sendSystemMetrics_(systemMetrics)
18 lastCPU_ = ReadProcStat_();
19 lastProcessCPUTime_ = times(&lastProcessCPUTimes_);
20 thisNetStat_ = ReadProcNetDev_();
21 lastNetStat_ = thisNetStat_;
26 auto thisCPU = ReadProcStat_();
27 auto totalUsage = thisCPU.totalUsage - lastCPU_.totalUsage;
28 auto total = thisCPU.total - lastCPU_.total;
30 return totalUsage * 100.0 /
static_cast<double>(total);
35 struct tms this_times;
36 auto now = times(&this_times);
42 auto delta_t = now - lastProcessCPUTime_;
43 auto utime = this_times.tms_utime - lastProcessCPUTimes_.tms_utime;
44 auto stime = this_times.tms_stime - lastProcessCPUTimes_.tms_stime;
46 lastProcessCPUTime_ = now;
47 lastProcessCPUTimes_ = this_times;
49 return utime + stime * 100.0 /
static_cast<double>(delta_t);
54 struct sysinfo meminfo;
55 auto err = sysinfo(&meminfo);
58 return meminfo.freeram * meminfo.mem_unit;
65 struct sysinfo meminfo;
66 auto err = sysinfo(&meminfo);
69 return meminfo.bufferram * meminfo.mem_unit;
76 struct sysinfo meminfo;
77 auto err = sysinfo(&meminfo);
80 return meminfo.totalram * meminfo.mem_unit;
87 struct sysinfo meminfo;
88 auto err = sysinfo(&meminfo);
91 auto available = meminfo.freeram + (buffers ? meminfo.bufferram : 0);
92 return available * 100.0 /
static_cast<double>(meminfo.totalram);
99 auto filp = fopen(
"/proc/self/statm",
"r");
101 fscanf(filp,
"%*u %lu", &mem);
103 return mem * sysconf(_SC_PAGESIZE);
108 auto proc = GetProcessMemUsage();
109 auto total = GetTotalRAM();
110 return proc * 100.0 /
static_cast<double>(total);
116 return thisNetStat_.recv_bytes - lastNetStat_.recv_bytes;
122 return thisNetStat_.send_bytes - lastNetStat_.send_bytes;
128 return thisNetStat_.recv_errs - lastNetStat_.recv_errs;
134 return thisNetStat_.send_errs - lastNetStat_.send_errs;
139 auto start_time = std::chrono::steady_clock::now();
140 std::list<std::unique_ptr<MetricData>> output;
141 if (sendProcessMetrics_)
146 if (sendSystemMetrics_)
154 output.emplace_back(
new MetricData(
"Network Receive Rate", GetNetworkReceiveBytes(),
"B", MLEVEL_NETWORK,
MetricMode::Rate,
"",
false));
155 output.emplace_back(
new MetricData(
"Network Send Rate", GetNetworkSendBytes(),
"B", MLEVEL_NETWORK,
MetricMode::Rate,
"",
false));
161 <<
"Time to collect system metrics: "
162 << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start_time).count()
167 artdaq::SystemMetricCollector::cpustat artdaq::SystemMetricCollector::ReadProcStat_()
169 auto filp = fopen(
"/proc/stat",
"r");
172 fscanf(filp,
"cpu %lu %lu %lu %lu %lu %lu %lu", &this_cpu.user, &this_cpu.nice, &this_cpu.system,
173 &this_cpu.idle, &this_cpu.iowait, &this_cpu.irq, &this_cpu.softirq);
176 this_cpu.totalUsage =
177 this_cpu.user + this_cpu.nice + this_cpu.system + this_cpu.iowait + this_cpu.irq + this_cpu.softirq;
178 this_cpu.total = this_cpu.totalUsage + this_cpu.idle;
183 artdaq::SystemMetricCollector::netstat artdaq::SystemMetricCollector::ReadProcNetDev_()
185 auto filp = fopen(
"/proc/net/dev",
"r");
186 char buf[200], ifname[20];
188 auto start_time = std::chrono::steady_clock::now();
191 for (
int i = 0; i < 2; i++)
193 fgets(buf, 200, filp);
196 uint64_t rbytes, rerrs, rdrop, rfifo, rframe, tbytes, terrs, tdrop, tfifo, tcolls, tcarrier;
198 while (fgets(buf, 200, filp) !=
nullptr)
200 sscanf(buf,
"%[^:]: %lu %*u %lu %lu %lu %lu %*u %*u %lu %*u %lu %lu %lu %lu %lu", ifname, &rbytes, &rerrs,
201 &rdrop, &rfifo, &rframe, &tbytes, &terrs, &tdrop, &tfifo, &tcolls, &tcarrier);
203 if (ifname[0] ==
'e')
205 auto total_rerrs = rerrs + rdrop + rfifo + rframe;
206 auto total_terrs = terrs + tdrop + tfifo + tcolls + tcarrier;
207 output.recv_bytes += rbytes;
208 output.send_bytes += tbytes;
209 output.send_errs += total_terrs;
210 output.recv_errs += total_rerrs;
213 output.collectionTime = start_time;
219 void artdaq::SystemMetricCollector::UpdateNetstat_()
221 auto start_time = std::chrono::steady_clock::now();
223 if (std::chrono::duration_cast<std::chrono::duration<
double, std::ratio<1>>>(start_time - thisNetStat_.collectionTime)
226 auto output = ReadProcNetDev_();
227 lastNetStat_ = thisNetStat_;
228 thisNetStat_ = output;
uint64_t GetNetworkSendBytes()
Get the amount of data sent to the network in the last network collection interval (1...
uint64_t GetNetworkSendErrors()
Get the number of network send errors in the last network collection interval (1.0 s) ...
Report the sum of all values. Use for counters to report accurate results.
uint64_t GetNetworkReceiveBytes()
Get the amount of data received from the network in the last network collection interval (1...
uint64_t GetTotalRAM()
Get the total amount of RAM in the system
uint64_t GetProcessMemUsage()
Get the amount of RAM being used by this process
over. Use to create rates from counters.
Report only the last value recorded. Useful for event counters, run numbers, etc. ...
std::list< std::unique_ptr< MetricData > > SendMetrics()
Send the configured metrics
double GetAvailableRAMPercent(bool buffers)
Get the percentage of available RAM
uint64_t GetAvailableRAM()
Get the amount of available RAM in the system
Small structure used to hold a metric data point before sending to the metric plugins ...
double GetProcessCPUUsagePercent()
Return the current amount of CPU usage for the current process, %
Report the average of all values. Use for rates to report accurate results.
SystemMetricCollector(bool processMetrics, bool systemMetrics)
SystemMetricCollector Constructor
double GetProcessMemUsagePercent()
Get the amount of RAM being used by this process
double GetSystemCPUUsagePercent()
Return the current overall system CPU usage in %
uint64_t GetNetworkReceiveErrors()
Get the number of network receive errors in the last network collection interval (1.0 s)
uint64_t GetBufferedRAM()
Get the amount of RAM currently being used for cache