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