Merge branch 'collectd-5.5'
authorFlorian Forster <octo@collectd.org>
Thu, 11 Jun 2015 16:33:17 +0000 (17:33 +0100)
committerFlorian Forster <octo@collectd.org>
Thu, 11 Jun 2015 16:33:17 +0000 (17:33 +0100)
1  2 
contrib/redhat/collectd.spec
src/processes.c

  %define with_write_mongodb 0%{!?_without_write_mongodb:0}
  # plugin xmms disabled, requires xmms
  %define with_xmms 0%{!?_without_xmms:0}
 +# plugin zone disabled, requires Solaris
 +%define with_zone 0%{!?_without_zone:0}
  
  Summary:      statistics collection and monitoring daemon
  Name:         collectd
@@@ -226,7 -224,7 +226,7 @@@ Source:            http://collectd.org/files/%{na
  License:      GPLv2
  Group:                System Environment/Daemons
  BuildRoot:    %{_tmppath}/%{name}-%{version}-root
- BuildRequires:        libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel
+ BuildRequires:        libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel, flex, bison
  Vendor:               collectd development team <collectd@verplant.org>
  
  %if 0%{?el7:1}
@@@ -1573,18 -1571,15 +1573,21 @@@ Collectd utilitie
  %define _with_zfs_arc --disable-zfs_arc
  %endif
  
 +%if %{with_zone}
 +%define _with_zone --enable-zone
 +%else
 +%define _with_zone --disable-zone
 +%endif
 +
  %if %{with_zookeeper}
  %define _with_zookeeper --enable-zookeeper
  %else
  %define _with_zookeeper --disable-zookeeper
  %endif
  
+ export YACC=bison
+ export YFLAGS=-y
  %configure CFLAGS="%{optflags} -DLT_LAZY_OR_NOW=\"RTLD_LAZY|RTLD_GLOBAL\"" \
        --disable-static \
        --without-included-ltdl \
        %{?_with_write_redis} \
        %{?_with_xmms} \
        %{?_with_zfs_arc} \
 +      %{?_with_zone} \
        %{?_with_zookeeper} \
        %{?_with_irq} \
        %{?_with_load} \
  %doc contrib/
  
  %changelog
 +#* TODO: next feature release changelog
 +#- New upstream version
 +#- New plugins disabled by default: zone
 +#
  * Wed May 27 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
  - New upstream version
  - New plugins enabled by default: ceph, drbd, log_logstash, write_tsdb, smart,
diff --combined src/processes.c
@@@ -180,9 -180,6 +180,9 @@@ typedef struct procstat_entry_
        derive_t io_syscr;
        derive_t io_syscw;
  
 +      derive_t cswitch_vol;
 +      derive_t cswitch_invol;
 +
        struct procstat_entry_s *next;
  } procstat_entry_t;
  
@@@ -214,17 -211,12 +214,17 @@@ typedef struct procsta
        derive_t io_syscr;
        derive_t io_syscw;
  
 +      derive_t cswitch_vol;
 +      derive_t cswitch_invol;
 +
        struct procstat   *next;
        struct procstat_entry_s *instances;
  } procstat_t;
  
  static procstat_t *list_head_g = NULL;
  
 +static _Bool report_ctx_switch = 0;
 +
  #if HAVE_THREAD_INFO
  static mach_port_t port_host_self;
  static mach_port_t port_task_self;
