[collectd] [PATCH] Plugin cpu - added CPU percent and summary usage
Vladimir I. Umnov
vladimir.umnov at gmail.com
Wed Mar 16 12:08:47 CET 2011
Added HZ and for all systems numcpu defaults to 1. Now jiffies multiplied to 100/HZ.
In sysctl capable systems HZ extracted from kern.clockrate stathz. In linux it's sysconf(_SC_CLK_TCK); For other systems it's defaults to 100 for now.
Added config options
<Plugin cpu>
PerCpuStatistic true
ScaleTo100 false
</Plugin>
Now summary CPU statistic always collected (it's more usefull than percore).
PerCpuStatistic - also collect data for each cpu
ScaleTo100 - scale summary cpu data to 100% (divide by numcpu).
---
src/cpu.c | 209 +++++++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 155 insertions(+), 54 deletions(-)
diff --git a/src/cpu.c b/src/cpu.c
index 12071a2..6f533e6 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -113,7 +113,6 @@ static int cpu_temp_retry_max = 1;
/* #endif PROCESSOR_CPU_LOAD_INFO */
#elif defined(KERNEL_LINUX)
-/* no variables needed */
/* #endif KERNEL_LINUX */
#elif defined(HAVE_LIBKSTAT)
@@ -121,15 +120,14 @@ static int cpu_temp_retry_max = 1;
# define MAX_NUMCPU 256
extern kstat_ctl_t *kc;
static kstat_t *ksp[MAX_NUMCPU];
-static int numcpu;
+//static int numcpu;
/* #endif HAVE_LIBKSTAT */
#elif CAN_USE_SYSCTL
-static int numcpu;
/* #endif CAN_USE_SYSCTL */
#elif defined(HAVE_SYSCTLBYNAME)
-static int numcpu;
+//static int numcpu;
# ifdef HAVE_SYSCTL_KERN_CP_TIMES
static int maxcpu;
# endif /* HAVE_SYSCTL_KERN_CP_TIMES */
@@ -141,10 +139,48 @@ static int maxcpu;
#elif defined(HAVE_PERFSTAT)
static perfstat_cpu_t *perfcpu;
-static int numcpu;
+//static int numcpu;
static int pnumcpu;
#endif /* HAVE_PERFSTAT */
+static const char *config_keys[] =
+{
+ "PerCpuStatistic",
+ "ScaleTo100",
+ NULL
+};
+static int config_keys_num = 2;
+
+static int numcpu = 1;
+static bool per_cpu_statistic = false;
+static bool scale = true;
+static int hz=100;
+
+
+static int cpu_config (const char *key, const char *value)
+{
+ if (strcasecmp (key, "PerCpuStatistic") == 0)
+ {
+ if (IS_TRUE (value))
+ per_cpu_statistic = true;
+ else
+ per_cpu_statistic = false;
+ }
+ else if (strcasecmp (key, "ScaleTo100") == 0)
+ {
+ if (IS_TRUE (value))
+ scale = true;
+ else
+ scale = false;
+ }
+ else
+ {
+ return (-1);
+ }
+
+ return (0);
+}
+
static int init (void)
{
#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
@@ -199,6 +235,21 @@ static int init (void)
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
+
+ struct clockinfo ci;
+ size_t ci_size = sizeof (ci);
+ int mib[2] = {CTL_KERN, KERN_CLOCKRATE};
+
+ status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+ &ci, &ci_size, NULL, 0);
+ if (status == -1)
+ {
+ char errbuf[1024];
+ WARNING ("cpu plugin: sysctl: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+ hz = ci.stathz;
/* #endif CAN_USE_SYSCTL */
#elif defined (HAVE_SYSCTLBYNAME)
@@ -214,6 +265,17 @@ static int init (void)
return (-1);
}
+ struct clockinfo ci;
+ size_t ci_size = sizeof (ci);
+ if (sysctlbyname ("kern.clockrate", &ci, &ci_size, NULL, 0) < 0)
+ {
+ char errbuf[1024];
+ WARNING ("cpu plugin: sysctlbyname(kern.clockrate): %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+ hz = ci.stathz;
+
#ifdef HAVE_SYSCTL_KERN_CP_TIMES
numcpu_size = sizeof (maxcpu);
@@ -238,6 +300,11 @@ static int init (void)
/* nothing to initialize */
#endif /* HAVE_PERFSTAT */
+#if defined(KERNEL_LINUX)
+ numcpu = sysconf( _SC_NPROCESSORS_ONLN );
+ hz = sysconf(_SC_CLK_TCK);
+#endif /* KERNEL_LINUX */
+
return (0);
} /* int init */
@@ -246,13 +313,20 @@ static void submit (int cpu_num, const char *type_instance, derive_t value)
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- values[0].derive = value;
+ if (hz != 100)
+ values[0].derive = (derive_t) (value * (100.0 / hz));
+ else
+ values[0].derive = value;
+
+ if (scale && cpu_num < 0)
+ values[0].derive = values[0].derive / numcpu;
vl.values = values;
vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
- ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ if (cpu_num >= 0)
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
"%i", cpu_num);
sstrncpy (vl.type, "cpu", sizeof (vl.type));
sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
@@ -359,6 +433,7 @@ static int cpu_read (void)
char *fields[9];
int numfields;
+ bool allcpu;
if ((fh = fopen ("/proc/stat", "r")) == NULL)
{
@@ -372,14 +447,20 @@ static int cpu_read (void)
{
if (strncmp (buf, "cpu", 3))
continue;
- if ((buf[3] < '0') || (buf[3] > '9'))
+
+ allcpu = buf[3] == ' ';
+ if ( ((!per_cpu_statistic) || (buf[3] < '0') || (buf[3] > '9')) && (!allcpu) )
continue;
numfields = strsplit (buf, fields, 9);
if (numfields < 5)
continue;
- cpu = atoi (fields[0] + 3);
+ if (allcpu)
+ cpu = -1;
+ else
+ cpu = atoi (fields[0] + 3);
+
user = atoll (fields[1]);
nice = atoll (fields[2]);
syst = atoll (fields[3]);
@@ -449,7 +530,7 @@ static int cpu_read (void)
memset (cpuinfo, 0, sizeof (cpuinfo));
#if defined(KERN_CPTIME2)
- if (numcpu > 1) {
+ if (per_cpu_statistic && numcpu > 1) {
for (i = 0; i < numcpu; i++) {
int mib[] = {CTL_KERN, KERN_CPTIME2, i};
@@ -464,61 +545,79 @@ static int cpu_read (void)
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]);
+ }
}
- else
#endif /* defined(KERN_CPTIME2) */
- {
- int mib[] = {CTL_KERN, KERN_CPTIME};
- long cpuinfo_tmp[CPUSTATES];
+ int mib[] = {CTL_KERN, KERN_CPTIME};
+ long cpuinfo_tmp[CPUSTATES];
- cpuinfo_size = sizeof(cpuinfo_tmp);
+ cpuinfo_size = sizeof(cpuinfo_tmp);
- status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+ 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];
- }
+ if (status == -1)
+ {
+ char errbuf[1024];
+ ERROR ("cpu plugin: sysctl 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]);
- }
+ submit (-1, "user", cpuinfo_tmp[CP_USER]);
+ submit (-1, "nice", cpuinfo_tmp[CP_NICE]);
+ submit (-1, "system", cpuinfo_tmp[CP_SYS]);
+ submit (-1, "idle", cpuinfo_tmp[CP_IDLE]);
+ submit (-1, "interrupt", cpuinfo_tmp[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)
+ size_t cpuinfo_size;
+ if (per_cpu_statistic) {
+ long cpuinfo[maxcpu][CPUSTATES];
+ 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]);
+ }
+ }
+
+ long cpuinfo2[CPUSTATES];
+
+ cpuinfo_size = sizeof (cpuinfo2);
+
+ if (sysctlbyname("kern.cp_time", &cpuinfo2, &cpuinfo_size, NULL, 0) < 0)
{
char errbuf[1024];
ERROR ("cpu plugin: sysctlbyname failed: %s.",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
+ submit (-1, "user", cpuinfo2[CP_USER]);
+ submit (-1, "nice", cpuinfo2[CP_NICE]);
+ submit (-1, "system", cpuinfo2[CP_SYS]);
+ submit (-1, "idle", cpuinfo2[CP_IDLE]);
+ submit (-1, "interrupt", cpuinfo2[CP_INTR]);
- 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];
@@ -534,11 +633,11 @@ static int cpu_read (void)
return (-1);
}
- submit (0, "user", cpuinfo[CP_USER]);
- submit (0, "nice", cpuinfo[CP_NICE]);
- submit (0, "system", cpuinfo[CP_SYS]);
- submit (0, "idle", cpuinfo[CP_IDLE]);
- submit (0, "interrupt", cpuinfo[CP_INTR]);
+ submit (-1, "user", cpuinfo[CP_USER]);
+ submit (-1, "nice", cpuinfo[CP_NICE]);
+ submit (-1, "system", cpuinfo[CP_SYS]);
+ submit (-1, "idle", cpuinfo[CP_IDLE]);
+ submit (-1, "interrupt", cpuinfo[CP_INTR]);
/* #endif HAVE_SYSCTLBYNAME */
#elif defined(HAVE_LIBSTATGRAB)
@@ -603,6 +702,8 @@ static int cpu_read (void)
void module_register (void)
{
+ plugin_register_config ("cpu", cpu_config,
+ config_keys, config_keys_num);
plugin_register_init ("cpu", init);
plugin_register_read ("cpu", cpu_read);
} /* void module_register */
--
1.7.4.1
More information about the collectd
mailing list