blob: 668173a0f7ecb65b3ce1814edc796eeefd7c2b48 [file]
#include "ProcStats.h"
#include "yagpcc_metrics.pb.h"
#include <string>
#include <fstream>
#include <unistd.h>
extern "C" {
#include "postgres.h"
#include "utils/elog.h"
}
namespace {
#define FILL_IO_STAT(stat_name) \
uint64_t stat_name; \
proc_stat >> tmp >> stat_name; \
stats->set_##stat_name(stat_name - stats->stat_name());
void fill_io_stats(yagpcc::SystemStat *stats) {
std::ifstream proc_stat("/proc/self/io");
std::string tmp;
FILL_IO_STAT(rchar);
FILL_IO_STAT(wchar);
FILL_IO_STAT(syscr);
FILL_IO_STAT(syscw);
FILL_IO_STAT(read_bytes);
FILL_IO_STAT(write_bytes);
FILL_IO_STAT(cancelled_write_bytes);
}
void fill_cpu_stats(yagpcc::SystemStat *stats) {
static const int UTIME_ID = 13;
static const int STIME_ID = 14;
static const int VSIZE_ID = 22;
static const int RSS_ID = 23;
static const double tps = sysconf(_SC_CLK_TCK);
std::ifstream proc_stat("/proc/self/stat");
std::string trash;
for (int i = 0; i <= RSS_ID; ++i) {
switch (i) {
case UTIME_ID:
double utime;
proc_stat >> utime;
stats->set_usertimeseconds(utime / tps - stats->usertimeseconds());
break;
case STIME_ID:
double stime;
proc_stat >> stime;
stats->set_kerneltimeseconds(stime / tps - stats->kerneltimeseconds());
break;
case VSIZE_ID:
uint64_t vsize;
proc_stat >> vsize;
stats->set_vsize(vsize);
break;
case RSS_ID:
uint64_t rss;
proc_stat >> rss;
// NOTE: this is a double AFAIU, need to double-check
stats->set_rss(rss);
break;
default:
proc_stat >> trash;
}
}
}
void fill_status_stats(yagpcc::SystemStat *stats) {
std::ifstream proc_stat("/proc/self/status");
std::string key, measure;
while (proc_stat >> key) {
if (key == "VmPeak:") {
uint64_t value;
proc_stat >> value;
stats->set_vmpeakkb(value);
proc_stat >> measure;
if (measure != "kB") {
ereport(FATAL, (errmsg("Expected memory sizes in kB, but got in %s",
measure.c_str())));
}
} else if (key == "VmSize:") {
uint64_t value;
proc_stat >> value;
stats->set_vmsizekb(value);
if (measure != "kB") {
ereport(FATAL, (errmsg("Expected memory sizes in kB, but got in %s",
measure.c_str())));
}
}
}
}
} // namespace
void fill_self_stats(yagpcc::SystemStat *stats) {
static yagpcc::SystemStat prev_stats;
fill_io_stats(&prev_stats);
fill_cpu_stats(&prev_stats);
fill_status_stats(&prev_stats);
*stats = prev_stats;
}