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;
29 std::map<std::string, bool> allowedDisks_;
30 if (getenv(
"OBMON_ALLOWED_DISKS")) {
31 std::istringstream envAllowDisks(getenv(
"OBMON_ALLOWED_DISKS"));
34 for (std::string diskStr; std::getline(envAllowDisks, diskStr,
','); ) {
35 bool permitAny =
false;
41 if (diskStr.back() ==
'+')
47 allowedDisks_[diskStr] = permitAny;
51 allowedDisks_[
"sd"] =
false;
52 allowedDisks_[
"nvme"] =
false;
53 allowedDisks_[
"md"] =
false;
57 for (
auto entry : allowedDisks_) {
58 allowedDisks.push_back(entry);
62 std::sort(allowedDisks.begin(), allowedDisks.end(),
63 [](std::pair<std::string, bool>
const &a,
64 std::pair<std::string, bool>
const &b) {
65 return a.first.length() > b.first.length();
68 for (
auto &a : allowedDisks) {
69 _logger->info(
"Allowed disk device [{}]:[{}]", a.first, a.second);
75 if (getenv(
"OBMON_ALLOWED_NETWORK")) {
76 std::istringstream envAllowNICs(getenv(
"OBMON_ALLOWED_NETWORK"));
79 for (std::string netStr; std::getline(envAllowNICs, netStr,
','); ) {
80 allowedNICs.push_back(netStr);
84 std::string
const diskSpeedEnvStr =
"OBMON_MAX_DISK_SPEED";
85 if (getenv(diskSpeedEnvStr.c_str())) {
88 uint32_t usrDiskSpeed =
89 static_cast<uint32_t
>(std::stoi(getenv(diskSpeedEnvStr.c_str())));
90 if (usrDiskSpeed > 1) {
91 maxDiskSpeed =
static_cast<double>(sz_MiB_kiB_(usrDiskSpeed));
122 _logger->trace(
"ObSensorSystem::process cpu ...");
123 glibtop_get_cpu(&
_cpu);
124 _logger->trace(
"ObSensorSystem::process load average ...");
126 _logger->trace(
"ObSensorSystem::process mem ...");
127 glibtop_get_mem(&
_mem);
129 std::string net_name;
133 _logger->trace(
"ObSensorSystem::process net {}", net_name.data());
134 glibtop_get_netload(net, net_name.data());
139 uint64_t majorID = 0;
140 uint64_t minorID = 0;
144 uint64_t rMerged = 0;
145 uint64_t rSectors = 0;
149 uint64_t wMerged = 0;
150 uint64_t wSectors = 0;
153 uint64_t currentIOCount = 0;
155 uint64_t weightedTimeIO = 0;
157 std::ifstream procDisksFile(
"/proc/diskstats");
163 >> majorID >> minorID >> devName
164 >> rCount >> rMerged >> rSectors >> rTime
165 >> wCount >> wMerged >> wSectors >> wTime
166 >> currentIOCount >> timeIO >> weightedTimeIO
168 bool allowInfo =
false;
170 for (
auto permit : allowedDisks) {
171 if (devName.find(permit.first) == 0) {
172 if (permit.second ==
true) {
175 if (permit.first == devName) {
179 if (permit.first ==
"sd") {
180 if (devName.back() >
'9') {
183 }
else if (permit.first ==
"nvme" || permit.first ==
"md") {
184 if (devName.find(
'p') == std::string::npos) {
195 _logger->trace(
"Disk: Denied [{}:{}:{}]", majorID, minorID, devName);
199 _logger->debug(
"Disk: Allowed [{}:{}:{}]", majorID, minorID, devName);
202 auto &disk = diskInfos[devName];
205 disk.majorID = majorID;
206 disk.minorID = minorID;
207 disk.devName = devName;
208 disk.rCount = rCount;
209 disk.rMerged = rMerged;
210 disk.rSectors = rSectors;
212 disk.wCount = wCount;
213 disk.wMerged = wMerged;
214 disk.wSectors = wSectors;
216 disk.currentIOCount = currentIOCount;
217 disk.timeIO = timeIO;
218 disk.weightedTimeIO = weightedTimeIO;
220 procDisksFile.close();
230 glibtop_cpu cpu1 = ss1->
cpu();
231 glibtop_cpu cpu2 = ss2->
cpu();
233 _cpu.total = (cpu2.total - cpu1.total);
234 _cpu.sys = (cpu2.sys - cpu1.sys);
235 _cpu.user = (cpu2.user - cpu1.user);
236 _cpu.nice = (cpu2.nice - cpu1.nice);
237 _cpu.idle = (cpu2.idle - cpu1.idle);
238 _cpu.iowait = (cpu2.iowait - cpu1.iowait);
239 _cpu.irq = (cpu2.irq - cpu1.irq);
240 _cpu.softirq = (cpu2.softirq - cpu1.softirq);
241 _cpu.frequency = (cpu2.frequency - cpu1.frequency);
243 glibtop_mem mem1 = ss1->
mem();
244 glibtop_mem mem2 = ss2->
mem();
246 _mem.total = (mem2.total - mem1.total) * 1000 / timeout;
247 _mem.used = (mem2.used - mem1.used) * 1000 / timeout;
248 _mem.free = (mem2.free - mem1.free) * 1000 / timeout;
249 _mem.shared = (mem2.shared - mem1.shared) * 1000 / timeout;
250 _mem.buffer = (mem2.buffer - mem1.buffer) * 1000 / timeout;
251 _mem.cached = (mem2.cached - mem1.cached) * 1000 / timeout;
252 _mem.locked = (mem2.locked - mem1.locked) * 1000 / timeout;
254 std::string net_name;
255 glibtop_netload *net1, *net2;
262 net->address = (net2->address - net1->address) * 1000 / timeout;
263 net->bytes_in = (net2->bytes_in - net1->bytes_in) * 1000 / timeout;
264 net->bytes_out = (net2->bytes_out - net1->bytes_out) * 1000 / timeout;
265 net->errors_in = (net2->errors_in - net1->errors_in) * 1000 / timeout;
266 net->errors_out = (net2->errors_out - net1->errors_out) * 1000 / timeout;
267 net->packets_in = (net2->packets_in - net1->packets_in) * 1000 / timeout;
269 (net2->packets_out - net1->packets_out) * 1000 / timeout;
274 auto newDisks = ss2->disks();
275 auto oldDisks = ss1->disks();
276 for (
auto &newDisk_ : newDisks) {
277 auto &newDisk = newDisk_.second;
278 auto &oldDisk = oldDisks[newDisk.devName];
279 auto &disk = diskInfos[newDisk.devName];
282 disk.majorID = newDisk.majorID;
283 disk.minorID = newDisk.minorID;
284 disk.devName = newDisk.devName;
285 disk.rSectors = newDisk.rSectors - oldDisk.rSectors;
286 disk.wSectors = newDisk.wSectors - oldDisk.wSectors;
295 using namespace fmt::literals;
297 double percent =
static_cast<double>(
_cpu.total);
299 json +=
"\"" + name +
"\": {";
301 if (
type() == SensorType::SPEED) {
303 ((
static_cast<double>(
_cpu.total) / percent * 100.0) > 1.0) ? 1.0 : 0.0;
307 R"("total": {{ "value": {totalV:.3f}, "alpha": {totalA:.2f} }},)"
308 R"("sys": {{ "value": {sysV:.3f}, "alpha": {sysA:.2f} }},)"
309 R"("user": {{ "value": {userV:.3f}, "alpha": {userA:.2f} }},)"
310 R"("nice": {{ "value": {niceV:.3f}, "alpha": {niceA:.2f} }},)"
311 R"("idle": {{ "value": {idleV:.3f}, "alpha": {idleA:.2f} }},)"
312 R"("frequency": {{ "value": {freqV:.3f}, "alpha": 0 }},)"
314 R"("iowait": {{ "value": {iowaitV:.3f}, "alpha": {iowaitA:.2f} }},)"
315 R"("busy": {{ "value": {busyV}, "alpha": {busyA} }})"
318 "totalV"_a = static_cast<double>(
_cpu.total) / percent * 100.0,
319 "totalA"_a = static_cast<double>(
_cpu.total) / percent,
320 "sysV"_a = static_cast<double>(
_cpu.sys) / percent * 100.0,
321 "sysA"_a = static_cast<double>(
_cpu.sys) / percent,
322 "userV"_a = static_cast<double>(
_cpu.user) / percent * 100.0,
323 "userA"_a = static_cast<double>(
_cpu.user) / percent,
324 "niceV"_a = static_cast<double>(
_cpu.nice) / percent * 100.0,
325 "niceA"_a = static_cast<double>(
_cpu.nice) / percent,
326 "idleV"_a = static_cast<double>(
_cpu.idle) / percent * 100.0,
327 "idleA"_a = 1.0 - static_cast<double>(
_cpu.idle) / percent,
328 "iowaitV"_a = static_cast<double>(
_cpu.iowait) / percent * 100.0,
329 "iowaitA"_a = static_cast<double>(
_cpu.iowait) / percent,
330 "freqV"_a = static_cast<double>(
_cpu.frequency),
"busyV"_a = busy,
336 if (
type() == SensorType::VALUE) {
338 double ncpu =
_sysinfo->real_ncpu + 1;
340 json += fmt::format(R
"("load1": {{ "value": {:.3f}, "alpha": {:.2f} }},)"
341 R"("load5": {{ "value": {:.3f}, "alpha": {:.2f} }},)"
342 R"("load15": {{ "value": {:.3f}, "alpha": {:.2f} }},)"
345 avg[0], avg[0] / ncpu,
347 avg[1], avg[1] / ncpu,
349 avg[2], avg[2] / ncpu,
356 if (
type() == SensorType::VALUE) {
360 R"("total": {{ "value": {totalV}, "alpha": 1.0 }},)"
361 R"("used": {{ "value": {usedV}, "alpha": {usedA:.2f} }},)"
362 R"("free": {{ "value": {freeV}, "alpha": {freeA:.2f} }},)"
363 R"("shared": {{ "value": {sharedV}, "alpha": {sharedA:.2f} }},)"
364 R"("buffer": {{ "value": {bufferV}, "alpha": {bufferA:.2f} }},)"
365 R"("cached": {{ "value": {cachedV}, "alpha": {cachedA:.2f} }},)"
366 R"("locked": {{ "value": {lockedV}, "alpha": {lockedA:.2f} }})"
369 "totalV"_a =
_mem.total,
370 "usedV"_a =
_mem.used,
371 "usedA"_a = static_cast<double>(
_mem.used) /
_mem.total,
372 "freeV"_a =
_mem.free,
373 "freeA"_a = 1.0 - static_cast<double>(
_mem.free) /
_mem.total,
374 "sharedV"_a =
_mem.shared,
375 "sharedA"_a = static_cast<double>(
_mem.shared) /
_mem.total,
376 "bufferV"_a =
_mem.buffer,
377 "bufferA"_a = static_cast<double>(
_mem.buffer) /
_mem.total,
378 "cachedV"_a =
_mem.cached,
379 "cachedA"_a = static_cast<double>(
_mem.cached) /
_mem.total,
380 "lockedV"_a =
_mem.locked,
381 "lockedA"_a = static_cast<double>(
_mem.locked) /
_mem.total
386 if (
type() == SensorType::SPEED) {
389 json +=
"\"net\" : [";
391 double const MAX_BYTES_ALPHA = 100 * 1048576;
393 std::string net_name;
397 if (allowedNICs.empty() ||
398 std::find(allowedNICs.begin(), allowedNICs.end(), net_name) !=
403 R"("adapter": "{name}", "address": "{address}",)"
404 R"("bytes_in": {{ "value": {inV}, "alpha": {inA:.2f} }},)"
405 R"("bytes_out": {{ "value": {outV}, "alpha": {outA:.2f} }},)"
406 R"("errors_in": {{ "value": {errI}, "alpha": 0 }},)"
407 R"("errors_out": {{ "value": {errO}, "alpha": 0 }},)"
408 R"("packets_in": {{ "value": {pacI}, "alpha": 0 }},)"
409 R"("packets_out": {{ "value": {pacO}, "alpha": 0 }})"
412 "name"_a = net_name,
"address"_a = net->address,
413 "inV"_a = net->bytes_in,
414 "inA"_a = static_cast<double>(net->bytes_in) / MAX_BYTES_ALPHA,
415 "outV"_a = net->bytes_out,
416 "outA"_a = static_cast<double>(net->bytes_out) / MAX_BYTES_ALPHA,
417 "errI"_a = net->errors_in,
"errO"_a = net->errors_out,
418 "pacI"_a = net->packets_in,
"pacO"_a = net->packets_out
428 if (
json.back() ==
',')
433 if (
type() == SensorType::SPEED) {
436 json += R
"("disks" : [)";
438 for (
auto &disk_ : diskInfos) {
439 auto &disk = disk_.second;
441 double raSectors = disk.rSectors / maxDiskSpeed;
442 double rwSectors = disk.wSectors / maxDiskSpeed;
446 R"("majorID": {majorID}, "minorID": {minorID},)"
447 R"("deviceName": "{devName}",)"
449 R"("bytes_read": {{ "value": {rSectors}, "alpha": {raSectors:.2f} }},)"
451 R"("bytes_write": {{ "value": {wSectors}, "alpha": {rwSectors:.2f} }})"
454 "majorID"_a = disk.majorID,
"minorID"_a = disk.minorID,
455 "devName"_a = disk.devName,
"rSectors"_a = disk.rSectors * 1024,
456 "raSectors"_a = raSectors > 1.0 ? 1.0 : raSectors,
457 "wSectors"_a = disk.wSectors * 1024,
458 "rwSectors"_a = rwSectors > 1.0 ? 1.0 : rwSectors
463 if (
json.back() ==
',') {
470 if (
json.back() ==
',') {
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_mem mem() const
returns glibtop_mem
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
std::vector< glibtop_netload * > netloads() const
returns netloads
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
glibtop_cpu _cpu
CPU info from glitop.
glibtop_cpu cpu() const
returns glibtop_cpu
glibtop_loadavg _loadavg
Load average info from glibtop.
SensorType type() const
Returns sensor type.
glibtop_netlist _netlist
NetList from glitop.
std::vector< glibtop_netload * > _netloads
List of netload.