32 #if defined(TCMALLOC) || defined(TCMALLOC_MINIMAL)
33 #include <gperftools/malloc_extension.h>
46 #include <sigar_format.h>
49 #define HT_FIELD_NOTIMPL(_field_) (_field_ == (uint64_t)-1)
55 if (vendor == other.
vendor &&
56 model == other.
model &&
100 if (prefix == other.
prefix &&
141 if (name == other.
name &&
146 arch == other.
arch &&
159 if (pid == other.
pid &&
160 user == other.
user &&
163 root == other.
root &&
187 if (prefix == other.
prefix &&
188 total == other.
total &&
189 free == other.
free &&
190 used == other.
used &&
191 avail == other.
avail &&
193 files == other.
files &&
200 if (term == other.
term &&
209 recursive_mutex _mutex;
212 recursive_mutex _cpu_mutex;
213 sigar_cpu_t _prev_cpu, *_prev_cpup = NULL;
216 const int DEFAULT_PAUSE = 500;
219 const double KiB = 1024.;
220 const double MiB = KiB * 1024;
224 recursive_mutex _net_mutex;
225 sigar_net_interface_stat_t _prev_net_stat, *_prev_net_statp = NULL;
227 const int DEFAULT_NET_STAT_FLAGS =
228 SIGAR_NETCONN_CLIENT|SIGAR_NETCONN_SERVER|SIGAR_NETCONN_TCP;
231 CpuInfo _cpu_info, *_cpu_infop = NULL;
236 OsInfo _os_info, *_os_infop = NULL;
238 NetInfo _net_info, *_net_infop = NULL;
240 ProcInfo _proc_info, *_proc_infop = NULL;
243 TermInfo _term_info, *_term_infop = NULL;
246 sigar_t *_sigar = NULL;
250 HT_ASSERT(sigar_open(&_sigar) == SIGAR_OK);
256 sigar_file_system_list_t _fs_list, *_fs_listp = NULL;
258 sigar_file_system_list_t &fs_list() {
260 HT_ASSERT(sigar_file_system_list_get(sigar(), &_fs_list) == SIGAR_OK);
261 _fs_listp = &_fs_list;
266 bool compute_disk_usage(
const char *prefix, sigar_disk_usage_t &u) {
267 sigar_disk_usage_t t;
268 sigar_file_system_t *fs = fs_list().data, *fs_end = fs + fs_list().number;
269 size_t prefix_len = strlen(prefix);
270 u.reads = u.writes = u.write_bytes = u.read_bytes = 0;
271 size_t num_found = 0;
273 for (; fs < fs_end; ++fs) {
274 if (strncmp(prefix, fs->dir_name, prefix_len) == 0
275 && sigar_disk_usage_get(sigar(), fs->dir_name, &t) == SIGAR_OK) {
277 u.writes += t.writes;
278 u.read_bytes += t.read_bytes;
279 u.write_bytes += t.write_bytes;
289 bool compute_fs_usage(
const char *prefix, sigar_file_system_usage_t &u) {
290 sigar_file_system_usage_t t;
291 sigar_file_system_t *fs = fs_list().data, *fs_end = fs + fs_list().number;
292 size_t prefix_len = strlen(prefix);
294 u.total = u.free = u.used = u.avail = u.files = u.free_files = 0;
295 size_t num_found = 0;
297 for (; fs < fs_end; ++fs) {
298 if (strncmp(prefix, fs->dir_name, prefix_len) == 0
299 && sigar_file_system_usage_get(sigar(), fs->dir_name, &t) == SIGAR_OK) {
301 u.use_percent += t.use_percent * t.total;
307 u.free_files += t.free_files;
312 u.use_percent /= u.total;
323 lock_guard<recursive_mutex> lock(_mutex);
326 _cpu_infop = &_cpu_info.
init();
336 return _loadavg_stat.
refresh();
348 lock_guard<recursive_mutex> lock(_mutex);
351 _os_infop = &_os_info.
init();
361 lock_guard<recursive_mutex> lock(_mutex);
364 _net_infop = &_net_info.
init();
374 lock_guard<recursive_mutex> lock(_mutex);
377 _proc_infop = &_proc_info.
init();
391 lock_guard<recursive_mutex> lock(_mutex);
394 _term_infop = &_term_info.
init();
400 lock_guard<recursive_mutex> lock(_mutex);
401 sigar_cpu_info_list_t l;
403 HT_ASSERT(sigar_cpu_info_list_get(sigar(), &l) == SIGAR_OK);
404 sigar_cpu_info_t &s = l.data[0];
409 cache_size = s.cache_size;
410 total_sockets = s.total_sockets;
411 total_cores = s.total_cores;
412 cores_per_socket = s.cores_per_socket;
414 sigar_cpu_info_list_destroy(sigar(), &l);
420 lock_guard<recursive_mutex> cpu_lock(_cpu_mutex);
421 bool need_pause =
false;
423 lock_guard<recursive_mutex> lock(_mutex);
426 HT_ASSERT(sigar_cpu_get(sigar(), &_prev_cpu) == SIGAR_OK);
427 _prev_cpup = &_prev_cpu;
433 this_thread::sleep_for(chrono::milliseconds(DEFAULT_PAUSE));
436 lock_guard<recursive_mutex> lock(_mutex);
438 HT_ASSERT(sigar_cpu_get(sigar(), &curr) == SIGAR_OK);
441 HT_ASSERT(sigar_cpu_perc_calculate(&_prev_cpu, &curr, &p) == SIGAR_OK);
443 user = p.user * 100.;
445 nice = p.nice * 100.;
446 idle = p.idle * 100.;
447 wait = p.wait * 100.;
449 soft_irq = p.soft_irq * 100.;
450 stolen = p.stolen * 100.;
451 total = p.combined * 100.;
459 lock_guard<recursive_mutex> lock(_mutex);
461 HT_ASSERT(sigar_loadavg_get(sigar(), &m) == SIGAR_OK);
463 loadavg[0] = m.loadavg[0];
464 loadavg[1] = m.loadavg[1];
465 loadavg[2] = m.loadavg[2];
471 lock_guard<recursive_mutex> lock(_mutex);
474 HT_ASSERT(sigar_mem_get(sigar(), &m) == SIGAR_OK);
477 total = m.total /
MiB;
480 actual_used = m.actual_used /
MiB;
481 actual_free = m.actual_free /
MiB;
493 prev_stat =
new sigar_disk_usage_t();
494 memcpy(prev_stat, other.
prev_stat,
sizeof(sigar_disk_usage_t));
498 delete (sigar_disk_usage_t *)prev_stat;
502 prefix.swap(other.
prefix);
512 lock_guard<recursive_mutex> lock(_mutex);
513 sigar_disk_usage_t s;
515 memset(&s, 0,
sizeof(s));
517 if (compute_disk_usage(dir_prefix, s)) {
518 HT_DEBUGF(
"curr_disk_stat: reads=%llu, reads=%llu, read_bytes=%llu "
519 "write_bytes=%llu", (
Llu)s.reads, (
Llu)s.writes,
520 (
Llu)s.read_bytes, (
Llu)s.write_bytes);
524 double elapsed = stopwatch.elapsed();
525 reads_rate = (s.reads - ((sigar_disk_usage_t *)prev_stat)->reads) / elapsed;
526 writes_rate = (s.writes - ((sigar_disk_usage_t *)prev_stat)->writes) / elapsed;
528 (s.read_bytes - ((sigar_disk_usage_t *)prev_stat)->read_bytes) / elapsed;
530 (s.write_bytes - ((sigar_disk_usage_t *)prev_stat)->write_bytes) / elapsed;
533 prev_stat =
new sigar_disk_usage_t();
535 *((sigar_disk_usage_t *)prev_stat) = s;
550 prev_stat =
new sigar_swap_t();
551 memcpy(prev_stat, other.
prev_stat,
sizeof(sigar_swap_t));
556 delete (sigar_swap_t *)prev_stat;
569 lock_guard<recursive_mutex> lock(_mutex);
572 HT_ASSERT(sigar_swap_get(sigar(), &s) == SIGAR_OK);
574 total = s.total /
MiB;
579 page_in = s.page_in - ((sigar_swap_t *)prev_stat)->page_in;
580 page_out = s.page_out - ((sigar_swap_t *)prev_stat)->page_out;
583 prev_stat =
new sigar_swap_t();
585 page_out = s.page_out;
588 *((sigar_swap_t *)prev_stat) = s;
594 lock_guard<recursive_mutex> lock(_mutex);
597 HT_ASSERT(sigar_sys_info_get(sigar(), &s) == SIGAR_OK);
602 char *ptr = (
char *)version.c_str();
611 description = s.description;
612 patch_level = s.patch_level;
614 vendor_version = s.vendor_version;
615 vendor_name = s.vendor_name;
621 lock_guard<recursive_mutex> lock(_mutex);
622 sigar_net_interface_config_t ifc;
624 char addrbuf[SIGAR_INET6_ADDRSTRLEN];
627 HT_ASSERT(sigar_net_info_get(sigar(), &ni) == SIGAR_OK);
628 host_name = ni.host_name;
629 default_gw = ni.default_gateway;
632 ifname = Hypertable::Config::get_str(
"Hypertable.Network.Interface");
635 if (sigar_net_interface_config_get(sigar(), ifname.c_str(), &ifc) == SIGAR_OK) {
636 primary_if = ifc.name;
637 HT_ASSERT(sigar_net_address_to_string(sigar(), &ifc.address, addrbuf)
639 primary_addr = addrbuf;
642 HT_FATALF(
"Unable to find network interface '%s'", ifname.c_str());
644 else if (sigar_net_interface_config_primary_get(sigar(), &ifc) == SIGAR_OK) {
645 primary_if = ifc.name;
646 HT_ASSERT(sigar_net_address_to_string(sigar(), &ifc.address, addrbuf)
648 primary_addr = addrbuf;
650 if (primary_addr.empty())
651 primary_addr =
"127.0.0.1";
657 lock_guard<recursive_mutex> net_lock(_net_mutex);
659 lock_guard<recursive_mutex> lock(_mutex);
662 if (sigar_net_stat_get(sigar(), &s, DEFAULT_NET_STAT_FLAGS) == SIGAR_OK) {
663 tcp_established = s.tcp_states[SIGAR_TCP_ESTABLISHED];
664 tcp_listen = s.tcp_states[SIGAR_TCP_LISTEN];
665 tcp_time_wait = s.tcp_states[SIGAR_TCP_TIME_WAIT];
666 tcp_close_wait = s.tcp_states[SIGAR_TCP_CLOSE_WAIT];
667 tcp_idle = s.tcp_states[SIGAR_TCP_IDLE];
670 tcp_established = tcp_listen = tcp_time_wait = tcp_close_wait =
674 bool need_pause =
false;
677 lock_guard<recursive_mutex> lock(_mutex);
679 if (!_prev_net_statp) {
680 if (sigar_net_interface_stat_get(sigar(), ifname, &_prev_net_stat)
682 _prev_net_statp = &_prev_net_stat;
683 _net_stat_stopwatch.
start();
684 HT_DEBUGF(
"prev_net_stat: rx_bytes=%llu, tx_bytes=%llu",
685 (
Llu)_prev_net_stat.rx_bytes, (
Llu)_prev_net_stat.tx_bytes);
689 rx_rate = tx_rate = 0;
694 this_thread::sleep_for(chrono::milliseconds(DEFAULT_PAUSE));
697 lock_guard<recursive_mutex> lock(_mutex);
699 if (_prev_net_statp) {
700 sigar_net_interface_stat_t curr;
702 if (sigar_net_interface_stat_get(sigar(), ifname, &curr) == SIGAR_OK) {
703 _net_stat_stopwatch.
stop();
704 double elapsed = _net_stat_stopwatch.
elapsed();
705 HT_DEBUGF(
"curr_net_stat: rx_bytes=%llu, tx_bytes=%llu",
706 (
Llu)curr.rx_bytes, (
Llu)curr.tx_bytes);
708 rx_rate = (curr.rx_bytes - _prev_net_stat.rx_bytes) / elapsed;
709 tx_rate = (curr.tx_bytes - _prev_net_stat.tx_bytes) / elapsed;
711 _prev_net_stat = curr;
712 _net_stat_stopwatch.
reset();
713 _net_stat_stopwatch.
start();
721 lock_guard<recursive_mutex> lock(_mutex);
722 sigar_proc_exe_t exeinfo;
723 sigar_proc_args_t arginfo;
725 memset(&exeinfo, 0,
sizeof(exeinfo));
726 pid = sigar_pid_get(sigar());
727 HT_ASSERT(sigar_proc_exe_get(sigar(), pid, &exeinfo) == SIGAR_OK);
728 HT_ASSERT(sigar_proc_args_get(sigar(), pid, &arginfo) == SIGAR_OK);
741 for (
size_t i = 0; i < arginfo.number; ++i)
742 args.push_back(arginfo.data[i]);
744 sigar_proc_args_destroy(sigar(), &arginfo);
750 lock_guard<recursive_mutex> lock(_mutex);
754 sigar_pid_t pid = sigar_pid_get(sigar());
755 HT_ASSERT(sigar_proc_cpu_get(sigar(), pid, &c) == SIGAR_OK);
756 HT_ASSERT(sigar_proc_mem_get(sigar(), pid, &m) == SIGAR_OK);
761 cpu_pct = c.percent * 100.;
762 vm_size = m.size /
MiB;
763 vm_resident = m.resident /
MiB;
768 #if defined(TCMALLOC) || defined(TCMALLOC_MINIMAL)
769 size_t tmp_heap_size, tmp_heap_slack;
770 MallocExtension::instance()->GetNumericProperty(
"generic.heap_size", &tmp_heap_size);
771 heap_size = tmp_heap_size;
772 MallocExtension::instance()->GetNumericProperty(
"tcmalloc.slack_bytes", &tmp_heap_slack);
773 heap_slack = tmp_heap_slack;
783 lock_guard<recursive_mutex> lock(_mutex);
784 sigar_file_system_usage_t u;
787 if (compute_fs_usage(dir_prefix, u)) {
788 use_pct = u.use_percent * 100.0;
794 free_files = u.free_files;
800 lock_guard<recursive_mutex> lock(_mutex);
803 if (setupterm(0, 1, &err) != ERR) {
804 term = getenv(
"TERM");
817 sigar_version_t *v = sigar_version_get();
818 return v->description;
822 out <<
"{CpuInfo: vendor='"<< i.
vendor <<
"' model='"<< i.
model
830 out <<
"{CpuStat: user="<< s.
user <<
" sys="<< s.
sys <<
" nice="<< s.
nice
831 <<
" idle="<< s.
idle <<
" wait="<< s.
wait <<
"\n irq="<< s.
irq
833 <<
" total="<< s.
total <<
'}';
838 out <<
"{MemStat: ram="<< s.
ram <<
" total="<< s.
total <<
" used="<< s.
used
852 out <<
"{OsInfo: name="<< i.
name <<
" version="<< i.
version <<
" arch="<< i.
arch
861 out <<
"{SwapStat: total="<< s.
total <<
" used="<< s.
used <<
" free="<< s.
free
867 out <<
"{NetInfo: host_name="<< i.
host_name <<
" primary_if="
882 out <<
"{ProcInfo: pid="<< i.
pid <<
" user="<< i.
user <<
" exe='"<< i.
exe
883 <<
"'\n cwd='"<< i.
cwd <<
"' root='"<< i.
root <<
"'\n args=[";
885 for (
const auto &arg : i.
args)
886 out <<
"'"<< arg <<
"', ";
904 out <<
"{FsStat: prefix='"<< s.
prefix <<
"' total="<< s.
total
905 <<
" free="<< s.
free <<
" used="<< s.
used <<
"\n avail="<< s.
avail
906 <<
" use_pct="<< s.
use_pct <<
'}';
911 out <<
"{TermInfo: term='"<< i.
term <<
"' num_lines="<< i.
num_lines
void swap(SwapStat &other)
bool operator==(const ProcStat &other) const
double elapsed()
Returns the elapsed time.
static const NetStat & net_stat()
Retrieves updated Network statistics (see SystemInfo.h)
bool operator==(const MemStat &other) const
static const CpuInfo & cpu_info()
Retrieves updated CPU information (see SystemInfo.h)
A structure to retrieve Swapping statistics (pages swapped in/out, aggregate total numbers etc) ...
bool operator==(const ProcInfo &other) const
void swap(DiskStat &other)
std::string String
A String is simply a typedef to std::string.
static const CpuStat & cpu_stat()
Retrieves updated CPU statistics (see SystemInfo.h)
#define HT_FIELD_NOTIMPL(_field_)
bool operator==(const NetInfo &other) const
bool operator==(const OsInfo &other) const
A structure to retrieve CPU statistics (system wide cpu times, idle time etc).
long long unsigned int Llu
Shortcut for printf formats.
static const ProcInfo & proc_info()
Retrieves updated Process information (see SystemInfo.h)
static const ProcStat & proc_stat()
Retrieves updated Process statistics (see SystemInfo.h)
bool operator==(const CpuInfo &other) const
A structure to retrieve disk statistics (read/write IOPS, transfer rates etc)
bool operator==(const LoadAvgStat &other) const
static const LoadAvgStat & loadavg_stat()
Retrieves updated Load average statistics (see SystemInfo.h)
static const DiskStat & disk_stat()
Retrieves updated Disk statistics (see SystemInfo.h)
bool has(const String &name)
Check existence of a configuration value.
A structure to retrieve terminal information (lines, columns etc)
FsStat & refresh(const char *prefix="/")
Logging routines and macros.
static const OsInfo & os_info()
Retrieves updated Operating system information (see SystemInfo.h)
bool operator==(const NetStat &other) const
Compatibility Macros for C/C++.
A structure to retrieve CPU information (vendor, model, speed, number of cores etc.)
std::ostream & operator<<(std::ostream &os, const crontab_entry &entry)
Helper function to write crontab_entry to an ostream.
bool operator==(const DiskStat &other) const
void start()
Starts the Stopwatch.
DiskStat & refresh(const char *dir_prefix="/")
Functions to serialize/deserialize primitives to/from a memory buffer.
A structure to receive process statistics (CPU user time, system time, virtmal machine sizes etc) ...
A structure to retrieve memory statistics (RAM size, used size, free size etc)
static const SwapStat & swap_stat()
Retrieves updated Swap statistics (see SystemInfo.h)
static const FsStat & fs_stat()
Retrieves updated Filesystem statistics (see SystemInfo.h)
#define HT_FATALF(msg,...)
#define HT_DEBUGF(msg,...)
std::vector< String > args
void reset()
Resets the Stopwatch.
A structure to retrieve network information (host name, primary interface, primary address...
bool operator==(const CpuStat &other) const
A structure to retrieve Filesystem statistics (total size, free size, used size etc) ...
A structure to retrieve load average-statistics.
bool operator==(const TermInfo &other) const
const char * system_info_lib_version()
Returns a descriptive string of the libsigar version.
bool equal(double a, double b)
Compare doubles that may have been serialized and unserialized.
The Stopwatch class measures elapsed time between instantiation (or a call to start) and a call to st...
bool operator==(const SwapStat &other) const
static const TermInfo & term_info()
Retrieves updated Terminal information (see SystemInfo.h)
System information and statistics based on libsigar.
A structure to receive process information (pid, user name, exe name, working directory, program arguments etc)
static const MemStat & mem_stat()
Retrieves updated Memory statistics (see SystemInfo.h)
static const NetInfo & net_info()
Retrieves updated Network information (see SystemInfo.h)
bool operator==(const FsStat &other) const
A structure to retrieve operating system information (name, version, vendor, architecture) ...
void stop()
Stops the Stopwatch.
A structure to retrieve network statistics (receiving rate, transmitting rate etc) ...