23 #include <boost/algorithm/string.hpp>
24 #include <gutil/strings/substitute.h>
32 using boost::algorithm::is_any_of;
33 using boost::algorithm::join;
34 using boost::algorithm::split;
35 using boost::algorithm::token_compress_on;
36 using boost::algorithm::trim;
38 using namespace strings;
42 int ProcessStateInfo::GetInt(
const string& state_key)
const {
43 ProcessStateMap::const_iterator it = process_state_map_.find(state_key);
44 if (it != process_state_map_.end())
return atoi(it->second.c_str());
48 int64_t ProcessStateInfo::GetInt64(
const string& state_key)
const {
49 ProcessStateMap::const_iterator it = process_state_map_.find(state_key);
50 if (it != process_state_map_.end()) {
52 int64_t state_value = StringParser::StringToInt<int64_t>(it->second.data(),
53 it->second.size(), &result);
54 if (result == StringParser::PARSE_SUCCESS)
return state_value;
59 string ProcessStateInfo::GetString(
const string& state_key)
const {
60 ProcessStateMap::const_iterator it = process_state_map_.find(state_key);
61 if (it != process_state_map_.end())
return it->second;
65 int64_t ProcessStateInfo::GetBytes(
const string& state_key)
const {
66 ProcessStateMap::const_iterator it = process_state_map_.find(state_key);
67 if (it != process_state_map_.end()) {
68 vector<string> fields;
69 split(fields, it->second, is_any_of(
" "), token_compress_on);
72 int64_t state_value = StringParser::StringToInt<int64_t>(fields[0].data(),
73 fields[0].size(), &result);
74 if (result == StringParser::PARSE_SUCCESS) {
75 if (fields.size() < 2)
return state_value;
76 if (fields[1].compare(
"kB") == 0)
return state_value * 1024L;
82 void ProcessStateInfo::ReadProcIO() {
83 const string&
path = Substitute(
"/proc/$0/io", getpid());
84 ifstream ioinfo(path.c_str(), ios::in);
86 while (ioinfo.good() && !ioinfo.eof()) {
87 getline(ioinfo, line);
88 vector<string> fields;
89 split(fields, line, is_any_of(
" "), token_compress_on);
90 if (fields.size() < 2)
continue;
91 string key = fields[0].substr(0, fields[0].size() - 1);
92 process_state_map_[Substitute(
"io/$0", key)] = fields[1];
95 if (ioinfo.is_open()) ioinfo.close();
98 void ProcessStateInfo::ReadProcCgroup() {
99 const string&
path = Substitute(
"/proc/$0/cgroup", getpid());
100 ifstream cgroupinfo(path.c_str(), ios::in);
102 while (cgroupinfo.good() && !cgroupinfo.eof()) {
103 getline(cgroupinfo, line);
104 vector<string> fields;
105 split(fields, line, is_any_of(
":"), token_compress_on);
106 if (fields.size() < 3)
continue;
107 process_state_map_[
"cgroup/hierarchy_id"] = fields[0];
108 process_state_map_[
"cgroup/subsystems"] = fields[1];
109 process_state_map_[
"cgroup/control_group"] = fields[2];
113 if (cgroupinfo.is_open()) cgroupinfo.close();
116 void ProcessStateInfo::ReadProcSched() {
117 const string&
path = Substitute(
"/proc/$0/sched", getpid());
118 ifstream schedinfo(path.c_str(), ios::in);
120 while (schedinfo.good() && !schedinfo.eof()) {
121 getline(schedinfo, line);
122 vector<string> fields;
123 split(fields, line, is_any_of(
":"), token_compress_on);
124 if (fields.size() < 2)
continue;
127 process_state_map_[Substitute(
"sched/$0", fields[0])] = fields[1];
130 if (schedinfo.is_open()) schedinfo.close();
133 void ProcessStateInfo::ReadProcStatus() {
134 const string&
path = Substitute(
"/proc/$0/status", getpid());
135 ifstream statusinfo(path.c_str(), ios::in);
137 while (statusinfo.good() && !statusinfo.eof()) {
138 getline(statusinfo, line);
139 vector<string> fields;
140 split(fields, line, is_any_of(
"\t"), token_compress_on);
141 if (fields.size() < 2)
continue;
143 string key = fields[0].substr(0, fields[0].size() - 1);
144 process_state_map_[Substitute(
"status/$0", key)] = fields[1];
147 if (statusinfo.is_open()) statusinfo.close();
150 void ProcessStateInfo::ReadProcFileDescriptorInfo() {
151 const string& command = Substitute(
"ls -l /proc/$0/fd | awk '{print $$(NF-2), $$NF}'",
153 FILE* fp = popen(command.c_str(),
"r");
155 int max_buffer = 1024;
156 char buf[max_buffer];
158 if (fgets(buf, max_buffer, fp) != NULL) {
161 vector<string> fields;
162 split(fields, line, is_any_of(
" "), token_compress_on);
163 if (fields.size() < 2)
continue;
164 fd_desc_[atoi(fields[0].c_str())] = fields[1];
171 ProcessStateInfo::ProcessStateInfo() {
176 ReadProcFileDescriptorInfo();
181 stream <<
"Process State: " << endl
184 << PrettyPrinter::Print(GetBytes(
"io/read_bytes"), TUnit::BYTES) << endl
186 << PrettyPrinter::Print(GetBytes(
"io/write_bytes"), TUnit::BYTES) << endl
187 <<
" Read I/O: " << GetInt64(
"io/syscr") << endl
188 <<
" Write I/O: " << GetInt64(
"io/syscw") << endl
189 <<
" CGroups: " << endl
190 <<
" Hierarchy: " << GetString(
"cgroup/hierarchy_id") << endl
191 <<
" Subsystems: " << GetString(
"cgroup/subsystems") <<endl
192 <<
" Control Group: " << GetString(
"cgroup/control_group") << endl
193 <<
" Schedule: " << endl
194 <<
" Sum Execute Time: " << GetString(
"sched/se.sum_exec_runtime") << endl
195 <<
" Max Wait Time: " << GetString(
"sched/se.statistics.wait_max") << endl
196 <<
" Sum Wait Time: " << GetString(
"sched/se.statistics.wait_sum") << endl
197 <<
" Wait Count: " << GetInt64(
"sched/se.statistics.wait_count") << endl
198 <<
" Sum I/O Wait Time: "
199 << GetString(
"sched/se.statistics.iowait_sum") << endl
200 <<
" I/O Wait Count: "
201 << GetInt64(
"sched/se.statistics.iowait_count") << endl
202 <<
" Wakeup Count with cpu migration: "
203 << GetInt64(
"sched/se.statistics.nr_wakeups_migrate") << endl
204 <<
" Switches: " << GetInt64(
"sched/nr_switches") << endl
205 <<
" Voluntary Switches: " << GetInt(
"sched/nr_voluntary_switches") << endl
206 <<
" Involuntary Switches: "
207 << GetInt(
"sched/nr_involuntary_switches") << endl
208 <<
" Process Priority: " << GetInt(
"sched/prio") << endl
209 <<
" Status: " << endl
210 <<
" Process ID: " << getpid() << endl
211 <<
" Thread Number: " << GetInt(
"status/Threads") << endl
213 << PrettyPrinter::Print(GetBytes(
"status/VmPeak"), TUnit::BYTES) << endl
215 << PrettyPrinter::Print(GetBytes(
"status/VmSize"), TUnit::BYTES) << endl
217 << PrettyPrinter::Print(GetBytes(
"status/VmLck"), TUnit::BYTES) << endl
219 << PrettyPrinter::Print(GetBytes(
"status/VmPin"), TUnit::BYTES) << endl
221 << PrettyPrinter::Print(GetBytes(
"status/VmHWM"), TUnit::BYTES) << endl
223 << PrettyPrinter::Print(GetBytes(
"status/VmRSS"), TUnit::BYTES) << endl
225 << PrettyPrinter::Print(GetBytes(
"status/VmData"), TUnit::BYTES) << endl
227 << PrettyPrinter::Print(GetBytes(
"status/VmStk"), TUnit::BYTES) << endl
229 << PrettyPrinter::Print(GetBytes(
"status/VmExe"), TUnit::BYTES) << endl
231 << PrettyPrinter::Print(GetBytes(
"status/VmLib"), TUnit::BYTES) << endl
233 << PrettyPrinter::Print(GetBytes(
"status/VmPTE"), TUnit::BYTES) << endl
235 << PrettyPrinter::Print(GetBytes(
"status/VmSwap"), TUnit::BYTES) << endl
236 <<
" Cpus Allowed List: " << GetString(
"status/Cpus_allowed_list") << endl
237 <<
" Mems Allowed List: " << GetString(
"status/Mems_allowed_list") << endl
238 <<
" File Descriptors: " << endl
239 <<
" Number of File Descriptors: " << fd_desc_.size() << endl;
string path("/usr/lib/sasl2:/usr/lib64/sasl2:/usr/local/lib/sasl2:/usr/lib/x86_64-linux-gnu/sasl2")
std::string DebugString(const T &val)