Current section

Files

Jump to
prometheus_process_collector c_src prometheus_process_info_freebsd.cc
Raw

c_src/prometheus_process_info_freebsd.cc

#include "prometheus_process_info.h"
#include <cstdio>
#include <ctime>
#include <memory>
namespace Prometheus
{
static long pagesize(void)
{
uint pageSize;
size_t len = sizeof(pageSize);
if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1)
{
long spageSize = sysconf(_SC_PAGESIZE);
if (spageSize == -1)
{
throw ProcessInfoException();
}
else
{
return spageSize;
}
}
else
{
return pageSize;
}
}
static std::unique_ptr<kinfo_proc> kinfo_getproc(pid_t pid)
{
int mib[4];
size_t len;
len = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = pid;
if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) < 0)
{
throw ProcessInfoException();
}
std::unique_ptr<kinfo_proc>
kipp {reinterpret_cast<kinfo_proc*>(new char[len])};
if (sysctl(mib, 4, kipp.get(), &len, NULL, 0) < 0)
{
throw ProcessInfoException();
}
if (len != sizeof(*kipp))
{
throw ProcessInfoException();
}
if (kipp->ki_structsize != sizeof(*kipp))
{
throw ProcessInfoException();
}
if (kipp->ki_pid != pid)
{
throw ProcessInfoException();
}
return kipp;
}
/*
from https://github.com/freebsd/freebsd/blob/9e0a154b0fd5fa9010238ac9497ec59f84167c92/lib/libutil/kinfo_getfile.c#L22-L51
I don't need unpacked structs here, just count. Hope it won't break someday.
*/
int ProcessInfo::get_fds_total()
{
int mib[4];
int error;
int count;
size_t len;
char *buf, *eb;
struct kinfo_file *kf;
// get size of all pids
len = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_FILEDESC;
mib[3] = pid;
error = sysctl(mib, nitems(mib), NULL, &len, NULL, 0);
if (error)
{
throw ProcessInfoException();
}
// allocate buf for pids
len = len * 4 / 3;
buf = (char*)malloc(len);
if (buf == NULL)
{
throw ProcessInfoException();
}
// fill buf with kinfo_files
error = sysctl(mib, nitems(mib), buf, &len, NULL, 0);
if (error)
{
free(buf);
throw ProcessInfoException();
}
// count structs in the buf
count = 0;
eb = buf + len;
while (buf < eb)
{
kf = (struct kinfo_file *)(uintptr_t)buf;
if (kf->kf_structsize == 0)
break;
buf += kf->kf_structsize;
count++;
}
free(buf - len);
return count;
}
void ProcessInfo::set_proc_stat()
{
auto proc = kinfo_getproc(pid);
start_time_seconds = proc->ki_start.tv_sec;
uptime_seconds = now - proc->ki_start.tv_sec;
threads_total = proc->ki_numthreads;
vm_bytes = proc->ki_size;
rm_bytes = proc->ki_rssize * pagesize();
}
}