0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
StatsSystem.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; version 3 of the
9  * License.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
26 #include "Common/Compat.h"
27 #include "Common/FailureInducer.h"
28 #include "Common/Logger.h"
29 #include "Common/Serialization.h"
30 
31 #include <boost/algorithm/string.hpp>
32 
33 #include "StatsSystem.h"
34 
35 using namespace Hypertable;
36 
37 namespace {
38  enum Group {
39  CPUINFO_GROUP = 0,
40  CPU_GROUP = 1,
41  LOADAVG_GROUP = 2,
42  MEMORY_GROUP = 3,
43  DISK_GROUP = 4,
44  SWAP_GROUP = 5,
45  NETINFO_GROUP = 6,
46  NET_GROUP = 7,
47  OSINFO_GROUP = 8,
48  PROCINFO_GROUP = 9,
49  PROC_GROUP = 10,
50  FS_GROUP = 11,
51  TERMINFO_GROUP = 12
52  };
53 }
54 
55 StatsSystem::StatsSystem(int32_t categories)
56  : StatsSerializable(SYSTEM, 0), m_categories(categories) {
57  group_count = 0;
58  add_categories(categories);
59  HT_ASSERT((categories&(DISK|FS)) == 0);
60 }
61 
62 StatsSystem::StatsSystem(int32_t categories, std::vector<String> &dirs)
63  : StatsSerializable(SYSTEM, 0), m_categories(categories) {
64  group_count = 0;
65  add_categories(categories, dirs);
66  HT_ASSERT((categories&(DISK|FS)) != 0);
67 }
68 
69 void StatsSystem::add_categories(int32_t categories) {
70  m_categories |= categories;
71  if (categories & CPUINFO) {
72  group_ids[group_count++] = CPUINFO_GROUP;
73  cpu_info.init();
74  }
75  if (categories & NETINFO) {
76  group_ids[group_count++] = NETINFO_GROUP;
77  net_info.init();
78  }
79  if (categories & OSINFO) {
80  group_ids[group_count++] = OSINFO_GROUP;
81  os_info.init();
82  }
83  if (categories & PROCINFO) {
84  group_ids[group_count++] = PROCINFO_GROUP;
85  proc_info.init();
86  }
87  if (categories & TERMINFO) {
88  group_ids[group_count++] = TERMINFO_GROUP;
89  term_info.init();
90  }
91  if (categories & CPU) {
92  group_ids[group_count++] = CPU_GROUP;
93  cpu_stat.refresh();
94  }
95  if (categories & LOADAVG) {
96  group_ids[group_count++] = LOADAVG_GROUP;
98  }
99  if (categories & MEMORY) {
100  group_ids[group_count++] = MEMORY_GROUP;
101  mem_stat.refresh();
102  }
103  if (categories & SWAP) {
104  group_ids[group_count++] = SWAP_GROUP;
105  swap_stat.refresh();
106  }
107  if (categories & NET) {
108  group_ids[group_count++] = NET_GROUP;
109  net_stat.refresh();
110  }
111  if (categories & PROC) {
112  group_ids[group_count++] = PROC_GROUP;
113  proc_stat.refresh();
114  }
115 }
116 
117 void StatsSystem::add_categories(int32_t categories, std::vector<String> &dirs) {
118  add_categories(categories);
119 
120  // strip trailing '/'
121  for (size_t i = 0; i < dirs.size(); i++) {
122  boost::trim_right_if(dirs[i], boost::is_any_of("/"));
123  if (dirs[i] == "")
124  dirs[i] = "/";
125  }
126 
127  if (categories & DISK) {
128  group_ids[group_count++] = DISK_GROUP;
129  disk_stat.resize(dirs.size());
130  for (size_t i = 0; i < dirs.size(); i++)
131  disk_stat[i].prefix = dirs[i];
132  }
133  if (categories & FS) {
134  group_ids[group_count++] = FS_GROUP;
135  fs_stat.resize(dirs.size());
136  for (size_t i = 0; i < dirs.size(); i++)
137  fs_stat[i].prefix = dirs[i];
138  }
139 }
140 
142  if (m_categories & CPU)
143  cpu_stat.refresh();
144  if (m_categories & LOADAVG)
146  if (m_categories & MEMORY)
147  mem_stat.refresh();
148  if (m_categories & SWAP)
149  swap_stat.refresh();
150  if (m_categories & NET)
151  net_stat.refresh();
152  if (m_categories & PROC)
153  proc_stat.refresh();
154  if (m_categories & DISK) {
155  for (size_t i = 0; i < disk_stat.size(); i++)
156  disk_stat[i].refresh(disk_stat[i].prefix.c_str());
157  }
158  if (m_categories & FS) {
159  bool simulate_disk_full = HT_FAILURE_SIGNALLED("fsstat-disk-full");
160  for (size_t i = 0; i < fs_stat.size(); i++) {
161  fs_stat[i].refresh(fs_stat[i].prefix.c_str());
162  if (simulate_disk_full)
163  fs_stat[i].avail = 0;
164  }
165  }
166 }
167 
168 bool StatsSystem::operator==(const StatsSystem &other) const {
169  if (StatsSerializable::operator!=(other))
170  return false;
171  if (m_categories != other.m_categories)
172  return false;
173  if ((m_categories & CPUINFO) &&
174  cpu_info != other.cpu_info)
175  return false;
176  if ((m_categories & CPU) &&
177  cpu_stat != other.cpu_stat)
178  return false;
179  if ((m_categories & LOADAVG) &&
180  loadavg_stat != other.loadavg_stat)
181  return false;
182  if ((m_categories & MEMORY) &&
183  mem_stat != other.mem_stat)
184  return false;
185  if ((m_categories & SWAP) &&
186  swap_stat != other.swap_stat)
187  return false;
188  if ((m_categories & NETINFO) &&
189  net_info != other.net_info)
190  return false;
191  if ((m_categories & NET) &&
192  net_stat != other.net_stat)
193  return false;
194  if ((m_categories & OSINFO) &&
195  os_info != other.os_info)
196  return false;
197  if ((m_categories & PROCINFO) &&
198  proc_info != other.proc_info)
199  return false;
200  if ((m_categories & PROC) &&
201  proc_stat != other.proc_stat)
202  return false;
203  if ((m_categories & TERMINFO) &&
204  term_info != other.term_info)
205  return false;
206  if (m_categories & DISK) {
207  if (disk_stat.size() != other.disk_stat.size())
208  return false;
209  for (size_t i = 0; i < disk_stat.size(); i++) {
210  if (disk_stat[i] != other.disk_stat[i])
211  return false;
212  }
213  }
214  if (m_categories & FS) {
215  if (fs_stat.size() != other.fs_stat.size())
216  return false;
217  for (size_t i = 0; i < fs_stat.size(); i++) {
218  if (fs_stat[i] != other.fs_stat[i])
219  return false;
220  }
221  }
222  return true;
223 }
224 
225 size_t StatsSystem::encoded_length_group(int group) const {
226  if (group == CPUINFO_GROUP) {
229  }
230  else if (group == CPU_GROUP) {
232  }
233  else if (group == LOADAVG_GROUP) {
235  }
236  else if (group == MEMORY_GROUP) {
238  }
239  else if (group == DISK_GROUP) {
240  size_t len = Serialization::encoded_length_vi32(disk_stat.size());
241  for (size_t i = 0; i < disk_stat.size(); i++) {
244  }
245  return len;
246  }
247  else if (group == SWAP_GROUP) {
248  return (3 * Serialization::encoded_length_double()) + 16;
249  }
250  else if (group == NETINFO_GROUP) {
255  }
256  else if (group == NET_GROUP) {
257  return (5 * 4) + (2 * Serialization::encoded_length_double());
258  }
259  else if (group == OSINFO_GROUP) {
270  }
271  else if (group == PROCINFO_GROUP) {
277  for (size_t i = 0; i < proc_info.args.size(); i++)
279  return len;
280  }
281  else if (group == PROC_GROUP) {
282  return (6 * 8) + (4 * Serialization::encoded_length_double()) + 2 * 8;
283  }
284  else if (group == FS_GROUP) {
285  size_t len = Serialization::encoded_length_vi32(fs_stat.size());
286  for (size_t i = 0; i < fs_stat.size(); i++) {
287  len += (6 * 8) + Serialization::encoded_length_double()
289  }
290  return len;
291  }
292  else if (group == TERMINFO_GROUP) {
294  }
295  else
296  HT_FATALF("Invalid group number (%d)", group);
297  return 0;
298 }
299 
300 void StatsSystem::encode_group(int group, uint8_t **bufp) const {
301  if (group == CPUINFO_GROUP) {
309  }
310  else if (group == CPU_GROUP) {
320  }
321  else if (group == LOADAVG_GROUP) {
325  }
326  else if (group == MEMORY_GROUP) {
333  }
334  else if (group == DISK_GROUP) {
336  for (size_t i = 0; i < disk_stat.size(); i++) {
337  Serialization::encode_vstr(bufp, disk_stat[i].prefix);
338  Serialization::encode_double(bufp, disk_stat[i].reads_rate);
339  Serialization::encode_double(bufp, disk_stat[i].writes_rate);
340  Serialization::encode_double(bufp, disk_stat[i].read_rate);
341  Serialization::encode_double(bufp, disk_stat[i].write_rate);
342  }
343  }
344  else if (group == SWAP_GROUP) {
350  }
351  else if (group == NETINFO_GROUP) {
356  }
357  else if (group == NET_GROUP) {
365  }
366  else if (group == OSINFO_GROUP) {
380  }
381  else if (group == PROCINFO_GROUP) {
388  for (size_t i = 0; i < proc_info.args.size(); i++)
390  }
391  else if (group == PROC_GROUP) {
404  }
405  else if (group == FS_GROUP) {
406  Serialization::encode_vi32(bufp, fs_stat.size());
407  for (size_t i = 0; i < fs_stat.size(); i++) {
408  Serialization::encode_vstr(bufp, fs_stat[i].prefix);
409  Serialization::encode_double(bufp, fs_stat[i].use_pct);
410  Serialization::encode_i64(bufp, fs_stat[i].total);
411  Serialization::encode_i64(bufp, fs_stat[i].free);
412  Serialization::encode_i64(bufp, fs_stat[i].used);
413  Serialization::encode_i64(bufp, fs_stat[i].avail);
414  Serialization::encode_i64(bufp, fs_stat[i].files);
415  Serialization::encode_i64(bufp, fs_stat[i].free_files);
416  }
417  }
418  else if (group == TERMINFO_GROUP) {
422  }
423  else
424  HT_FATALF("Invalid group number (%d)", group);
425 }
426 
427 void StatsSystem::decode_group(int group, uint16_t len, const uint8_t **bufp,
428  size_t *remainp) {
429  if (group == CPUINFO_GROUP) {
430  cpu_info.vendor = Serialization::decode_vstr(bufp, remainp);
431  cpu_info.model = Serialization::decode_vstr(bufp, remainp);
432  cpu_info.mhz = Serialization::decode_i32(bufp, remainp);
438  }
439  else if (group == CPU_GROUP) {
440  cpu_stat.user = Serialization::decode_double(bufp, remainp);
441  cpu_stat.sys = Serialization::decode_double(bufp, remainp);
442  cpu_stat.nice = Serialization::decode_double(bufp, remainp);
443  cpu_stat.idle = Serialization::decode_double(bufp, remainp);
444  cpu_stat.wait = Serialization::decode_double(bufp, remainp);
445  cpu_stat.irq = Serialization::decode_double(bufp, remainp);
449  m_categories |= CPU;
450  }
451  else if (group == LOADAVG_GROUP) {
456  }
457  else if (group == MEMORY_GROUP) {
458  mem_stat.ram = Serialization::decode_double(bufp, remainp);
460  mem_stat.used = Serialization::decode_double(bufp, remainp);
461  mem_stat.free = Serialization::decode_double(bufp, remainp);
464  m_categories |= MEMORY;
465  }
466  else if (group == DISK_GROUP) {
467  size_t count = Serialization::decode_vi32(bufp, remainp);
468  disk_stat.resize(count);
469  for (size_t i = 0; i < count; i++) {
470  disk_stat[i].prefix = Serialization::decode_vstr(bufp, remainp);
471  disk_stat[i].reads_rate = Serialization::decode_double(bufp, remainp);
472  disk_stat[i].writes_rate = Serialization::decode_double(bufp, remainp);
473  disk_stat[i].read_rate = Serialization::decode_double(bufp, remainp);
474  disk_stat[i].write_rate = Serialization::decode_double(bufp, remainp);
475  }
476  m_categories |= DISK;
477  }
478  else if (group == SWAP_GROUP) {
484  m_categories |= SWAP;
485  }
486  else if (group == NETINFO_GROUP) {
492  }
493  else if (group == NET_GROUP) {
501  m_categories |= NET;
502  }
503  else if (group == OSINFO_GROUP) {
504  os_info.name = Serialization::decode_vstr(bufp, remainp);
505  os_info.version = Serialization::decode_vstr(bufp, remainp);
509  os_info.arch = Serialization::decode_vstr(bufp, remainp);
510  os_info.machine = Serialization::decode_vstr(bufp, remainp);
513  os_info.vendor = Serialization::decode_vstr(bufp, remainp);
517  m_categories |= OSINFO;
518  }
519  else if (group == PROCINFO_GROUP) {
520  proc_info.pid = Serialization::decode_i64(bufp, remainp);
521  proc_info.user = Serialization::decode_vstr(bufp, remainp);
522  proc_info.exe = Serialization::decode_vstr(bufp, remainp);
523  proc_info.cwd = Serialization::decode_vstr(bufp, remainp);
524  proc_info.root = Serialization::decode_vstr(bufp, remainp);
525  size_t len = Serialization::decode_vi32(bufp, remainp);
526  for (size_t i = 0; i < len; i++)
527  proc_info.args.push_back(Serialization::decode_vstr(bufp, remainp));
529  }
530  else if (group == PROC_GROUP) {
543  m_categories |= PROC;
544  }
545  else if (group == FS_GROUP) {
546  size_t count = Serialization::decode_vi32(bufp, remainp);
547  fs_stat.resize(count);
548  for (size_t i = 0; i < count; i++) {
549  fs_stat[i].prefix = Serialization::decode_vstr(bufp, remainp);
550  fs_stat[i].use_pct = Serialization::decode_double(bufp, remainp);
551  fs_stat[i].total = Serialization::decode_i64(bufp, remainp);
552  fs_stat[i].free = Serialization::decode_i64(bufp, remainp);
553  fs_stat[i].used = Serialization::decode_i64(bufp, remainp);
554  fs_stat[i].avail = Serialization::decode_i64(bufp, remainp);
555  fs_stat[i].files = Serialization::decode_i64(bufp, remainp);
556  fs_stat[i].free_files = Serialization::decode_i64(bufp, remainp);
557  }
558  m_categories |= FS;
559  }
560  else if (group == TERMINFO_GROUP) {
561  term_info.term = Serialization::decode_vstr(bufp, remainp);
565  }
566  else {
567  HT_WARNF("Unrecognized StatsSystem group %d, skipping...", group);
568  (*bufp) += len;
569  (*remainp) -= len;
570  }
571 }
Abstract base class for managing serialized statistics.
char * decode_vstr(const uint8_t **bufp, size_t *remainp)
Decode a vstr (vint64, data, null).
bool operator==(const StatsSystem &other) const
Equal operator.
Definition: StatsSystem.cc:168
int32_t tcp_established
Definition: SystemInfo.h:211
virtual void encode_group(int group, uint8_t **bufp) const
Serializes a statistics group to memory.
Definition: StatsSystem.cc:300
int encoded_length_double()
Length of an encoded double (16 bytes)
#define HT_WARNF(msg,...)
Definition: Logger.h:290
uint16_t version_major
Definition: SystemInfo.h:235
The FailureInducer simulates errors.
NetInfo & init()
Definition: SystemInfo.cc:620
struct NetInfo net_info
Network information (host name, primary interface, gateway etc)
Definition: StatsSystem.h:112
virtual size_t encoded_length_group(int group) const
Returns the encoded length of a statistics group.
Definition: StatsSystem.cc:225
uint16_t version_micro
Definition: SystemInfo.h:237
struct NetStat net_stat
Network statistics (transfer rates, receiving rate etc)
Definition: StatsSystem.h:115
NetStat & refresh()
Definition: SystemInfo.cc:656
size_t encoded_length_vstr(size_t len)
Computes the encoded length of vstr (vint64, data, null)
virtual void decode_group(int group, uint16_t len, const uint8_t **bufp, size_t *remainp)
Deserializes a statistics group from memory.
Definition: StatsSystem.cc:427
Collecting and (de)serializing system-wide statistics.
struct CpuInfo cpu_info
CPU information (vendor, model, cores, cache sizes etc)
Definition: StatsSystem.h:97
struct TermInfo term_info
Terminal information (number of lines, number of columns etc)
Definition: StatsSystem.h:127
uint32_t decode_i32(const uint8_t **bufp, size_t *remainp)
Decode a 32-bit integer in little-endian order.
CpuStat & refresh()
Definition: SystemInfo.cc:419
MemStat & refresh()
Definition: SystemInfo.cc:470
#define HT_ASSERT(_e_)
Definition: Logger.h:396
uint8_t group_count
Number of groups in group_ids.
uint64_t decode_i64(const uint8_t **bufp, size_t *remainp)
Decode a 64-bit integer in little-endian order.
int encoded_length_vi32(uint32_t val)
Length of a variable length encoded 32-bit integer (up to 5 bytes)
Group
Definition: StatsSystem.cc:38
StatsSystem()
Default constructor; creates an empty object.
Definition: StatsSystem.h:63
uint16_t decode_i16(const uint8_t **bufp, size_t *remainp)
Decode a 16-bit integer in little-endian order.
LoadAvgStat & refresh()
Definition: SystemInfo.cc:458
Logging routines and macros.
void refresh()
Refreshes the statistics.
Definition: StatsSystem.cc:141
int32_t tcp_close_wait
Definition: SystemInfo.h:214
void encode_i32(uint8_t **bufp, uint32_t val)
Encode a 32-bit integer in little-endian order.
Compatibility Macros for C/C++.
void encode_i16(uint8_t **bufp, uint16_t val)
Encode a 16-bit integer in little-endian order.
void encode_i64(uint8_t **bufp, uint64_t val)
Encode a 64-bit integer in little-endian order.
Functions to serialize/deserialize primitives to/from a memory buffer.
struct ProcStat proc_stat
Process statistics (CPU user time, system time, vm size etc)
Definition: StatsSystem.h:124
struct ProcInfo proc_info
Process information (pid, user, working directory etc)
Definition: StatsSystem.h:121
Collects, serializes and deserializes system-wide statistics.
Definition: StatsSystem.h:43
void encode_vstr(uint8_t **bufp, const void *buf, size_t len)
Encode a buffer as variable length string (vint64, data, null)
Hypertable definitions
#define HT_FATALF(msg,...)
Definition: Logger.h:343
void encode_vi32(uint8_t **bufp, uint32_t val)
Encode a integer (up to 32-bit) in variable length encoding.
std::vector< String > args
Definition: SystemInfo.h:264
struct MemStat mem_stat
Memory statistics (total size, free space, used etc)
Definition: StatsSystem.h:106
double decode_double(const uint8_t **bufp, size_t *remainp)
Decodes a double as 64-bit left-of-decimal, followed by 64-bit right-of-decimal, both in little-endia...
uint32_t cache_size
Definition: SystemInfo.h:56
ProcInfo & init()
Definition: SystemInfo.cc:720
#define HT_FAILURE_SIGNALLED(_label_)
const char * SYSTEM
Definition: Operation.cc:49
struct OsInfo os_info
OS information (name, architecture, version etc)
Definition: StatsSystem.h:118
struct LoadAvgStat loadavg_stat
Load average normalized over number of cores.
Definition: StatsSystem.h:103
std::vector< struct FsStat > fs_stat
Filesystem statistics (free space, used space, aggregate files etc)
Definition: StatsSystem.h:133
struct SwapStat swap_stat
Swapping statistics (page in, page out etc)
Definition: StatsSystem.h:109
void add_categories(int32_t categories)
Adds more categories to the already existing categories.
Definition: StatsSystem.cc:69
CpuInfo & init()
Definition: SystemInfo.cc:399
uint8_t group_ids[32]
The actual group IDs.
SwapStat & refresh()
Definition: SystemInfo.cc:568
ProcStat & refresh()
Definition: SystemInfo.cc:749
std::vector< struct DiskStat > disk_stat
Per-Disk statistics (read-rate, write-rate, etc)
Definition: StatsSystem.h:130
uint32_t decode_vi32(const uint8_t **bufp, size_t *remainp)
Decode a variable length encoded integer up to 32-bit.
uint16_t version_minor
Definition: SystemInfo.h:236
struct CpuStat cpu_stat
CPU statistics (user load, system load, idle etc)
Definition: StatsSystem.h:100
TermInfo & init()
Definition: SystemInfo.cc:799
void encode_double(uint8_t **bufp, double val)
Encodes a double with 18 decimal digits of precision as 64-bit left-of-decimal, followed by 64-bit ri...