![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* proc_stats.h -*- C++ -*- 00002 Rémi Attab, 19 January 2012 00003 Copyright (c) 2012 Datacratic. All rights reserved. 00004 00005 Gathers process and system stats from the proc files. 00006 */ 00007 00008 00009 #include "soa/service/process_stats.h" 00010 #include "jml/arch/exception.h" 00011 00012 #include <boost/algorithm/string/split.hpp> 00013 #include <boost/lexical_cast.hpp> 00014 #include <string> 00015 #include <vector> 00016 #include <array> 00017 #include <functional> 00018 #include <fstream> 00019 #include <iostream> 00020 #include <unistd.h> 00021 #include <sys/resource.h> 00022 00023 00024 using namespace Datacratic; 00025 using namespace std; 00026 using namespace boost; 00027 00028 00029 namespace { 00030 00031 static const string ProcStatFile = "/proc/self/stat"; 00032 enum ProcStatFields { 00033 STAT_MINFLT = 9, 00034 STAT_MAJFLT = 11, 00035 STAT_UTIME = 13, 00036 STAT_STIME = 14, 00037 STAT_VSIZE = 22, 00038 STAT_RSS = 23 00039 }; 00040 00041 static const string ProcStatmFile = "/proc/self/statm"; 00042 enum ProcStatmFields { 00043 STATM_SIZE = 0, 00044 STATM_RESIDENT = 1, 00045 STATM_SHARED = 2, 00046 }; 00047 00048 00049 static const string ProcLoadAvgFile = "/proc/loadavg"; 00050 enum ProcLoadAvgFields { 00051 LOADAVG_1 = 0, 00052 LOADAVG_5 = 1, 00053 LOADAVG_15 = 2 00054 }; 00055 00056 00057 vector<string> readProcFile(const string& procFile) { 00058 ifstream ifs(procFile); 00059 if (ifs.fail()) { 00060 throw ML::Exception ("Unable to open proc file " + procFile); 00061 } 00062 00063 std::array<char, 1024> buffer; 00064 ifs.getline(&buffer[0], buffer.max_size()); 00065 if (ifs.fail() || ifs.eof()) { 00066 throw ML::Exception ("Unable to read proc file " + procFile); 00067 } 00068 00069 std::string rawStats = &buffer[0]; 00070 00071 vector<string> stats; 00072 split(stats, rawStats, [](char rhs)->bool {return rhs == ' ';}); 00073 00074 return stats; 00075 } 00076 00077 }; 00078 00079 void ProcessStats::sampleLoadAverage () { 00080 if (!doLoadAverage) { 00081 return; 00082 } 00083 00084 vector<string> stats = readProcFile(ProcLoadAvgFile); 00085 00086 loadAverage1 = lexical_cast<float>(stats[LOADAVG_1]); 00087 loadAverage5 = lexical_cast<float>(stats[LOADAVG_5]); 00088 loadAverage15 = lexical_cast<float>(stats[LOADAVG_15]); 00089 } 00090 00092 void ProcessStats::sampleStat () { 00093 vector<string> stats = readProcFile(ProcStatFile); 00094 00095 long ticks = sysconf(_SC_CLK_TCK); 00096 00097 minorFaults = lexical_cast<uint64_t>(stats[STAT_MINFLT]); 00098 majorFaults = lexical_cast<uint64_t>(stats[STAT_MAJFLT]); 00099 00100 userTime = lexical_cast<uint64_t>(stats[STAT_UTIME]) / ((double) ticks); 00101 systemTime = lexical_cast<uint64_t>(stats[STAT_STIME]) / ((double) ticks); 00102 00103 virtualMem = lexical_cast<uint64_t>(stats[STAT_VSIZE]); 00104 residentMem = lexical_cast<uint64_t>(stats[STAT_RSS]); 00105 } 00106 00107 void ProcessStats::sampleStatm () { 00108 vector<string> stats = readProcFile(ProcStatmFile); 00109 00110 int pageSize = getpagesize(); 00111 virtualMem = lexical_cast<uint64_t>(stats[STATM_SIZE]) * pageSize; 00112 residentMem = lexical_cast<uint64_t>(stats[STATM_RESIDENT]) * pageSize; 00113 sharedMem = lexical_cast<uint64_t>(stats[STATM_SHARED]) * pageSize; 00114 } 00115 00116 void ProcessStats::sampleRUsage () { 00117 struct rusage ru; 00118 getrusage(RUSAGE_SELF, &ru); 00119 00120 userTime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 1000000.0); 00121 systemTime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 1000000.0); 00122 00123 minorFaults = ru.ru_minflt; 00124 majorFaults = ru.ru_majflt; 00125 00126 voluntaryContextSwitches = ru.ru_nvcsw; 00127 involuntaryContextSwitches = ru.ru_nivcsw; 00128 } 00129 00130 00131 void ProcessStats::logToCallback ( 00132 LogCallback cb, 00133 const ProcessStats& last, 00134 const ProcessStats& cur, 00135 const string& prefix) 00136 { 00137 std::string p = !prefix.empty() ? prefix + "." : ""; 00138 00139 cb(p + "timeUser", cur.userTime - last.userTime); 00140 cb(p + "timeSystem", cur.systemTime - last.systemTime); 00141 00142 cb(p + "faultsMinor", cur.minorFaults - last.minorFaults); 00143 cb(p + "faultsMajor", cur.majorFaults - last.majorFaults); 00144 00145 cb(p + "memVirtual", cur.virtualMem); 00146 cb(p + "memResident", cur.residentMem); 00147 cb(p + "memShared", cur.sharedMem); 00148 00149 cb(p + "contextSwitchesVoluntary", 00150 cur.voluntaryContextSwitches - last.voluntaryContextSwitches); 00151 cb(p + "contextSwitchesInvoluntary", 00152 cur.involuntaryContextSwitches - last.involuntaryContextSwitches); 00153 00154 if (cur.doLoadAverage) { 00155 cb(p + "loadAverage01", cur.loadAverage1); 00156 cb(p + "loadAverage05", cur.loadAverage5); 00157 cb(p + "loadAverage15", cur.loadAverage15); 00158 } 00159 } 00160 00161 00162 Json::Value ProcessStats::toJson ( 00163 const ProcessStats& last, 00164 const ProcessStats& cur, 00165 const string& prefix) 00166 { 00167 Json::Value result; 00168 00169 auto cb = [&](string name, double val) { 00170 result[name] = (long long)val; 00171 }; 00172 logToCallback(cb, last, cur, prefix); 00173 00174 return result; 00175 }