@@@ -406,8 -398,6 +406,8 @@@ static void ps_list_add (const char *na
                pse->io_wchar   = entry->io_wchar;
                pse->io_syscr   = entry->io_syscr;
                pse->io_syscw   = entry->io_syscw;
 +              pse->cswitch_vol   = entry->cswitch_vol;
 +              pse->cswitch_invol = entry->cswitch_invol;
  
                ps->num_proc   += pse->num_proc;
                ps->num_lwp    += pse->num_lwp;
                ps->io_syscr   += ((pse->io_syscr == -1)?0:pse->io_syscr);
                ps->io_syscw   += ((pse->io_syscw == -1)?0:pse->io_syscw);
  
 +              ps->cswitch_vol   += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol);
 +              ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol);
 +
                if ((entry->vmem_minflt_counter == 0)
                                && (entry->vmem_majflt_counter == 0))
                {
@@@ -521,8 -508,6 +521,8 @@@ static void ps_list_reset (void
                ps->io_wchar = -1;
                ps->io_syscr = -1;
                ps->io_syscw = -1;
 +              ps->cswitch_vol   = -1;
 +              ps->cswitch_invol = -1;
  
                pse_prev = NULL;
                pse = ps->instances;
@@@ -607,10 -592,6 +607,10 @@@ static int ps_config (oconfig_item_t *c
                        ps_list_register (c->values[0].value.string,
                                        c->values[1].value.string);
                }
 +              else if (strcasecmp (c->key, "CollectContextSwitch") == 0)
 +              {
 +                      cf_util_get_boolean (c, &report_ctx_switch);
 +              }
                else
                {
                        ERROR ("processes plugin: The `%s' configuration option is not "
@@@ -760,36 -741,19 +760,36 @@@ static void ps_submit_proc_list (procst
                plugin_dispatch_values (&vl);
        }
  
 +      if ( report_ctx_switch )
 +      {
 +              sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
 +              sstrncpy (vl.type_instance, "voluntary", sizeof (vl.type_instance));
 +              vl.values[0].derive = ps->cswitch_vol;
 +              vl.values_len = 1;
 +              plugin_dispatch_values (&vl);
 +
 +              sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
 +              sstrncpy (vl.type_instance, "involuntary", sizeof (vl.type_instance));
 +              vl.values[0].derive = ps->cswitch_invol;
 +              vl.values_len = 1;
 +              plugin_dispatch_values (&vl);
 +      }
 +
        DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
                        "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
                        "vmem_code = %lu; "
                        "vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
                        "cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
                        "io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; "
 -                      "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";",
 +                      "io_syscr = %"PRIi64"; io_syscw = %"PRIi64"; "
 +                      "cswitch_vol = %"PRIi64"; cswitch_invol = %"PRIi64";",
                        ps->name, ps->num_proc, ps->num_lwp,
                        ps->vmem_size, ps->vmem_rss,
                        ps->vmem_data, ps->vmem_code,
                        ps->vmem_minflt_counter, ps->vmem_majflt_counter,
                        ps->cpu_user_counter, ps->cpu_system_counter,
 -                      ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw);
 +                      ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw,
 +                      ps->cswitch_vol, ps->cswitch_invol);
  } /* void ps_submit_proc_list */
  
  #if KERNEL_LINUX || KERNEL_SOLARIS
@@@ -814,99 -778,42 +814,99 @@@ static void ps_submit_fork_rate (derive
  
  /* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
  #if KERNEL_LINUX
 -static int ps_read_tasks (int pid)
 +static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps)
  {
        char           dirname[64];
        DIR           *dh;
 +      char           filename[64];
 +      FILE          *fh;
        struct dirent *ent;
 -      int count = 0;
 +      derive_t cswitch_vol = 0;
 +      derive_t cswitch_invol = 0;
 +      char buffer[1024];
 +      char *fields[8];
 +      int numfields;
  
        ssnprintf (dirname, sizeof (dirname), "/proc/%i/task", pid);
  
        if ((dh = opendir (dirname)) == NULL)
        {
                DEBUG ("Failed to open directory `%s'", dirname);
 -              return (-1);
 +              return (NULL);
        }
  
        while ((ent = readdir (dh)) != NULL)
        {
 +              char *tpid;
 +
                if (!isdigit ((int) ent->d_name[0]))
                        continue;
 -              else
 -                      count++;
 +
 +              tpid = ent->d_name;
 +
 +              ssnprintf (filename, sizeof (filename), "/proc/%i/task/%s/status", pid, tpid);
 +              if ((fh = fopen (filename, "r")) == NULL)
 +              {
 +                      DEBUG ("Failed to open file `%s'", filename);
 +                      continue;
 +              }
 +
 +              while (fgets (buffer, sizeof(buffer), fh) != NULL)
 +              {
 +                      derive_t tmp;
 +                      char *endptr;
 +
 +                      if (strncmp (buffer, "voluntary_ctxt_switches", 23) != 0
 +                              && strncmp (buffer, "nonvoluntary_ctxt_switches", 26) != 0)
 +                              continue;
 +
 +                      numfields = strsplit (buffer, fields,
 +                              STATIC_ARRAY_SIZE (fields));
 +
 +                      if (numfields < 2)
 +                              continue;
 +
 +                      errno = 0;
 +                      endptr = NULL;
 +                      tmp = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
 +                      if ((errno == 0) && (endptr != fields[1]))
 +                      {
 +                              if (strncmp (buffer, "voluntary_ctxt_switches", 23) == 0)
 +                              {
 +                                      cswitch_vol += tmp;
 +                              }
 +                              else if (strncmp (buffer, "nonvoluntary_ctxt_switches", 26) == 0)
 +                              {
 +                                      cswitch_invol += tmp;
 +                              }
 +                      }
 +              } /* while (fgets) */
 +
 +              if (fclose (fh))
 +              {
 +                      char errbuf[1024];
 +                              WARNING ("processes: fclose: %s",
 +                                      sstrerror (errno, errbuf, sizeof (errbuf)));
 +              }
        }
        closedir (dh);
  
 -      return ((count >= 1) ? count : 1);
 -} /* int *ps_read_tasks */
 +      ps->cswitch_vol = cswitch_vol;
 +      ps->cswitch_invol = cswitch_invol;
 +
 +      return (ps);
 +} /* int *ps_read_tasks_status */
  
 -/* Read advanced virtual memory data from /proc/pid/status */
 -static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
 +/* Read data from /proc/pid/status */
 +static procstat_t *ps_read_status (int pid, procstat_t *ps)
  {
        FILE *fh;
        char buffer[1024];
        char filename[64];
 -      unsigned long long lib = 0;
 -      unsigned long long exe = 0;
 -      unsigned long long data = 0;
 +      unsigned long lib = 0;
 +      unsigned long exe = 0;
 +      unsigned long data = 0;
 +      unsigned long threads = 0;
        char *fields[8];
        int numfields;
  
  
        while (fgets (buffer, sizeof(buffer), fh) != NULL)
        {
 -              long long tmp;
 +              unsigned long tmp;
                char *endptr;
  
 -              if (strncmp (buffer, "Vm", 2) != 0)
 +              if (strncmp (buffer, "Vm", 2) != 0
 +                              && strncmp (buffer, "Threads", 7) != 0)
                        continue;
  
                numfields = strsplit (buffer, fields,
  
                errno = 0;
                endptr = NULL;
 -              tmp = strtoll (fields[1], &endptr, /* base = */ 10);
 +              tmp = strtoul (fields[1], &endptr, /* base = */ 10);
                if ((errno == 0) && (endptr != fields[1]))
                {
                        if (strncmp (buffer, "VmData", 6) == 0)
                        {
                                exe = tmp;
                        }
 +                      else if  (strncmp(buffer, "Threads", 7) == 0)
 +                      {
 +                              threads = tmp;
 +                      }
                }
        } /* while (fgets) */
  
  
        ps->vmem_data = data * 1024;
        ps->vmem_code = (exe + lib) * 1024;
 +      if (threads != 0)
 +              ps->num_lwp = threads;
  
        return (ps);
  } /* procstat_t *ps_read_vmem */
@@@ -1106,16 -1006,11 +1106,16 @@@ int ps_read_process (int pid, procstat_
        }
        else
        {
 -              if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
 +              ps->num_lwp = strtoul (fields[17], /* endptr = */ NULL, /* base = */ 10);
 +              if ((ps_read_status(pid, ps)) == NULL)
                {
 -                      /* returns -1 => kernel 2.4 */
 -                      ps->num_lwp = 1;
 +                      /* No VMem data */
 +                      ps->vmem_data = -1;
 +                      ps->vmem_code = -1;
 +                      DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
                }
 +              if (ps->num_lwp <= 0)
 +                      ps->num_lwp = 1;
                ps->num_proc = 1;
        }
  
        cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ;
        vmem_rss = vmem_rss * pagesize_g;
  
 -      if ( (ps_read_vmem(pid, ps)) == NULL)
 -      {
 -              /* No VMem data */
 -              ps->vmem_data = -1;
 -              ps->vmem_code = -1;
 -              DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
 -      }
 -
        ps->cpu_user_counter = cpu_user_counter;
        ps->cpu_system_counter = cpu_system_counter;
        ps->vmem_size = (unsigned long) vmem_size;
                DEBUG("ps_read_process: not get io data for pid %i",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 %i",pid);
 +              }
 +      }
 +
        /* success */
        return (0);
  } /* int ps_read_process (...) */
