/**
* collectd - src/cpu.c
- * Copyright (C) 2005-2007 Florian octo Forster
+ * Copyright (C) 2005-2009 Florian octo Forster
+ * Copyright (C) 2008 Oleg King
+ * Copyright (C) 2009 Simon Kuhnle
+ * Copyright (C) 2009 Manuel Sanmartin
*
* 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
*
* Authors:
* Florian octo Forster <octo at verplant.org>
+ * Oleg King <king2 at kaluga.ru>
+ * Simon Kuhnle <simon at blarzwurst.de>
+ * Manuel Sanmartin
**/
#include "collectd.h"
# include <sys/sysinfo.h>
#endif /* HAVE_LIBKSTAT */
-#ifdef HAVE_SYSCTLBYNAME
+#if (defined(HAVE_SYSCTL) && HAVE_SYSCTL) \
+ || (defined(HAVE_SYSCTLBYNAME) && HAVE_SYSCTLBYNAME)
# ifdef HAVE_SYS_SYSCTL_H
# include <sys/sysctl.h>
# endif
# define CP_IDLE 4
# define CPUSTATES 5
# endif
-#endif /* HAVE_SYSCTLBYNAME */
-
-#if defined(PROCESSOR_CPU_LOAD_INFO) || defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_SYSCTLBYNAME)
-# define CPU_HAVE_READ 1
+#endif /* HAVE_SYSCTL || HAVE_SYSCTLBYNAME */
+
+#if HAVE_SYSCTL
+# if defined(CTL_HW) && defined(HW_NCPU) \
+ && defined(CTL_KERN) && defined(KERN_CPTIME) && defined(CPUSTATES)
+# define CAN_USE_SYSCTL 1
+# else
+# define CAN_USE_SYSCTL 0
+# endif
#else
-# define CPU_HAVE_READ 0
+# define CAN_USE_SYSCTL 0
#endif
-static data_source_t dsrc[1] =
-{
- {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
-};
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
-static data_set_t ds =
-{
- "cpu", 1, dsrc
-};
+# ifdef HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+# endif /* HAVE_PERFSTAT */
+
+#if !PROCESSOR_CPU_LOAD_INFO && !KERNEL_LINUX && !HAVE_LIBKSTAT \
+ && !CAN_USE_SYSCTL && !HAVE_SYSCTLBYNAME && !HAVE_LIBSTATGRAB && !HAVE_PERFSTAT
+# error "No applicable input method."
+#endif
-#if CPU_HAVE_READ
#ifdef PROCESSOR_CPU_LOAD_INFO
static mach_port_t port_host;
static processor_port_array_t cpu_list;
static int numcpu;
/* #endif HAVE_LIBKSTAT */
+#elif CAN_USE_SYSCTL
+static int numcpu;
+/* #endif CAN_USE_SYSCTL */
+
#elif defined(HAVE_SYSCTLBYNAME)
static int numcpu;
-#endif /* HAVE_SYSCTLBYNAME */
+# ifdef HAVE_SYSCTL_KERN_CP_TIMES
+static int maxcpu;
+# endif /* HAVE_SYSCTL_KERN_CP_TIMES */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif defined(HAVE_LIBSTATGRAB)
+/* no variables needed */
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif defined(HAVE_PERFSTAT)
+static perfstat_cpu_t *perfcpu;
+static int numcpu;
+static int pnumcpu;
+#endif /* HAVE_PERFSTAT */
static int init (void)
{
ksp[numcpu++] = ksp_chain;
/* #endif HAVE_LIBKSTAT */
+#elif CAN_USE_SYSCTL
+ size_t numcpu_size;
+ int mib[2] = {CTL_HW, HW_NCPU};
+ int status;
+
+ numcpu = 0;
+ numcpu_size = sizeof (numcpu);
+
+ status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+ &numcpu, &numcpu_size, NULL, 0);
+ if (status == -1)
+ {
+ char errbuf[1024];
+ WARNING ("cpu plugin: sysctl: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+/* #endif CAN_USE_SYSCTL */
+
#elif defined (HAVE_SYSCTLBYNAME)
size_t numcpu_size;
if (sysctlbyname ("hw.ncpu", &numcpu, &numcpu_size, NULL, 0) < 0)
{
char errbuf[1024];
- WARNING ("cpu plugin: sysctlbyname: %s",
+ WARNING ("cpu plugin: sysctlbyname(hw.ncpu): %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
+#ifdef HAVE_SYSCTL_KERN_CP_TIMES
+ numcpu_size = sizeof (maxcpu);
+
+ if (sysctlbyname("kern.smp.maxcpus", &maxcpu, &numcpu_size, NULL, 0) < 0)
+ {
+ char errbuf[1024];
+ WARNING ("cpu plugin: sysctlbyname(kern.smp.maxcpus): %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+#else
if (numcpu != 1)
NOTICE ("cpu: Only one processor supported when using `sysctlbyname' (found %i)", numcpu);
#endif
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif defined(HAVE_LIBSTATGRAB)
+ /* nothing to initialize */
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif defined(HAVE_PERFSTAT)
+ /* nothing to initialize */
+#endif /* HAVE_PERFSTAT */
return (0);
} /* int init */
vl.values = values;
vl.values_len = 1;
- vl.time = time (NULL);
- strcpy (vl.host, hostname_g);
- strcpy (vl.plugin, "cpu");
- snprintf (vl.plugin_instance, sizeof (vl.type_instance),
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
"%i", cpu_num);
- vl.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
- strcpy (vl.type_instance, type_instance);
+ sstrncpy (vl.type, "cpu", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values ("cpu", &vl);
+ plugin_dispatch_values (&vl);
}
static int cpu_read (void)
}
submit (cpu, "user", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
- submit (cpu, "nice", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
- submit (cpu, "system", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
- submit (cpu, "idle", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+ submit (cpu, "nice", (counter_t) cpu_info.cpu_ticks[CPU_STATE_NICE]);
+ submit (cpu, "system", (counter_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM]);
+ submit (cpu, "idle", (counter_t) cpu_info.cpu_ticks[CPU_STATE_IDLE]);
#endif /* PROCESSOR_CPU_LOAD_INFO */
#if PROCESSOR_TEMPERATURE
/*
char *fields[9];
int numfields;
- static complain_t complain_obj;
-
if ((fh = fopen ("/proc/stat", "r")) == NULL)
{
char errbuf[1024];
- plugin_complain (LOG_ERR, &complain_obj, "cpu plugin: "
- "fopen (/proc/stat) failed: %s",
+ ERROR ("cpu plugin: fopen (/proc/stat) failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
- plugin_relief (LOG_NOTICE, &complain_obj, "cpu plugin: "
- "fopen (/proc/stat) succeeded.");
-
while (fgets (buf, 1024, fh) != NULL)
{
if (strncmp (buf, "cpu", 3))
static cpu_stat_t cs;
if (kc == NULL)
- return;
+ return (-1);
for (cpu = 0; cpu < numcpu; cpu++)
{
}
/* #endif defined(HAVE_LIBKSTAT) */
+#elif CAN_USE_SYSCTL
+ uint64_t cpuinfo[numcpu][CPUSTATES];
+ size_t cpuinfo_size;
+ int status;
+ int i;
+
+ if (numcpu < 1)
+ {
+ ERROR ("cpu plugin: Could not determine number of "
+ "installed CPUs using sysctl(3).");
+ return (-1);
+ }
+
+ memset (cpuinfo, 0, sizeof (cpuinfo));
+
+#if defined(KERN_CPTIME2)
+ if (numcpu > 1) {
+ for (i = 0; i < numcpu; i++) {
+ int mib[] = {CTL_KERN, KERN_CPTIME2, i};
+
+ cpuinfo_size = sizeof (cpuinfo[0]);
+
+ status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+ cpuinfo[i], &cpuinfo_size, NULL, 0);
+ if (status == -1) {
+ char errbuf[1024];
+ ERROR ("cpu plugin: sysctl failed: %s.",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+ }
+ }
+ else
+#endif /* defined(KERN_CPTIME2) */
+ {
+ int mib[] = {CTL_KERN, KERN_CPTIME};
+ long cpuinfo_tmp[CPUSTATES];
+
+ cpuinfo_size = sizeof(cpuinfo_tmp);
+
+ status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+ &cpuinfo_tmp, &cpuinfo_size, NULL, 0);
+ if (status == -1)
+ {
+ char errbuf[1024];
+ ERROR ("cpu plugin: sysctl failed: %s.",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ for(i = 0; i < CPUSTATES; i++) {
+ cpuinfo[0][i] = cpuinfo_tmp[i];
+ }
+ }
+
+ for (i = 0; i < numcpu; i++) {
+ submit (i, "user", cpuinfo[i][CP_USER]);
+ submit (i, "nice", cpuinfo[i][CP_NICE]);
+ submit (i, "system", cpuinfo[i][CP_SYS]);
+ submit (i, "idle", cpuinfo[i][CP_IDLE]);
+ submit (i, "interrupt", cpuinfo[i][CP_INTR]);
+ }
+/* #endif CAN_USE_SYSCTL */
+#elif defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYSCTL_KERN_CP_TIMES)
+ long cpuinfo[maxcpu][CPUSTATES];
+ size_t cpuinfo_size;
+ int i;
+
+ memset (cpuinfo, 0, sizeof (cpuinfo));
+
+ cpuinfo_size = sizeof (cpuinfo);
+ if (sysctlbyname("kern.cp_times", &cpuinfo, &cpuinfo_size, NULL, 0) < 0)
+ {
+ char errbuf[1024];
+ ERROR ("cpu plugin: sysctlbyname failed: %s.",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ for (i = 0; i < numcpu; i++) {
+ submit (i, "user", cpuinfo[i][CP_USER]);
+ submit (i, "nice", cpuinfo[i][CP_NICE]);
+ submit (i, "system", cpuinfo[i][CP_SYS]);
+ submit (i, "idle", cpuinfo[i][CP_IDLE]);
+ submit (i, "interrupt", cpuinfo[i][CP_INTR]);
+ }
+/* #endif HAVE_SYSCTL_KERN_CP_TIMES */
#elif defined(HAVE_SYSCTLBYNAME)
long cpuinfo[CPUSTATES];
size_t cpuinfo_size;
- static complain_t complain_obj;
-
cpuinfo_size = sizeof (cpuinfo);
if (sysctlbyname("kern.cp_time", &cpuinfo, &cpuinfo_size, NULL, 0) < 0)
{
char errbuf[1024];
- plugin_complain (LOG_ERR, &complain_obj, "cpu plugin: "
- "sysctlbyname failed: %s.",
+ ERROR ("cpu plugin: sysctlbyname failed: %s.",
sstrerror (errno, errbuf, sizeof (errbuf)));
- return;
+ return (-1);
}
- plugin_relief (LOG_NOTICE, &complain_obj, "cpu plugin: "
- "sysctlbyname succeeded.");
-
- cpuinfo[CP_SYS] += cpuinfo[CP_INTR];
-
submit (0, "user", cpuinfo[CP_USER]);
submit (0, "nice", cpuinfo[CP_NICE]);
submit (0, "system", cpuinfo[CP_SYS]);
submit (0, "idle", cpuinfo[CP_IDLE]);
-#endif
+ submit (0, "interrupt", cpuinfo[CP_INTR]);
+/* #endif HAVE_SYSCTLBYNAME */
- return (0);
-}
-#endif /* CPU_HAVE_READ */
+#elif defined(HAVE_LIBSTATGRAB)
+ sg_cpu_stats *cs;
+ cs = sg_get_cpu_stats ();
-void module_register (modreg_e load)
-{
- if (load & MR_DATASETS)
- plugin_register_data_set (&ds);
+ if (cs == NULL)
+ {
+ ERROR ("cpu plugin: sg_get_cpu_stats failed.");
+ return (-1);
+ }
+
+ submit (0, "idle", (counter_t) cs->idle);
+ submit (0, "nice", (counter_t) cs->nice);
+ submit (0, "swap", (counter_t) cs->swap);
+ submit (0, "system", (counter_t) cs->kernel);
+ submit (0, "user", (counter_t) cs->user);
+ submit (0, "wait", (counter_t) cs->iowait);
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif defined(HAVE_PERFSTAT)
+ perfstat_id_t id;
+ int i, cpus;
+
+ numcpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
+ if(numcpu == -1)
+ {
+ char errbuf[1024];
+ WARNING ("cpu plugin: perfstat_cpu: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ if (pnumcpu != numcpu || perfcpu == NULL)
+ {
+ if (perfcpu != NULL)
+ free(perfcpu);
+ perfcpu = malloc(numcpu * sizeof(perfstat_cpu_t));
+ }
+ pnumcpu = numcpu;
+
+ id.name[0] = '\0';
+ if ((cpus = perfstat_cpu(&id, perfcpu, sizeof(perfstat_cpu_t), numcpu)) < 0)
+ {
+ char errbuf[1024];
+ WARNING ("cpu plugin: perfstat_cpu: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
-#if CPU_HAVE_READ
- if (load & MR_READ)
+ for (i = 0; i < cpus; i++)
{
- plugin_register_init ("cpu", init);
- plugin_register_read ("cpu", cpu_read);
+ submit (i, "idle", (counter_t) perfcpu[i].idle);
+ submit (i, "system", (counter_t) perfcpu[i].sys);
+ submit (i, "user", (counter_t) perfcpu[i].user);
+ submit (i, "wait", (counter_t) perfcpu[i].wait);
}
-#endif /* CPU_HAVE_READ */
+#endif /* HAVE_PERFSTAT */
+
+ return (0);
+}
+
+void module_register (void)
+{
+ plugin_register_init ("cpu", init);
+ plugin_register_read ("cpu", cpu_read);
} /* void module_register */