linux_process_load.cpp
Go to the documentation of this file.
1 /**
2  * @author: Daniel Fuchs
3  * @contact: fuxeysolutions@gmail.com
4  *
5  * distributed under the MIT License (MIT).
6  * Copyright (c) Daniel Fuchs
7  *
8  */
9 
10 #include "linux_process_load.hpp"
11 #include <list>
12 #include <memory>
13 #include <iostream>
14 #include <algorithm>
15 #include <filesystem>
16 #include <fstream>
17 #include "linux_cpuload.hpp"
18 #include "linux_memoryload.hpp"
19 
20 static const std::list<std::string> stats {"pid",
21  "comm",
22  "state",
23  "ppid",
24  "pgrp",
25  "session",
26  "tty_nr",
27  "tpgid",
28  "flags",
29  "minflt",
30  "cminflt",
31  "majflt",
32  "cmajflt",
33  "utime",
34  "stime",
35  "cutime",
36  "cstime",
37  "priority",
38  "nice",
39  "num_threads",
40  "itrealvalue",
41  "starttime",
42  "vsize",
43  "rss",
44  "rsslim",
45  "startcode",
46  "endcode",
47  "startstack",
48  "kstkesp",
49  "kstkeip",
50  "signal",
51  "blocked",
52  "sigignore",
53  "sigcatch",
54  "wchan",
55  "nswap",
56  "cnswap",
57  "exit_signal",
58  "processor",
59  "rt_priority",
60  "policy",
61  "delaycct_blkio_ticks",
62  "guest_time",
63  "cguest_time",
64  "start_data",
65  "end_data",
66  "start_brk",
67  "arg_start",
68  "arg_end",
69  "env_start",
70  "env_end",
71  "exit_code"};
72 
73 std::map<std::string, double> linuxProcessLoad::getProcessCpuLoad() {
74  this->findProcesses();
75  return this->procCPUUsage;
76 }
77 
78 
79 void linuxProcessLoad::calculateProcessLoad() {
80  auto [ cpuTotalUserTime, cpuTotalUserLowTime, cpuTotalSysTime, cpuTotalIdleTime] = CpuTimes;
81 
82  auto [ oldCpuTotalUserTime, oldCpuTotalUserLowTime, oldCpuTotalSysTime, oldCpuTotalIdleTime] = oldCpuTimes;
83  auto TotalUserTime = cpuTotalUserTime - oldCpuTotalUserTime;
84  auto TotalSysTime = cpuTotalSysTime - oldCpuTotalSysTime;
85 
86  this->procCPUUsage.clear();
87  for(const auto& elem: processStat) {
88  auto pid = elem.first;
89  try {
90  auto oldProc = oldProcessStat.at(pid);
91  auto proc = elem.second;
92  auto procName = proc.at("comm");
93  uint64_t cpuTime = 0;
94  cpuTime += (std::stoull(proc.at("utime")) - std::stoull(oldProc.at("utime")));
95  cpuTime += (std::stoull(proc.at("stime")) - std::stoull(oldProc.at("stime")));
96 
97 
98  double percentage = ((static_cast<double>(cpuTime) *100.0) / static_cast<double>((TotalUserTime + TotalSysTime)) );
99 
100  if(percentage > 0.1) {
101  this->procCPUUsage[procName] = percentage;
102  }
103 
104  } catch(...) {
105  std::cerr << "process: " << pid << " disappeared in meantime" << std::endl;
106  }
107  }
108 }
109 
110 
111 void linuxProcessLoad::findProcesses() {
112 
113  auto cpuMonitoring = std::make_unique<cpuLoad>("/proc/stat");
114 
115  this->CpuTimes = cpuMonitoring->getCpuTimes();
116 
117 
118  std::string path{"/proc/"};
119  std::vector<std::string> processes;
120  for(auto& elem: std::filesystem::directory_iterator(path)) {
121  auto procPath = elem.path().string();
122  if(elem.exists()) {
123  procPath.erase(procPath.begin(), procPath.begin() + static_cast<int32_t >(path.size()));
124  if (std::isdigit(procPath.at(0))) {
125  if (!std::count_if(procPath.begin(), procPath.end(), [](auto c) {
126  return std::isalpha(c);
127  })) {
128  parseProcess(procPath);
129  }
130  }
131  }
132  }
133  this->calculateProcessLoad();
134 
135  this->oldProcessStat = this->processStat;
136  this->oldCpuTimes = this->CpuTimes;
137 }
138 
139 void linuxProcessLoad::parseProcess(const std::string& pid) {
140  std::string path {"/proc/" + pid + "/stat"};
141  std::ifstream ethFile(path);
142 
143  std::string strPart;
144  std::unordered_map<std::string, std::string> procStat;
145  auto identifierStart = stats.begin();
146  enum state {
147  normal,
148  isProcessParse
149  };
150  bool isProcessFound = false;
151  while (ethFile >> strPart) {
152 
153  if(identifierStart != stats.end()) {
154  if(isProcessFound) {
155  procStat[identifierStart->data()] += " " + strPart;
156  }
157  if(std::count_if(strPart.begin(),strPart.end(),[](auto c) { return c == '('; })) {
158  isProcessFound = true;
159  procStat[identifierStart->data()] = strPart;
160  }
161  if(!isProcessFound) {
162  procStat[identifierStart->data()] = strPart;
163  }
164 
165 
166  if(std::count_if(strPart.begin(), strPart.end(), [] (auto c) { return c == ')';})) {
167  isProcessFound = false;
168  }
169 
170  }
171  if(!isProcessFound) {
172  identifierStart++;
173  continue;
174  }
175 
176  }
177 
178  procStat["comm"].erase(std::remove_if(procStat["comm"].begin(),procStat["comm"].end(), [](auto c) {
179  return c == '(' || c == ')';
180  }), procStat["comm"].end());
181  processStat[pid] = procStat;
182 }
183 
linux_memoryload.hpp
linux_cpuload.hpp
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
linux_process_load.hpp
linuxProcessLoad::getProcessCpuLoad
std::map< std::string, double > getProcessCpuLoad()
get a map of [pid] which contains the cpu load between two calls.
Definition: linux_process_load.cpp:73