1 #include <ObSensorSystem.h> 12 char **devices = glibtop_get_netlist(&
_netlist);
15 for (
unsigned int i = 0; i <
_netlist.number; i++) {
16 net =
new glibtop_netload;
24 if (getenv(
"OBMON_RES_CPU"))
25 _resCpu = atoi(getenv(
"OBMON_RES_CPU"));
32 std::map<std::string, bool> allowedDisks_;
33 if (getenv(
"OBMON_ALLOWED_DISKS")) {
34 std::istringstream envAllowDisks(getenv(
"OBMON_ALLOWED_DISKS"));
37 for (std::string diskStr; std::getline(envAllowDisks, diskStr,
','); ) {
38 bool permitAny =
false;
44 if (diskStr.back() ==
'+')
50 allowedDisks_[diskStr] = permitAny;
54 allowedDisks_[
"sd"] =
false;
55 allowedDisks_[
"nvme"] =
false;
56 allowedDisks_[
"md"] =
false;
60 for (
auto entry : allowedDisks_) {
61 allowedDisks.push_back(entry);
65 std::sort(allowedDisks.begin(), allowedDisks.end(),
66 [](std::pair<std::string, bool>
const &a,
67 std::pair<std::string, bool>
const &b) {
68 return a.first.length() > b.first.length();
71 for (
auto &a : allowedDisks) {
72 _logger->info(
"Allowed disk device [{}]:[{}]", a.first, a.second);
78 if (getenv(
"OBMON_ALLOWED_NETWORK")) {
79 std::istringstream envAllowNICs(getenv(
"OBMON_ALLOWED_NETWORK"));
82 for (std::string netStr; std::getline(envAllowNICs, netStr,
','); ) {
83 allowedNICs.push_back(netStr);
87 std::string
const diskSpeedEnvStr =
"OBMON_MAX_DISK_SPEED";
88 if (getenv(diskSpeedEnvStr.c_str())) {
91 uint32_t usrDiskSpeed =
92 static_cast<uint32_t>(std::stoi(getenv(diskSpeedEnvStr.c_str())));
93 if (usrDiskSpeed > 1) {
94 maxDiskSpeed = static_cast<double>(sz_MiB_kiB_(usrDiskSpeed));
125 _logger->trace(
"ObSensorSystem::process cpu ...");
126 glibtop_get_cpu(&
_cpu);
127 _logger->trace(
"ObSensorSystem::process load average ...");
129 _logger->trace(
"ObSensorSystem::process mem ...");
130 glibtop_get_mem(&
_mem);
132 std::string net_name;
136 _logger->trace(
"ObSensorSystem::process net {}", net_name.data());
137 glibtop_get_netload(net, net_name.data());
142 uint64_t majorID = 0;
143 uint64_t minorID = 0;
147 uint64_t rMerged = 0;
148 uint64_t rSectors = 0;
152 uint64_t wMerged = 0;
153 uint64_t wSectors = 0;
156 uint64_t currentIOCount = 0;
158 uint64_t weightedTimeIO = 0;
160 std::ifstream procDisksFile(
"/proc/diskstats");
166 >> majorID >> minorID >> devName
167 >> rCount >> rMerged >> rSectors >> rTime
168 >> wCount >> wMerged >> wSectors >> wTime
169 >> currentIOCount >> timeIO >> weightedTimeIO
171 bool allowInfo =
false;
173 for (
auto permit : allowedDisks) {
174 if (devName.find(permit.first) == 0) {
175 if (permit.second ==
true) {
178 if (permit.first == devName) {
182 if (permit.first ==
"sd") {
183 if (devName.back() >
'9') {
186 }
else if (permit.first ==
"nvme" || permit.first ==
"md") {
187 if (devName.find(
'p') == std::string::npos) {
198 _logger->trace(
"Disk: Denied [{}:{}:{}]", majorID, minorID, devName);
202 _logger->debug(
"Disk: Allowed [{}:{}:{}]", majorID, minorID, devName);
205 auto &disk = diskInfos[devName];
208 disk.majorID = majorID;
209 disk.minorID = minorID;
210 disk.devName = devName;
211 disk.rCount = rCount;
212 disk.rMerged = rMerged;
213 disk.rSectors = rSectors;
215 disk.wCount = wCount;
216 disk.wMerged = wMerged;
217 disk.wSectors = wSectors;
219 disk.currentIOCount = currentIOCount;
220 disk.timeIO = timeIO;
221 disk.weightedTimeIO = weightedTimeIO;
223 procDisksFile.close();
233 glibtop_cpu cpu1 = ss1->
cpu();
234 glibtop_cpu cpu2 = ss2->
cpu();
236 _cpu.total = (cpu2.total - cpu1.total);
237 _cpu.sys = (cpu2.sys - cpu1.sys);
238 _cpu.user = (cpu2.user - cpu1.user);
239 _cpu.nice = (cpu2.nice - cpu1.nice);
240 _cpu.idle = (cpu2.idle - cpu1.idle);
241 _cpu.iowait = (cpu2.iowait - cpu1.iowait);
242 _cpu.irq = (cpu2.irq - cpu1.irq);
243 _cpu.softirq = (cpu2.softirq - cpu1.softirq);
244 _cpu.frequency = (cpu2.frequency - cpu1.frequency);
246 glibtop_mem mem1 = ss1->
mem();
247 glibtop_mem mem2 = ss2->
mem();
249 _mem.total = (mem2.total - mem1.total) * 1000 / timeout;
250 _mem.used = (mem2.used - mem1.used) * 1000 / timeout;
251 _mem.free = (mem2.free - mem1.free) * 1000 / timeout;
252 _mem.shared = (mem2.shared - mem1.shared) * 1000 / timeout;
253 _mem.buffer = (mem2.buffer - mem1.buffer) * 1000 / timeout;
254 _mem.cached = (mem2.cached - mem1.cached) * 1000 / timeout;
255 _mem.locked = (mem2.locked - mem1.locked) * 1000 / timeout;
257 std::string net_name;
258 glibtop_netload *net1, *net2;
265 net->address = (net2->address - net1->address) * 1000 / timeout;
266 net->bytes_in = (net2->bytes_in - net1->bytes_in) * 1000 / timeout;
267 net->bytes_out = (net2->bytes_out - net1->bytes_out) * 1000 / timeout;
268 net->errors_in = (net2->errors_in - net1->errors_in) * 1000 / timeout;
269 net->errors_out = (net2->errors_out - net1->errors_out) * 1000 / timeout;
270 net->packets_in = (net2->packets_in - net1->packets_in) * 1000 / timeout;
272 (net2->packets_out - net1->packets_out) * 1000 / timeout;
277 auto newDisks = ss2->disks();
278 auto oldDisks = ss1->disks();
279 for (
auto &newDisk_ : newDisks) {
280 auto &newDisk = newDisk_.second;
281 auto &oldDisk = oldDisks[newDisk.devName];
282 auto &disk = diskInfos[newDisk.devName];
285 disk.majorID = newDisk.majorID;
286 disk.minorID = newDisk.minorID;
287 disk.devName = newDisk.devName;
288 disk.rSectors = newDisk.rSectors - oldDisk.rSectors;
289 disk.wSectors = newDisk.wSectors - oldDisk.wSectors;
298 using namespace fmt::literals;
300 double percent = static_cast<double>(
_cpu.total);
304 if (
type() == SensorType::SPEED) {
306 ((static_cast<double>(
_cpu.total) / percent * 100.0) > 1.0) ? 1.0 : 0.0;
310 R"("total": {{ "value": {totalV:.3f}, "alpha": {totalA:.2f} }},)" 311 R"("sys": {{ "value": {sysV:.3f}, "alpha": {sysA:.2f} }},)" 312 R"("user": {{ "value": {userV:.3f}, "alpha": {userA:.2f} }},)" 313 R"("nice": {{ "value": {niceV:.3f}, "alpha": {niceA:.2f} }},)" 314 R"("idle": {{ "value": {idleV:.3f}, "alpha": {idleA:.2f} }},)" 315 R"("frequency": {{ "value": {freqV:.3f}, "alpha": 0 }},)" 317 R"("iowait": {{ "value": {iowaitV:.3f}, "alpha": {iowaitA:.2f} }},)" 318 R"("busy": {{ "value": {busyV}, "alpha": {busyA} }})" 321 "totalV"_a = static_cast<double>(
_cpu.total) / percent * 100.0,
322 "totalA"_a = static_cast<double>(
_cpu.total) / percent,
323 "sysV"_a = static_cast<double>(
_cpu.sys) / percent * 100.0,
324 "sysA"_a = static_cast<double>(
_cpu.sys) / percent,
325 "userV"_a = static_cast<double>(
_cpu.user) / percent * 100.0,
326 "userA"_a = static_cast<double>(
_cpu.user) / percent,
327 "niceV"_a = static_cast<double>(
_cpu.nice) / percent * 100.0,
328 "niceA"_a = static_cast<double>(
_cpu.nice) / percent,
329 "idleV"_a = static_cast<double>(
_cpu.idle) / percent * 100.0,
330 "idleA"_a = 1.0 - static_cast<double>(
_cpu.idle) / percent,
331 "iowaitV"_a = static_cast<double>(
_cpu.iowait) / percent * 100.0,
332 "iowaitA"_a = static_cast<double>(
_cpu.iowait) / percent,
333 "freqV"_a = static_cast<double>(
_cpu.frequency),
"busyV"_a = busy,
339 if (
type() == SensorType::VALUE) {
342 double ncpu_all =
_sysinfo->real_ncpu + 1;
343 double ncpu = ncpu_all -
_resCpu;
345 json += fmt::format(R
"("load1": {{ "value": {:.3f}, "alpha": {:.2f} }},)" 346 R"("load5": {{ "value": {:.3f}, "alpha": {:.2f} }},)" 347 R"("load15": {{ "value": {:.3f}, "alpha": {:.2f} }},)" 351 avg[0], avg[0] / ncpu,
353 avg[1], avg[1] / ncpu,
355 avg[2], avg[2] / ncpu,
364 if (
type() == SensorType::VALUE) {
368 R"("total": {{ "value": {totalV}, "alpha": 1.0 }},)" 369 R"("used": {{ "value": {usedV}, "alpha": {usedA:.2f} }},)" 370 R"("free": {{ "value": {freeV}, "alpha": {freeA:.2f} }},)" 371 R"("shared": {{ "value": {sharedV}, "alpha": {sharedA:.2f} }},)" 372 R"("buffer": {{ "value": {bufferV}, "alpha": {bufferA:.2f} }},)" 373 R"("cached": {{ "value": {cachedV}, "alpha": {cachedA:.2f} }},)" 374 R"("locked": {{ "value": {lockedV}, "alpha": {lockedA:.2f} }})" 377 "totalV"_a =
_mem.total,
378 "usedV"_a =
_mem.used,
379 "usedA"_a = static_cast<double>(
_mem.used) /
_mem.total,
380 "freeV"_a =
_mem.free,
381 "freeA"_a = 1.0 - static_cast<double>(
_mem.free) /
_mem.total,
382 "sharedV"_a =
_mem.shared,
383 "sharedA"_a = static_cast<double>(
_mem.shared) /
_mem.total,
384 "bufferV"_a =
_mem.buffer,
385 "bufferA"_a = static_cast<double>(
_mem.buffer) /
_mem.total,
386 "cachedV"_a =
_mem.cached,
387 "cachedA"_a = static_cast<double>(
_mem.cached) /
_mem.total,
388 "lockedV"_a =
_mem.locked,
389 "lockedA"_a = static_cast<double>(
_mem.locked) /
_mem.total
394 if (
type() == SensorType::SPEED) {
397 json +=
"\"net\" : [";
399 double const MAX_BYTES_ALPHA = 100 * 1048576;
401 std::string net_name;
405 if (allowedNICs.empty() ||
406 std::find(allowedNICs.begin(), allowedNICs.end(), net_name) !=
411 R"("adapter": "{name}", "address": "{address}",)" 412 R"("bytes_in": {{ "value": {inV}, "alpha": {inA:.2f} }},)" 413 R"("bytes_out": {{ "value": {outV}, "alpha": {outA:.2f} }},)" 414 R"("errors_in": {{ "value": {errI}, "alpha": 0 }},)" 415 R"("errors_out": {{ "value": {errO}, "alpha": 0 }},)" 416 R"("packets_in": {{ "value": {pacI}, "alpha": 0 }},)" 417 R"("packets_out": {{ "value": {pacO}, "alpha": 0 }})" 420 "name"_a = net_name,
"address"_a = net->address,
421 "inV"_a = net->bytes_in,
422 "inA"_a = static_cast<double>(net->bytes_in) / MAX_BYTES_ALPHA,
423 "outV"_a = net->bytes_out,
424 "outA"_a = static_cast<double>(net->bytes_out) / MAX_BYTES_ALPHA,
425 "errI"_a = net->errors_in,
"errO"_a = net->errors_out,
426 "pacI"_a = net->packets_in,
"pacO"_a = net->packets_out
436 if (
json.back() ==
',')
441 if (
type() == SensorType::SPEED) {
444 json += R
"("disks" : [)"; 446 for (
auto &disk_ : diskInfos) {
447 auto &disk = disk_.second;
449 double raSectors = disk.rSectors / maxDiskSpeed;
450 double rwSectors = disk.wSectors / maxDiskSpeed;
454 R"("majorID": {majorID}, "minorID": {minorID},)" 455 R"("deviceName": "{devName}",)" 457 R"("bytes_read": {{ "value": {rSectors}, "alpha": {raSectors:.2f} }},)" 459 R"("bytes_write": {{ "value": {wSectors}, "alpha": {rwSectors:.2f} }})" 462 "majorID"_a = disk.majorID,
"minorID"_a = disk.minorID,
463 "devName"_a = disk.devName,
"rSectors"_a = disk.rSectors * 1024,
464 "raSectors"_a = raSectors > 1.0 ? 1.0 : raSectors,
465 "wSectors"_a = disk.wSectors * 1024,
466 "rwSectors"_a = rwSectors > 1.0 ? 1.0 : rwSectors
471 if (
json.back() ==
',') {
478 if (
json.back() ==
',') {
glibtop_mem mem() const
returns glibtop_mem
int _resCpu
Cpus used by system (not for computation)
void process() override
Process function.
std::shared_ptr< spdlog::logger > _logger
Pointer to spd logger.
System Obmon sensor class.
ObSensorSystem(std::string name={"sys"})
glibtop_cpu cpu() const
returns glibtop_cpu
std::vector< std::string > _netnames
list of network names
glibtop * _sysinfo
Sys info from glitop.
void speed(ObSensor *s1, ObSensor *s2, unsigned int timeout=1000) override
Calculate time change (speed)
ObSensor * _first
Pointer to first sensor.
virtual ~ObSensorSystem() override
ObSensor * _change
Pointer to change sensor.
glibtop_mem _mem
Mem info from glitop.
ObSensor * _second
Pointer to second sensor.
std::string json(const std::string name={"static"}) const override
std::string name() const
Returns name of sensor.
SensorType type() const
Returns sensor type.
glibtop_cpu _cpu
CPU info from glitop.
glibtop_loadavg _loadavg
Load average info from glibtop.
std::vector< glibtop_netload * > netloads() const
returns netloads
glibtop_netlist _netlist
NetList from glitop.
std::vector< glibtop_netload * > _netloads
List of netload.