X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fvserver.c;h=dac4392693159ad63dc1a095536b5a4cbefe9d09;hb=d3fc6d0831a63af2e96300f488a9f8f5fc3183fb;hp=a6befa7eef2bfbbaf69c82608eb02f354587306b;hpb=5e70f2e08a23dd7c05d6124200bc030b30b11ebc;p=collectd.git diff --git a/src/vserver.c b/src/vserver.c index a6befa7e..dac43926 100644 --- a/src/vserver.c +++ b/src/vserver.c @@ -1,11 +1,10 @@ /** * collectd - src/vserver.c - * Copyright (C) 2006 Sebastian Harl + * Copyright (C) 2006,2007 Sebastian Harl * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Free Software Foundation; only version 2 of the license is applicable. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,200 +24,89 @@ #include "plugin.h" #include -#include -#include -#include -#include #include -#include #define BUFSIZE 512 -#define MODULE_NAME "vserver" #define PROCDIR "/proc/virtual" -#if defined(KERNEL_LINUX) -# define VSERVER_HAVE_READ 1 -#else -# define VSERVER_HAVE_READ 0 -#endif /* defined(KERNEL_LINUX) */ - -static char *rrd_socket = "vserver-%s/socket.rrd"; -static char *rrd_thread = "vserver-%s/threads.rrd"; -static char *rrd_load = "vserver-%s/load.rrd"; -static char *rrd_procs = "vserver-%s/processes.rrd"; -static char *rrd_memory = "vserver-%s/memory.rrd"; - -/* 9223372036854775807 == LLONG_MAX */ -/* bytes transferred */ -static char *ds_def_socket[] = -{ - "DS:unix_in:COUNTER:25:0:9223372036854775807", - "DS:unix_out:COUNTER:25:0:9223372036854775807", - "DS:inet_in:COUNTER:25:0:9223372036854775807", - "DS:inet_out:COUNTER:25:0:9223372036854775807", - "DS:inet6_in:COUNTER:25:0:9223372036854775807", - "DS:inet6_out:COUNTER:25:0:9223372036854775807", - "DS:other_in:COUNTER:25:0:9223372036854775807", - "DS:other_out:COUNTER:25:0:9223372036854775807", - "DS:unspec_in:COUNTER:25:0:9223372036854775807", - "DS:unspec_out:COUNTER:25:0:9223372036854775807", - NULL -}; -static int ds_num_socket = 10; - -static char *ds_def_threads[] = -{ - "DS:total:GAUGE:25:0:65535", - "DS:running:GAUGE:25:0:65535", - "DS:uninterruptible:GAUGE:25:0:65535", - "DS:onhold:GAUGE:25:0:65535", - NULL -}; -static int ds_num_threads = 4; - -static char *ds_def_load[] = -{ - "DS:avg1:GAUGE:25:0:100", - "DS:avg5:GAUGE:25:0:100", - "DS:avg15:GAUGE:25:0:100", - NULL -}; -static int ds_num_load = 3; - -static char *ds_def_procs[] = -{ - "DS:total:GAUGE:25:0:65535", - NULL -}; -static int ds_num_procs = 1; - -/* 9223372036854775807 == LLONG_MAX */ -/* bytes */ -static char *ds_def_memory[] = -{ - "DS:vm:GAUGE:25:0:9223372036854775807", - "DS:vml:GAUGE:25:0:9223372036854775807", - "DS:rss:GAUGE:25:0:9223372036854775807", - "DS:anon:GAUGE:25:0:9223372036854775807", - NULL -}; -static int ds_num_memory = 4; +#if !KERNEL_LINUX +# error "No applicable input method." +#endif static int pagesize = 0; -static void vserver_init (void) +static int vserver_init (void) { /* XXX Should we check for getpagesize () in configure? * What's the right thing to do, if there is no getpagesize ()? */ pagesize = getpagesize (); - return; -} /* static void vserver_init(void) */ - -static void vserver_socket_write (char *host, char *inst, char *val) -{ - int len; - char filename[BUFSIZE]; - len = snprintf (filename, BUFSIZE, rrd_socket, inst); - if ((len > 0) && (len < BUFSIZE)) - rrd_update_file (host, filename, val, ds_def_socket, ds_num_socket); - return; -} /* static void vserver_socket_write(char *host, char *inst, char *val) */ + return (0); +} /* static void vserver_init(void) */ -static void vserver_threads_write (char *host, char *inst, char *val) +static void traffic_submit (const char *plugin_instance, + const char *type_instance, counter_t rx, counter_t tx) { - int len; - char filename[BUFSIZE]; - - len = snprintf (filename, BUFSIZE, rrd_thread, inst); - if ((len > 0) && (len < BUFSIZE)) - rrd_update_file (host, filename, val, ds_def_threads, ds_num_threads); - return; -} /* static void vserver_threads_write(char *host, char *inst, char *val) */ - -static void vserver_load_write (char *host, char *inst, char *val) + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].counter = rx; + values[1].counter = tx; + + vl.values = values; + vl.values_len = STATIC_ARRAY_SIZE (values); + vl.time = time (NULL); + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin)); + sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); + sstrncpy (vl.type, "if_octets", sizeof (vl.type)); + sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} /* void traffic_submit */ + +static void load_submit (const char *plugin_instance, + gauge_t snum, gauge_t mnum, gauge_t lnum) { - int len; - char filename[BUFSIZE]; - - len = snprintf (filename, BUFSIZE, rrd_load, inst); - if ((len > 0) && (len < BUFSIZE)) - rrd_update_file (host, filename, val, ds_def_load, ds_num_load); - return; -} /* static void vserver_load_write(char *host, char *inst, char *val) */ - -static void vserver_procs_write (char *host, char *inst, char *val) -{ - int len; - char filename[BUFSIZE]; + value_t values[3]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].gauge = snum; + values[1].gauge = mnum; + values[2].gauge = lnum; + + vl.values = values; + vl.values_len = STATIC_ARRAY_SIZE (values); + vl.time = time (NULL); + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin)); + sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); + sstrncpy (vl.type, "load", sizeof (vl.type)); + + plugin_dispatch_values (&vl); +} - len = snprintf (filename, BUFSIZE, rrd_procs, inst); - if ((len > 0) && (len < BUFSIZE)) - rrd_update_file (host, filename, val, ds_def_procs, ds_num_procs); - return; -} /* static void vserver_procs_write(char *host, char *inst, char *val) */ +static void submit_gauge (const char *plugin_instance, const char *type, + const char *type_instance, gauge_t value) -static void vserver_memory_write (char *host, char *inst, char *val) { - int len; - char filename[BUFSIZE]; - - len = snprintf (filename, BUFSIZE, rrd_memory, inst); - if ((len > 0) && (len < BUFSIZE)) - rrd_update_file (host, filename, val, ds_def_memory, ds_num_memory); - return; -} /* static void vserver_memory_write(char *host, char *inst, char *val) */ - -#if VSERVER_HAVE_READ -static void vserver_submit (char *inst, long long unix_in, long long unix_out, - long long inet_in, long long inet_out, long long inet6_in, - long long inet6_out, long long other_in, long long other_out, - long long unspec_in, long long unspec_out, int t_total, int t_running, - int t_uninterruptible, int t_onhold, double avg1, double avg5, - double avg15, int p_total, long long vm, long long vml, long long rss, - long long anon) -{ - int len; - char buffer[BUFSIZE]; - - len = snprintf (buffer, BUFSIZE, - "N:%lld:%lld:%lld:%lld:%lld:%lld:%lld:%lld:%lld:%lld", - unix_in, unix_out, inet_in, inet_out, inet6_in, inet6_out, - other_in, other_out, unspec_in, unspec_out); + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; - if ((len > 0) && (len < BUFSIZE)) - plugin_submit ("vserver_socket", inst, buffer); + values[0].gauge = value; + vl.values = values; + vl.values_len = STATIC_ARRAY_SIZE (values); + vl.time = time (NULL); + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin)); + sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); + sstrncpy (vl.type, type, sizeof (vl.type)); + sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); - len = snprintf (buffer, BUFSIZE, "N:%d:%d:%d:%d", - t_total, t_running, t_uninterruptible, t_onhold); - - if ((len > 0) && (len < BUFSIZE)) - plugin_submit ("vserver_threads", inst, buffer); - - - len = snprintf (buffer, BUFSIZE, "N:%.2f:%.2f:%.2f", - avg1, avg5, avg15); - - if ((len > 0) && (len < BUFSIZE)) - plugin_submit ("vserver_load", inst, buffer); - - - len = snprintf (buffer, BUFSIZE, "N:%d", - p_total); - - if ((len > 0) && (len < BUFSIZE)) - plugin_submit ("vserver_procs", inst, buffer); - - - len = snprintf (buffer, BUFSIZE, "N:%lld:%lld:%lld:%lld", - vm, vml, rss, anon); - - if ((len > 0) && (len < BUFSIZE)) - plugin_submit ("vserver_memory", inst, buffer); - return; -} /* static void vserver_submit() */ + plugin_dispatch_values (&vl); +} /* void submit_gauge */ static inline long long __get_sock_bytes(const char *s) { @@ -230,177 +118,239 @@ static inline long long __get_sock_bytes(const char *s) return atoll(s); } -static void vserver_read (void) +static int vserver_read (void) { +#if NAME_MAX < 1024 +# define DIRENT_BUFFER_SIZE (sizeof (struct dirent) + 1024 + 1) +#else +# define DIRENT_BUFFER_SIZE (sizeof (struct dirent) + NAME_MAX + 1) +#endif + DIR *proc; struct dirent *dent; /* 42 */ + char dirent_buffer[DIRENT_BUFFER_SIZE]; errno = 0; - if (NULL == (proc = opendir (PROCDIR))) { - syslog (LOG_ERR, "Cannot open '%s': %s", PROCDIR, strerror (errno)); - return; + proc = opendir (PROCDIR); + if (proc == NULL) + { + char errbuf[1024]; + ERROR ("vserver plugin: fopen (%s): %s", PROCDIR, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); } - while (NULL != (dent = readdir (proc))) { - int len; + while (42) + { + size_t len; char file[BUFSIZE]; FILE *fh; char buffer[BUFSIZE]; + struct stat statbuf; char *cols[4]; - long long socket[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int threads[4] = {-1, -1, -1, -1}; - double load[3] = {-1, -1, -1}; - /* Just to be consistent ;-) */ - int procs[1] = {-1}; - long long memory[4] = {-1, -1, -1, -1}; + int status; + + status = readdir_r (proc, (struct dirent *) dirent_buffer, &dent); + if (status != 0) + { + char errbuf[4096]; + ERROR ("vserver plugin: readdir_r failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + closedir (proc); + return (-1); + } + else if (dent == NULL) + { + /* end of directory */ + break; + } if (dent->d_name[0] == '.') continue; - /* XXX This check is just the result of a trial-and-error test. - * I did not find any documentation describing the d_type field. */ - if (!(dent->d_type & 0x4)) - /* This is not a directory */ + len = snprintf (file, sizeof (file), PROCDIR "/%s", dent->d_name); + if ((len < 0) || (len >= BUFSIZE)) + continue; + + status = stat (file, &statbuf); + if (status != 0) + { + char errbuf[4096]; + WARNING ("vserver plugin: stat (%s) failed: %s", + file, sstrerror (errno, errbuf, sizeof (errbuf))); + continue; + } + + if (!S_ISDIR (statbuf.st_mode)) continue; /* socket message accounting */ - len = snprintf (file, BUFSIZE, PROCDIR "/%s/cacct", dent->d_name); - if ((len < 0) || (len >= BUFSIZE)) + len = ssnprintf (file, sizeof (file), + PROCDIR "/%s/cacct", dent->d_name); + if ((len < 0) || (len >= sizeof (file))) continue; - if (NULL == (fh = fopen (file, "r"))) { - syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno)); - continue; + if (NULL == (fh = fopen (file, "r"))) + { + char errbuf[1024]; + ERROR ("Cannot open '%s': %s", file, + sstrerror (errno, errbuf, sizeof (errbuf))); } - while (NULL != fgets (buffer, BUFSIZE, fh)) { - if (strsplit (buffer, cols, 3) < 3) + while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh))) + { + counter_t rx; + counter_t tx; + char *type_instance; + + if (strsplit (buffer, cols, 4) < 4) continue; - if (0 == strcmp (cols[0], "UNIX:")) { - socket[0] = __get_sock_bytes (cols[1]); - socket[1] = __get_sock_bytes (cols[2]); - } - else if (0 == strcmp (cols[0], "INET:")) { - socket[2] = __get_sock_bytes (cols[1]); - socket[3] = __get_sock_bytes (cols[2]); - } - else if (0 == strcmp (cols[0], "INET6:")) { - socket[4] = __get_sock_bytes (cols[1]); - socket[5] = __get_sock_bytes (cols[2]); - } - else if (0 == strcmp (cols[0], "OTHER:")) { - socket[6] = __get_sock_bytes (cols[1]); - socket[7] = __get_sock_bytes (cols[2]); - } - else if (0 == strcmp (cols[0], "UNSPEC:")) { - socket[8] = __get_sock_bytes (cols[1]); - socket[9] = __get_sock_bytes (cols[2]); - } - } + if (0 == strcmp (cols[0], "UNIX:")) + type_instance = "unix"; + else if (0 == strcmp (cols[0], "INET:")) + type_instance = "inet"; + else if (0 == strcmp (cols[0], "INET6:")) + type_instance = "inet6"; + else if (0 == strcmp (cols[0], "OTHER:")) + type_instance = "other"; + else if (0 == strcmp (cols[0], "UNSPEC:")) + type_instance = "unspec"; + else + continue; - fclose (fh); + rx = __get_sock_bytes (cols[1]); + tx = __get_sock_bytes (cols[2]); + /* cols[3] == errors */ + + traffic_submit (dent->d_name, type_instance, rx, tx); + } /* while (fgets) */ + + if (fh != NULL) + { + fclose (fh); + fh = NULL; + } /* thread information and load */ - len = snprintf (file, BUFSIZE, PROCDIR "/%s/cvirt", dent->d_name); - if ((len < 0) || (len >= BUFSIZE)) + len = ssnprintf (file, sizeof (file), + PROCDIR "/%s/cvirt", dent->d_name); + if ((len < 0) || (len >= sizeof (file))) continue; - if (NULL == (fh = fopen (file, "r"))) { - syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno)); - continue; + if (NULL == (fh = fopen (file, "r"))) + { + char errbuf[1024]; + ERROR ("Cannot open '%s': %s", file, + sstrerror (errno, errbuf, sizeof (errbuf))); } - while (NULL != fgets (buffer, BUFSIZE, fh)) { + while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh))) + { int n = strsplit (buffer, cols, 4); - if (2 == n) { - if (0 == strcmp (cols[0], "nr_threads:")) { - threads[0] = atoi (cols[1]); - } - else if (0 == strcmp (cols[0], "nr_running:")) { - threads[1] = atoi (cols[1]); - } - else if (0 == strcmp (cols[0], "nr_unintr:")) { - threads[2] = atoi (cols[1]); - } - else if (0 == strcmp (cols[0], "nr_onhold:")) { - threads[3] = atoi (cols[1]); - } + if (2 == n) + { + char *type_instance; + gauge_t value; + + if (0 == strcmp (cols[0], "nr_threads:")) + type_instance = "total"; + else if (0 == strcmp (cols[0], "nr_running:")) + type_instance = "running"; + else if (0 == strcmp (cols[0], "nr_unintr:")) + type_instance = "uninterruptable"; + else if (0 == strcmp (cols[0], "nr_onhold:")) + type_instance = "onhold"; + else + continue; + + value = atof (cols[1]); + submit_gauge (dent->d_name, "vs_threads", type_instance, value); } else if (4 == n) { - if (0 == strcmp (cols[0], "loadavg:")) { - load[0] = atof (cols[1]); - load[1] = atof (cols[2]); - load[2] = atof (cols[3]); + if (0 == strcmp (cols[0], "loadavg:")) + { + gauge_t snum = atof (cols[1]); + gauge_t mnum = atof (cols[2]); + gauge_t lnum = atof (cols[3]); + load_submit (dent->d_name, snum, mnum, lnum); } } - } + } /* while (fgets) */ - fclose (fh); + if (fh != NULL) + { + fclose (fh); + fh = NULL; + } /* processes and memory usage */ - len = snprintf (file, BUFSIZE, PROCDIR "/%s/limit", dent->d_name); - if ((len < 0) || (len >= BUFSIZE)) + len = ssnprintf (file, sizeof (file), + PROCDIR "/%s/limit", dent->d_name); + if ((len < 0) || (len >= sizeof (file))) continue; - if (NULL == (fh = fopen (file, "r"))) { - syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno)); - continue; + if (NULL == (fh = fopen (file, "r"))) + { + char errbuf[1024]; + ERROR ("Cannot open '%s': %s", file, + sstrerror (errno, errbuf, sizeof (errbuf))); } - while (NULL != fgets (buffer, BUFSIZE, fh)) { + while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh))) + { + char *type = "vs_memory"; + char *type_instance; + gauge_t value; + if (strsplit (buffer, cols, 2) < 2) continue; - if (0 == strcmp (cols[0], "PROC:")) { - procs[0] = atoi (cols[1]); - } - else if (0 == strcmp (cols[0], "VM:")) { - memory[0] = atoll (cols[1]) * pagesize; + if (0 == strcmp (cols[0], "PROC:")) + { + type = "vs_processes"; + type_instance = ""; + value = atof (cols[1]); } - else if (0 == strcmp (cols[0], "VML:")) { - memory[1] = atoll (cols[1]) * pagesize; + else + { + if (0 == strcmp (cols[0], "VM:")) + type_instance = "vm"; + else if (0 == strcmp (cols[0], "VML:")) + type_instance = "vml"; + else if (0 == strcmp (cols[0], "RSS:")) + type_instance = "rss"; + else if (0 == strcmp (cols[0], "ANON:")) + type_instance = "anon"; + else + continue; + + value = atof (cols[1]) * pagesize; } - else if (0 == strcmp (cols[0], "RSS:")) { - memory[2] = atoll (cols[1]) * pagesize; - } - else if (0 == strcmp (cols[0], "ANON:")) { - memory[3] = atoll (cols[1]) * pagesize; - } - } - - fclose (fh); - /* XXX What to do in case of an error (i.e. some value is - * still -1)? */ + submit_gauge (dent->d_name, type, type_instance, value); + } /* while (fgets) */ - vserver_submit (dent->d_name, socket[0], socket[1], socket[2], - socket[3], socket[4], socket[5], socket[6], socket[7], - socket[8], socket[9], threads[0], threads[1], threads[2], - threads[3], load[0], load[1], load[2], procs[0], memory[0], - memory[1], memory[2], memory[3]); - } + if (fh != NULL) + { + fclose (fh); + fh = NULL; + } + } /* while (readdir) */ closedir (proc); - return; -} /* static void vserver_read(void) */ -#else -# define vserver_read NULL -#endif /* VSERVER_HAVE_READ */ + + return (0); +} /* int vserver_read */ void module_register (void) { - plugin_register (MODULE_NAME, vserver_init, vserver_read, NULL); - plugin_register ("vserver_socket", NULL, NULL, vserver_socket_write); - plugin_register ("vserver_threads", NULL, NULL, vserver_threads_write); - plugin_register ("vserver_load", NULL, NULL, vserver_load_write); - plugin_register ("vserver_procs", NULL, NULL, vserver_procs_write); - plugin_register ("vserver_memory", NULL, NULL, vserver_memory_write); - return; + plugin_register_init ("vserver", vserver_init); + plugin_register_read ("vserver", vserver_read); } /* void module_register(void) */ /* vim: set ts=4 sw=4 noexpandtab : */