23 #include "procrrd_thread.h" 25 #include <utils/time/wait.h> 32 #define PROC_CONF_PREFIX "/plugins/procrrd/processes/" 66 __netinterface =
"wlan0";
71 __lastcpu =
new unsigned long int[11];
74 __net_recv_graph = NULL;
75 __net_trans_graph = NULL;
76 std::vector<RRDDataSource> rrds;
80 rrds.push_back(
RRDDataSource(
"net_recv_bytes", RRDDataSource::COUNTER));
82 rrds.push_back(
RRDDataSource(
"net_recv_packets", RRDDataSource::COUNTER));
84 rrds.push_back(
RRDDataSource(
"net_recv_errors", RRDDataSource::COUNTER));
86 rrds.push_back(
RRDDataSource(
"net_trans_bytes", RRDDataSource::COUNTER));
88 rrds.push_back(
RRDDataSource(
"net_trans_packets", RRDDataSource::COUNTER));
90 rrds.push_back(
RRDDataSource(
"net_trans_errors", RRDDataSource::COUNTER));
100 std::vector<RRDGraphDataDefinition> defs;
101 std::vector<RRDGraphElement *> els;
110 els.push_back(
new RRDGraphLine(
"net_recv_bytes", 1,
"006400",
"Bytes"));
111 els.push_back(
new RRDGraphGPrint(
"net_recv_bytes", RRDArchive::LAST,
112 " Current\\:%8.2lf %s"));
113 els.push_back(
new RRDGraphGPrint(
"net_recv_bytes", RRDArchive::AVERAGE,
114 "Average\\:%8.2lf %s"));
115 els.push_back(
new RRDGraphGPrint(
"net_recv_bytes", RRDArchive::MAX,
116 "Maximum\\:%8.2lf %s\\n"));
118 els.push_back(
new RRDGraphLine(
"net_recv_packets", 1,
"808000",
"Packets"));
119 els.push_back(
new RRDGraphGPrint(
"net_recv_packets", RRDArchive::LAST,
120 "Current\\:%8.2lf %s"));
121 els.push_back(
new RRDGraphGPrint(
"net_recv_packets", RRDArchive::AVERAGE,
122 "Average\\:%8.2lf %s"));
123 els.push_back(
new RRDGraphGPrint(
"net_recv_packets", RRDArchive::MAX,
124 "Maximum\\:%8.2lf %s\\n"));
126 els.push_back(
new RRDGraphLine(
"net_recv_errors", 1,
"FF0000",
"Errors"));
127 els.push_back(
new RRDGraphGPrint(
"net_recv_errors", RRDArchive::LAST,
128 " Current\\:%8.2lf %s"));
129 els.push_back(
new RRDGraphGPrint(
"net_recv_errors", RRDArchive::AVERAGE,
130 "Average\\:%8.2lf %s"));
131 els.push_back(
new RRDGraphGPrint(
"net_recv_errors", RRDArchive::MAX,
132 "Maximum\\:%8.2lf %s\\n"));
135 "Network Receive",
"",
148 els.push_back(
new RRDGraphLine(
"net_trans_bytes", 1,
"006400",
"Bytes"));
149 els.push_back(
new RRDGraphGPrint(
"net_trans_bytes", RRDArchive::LAST,
150 " Current\\:%8.2lf %s"));
151 els.push_back(
new RRDGraphGPrint(
"net_trans_bytes", RRDArchive::AVERAGE,
152 "Average\\:%8.2lf %s"));
153 els.push_back(
new RRDGraphGPrint(
"net_trans_bytes", RRDArchive::MAX,
154 "Maximum\\:%8.2lf %s\\n"));
156 els.push_back(
new RRDGraphLine(
"net_trans_packets", 1,
"808000",
"Packets"));
157 els.push_back(
new RRDGraphGPrint(
"net_trans_packets", RRDArchive::LAST,
158 "Current\\:%8.2lf %s"));
159 els.push_back(
new RRDGraphGPrint(
"net_trans_packets", RRDArchive::AVERAGE,
160 "Average\\:%8.2lf %s"));
161 els.push_back(
new RRDGraphGPrint(
"net_trans_packets", RRDArchive::MAX,
162 "Maximum\\:%8.2lf %s\\n"));
164 els.push_back(
new RRDGraphLine(
"net_trans_errors", 1,
"FF0000",
"Errors"));
165 els.push_back(
new RRDGraphGPrint(
"net_trans_errors", RRDArchive::LAST,
166 " Current\\:%8.2lf %s"));
167 els.push_back(
new RRDGraphGPrint(
"net_trans_errors", RRDArchive::AVERAGE,
168 "Average\\:%8.2lf %s"));
169 els.push_back(
new RRDGraphGPrint(
"net_trans_errors", RRDArchive::MAX,
170 "Maximum\\:%8.2lf %s\\n"));
173 "Network Transmit",
"",
184 std::string procprefix = PROC_CONF_PREFIX;
187 std::string selfid = get_process_id(
"fawkes");
188 add_process((procprefix+
"fawkes").c_str(), selfid,
"fawkes");
208 std::string pid = get_process_id(name.c_str());
211 logger->
log_warn(this->
name(),
"Failed to add process: %s, exception follows", name.c_str());
219 ProcessMap::iterator pi = __processes.begin();
222 for (; pi != __processes.end(); ++pi) {
223 p +=
", "+pi->second.name;
228 logger->
log_info(
name(),
"ProcRRD logging network interface %s and processes %s with a samplerate of %lu second(s)",
229 __netinterface.c_str(), p.c_str(), __samplerate);
243 for (ProcessMap::iterator i = __processes.begin(); i != __processes.end(); ++i) {
244 ProcessInfo &info = i->second;
246 delete info.cpu_graph;
247 delete info.mem_graph;
248 delete info.io_read_graph;
249 delete info.io_write_graph;
254 delete __net_recv_graph;
255 delete __net_trans_graph;
260 ProcRRDThread::add_process(
const char *path, std::string pid, std::string
name)
262 if (__processes.find(path) != __processes.end()) {
263 throw Exception(
"Process stats for config %s already monitored", path);
270 info.last_cpu =
new unsigned long int[3];
272 file = fopen((
"/proc/"+pid+
"/stat").c_str(),
"r");
277 fscanf(file,
"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*d %*d %*d %*d %*d %*d %*u %*u %*d %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %*d %*u %*u %*u %*d", info.last_cpu+1, info.last_cpu+2);
279 info.last_cpu[0] = info.last_cpu[1] + info.last_cpu[2];
283 std::vector<RRDDataSource> rrds;
286 rrds.push_back(
RRDDataSource(
"cpu_usage", RRDDataSource::GAUGE));
288 rrds.push_back(
RRDDataSource(
"cpu_threads", RRDDataSource::GAUGE));
291 rrds.push_back(
RRDDataSource(
"mem_maxvirt", RRDDataSource::GAUGE));
293 rrds.push_back(
RRDDataSource(
"mem_curvirt", RRDDataSource::GAUGE));
295 rrds.push_back(
RRDDataSource(
"mem_rss", RRDDataSource::GAUGE));
299 rrds.push_back(
RRDDataSource(
"io_rchar", RRDDataSource::COUNTER));
301 rrds.push_back(
RRDDataSource(
"io_wchar", RRDDataSource::COUNTER));
303 rrds.push_back(
RRDDataSource(
"io_syscr", RRDDataSource::COUNTER));
305 rrds.push_back(
RRDDataSource(
"io_syscw", RRDDataSource::COUNTER));
307 rrds.push_back(
RRDDataSource(
"io_read_bytes", RRDDataSource::COUNTER));
309 rrds.push_back(
RRDDataSource(
"io_write_bytes", RRDDataSource::COUNTER));
311 rrds.push_back(
RRDDataSource(
"io_cancelled_write", RRDDataSource::COUNTER));
316 info.rrd_name = info.name +
"_" + info.pid;
319 while((at = info.rrd_name.find_first_of(
" .-", pos)) != std::string::npos) {
320 info.rrd_name.replace(at, 1,
"_");
326 std::vector<RRDGraphDataDefinition> defs;
327 std::vector<RRDGraphElement *> els;
334 els.push_back(
new RRDGraphLine(
"cpu_usage", 1,
"FF0000",
"Usage %"));
336 "Current\\:%8.2lf %s"));
337 els.push_back(
new RRDGraphGPrint(
"cpu_usage", RRDArchive::AVERAGE,
338 "Average\\:%8.2lf %s"));
340 "Maximum\\:%8.2lf %s\\n"));
342 els.push_back(
new RRDGraphLine(
"cpu_threads", 1,
"008800",
"Threads"));
344 "Current\\:%8.2lf %s"));
345 els.push_back(
new RRDGraphGPrint(
"cpu_threads", RRDArchive::AVERAGE,
346 "Average\\:%8.2lf %s"));
348 "Maximum\\:%8.2lf %s\\n"));
350 std::string g1name = info.rrd_name +
"_cpu";
351 std::string g1title = std::string(
"CPU Usage in % and Number Threads for ") + info.name +
"(" + pid +
")";
353 g1title.c_str(),
"", defs, els);
356 defs.clear(); els.clear();
358 info.rrd,
"mem_maxvirt"));
360 info.rrd,
"mem_curvirt"));
362 info.rrd,
"mem_rss"));
367 els.push_back(
new RRDGraphArea(
"mem_maxvirt",
"3B7AD9",
"VmPeak"));
369 "Current\\:%8.2lf %s"));
370 els.push_back(
new RRDGraphGPrint(
"mem_maxvirt", RRDArchive::AVERAGE,
371 "Average\\:%8.2lf %s"));
373 "Maximum\\:%8.2lf %s\\n"));
375 els.push_back(
new RRDGraphArea(
"mem_curvirt",
"6FD1BF",
"VmSize"));
377 "Current\\:%8.2lf %s"));
378 els.push_back(
new RRDGraphGPrint(
"mem_curvirt", RRDArchive::AVERAGE,
379 "Average\\:%8.2lf %s"));
381 "Maximum\\:%8.2lf %s\\n"));
383 els.push_back(
new RRDGraphArea(
"mem_rss",
"0E6E5C",
"VmRSS"));
385 " Current\\:%8.2lf %s"));
387 "Average\\:%8.2lf %s"));
389 "Maximum\\:%8.2lf %s\\n"));
391 std::string g2name = info.rrd_name +
"_memory";
392 std::string g2title = std::string(
"Memory Usage for ") + info.name +
"(" + pid +
")";
394 g2title.c_str(),
"Bytes", defs, els);
406 els.push_back(
new RRDGraphLine(
"io_rchar", 1,
"556B2F",
"rchar"));
408 "Current\\:%8.2lf %s"));
410 "Average\\:%8.2lf %s"));
412 "Maximum\\:%8.2lf %s\\n"));
414 els.push_back(
new RRDGraphLine(
"io_syscr", 1,
"9ACD32",
"syscr"));
416 "Current\\:%8.2lf %s"));
418 "Average\\:%8.2lf %s"));
420 "Maximum\\:%8.2lf %s\\n"));
422 els.push_back(
new RRDGraphLine(
"io_read_bytes", 1,
"98FB98",
"bytes"));
423 els.push_back(
new RRDGraphGPrint(
"io_read_bytes", RRDArchive::LAST,
424 "Current\\:%8.2lf %s"));
425 els.push_back(
new RRDGraphGPrint(
"io_read_bytes", RRDArchive::AVERAGE,
426 "Average\\:%8.2lf %s"));
427 els.push_back(
new RRDGraphGPrint(
"io_read_bytes", RRDArchive::MAX,
428 "Maximum\\:%8.2lf %s\\n"));
430 std::string g3name = info.rrd_name +
"_io_read";
431 std::string g3title = std::string(
"IO Read Operations for ") + info.name +
"(" + pid +
")";
433 g3title.c_str(),
"Bytes", defs, els);
446 els.push_back(
new RRDGraphLine(
"io_wchar", 1,
"800000",
"wchar"));
448 " Current\\:%8.2lf %s"));
450 "Average\\:%8.2lf %s"));
452 "Maximum\\:%8.2lf %s\\n"));
454 els.push_back(
new RRDGraphLine(
"io_syscw", 1,
"FF0000",
"syscw"));
456 " Current\\:%8.2lf %s"));
458 "Average\\:%8.2lf %s"));
460 "Maximum\\:%8.2lf %s\\n"));
462 els.push_back(
new RRDGraphLine(
"io_write_bytes", 1,
"FF8C00",
"bytes"));
463 els.push_back(
new RRDGraphGPrint(
"io_write_bytes", RRDArchive::LAST,
464 " Current\\:%8.2lf %s"));
465 els.push_back(
new RRDGraphGPrint(
"io_write_bytes", RRDArchive::AVERAGE,
466 "Average\\:%8.2lf %s"));
467 els.push_back(
new RRDGraphGPrint(
"io_write_bytes", RRDArchive::MAX,
468 "Maximum\\:%8.2lf %s\\n"));
470 els.push_back(
new RRDGraphLine(
"io_cancelled_write", 1,
"FFA07A",
"cancelled"));
471 els.push_back(
new RRDGraphGPrint(
"io_cancelled_write", RRDArchive::LAST,
472 "Current\\:%8.2lf %s"));
473 els.push_back(
new RRDGraphGPrint(
"io_cancelled_write", RRDArchive::AVERAGE,
474 "Average\\:%8.2lf %s"));
475 els.push_back(
new RRDGraphGPrint(
"io_cancelled_write", RRDArchive::MAX,
476 "Maximum\\:%8.2lf %s\\n"));
478 std::string g4name = info.rrd_name +
"_io_write";
479 std::string g4title = std::string(
"IO Write Operations for ") + info.name +
"(" + pid +
")";
481 g4title.c_str(),
"Bytes", defs, els);
489 __processes[path] = info;
491 info.name.c_str(), info.pid.c_str());
494 delete info.cpu_graph;
495 delete info.mem_graph;
496 delete info.io_read_graph;
497 delete info.io_write_graph;
505 ProcRRDThread::remove_process(
const char *path)
507 if (__processes.find(path) != __processes.end()) {
508 ProcessInfo &info = __processes[path];
510 delete info.cpu_graph;
511 delete info.mem_graph;
512 delete info.io_read_graph;
513 delete info.io_write_graph;
517 info.name.c_str(), info.pid.c_str());
518 __processes.erase(path);
523 ProcRRDThread::get_process_id(
const char *process)
527 struct dirent *dir_entry_p;
532 dir_p = opendir(
"/proc/");
534 while(NULL != (dir_entry_p = readdir(dir_p))) {
536 if (strspn(dir_entry_p->d_name,
"0123456789") == strlen(dir_entry_p->d_name)) {
537 std::string f =
"/proc/" + std::string(dir_entry_p->d_name) +
"/status";
539 file = fopen(f.c_str(),
"r");
542 fscanf(file,
"Name: %s", name);
545 if(strcmp(process, name) == 0) {
546 result = std::string(dir_entry_p->d_name);
558 ProcRRDThread::get_cpu(
unsigned long int* cpus)
561 file = fopen(
"/proc/stat",
"r");
563 i = fscanf(file,
"cpu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", cpus+1, cpus+2, cpus+3, cpus+4, cpus+5, cpus+6, cpus+7, cpus+8, cpus+9, cpus+10);
565 for(
int j=1; j<=i; j++)
576 file = fopen(
"/proc/net/dev",
"r");
577 unsigned long long int recv_bytes, recv_packets, recv_errors, trans_bytes, trans_packets, trans_errors;
578 recv_bytes = recv_packets = recv_errors = trans_bytes = trans_packets = trans_errors = 0;
580 while (file && fgets(line, 1024, file) != NULL){
583 sscanf(line,
"%s", dev);
585 if (strncmp(dev, (__netinterface+
":").c_str(), __netinterface.length()+1) == 0){
586 sscanf(line,
"%*s %llu %llu %llu %*u %*u %*u %*u %*u %llu %llu %llu %*u %*u %*u %*u %*u", &recv_bytes, &recv_packets, &recv_errors, &trans_bytes, &trans_packets, &trans_errors);
592 rrd_manager->
add_data(
"network",
"N:%llu:%llu:%llu:%llu:%llu:%llu", recv_bytes, recv_packets, recv_errors, trans_bytes, trans_packets, trans_errors);
598 unsigned long int *curcpu =
new unsigned long int[11];
601 for (ProcessMap::iterator i = __processes.begin(); i != __processes.end(); ++i) {
602 file = fopen((
"/proc/"+i->second.pid+
"/stat").c_str(),
"r");
603 unsigned long int cpu[3];
605 fscanf(file,
"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu", cpu+1, cpu+2);
606 cpu[0] = cpu[1] + cpu[2];
609 file = fopen((
"/proc/"+i->second.pid+
"/status").c_str(),
"r");
610 unsigned long long int vmpeak, vmsize, vmrss;
611 long int threads = 0;
612 vmpeak = vmsize = vmrss = 0;
614 while (file && fgets(line, 128, file) != NULL){
615 if (strncmp(line,
"VmPeak:", 7) == 0){
616 sscanf(line,
"VmPeak: %llu", &vmpeak);
618 else if (strncmp(line,
"VmSize:", 7) == 0){
619 sscanf(line,
"VmSize: %llu", &vmsize);
621 else if (strncmp(line,
"VmRSS:", 6) == 0){
622 sscanf(line,
"VmRSS: %llu", &vmrss);
624 else if (strncmp(line,
"Threads:", 8) == 0){
625 sscanf(line,
"Threads: %ld", &threads);
630 file = fopen((
"/proc/"+i->second.pid+
"/io").c_str(),
"r");
631 unsigned long long int rchar, wchar, syscr, syscw, read_bytes, write_bytes, cancelled_write_bytes;
632 rchar = wchar = syscr = syscw = read_bytes = write_bytes = cancelled_write_bytes = 0;
634 while (file && fgets(line2, 128, file) != NULL){
635 if (strncmp(line2,
"rchar:", 6) == 0){
636 sscanf(line2,
"rchar: %llu", &rchar);
638 else if (strncmp(line2,
"wchar:", 6) == 0){
639 sscanf(line2,
"wchar: %llu", &wchar);
641 else if (strncmp(line2,
"syscr:", 6) == 0){
642 sscanf(line2,
"syscr: %llu", &syscr);
644 else if (strncmp(line2,
"syscw:", 6) == 0){
645 sscanf(line2,
"syscw: %llu", &syscw);
647 else if (strncmp(line2,
"read_bytes:", 11) == 0){
648 sscanf(line2,
"read_bytes: %llu", &read_bytes);
650 else if (strncmp(line2,
"write_bytes:", 12) == 0){
651 sscanf(line2,
"write_bytes: %llu", &write_bytes);
653 else if (strncmp(line2,
"cancelled_write_bytes:", 22) == 0){
654 sscanf(line2,
"cancelled_write_bytes: %llu", &cancelled_write_bytes);
661 if(curcpu[0] < __lastcpu[0] || curcpu[1] < __lastcpu[1] || curcpu[2] < __lastcpu[2] || curcpu[3] < __lastcpu[3] || curcpu[4] < __lastcpu[4] || curcpu[5] < __lastcpu[5] || curcpu[6] < __lastcpu[6] || curcpu[7] < __lastcpu[7] || curcpu[8] < __lastcpu[8] || curcpu[9] < __lastcpu[9] || curcpu[10] < __lastcpu[10] || cpu[0] < i->second.last_cpu[0] || cpu[1] < i->second.last_cpu[1] || cpu[2] < i->second.last_cpu[2]) {
664 rrd_manager->
add_data(i->second.rrd_name.c_str(),
"N:U:%ld:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu", threads, vmpeak, vmsize, vmrss, rchar, wchar, syscr, syscw, read_bytes, write_bytes, cancelled_write_bytes);
666 logger->
log_warn(
name(),
"Failed to update %s RRD, exception follows", i->second.rrd_name.c_str());
671 double cpuuse = 100.0 * (double)(cpu[0] - i->second.last_cpu[0]) / (double)(curcpu[0] - __lastcpu[0]);
673 rrd_manager->
add_data(i->second.rrd_name.c_str(),
"N:%f:%ld:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu", cpuuse, threads, vmpeak, vmsize, vmrss, rchar, wchar, syscr, syscw, read_bytes, write_bytes, cancelled_write_bytes);
675 logger->
log_warn(
name(),
"Failed to update %s RRD, exception follows", i->second.rrd_name.c_str());
680 i->second.last_cpu[0] = cpu[0];
689 ProcRRDThread::config_tag_changed(
const char *new_tag)
699 remove_process(v->
path());
701 std::string pid = get_process_id(name.c_str());
714 ProcRRDThread::config_value_erased(
const char *path)
717 remove_process(path);
virtual void loop()
Code to execute in the thread.
RRDManager * rrd_manager
Manager class to access RRD features.
virtual void add_rrd(RRDDefinition *rrd_def)=0
Add RRD.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
virtual const char * type() const =0
Type of value.
Fawkes library namespace.
Interface for configuration change handling.
virtual ValueIterator * search(const char *path)=0
Iterator with search results.
virtual bool next()=0
Check if there is another element and advance to this if possible.
virtual void add_graph(RRDGraphDefinition *rrd_graph_def)=0
Add graph.
Thread class encapsulation of pthreads.
void set_prepfin_conc_loop(bool concurrent=true)
Set concurrent execution of prepare_finalize() and loop().
virtual void add_data(const char *rrd_name, const char *format,...)=0
Add data.
Logger * logger
This is the Logger member used to access the logger.
void wait_systime()
Wait until minimum loop time has been reached in real time.
virtual void finalize()
Finalize the thread.
Clock * clock
By means of this member access to the clock is given.
virtual bool is_string() const =0
Check if current value is a string.
Represent data definition in graph arguments.
Base class for exceptions in Fawkes.
Class representing a graph definition.
virtual ~ProcRRDThread()
Destructor.
virtual void rem_change_handler(ConfigurationChangeHandler *h)
Remove a configuration change handler.
Class to represent a RRD data source.
virtual std::string get_string() const =0
Get string value.
const char * name() const
Get name of thread.
virtual void remove_rrd(RRDDefinition *rrd_def)=0
Remove RRD.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual const char * path() const =0
Path of value.
void mark_start()
Mark start of loop.
Iterator interface to iterate over config values.
ProcRRDThread()
Constructor.
virtual void add_change_handler(ConfigurationChangeHandler *h)
Add a configuration change handler.
Print string inside graph.
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
virtual void init()
Initialize the thread.
Configuration * config
This is the Configuration member used to access the configuration.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.