@@@ -1849,6 -1740,7 +1849,7 @@@ static int ps_read (void
                        continue;
                }
  
+               memset (&pse, 0, sizeof (pse));
                pse.id       = pid;
                pse.age      = 0;
  
                pse.io_syscr = ps.io_syscr;
                pse.io_syscw = ps.io_syscw;
  
 +              pse.cswitch_vol = ps.cswitch_vol;
 +              pse.cswitch_invol = ps.cswitch_invol;
 +
                switch (state)
                {
                        case 'R': running++;  break;
                                }
                        } /* if (process has argument list) */
  
+                       memset (&pse, 0, sizeof (pse));
                        pse.id       = procs[i].p_pid;
                        pse.age      = 0;
  
                        pse.io_syscr = -1;
                        pse.io_syscw = -1;
  
+                       pse.cswitch_vol = -1;
+                       pse.cswitch_invol = -1;
                        ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
                } /* if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid)) */
  
                        continue;
                }
  
+               memset (&pse, 0, sizeof (pse));
                pse.id = pid;
                pse.age = 0;
  
                pse.io_syscr = ps.io_syscr;
                pse.io_syscw = ps.io_syscw;
  
+               pse.cswitch_vol = -1;
+               pse.cswitch_invol = -1;
                switch (state)
                {
                        case 'R': running++;  break;