From fdfc8dc0e165088350f7c92972234cea142cd131 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Ritschard Date: Wed, 15 Jan 2014 21:26:19 +0100 Subject: [PATCH] Add ReportByCpu and ValuesPercentage for cpu plugin ReportByCpu defaults to true, ValuesPercentage to false This enables the following use cases: - ReportByCpu false: emits normalized percentage values - ValuesPercentage true: emits percentage values - default: send per core ticks, as previously --- src/cpu.c | 315 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 213 insertions(+), 102 deletions(-) diff --git a/src/cpu.c b/src/cpu.c index f1aa4abe..5edb5923 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -86,6 +86,19 @@ # define CAN_USE_SYSCTL 0 #endif +#define CPU_SUBMIT_USER 1 +#define CPU_SUBMIT_SYSTEM 2 +#define CPU_SUBMIT_WAIT 3 +#define CPU_SUBMIT_NICE 4 +#define CPU_SUBMIT_SWAP 5 +#define CPU_SUBMIT_INTERRUPT 6 +#define CPU_SUBMIT_SOFTIRQ 7 +#define CPU_SUBMIT_STEAL 8 +#define CPU_SUBMIT_IDLE 9 +#define CPU_SUBMIT_ACTIVE 10 +#define CPU_SUBMIT_MAX 11 +#define CPU_SUBMIT_FLUSH -1 + #if HAVE_STATGRAB_H # include #endif @@ -100,6 +113,20 @@ # error "No applicable input method." #endif +static const char *submit_names[] = { + "none", + "user", + "system", + "wait", + "nice", + "swap", + "interrupt", + "softirq", + "steal", + "idle", + "active" +}; + #ifdef PROCESSOR_CPU_LOAD_INFO static mach_port_t port_host; static processor_port_array_t cpu_list; @@ -145,6 +172,29 @@ static int numcpu; static int pnumcpu; #endif /* HAVE_PERFSTAT */ + +static _Bool report_by_cpu = 1; +static _Bool report_percent = 0; + +static const char *config_keys[] = +{ + "ReportByCpu", + "ValuesPercentage" +}; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); + +static int cpu_config (const char *key, const char *value) +{ + if (strcasecmp (key, "ReportByCpu") == 0) { + report_by_cpu = IS_TRUE (value) ? 1 : 0; + if (!report_by_cpu) + report_percent = 1; + } + if (strcasecmp (key, "ValuesPercentage") == 0) + report_percent = IS_TRUE (value) ? 1 : 0; + return (-1); +} + static int init (void) { #if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE @@ -241,32 +291,112 @@ static int init (void) return (0); } /* int init */ -static void submit (int cpu_num, const char *type_instance, derive_t value) +static void submit_value (int plugin_instance, int type_instance, + derive_t val_d, gauge_t val_g) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; vl.values = values; vl.values_len = 1; + + if (report_percent) + values[0].gauge = val_g; + else + values[0].derive = val_d; + 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); - sstrncpy (vl.type, "cpu", sizeof (vl.type)); - sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + sstrncpy (vl.type, report_percent?"percent":"cpu", sizeof (vl.type)); + sstrncpy (vl.type_instance, submit_names[type_instance], + sizeof (vl.type_instance)); + if (plugin_instance > 0) { + ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance), + "%i", plugin_instance); + } plugin_dispatch_values (&vl); } +static void submit (int cpu_num, derive_t *derives) +{ + + int i = 0; + derive_t cpu_active = 0; + derive_t cpu_total = 0; + static int numcpu = 0; + static gauge_t percents[CPU_SUBMIT_MAX] = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }; + gauge_t gauges[CPU_SUBMIT_MAX] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + if (cpu_num == CPU_SUBMIT_FLUSH) + { + if (report_by_cpu) + return; + for (i = 1; i < CPU_SUBMIT_MAX; i++) { + if (percents[i] == -1) + continue; + submit_value (-1, i, 0, percents[i] / numcpu); + } + numcpu = 0; + memset(percents, 0, sizeof(percents)); + return; + } + + if (!report_percent && report_by_cpu) { + + for (i = 1; i < CPU_SUBMIT_ACTIVE; i++) + { + if (derives[i] == -1) + continue; + + if (i != CPU_SUBMIT_IDLE) + cpu_active += derives[i]; + + submit_value(cpu_num, i, derives[i], 0); + } + submit_value(cpu_num, CPU_SUBMIT_ACTIVE, cpu_active, 0); + } + else /* we are reporting percents */ + { + for (i = 1; i < CPU_SUBMIT_ACTIVE; i++) { + if (derives[i] == -1) + continue; + cpu_total += derives[i]; + if (i != CPU_SUBMIT_IDLE) + cpu_active += derives[i]; + } + derives[CPU_SUBMIT_ACTIVE] = cpu_active; + + numcpu++; + for (i = 1; i < CPU_SUBMIT_MAX; i++) { + if (derives[i] == -1) { + percents[i] = -1; + continue; + } + gauges[i] = ((gauge_t)derives[i] / (gauge_t)cpu_total) * 100.0; + + if (report_by_cpu) + { + submit_value (cpu_num, i, 0, gauges[i]); + } else if (gauges[i] != -1) { + percents[i] += gauges[i]; + } + } + } +} + static int cpu_read (void) { #if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE int cpu; kern_return_t status; - + #if PROCESSOR_CPU_LOAD_INFO derive_t cpu_active; processor_cpu_load_info_data_t cpu_info; @@ -278,10 +408,12 @@ static int cpu_read (void) #endif host_t cpu_host; + derive_t derives[CPU_SUBMIT_MAX]; for (cpu = 0; cpu < cpu_list_len; cpu++) { #if PROCESSOR_CPU_LOAD_INFO + memset(derives, -1, sizeof(derives)); cpu_host = 0; cpu_info_len = PROCESSOR_BASIC_INFO_COUNT; @@ -299,15 +431,12 @@ static int cpu_read (void) continue; } - submit (cpu, "user", (derive_t) cpu_info.cpu_ticks[CPU_STATE_USER]); - submit (cpu, "nice", (derive_t) cpu_info.cpu_ticks[CPU_STATE_NICE]); - submit (cpu, "system", (derive_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM]); - submit (cpu, "idle", (derive_t) cpu_info.cpu_ticks[CPU_STATE_IDLE]); - cpu_active = (derive_t) (cpu_info.cpu_ticks[CPU_STATE_USER] + - cpu_info.cpu_ticks[CPU_STATE_NICE] + - cpu_info.cpu_ticks[CPU_STATE_SYSTEM]); - submit (cpu, "active", cpu_active); - + derives[CPU_USER] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_USER]; + derives[CPU_NICE] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_NICE]; + derives[CPU_SYSTEM] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM]; + derives[CPU_IDLE] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_IDLE]; + submit (cpu, derives); + #endif /* PROCESSOR_CPU_LOAD_INFO */ #if PROCESSOR_TEMPERATURE /* @@ -352,13 +481,12 @@ static int cpu_read (void) cpu_temp_retry_step = 1; #endif /* PROCESSOR_TEMPERATURE */ } + submit(CPU_SUBMIT_FLUSH, NULL); /* #endif PROCESSOR_CPU_LOAD_INFO */ #elif defined(KERNEL_LINUX) int cpu; - derive_t cpu_active; - derive_t user, nice, syst, idle; - derive_t wait, intr, sitr; /* sitr == soft interrupt */ + derive_t derives[CPU_SUBMIT_MAX]; FILE *fh; char buf[1024]; @@ -385,42 +513,31 @@ static int cpu_read (void) continue; cpu = atoi (fields[0] + 3); - user = atoll (fields[1]); - nice = atoll (fields[2]); - syst = atoll (fields[3]); - idle = atoll (fields[4]); - - submit (cpu, "user", user); - submit (cpu, "nice", nice); - submit (cpu, "system", syst); - submit (cpu, "idle", idle); - cpu_active = user + nice + syst; + memset(derives, -1, sizeof(derives)); + derives[CPU_SUBMIT_USER] = atoll(fields[1]); + derives[CPU_SUBMIT_NICE] = atoll(fields[2]); + derives[CPU_SUBMIT_SYSTEM] = atoll(fields[3]); + derives[CPU_SUBMIT_IDLE] = atoll(fields[4]); if (numfields >= 8) { - wait = atoll (fields[5]); - intr = atoll (fields[6]); - sitr = atoll (fields[7]); - - submit (cpu, "wait", wait); - submit (cpu, "interrupt", intr); - submit (cpu, "softirq", sitr); - - cpu_active += wait + intr + sitr; + derives[CPU_SUBMIT_WAIT] = atoll(fields[5]); + derives[CPU_SUBMIT_INTERRUPT] = atoll(fields[6]); + derives[CPU_SUBMIT_SOFTIRQ] = atoll(fields[6]); if (numfields >= 9) - cpu_active += (derive_t) atoll (fields[8]); - submit (cpu, "steal", atoll (fields[8])); + derives[CPU_SUBMIT_STEAL] = atoll(fields[8]); } - submit (cpu, "active", cpu_active); + submit(cpu, derives); } + submit(CPU_SUBMIT_FLUSH, NULL); fclose (fh); /* #endif defined(KERNEL_LINUX) */ #elif defined(HAVE_LIBKSTAT) int cpu; - derive_t user, syst, idle, wait; + derive_t derives[]user, syst, idle, wait; static cpu_stat_t cs; if (kc == NULL) @@ -431,17 +548,14 @@ static int cpu_read (void) if (kstat_read (kc, ksp[cpu], &cs) == -1) continue; /* error message? */ - idle = (derive_t) cs.cpu_sysinfo.cpu[CPU_IDLE]; - user = (derive_t) cs.cpu_sysinfo.cpu[CPU_USER]; - syst = (derive_t) cs.cpu_sysinfo.cpu[CPU_KERNEL]; - wait = (derive_t) cs.cpu_sysinfo.cpu[CPU_WAIT]; - - submit (ksp[cpu]->ks_instance, "user", user); - submit (ksp[cpu]->ks_instance, "system", syst); - submit (ksp[cpu]->ks_instance, "idle", idle); - submit (ksp[cpu]->ks_instance, "wait", wait); - submit (ksp[cpu]->ks_instance, "active", user + syst + wait); + memset(derives, -1, sizeof(derives)); + derives[CPU_SUBMIT_IDLE] = cs.cpu_sysinfo.cpu[CPU_IDLE]; + derives[CPU_SUBMIT_USER] = cs.cpu_sysinfo.cpu[CPU_USER]; + derives[CPU_SUBMIT_SYSTEM] = cs.cpu_sysinfo.cpu[CPU_KERNEL]; + derives[CPU_SUBMIT_WAIT] = cs.cpu_sysinfo.cpu[CPU_WAIT]; + submit (ksp[cpu]->ks_instance, derives); } + submit (CPU_SUBMIT_FLUSH, NULL); /* #endif defined(HAVE_LIBKSTAT) */ #elif CAN_USE_SYSCTL @@ -500,21 +614,21 @@ static int cpu_read (void) } 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 (i, "active", cpuinfo[i][CP_USER] + - cpuinfo[i][CP_NICE] + - cpuinfo[i][CP_SYS] + - cpuinfo[i][CP_INTR]); + memset(derives, -1, sizeof(derives)); + derives[CPU_SUBMIT_USER] = cpuinfo[i][CP_USER]; + derives[CPU_SUBMIT_NICE] = cpuinfo[i][CP_NICE]; + derives[CPU_SUBMIT_SYSTEM] = cpuinfo[i][CP_SYS]; + derives[CPU_SUBMIT_IDLE] = cpuinfo[i][CP_IDLE]; + derives[CPU_SUBMIT_INTERRUPT] = cpuinfo[i][CP_INTR]; + submit(i, derives); } + submit(CPU_SUBMIT_FLUSH, NULL); /* #endif CAN_USE_SYSCTL */ #elif defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYSCTL_KERN_CP_TIMES) long cpuinfo[maxcpu][CPUSTATES]; size_t cpuinfo_size; int i; + derive_t derives[CPU_SUBMIT_MAX]; memset (cpuinfo, 0, sizeof (cpuinfo)); @@ -528,20 +642,20 @@ static int cpu_read (void) } 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 (i, "active", cpuinfo[i][CP_USER] + - cpuinfo[i][CP_NICE] + - cpuinfo[i][CP_SYS] + - cpuinfo[i][CP_INTR]); + memset(derives, -1, sizeof(derives)); + derives[CPU_SUBMIT_USER] = cpuinfo[i][CP_USER]; + derives[CPU_SUBMIT_NICE] = cpuinfo[i][CP_NICE]; + derives[CPU_SUBMIT_SYSTEM] = cpuinfo[i][CP_SYS]; + derives[CPU_SUBMIT_IDLE] = cpuinfo[i][CP_IDLE]; + derives[CPU_SUBMIT_INTERRUPT] = cpuinfo[i][CP_INTR]; } + submit(CPU_SUBMIT_FLUSH, NULL); + /* #endif HAVE_SYSCTL_KERN_CP_TIMES */ #elif defined(HAVE_SYSCTLBYNAME) long cpuinfo[CPUSTATES]; size_t cpuinfo_size; + derive_t derives[CPU_SUBMIT_MAX]; cpuinfo_size = sizeof (cpuinfo); @@ -553,19 +667,20 @@ 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 (0, "active", cpuinfo[CP_USER] + - cpuinfo[CP_NICE] + - cpuinfo[CP_SYS] + - cpuinfo[CP_INTR]); + memset(derives, -1, sizeof(derives)); + derives[CPU_SUBMIT_USER] = cpuinfo[CP_USER]; + derives[CPU_SUBMIT_SYSTEM] = cpuinfo[CP_SYS]; + derives[CPU_SUBMIT_NICE] = cpuinfo[CP_NICE]; + derives[CPU_SUBMIT_IDLE] = cpuinfo[CP_IDLE]; + derives[CPU_SUBMIT_INTERRUPT] = cpuinfo[CP_INTR]; + submit(0, derives); + submit(CPU_SUBMIT_FLUSH, NULL); + /* #endif HAVE_SYSCTLBYNAME */ #elif defined(HAVE_LIBSTATGRAB) sg_cpu_stats *cs; + derive_t derives[CPU_SUBMIT_MAX]; cs = sg_get_cpu_stats (); if (cs == NULL) @@ -574,23 +689,19 @@ static int cpu_read (void) return (-1); } - submit (0, "idle", (derive_t) cs->idle); - submit (0, "nice", (derive_t) cs->nice); - submit (0, "swap", (derive_t) cs->swap); - submit (0, "system", (derive_t) cs->kernel); - submit (0, "user", (derive_t) cs->user); - submit (0, "wait", (derive_t) cs->iowait); - submit (0, "active", (derive_t) cs->nice + - cs->swap + - cs->kernel + - cs->user + - cs->iowait + - cs->nice); + memset(derives, -1, sizeof(derives)); + derives[CPU_SUBMIT_IDLE] = (derive_t) cs->idle; + derives[CPU_SUBMIT_NICE] = (derive_t) cs->nice; + derives[CPU_SUBMIT_SWAP] = (derive_t) cs->swap; + derives[CPU_SUBMIT_SYSTEM] = (derive_t) cs->kernel; + derives[CPU_SUBMIT_USER] = (derive_t) cs->user; + derives[CPU_SUBMIT_WAIT] = (derive_t) cs->iowait; /* #endif HAVE_LIBSTATGRAB */ #elif defined(HAVE_PERFSTAT) perfstat_id_t id; int i, cpus; + derive_t derives[CPU_SUBMIT_MAX]; numcpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); if(numcpu == -1) @@ -600,10 +711,10 @@ static int cpu_read (void) sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } - - if (pnumcpu != numcpu || perfcpu == NULL) + + if (pnumcpu != numcpu || perfcpu == NULL) { - if (perfcpu != NULL) + if (perfcpu != NULL) free(perfcpu); perfcpu = malloc(numcpu * sizeof(perfstat_cpu_t)); } @@ -618,16 +729,15 @@ static int cpu_read (void) return (-1); } - for (i = 0; i < cpus; i++) + for (i = 0; i < cpus; i++) { - submit (i, "idle", (derive_t) perfcpu[i].idle); - submit (i, "system", (derive_t) perfcpu[i].sys); - submit (i, "user", (derive_t) perfcpu[i].user); - submit (i, "wait", (derive_t) perfcpu[i].wait); - submit (i, "active", (derive_t) perfcpu[i].sys + - perfcpu[i].user + - perfcpu[i].wait); + memset(derives, -1, sizeof(derives)); + derives[CPU_SUBMIT_IDLE] = perfcpu[i].idle; + derives[CPU_SUBMIT_SYSTEM] = perfcpu[i].sys; + derives[CPU_SUBMIT_USER] = perfcpu[i].user; + derives[CPU_SUBMIT_WAIT] = perfcpu[i].wait; } + submit(CPU_SUBMIT_FLUSH, NULL); #endif /* HAVE_PERFSTAT */ return (0); @@ -636,5 +746,6 @@ static int cpu_read (void) void module_register (void) { plugin_register_init ("cpu", init); + plugin_register_config ("cpu", cpu_config, config_keys, config_keys_num); plugin_register_read ("cpu", cpu_read); } /* void module_register */ -- 2.11.0