processes plugin: Do not gather processes IO and context switch data when unneeded
[collectd.git] / src / processes.c
index 5bacd5b..a29fbbc 100644 (file)
@@ -35,9 +35,9 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
-#include "configfile.h"
 
 /* Include header files for the mach system, if they exist.. */
 #if HAVE_THREAD_INFO
@@ -185,9 +185,11 @@ typedef struct procstat_entry_s
        derive_t io_wchar;
        derive_t io_syscr;
        derive_t io_syscw;
+       _Bool    has_io;
 
        derive_t cswitch_vol;
        derive_t cswitch_invol;
+       _Bool    has_cswitch;
 
        struct procstat_entry_s *next;
 } procstat_entry_t;
@@ -241,6 +243,7 @@ static mach_msg_type_number_t     pset_list_len;
 
 #elif KERNEL_LINUX
 static long pagesize_g;
+static void ps_fill_details (const procstat_t *ps, procstat_entry_t *entry);
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
@@ -366,47 +369,46 @@ static int ps_list_match (const char *name, const char *cmdline, procstat_t *ps)
        return (0);
 } /* int ps_list_match */
 
-static void ps_update_counter (
-        _Bool init,
-        derive_t *group_counter,
-        derive_t *curr_counter, unsigned long *curr_value,
-        derive_t new_counter, unsigned long new_value) {
-    if (init)
-    {
-        *curr_value = new_value;
-        *curr_counter += new_value;
-        *group_counter += new_value;
-        return;
-    }
-
-    if (new_counter < *curr_counter)
-    {
-        *curr_value = new_counter + (ULONG_MAX - *curr_counter);
-    }
-    else
-    {
-        *curr_value = new_counter - *curr_counter;
-    }
-    *curr_counter = new_counter;
-    *group_counter += *curr_value;
+static void ps_update_counter (_Bool init, derive_t *group_counter,
+                               derive_t *curr_counter, unsigned long *curr_value,
+                               derive_t new_counter, unsigned long new_value)
+{
+       if (init)
+       {
+               *curr_value = new_value;
+               *curr_counter += new_value;
+               *group_counter += new_value;
+               return;
+       }
+
+       if (new_counter < *curr_counter)
+               *curr_value = new_counter + (ULONG_MAX - *curr_counter);
+       else
+               *curr_value = new_counter - *curr_counter;
+
+       *curr_counter = new_counter;
+       *group_counter += *curr_value;
 }
 
 /* add process entry to 'instances' of process 'name' (or refresh it) */
 static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t *entry)
 {
-       procstat_t *ps;
        procstat_entry_t *pse;
 
        if (entry->id == 0)
                return;
 
-       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
        {
-        _Bool want_init;
+               _Bool want_init;
 
                if ((ps_list_match (name, cmdline, ps)) == 0)
                        continue;
 
+#if KERNEL_LINUX
+               ps_fill_details(ps, entry);
+#endif
+
                for (pse = ps->instances; pse != NULL; pse = pse->next)
                        if ((pse->id == entry->id) || (pse->next == NULL))
                                break;
@@ -486,11 +488,10 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
 /* remove old entries from instances of processes in list_head_g */
 static void ps_list_reset (void)
 {
-       procstat_t *ps;
        procstat_entry_t *pse;
        procstat_entry_t *pse_prev;
 
-       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
        {
                ps->num_proc    = 0;
                ps->num_lwp     = 0;
@@ -542,15 +543,13 @@ static void ps_list_reset (void)
 /* put all pre-defined 'Process' names from config to list_head_g tree */
 static int ps_config (oconfig_item_t *ci)
 {
-       int i;
-
 #if KERNEL_LINUX
        const size_t max_procname_len = 15;
 #elif KERNEL_SOLARIS || KERNEL_FREEBSD
        const size_t max_procname_len = MAXCOMLEN -1;
 #endif
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (strcasecmp (c->key, "Process") == 0)
@@ -668,14 +667,10 @@ static int ps_init (void)
 /* submit global state (e.g.: qty of zombies, running, etc..) */
 static void ps_submit_state (const char *state, double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
-       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
        sstrncpy (vl.type, "ps_state", sizeof (vl.type));
@@ -687,12 +682,10 @@ static void ps_submit_state (const char *state, double value)
 /* submit info about specific process (e.g.: memory taken, cpu usage, etc..) */
 static void ps_submit_proc_list (procstat_t *ps)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
+       value_t values[2];
 
        vl.values = values;
-       vl.values_len = 2;
-       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
 
@@ -792,14 +785,10 @@ static void ps_submit_proc_list (procstat_t *ps)
 #if KERNEL_LINUX || KERNEL_SOLARIS
 static void ps_submit_fork_rate (derive_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .derive = value };
        vl.values_len = 1;
-       sstrncpy(vl.host, hostname_g, sizeof (vl.host));
        sstrncpy(vl.plugin, "processes", sizeof (vl.plugin));
        sstrncpy(vl.plugin_instance, "", sizeof (vl.plugin_instance));
        sstrncpy(vl.type, "fork_rate", sizeof (vl.type));
@@ -811,7 +800,7 @@ static void ps_submit_fork_rate (derive_t value)
 
 /* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
 #if KERNEL_LINUX
-static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
+static int ps_read_tasks_status (procstat_entry_t *ps)
 {
        char           dirname[64];
        DIR           *dh;
@@ -824,12 +813,12 @@ static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
        char *fields[8];
        int numfields;
 
-       ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", pid);
+       ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", ps->id);
 
        if ((dh = opendir (dirname)) == NULL)
        {
                DEBUG ("Failed to open directory `%s'", dirname);
-               return (NULL);
+               return (-1);
        }
 
        while ((ent = readdir (dh)) != NULL)
@@ -841,7 +830,7 @@ static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
 
                tpid = ent->d_name;
 
-               ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", pid, tpid);
+               ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", ps->id, tpid);
                if ((fh = fopen (filename, "r")) == NULL)
                {
                        DEBUG ("Failed to open file `%s'", filename);
@@ -882,8 +871,8 @@ static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
                if (fclose (fh))
                {
                        char errbuf[1024];
-                               WARNING ("processes: fclose: %s",
-                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       WARNING ("processes: fclose: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
                }
        }
        closedir (dh);
@@ -891,7 +880,7 @@ static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
        ps->cswitch_vol = cswitch_vol;
        ps->cswitch_invol = cswitch_invol;
 
-       return (ps);
+       return (0);
 } /* int *ps_read_tasks_status */
 
 /* Read data from /proc/pid/status */
@@ -965,7 +954,7 @@ static procstat_t *ps_read_status (long pid, procstat_t *ps)
        return (ps);
 } /* procstat_t *ps_read_vmem */
 
-static procstat_t *ps_read_io (long pid, procstat_t *ps)
+static int ps_read_io (procstat_entry_t *ps)
 {
        FILE *fh;
        char buffer[1024];
@@ -974,9 +963,9 @@ static procstat_t *ps_read_io (long pid, procstat_t *ps)
        char *fields[8];
        int numfields;
 
-       ssnprintf (filename, sizeof (filename), "/proc/%li/io", pid);
+       ssnprintf (filename, sizeof (filename), "/proc/%li/io", ps->id);
        if ((fh = fopen (filename, "r")) == NULL)
-               return (NULL);
+               return (-1);
 
        while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
@@ -1016,9 +1005,36 @@ static procstat_t *ps_read_io (long pid, procstat_t *ps)
                WARNING ("processes: fclose: %s",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
        }
+       return (0);
+} /* int ps_read_io (...) */
 
-       return (ps);
-} /* procstat_t *ps_read_io */
+static void ps_fill_details (const procstat_t *ps, procstat_entry_t *entry)
+{
+       if ( entry->has_io == 0 && ps_read_io (entry) != 0 )
+       {
+               /* no io data */
+               entry->io_rchar = -1;
+               entry->io_wchar = -1;
+               entry->io_syscr = -1;
+               entry->io_syscw = -1;
+
+               DEBUG("ps_read_process: not get io data for pid %li", entry->id);
+       }
+       entry->has_io = 1;
+
+       if ( report_ctx_switch )
+       {
+               if ( entry->has_cswitch == 0 && ps_read_tasks_status(entry) != 0 )
+               {
+                       entry->cswitch_vol = -1;
+                       entry->cswitch_invol = -1;
+
+                       DEBUG("ps_read_tasks_status: not get context "
+                                       "switch data for pid %li", entry->id);
+               }
+               entry->has_cswitch = 1;
+       }
+} /* void ps_fill_details (...) */
 
 static int ps_read_process (long pid, procstat_t *ps, char *state)
 {
@@ -1151,29 +1167,6 @@ static int ps_read_process (long pid, procstat_t *ps, char *state)
        ps->vmem_rss = (unsigned long) vmem_rss;
        ps->stack_size = (unsigned long) stack_size;
 
-       if ( (ps_read_io (pid, ps)) == NULL)
-       {
-               /* no io data */
-               ps->io_rchar = -1;
-               ps->io_wchar = -1;
-               ps->io_syscr = -1;
-               ps->io_syscw = -1;
-
-               DEBUG("ps_read_process: not get io data for pid %li", pid);
-       }
-
-       if ( report_ctx_switch )
-       {
-               if ( (ps_read_tasks_status(pid, ps)) == NULL)
-               {
-                       ps->cswitch_vol = -1;
-                       ps->cswitch_invol = -1;
-
-                       DEBUG("ps_read_tasks_status: not get context "
-                                       "switch data for pid %li", pid);
-               }
-       }
-
        /* success */
        return (0);
 } /* int ps_read_process (...) */
@@ -1471,13 +1464,12 @@ static int ps_read_process(long pid, procstat_t *ps, char *state)
 static int read_fork_rate (void)
 {
        extern kstat_ctl_t *kc;
-       kstat_t *ksp_chain = NULL;
        derive_t result = 0;
 
        if (kc == NULL)
                return (-1);
 
-       for (ksp_chain = kc->kc_chain;
+       for (kstat_t *ksp_chain = kc->kc_chain;
                        ksp_chain != NULL;
                        ksp_chain = ksp_chain->ks_next)
        {
@@ -1543,17 +1535,14 @@ static int ps_read (void)
 #if HAVE_THREAD_INFO
        kern_return_t            status;
 
-       int                      pset;
        processor_set_t          port_pset_priv;
 
-       int                      task;
        task_array_t             task_list;
        mach_msg_type_number_t   task_list_len;
 
        int                      task_pid;
        char                     task_name[MAXCOMLEN + 1];
 
-       int                      thread;
        thread_act_array_t       thread_list;
        mach_msg_type_number_t   thread_list_len;
        thread_basic_info_data_t thread_data;
@@ -1578,7 +1567,7 @@ static int ps_read (void)
         * Tasks are assigned to sets of processors, so that's where you go to
         * get a list.
         */
-       for (pset = 0; pset < pset_list_len; pset++)
+       for (mach_msg_type_number_t pset = 0; pset < pset_list_len; pset++)
        {
                if ((status = host_processor_set_priv (port_host_self,
                                                pset_list[pset],
@@ -1599,7 +1588,7 @@ static int ps_read (void)
                        continue;
                }
 
-               for (task = 0; task < task_list_len; task++)
+               for (mach_msg_type_number_t task = 0; task < task_list_len; task++)
                {
                        ps = NULL;
                        if (mach_get_task_name (task_list[task],
@@ -1697,7 +1686,7 @@ static int ps_read (void)
                                continue; /* with next task_list */
                        }
 
-                       for (thread = 0; thread < thread_list_len; thread++)
+                       for (mach_msg_type_number_t thread = 0; thread < thread_list_len; thread++)
                        {
                                thread_data_len = THREAD_BASIC_INFO_COUNT;
                                status = thread_info (thread_list[thread],
@@ -1828,8 +1817,6 @@ static int ps_read (void)
        procstat_entry_t pse;
        char       state;
 
-       procstat_t *ps_ptr;
-
        running = sleeping = zombies = stopped = paging = blocked = 0;
        ps_list_reset ();
 
@@ -1910,7 +1897,7 @@ static int ps_read (void)
        ps_submit_state ("paging",   paging);
        ps_submit_state ("blocked",  blocked);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 
        read_fork_rate();
@@ -1930,9 +1917,7 @@ static int ps_read (void)
        struct kinfo_proc *procs;          /* array of processes */
        struct kinfo_proc *proc_ptr = NULL;
        int count;                         /* returns number of processes */
-       int i;
 
-       procstat_t *ps_ptr;
        procstat_entry_t pse;
 
        ps_list_reset ();
@@ -1957,7 +1942,7 @@ static int ps_read (void)
        }
 
        /* Iterate through the processes in kinfo_proc */
-       for (i = 0; i < count; i++)
+       for (int i = 0; i < count; i++)
        {
                /* Create only one process list entry per _process_, i.e.
                 * filter out threads (duplicate PID entries). */
@@ -2060,7 +2045,7 @@ static int ps_read (void)
        ps_submit_state ("idle",     idle);
        ps_submit_state ("wait",     wait);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
 
@@ -2078,9 +2063,7 @@ static int ps_read (void)
        struct kinfo_proc *procs;          /* array of processes */
        struct kinfo_proc *proc_ptr = NULL;
        int count;                         /* returns number of processes */
-       int i;
 
-       procstat_t *ps_ptr;
        procstat_entry_t pse;
 
        ps_list_reset ();
@@ -2105,7 +2088,7 @@ static int ps_read (void)
        }
 
        /* Iterate through the processes in kinfo_proc */
-       for (i = 0; i < count; i++)
+       for (int i = 0; i < count; i++)
        {
                /* Create only one process list entry per _process_, i.e.
                 * filter out threads (duplicate PID entries). */
@@ -2197,7 +2180,7 @@ static int ps_read (void)
        ps_submit_state ("idle",     idle);
        ps_submit_state ("dead",     dead);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD */
 
@@ -2213,7 +2196,6 @@ static int ps_read (void)
        pid_t pindex = 0;
        int nprocs;
 
-       procstat_t *ps;
        procstat_entry_t pse;
 
        ps_list_reset ();
@@ -2221,9 +2203,7 @@ static int ps_read (void)
                                        /* fdsinfo = */ NULL, sizeof(struct fdsinfo64),
                                        &pindex, MAXPROCENTRY)) > 0)
        {
-               int i;
-
-               for (i = 0; i < nprocs; i++)
+               for (int i = 0; i < nprocs; i++)
                {
                        tid64_t thindex;
                        int nthreads;
@@ -2334,7 +2314,7 @@ static int ps_read (void)
        ps_submit_state ("paging",   paging);
        ps_submit_state ("blocked",  blocked);
 
-       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
                ps_submit_proc_list (ps);
 /* #endif HAVE_PROCINFO_H */
 
@@ -2358,7 +2338,6 @@ static int ps_read (void)
        DIR *proc;
 
        int status;
-       procstat_t *ps_ptr;
        char state;
 
        char cmdline[PRARGSZ];
@@ -2448,7 +2427,7 @@ static int ps_read (void)
        ps_submit_state ("system",   system);
        ps_submit_state ("orphan",   orphan);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 
        read_fork_rate();