X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fprocesses.c;h=ff4012660dff3888c5cb28cfa75107da3c7ed8cf;hb=566dd2bb07f2a9db3106f4a883b208d5310af511;hp=c8f301684f5f7bd819a1c3ae1601df42b12c5634;hpb=f807d67073930df2240b60c5d20c863f6e32e915;p=collectd.git diff --git a/src/processes.c b/src/processes.c index c8f30168..ff401266 100644 --- a/src/processes.c +++ b/src/processes.c @@ -1,7 +1,7 @@ /** * collectd - src/processes.c * Copyright (C) 2005 Lyonel Vincent - * Copyright (C) 2006 Florian Forster (Mach code) + * Copyright (C) 2006-2007 Florian Forster (Mach code) * * 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 @@ -25,7 +25,6 @@ #include "collectd.h" #include "common.h" #include "plugin.h" -#include "utils_debug.h" #include "configfile.h" /* Include header files for the mach system, if they exist.. */ @@ -93,63 +92,15 @@ #define BUFSIZE 256 -static char *processes_file = "processes.rrd"; -static char *processes_ds_def[] = -{ - "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - "DS:sleeping:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - "DS:zombies:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - "DS:stopped:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - "DS:paging:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - "DS:blocked:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - NULL -}; -static int processes_ds_num = 6; - -static char *ps_rss_file = "processes/ps_rss-%s.rrd"; -static char *ps_rss_ds_def[] = -{ - /* max = 2^63 - 1 */ - "DS:byte:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", - NULL -}; -static int ps_rss_ds_num = 1; - -static char *ps_cputime_file = "processes/ps_cputime-%s.rrd"; -static char *ps_cputime_ds_def[] = -{ - /* 1 second in user-mode per second ought to be enough.. */ - "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:1000000", - "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:1000000", - NULL -}; -static int ps_cputime_ds_num = 2; - -static char *ps_count_file = "processes/ps_count-%s.rrd"; -static char *ps_count_ds_def[] = -{ - "DS:processes:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - "DS:threads:GAUGE:"COLLECTD_HEARTBEAT":0:65535", - NULL -}; -static int ps_count_ds_num = 2; - -static char *ps_pagefaults_file = "processes/ps_pagefaults-%s.rrd"; -static char *ps_pagefaults_ds_def[] = -{ - /* max = 2^63 - 1 */ - "DS:minflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", - "DS:majflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", - NULL -}; -static int ps_pagefaults_ds_num = 2; - -static char *config_keys[] = +#if PROCESSES_HAVE_READ +#if HAVE_THREAD_INFO | KERNEL_LINUX +static const char *config_keys[] = { "Process", NULL }; static int config_keys_num = 1; +#endif typedef struct procstat_entry_s { @@ -192,7 +143,9 @@ typedef struct procstat struct procstat_entry_s *instances; } procstat_t; +#if HAVE_THREAD_INFO | KERNEL_LINUX static procstat_t *list_head_g = NULL; +#endif #if HAVE_THREAD_INFO static mach_port_t port_host_self; @@ -377,7 +330,7 @@ static void ps_list_reset (void) { if (pse->age > 10) { - DBG ("Removing this procstat entry cause it's too old: " + DEBUG ("Removing this procstat entry cause it's too old: " "id = %lu; name = %s;", pse->id, ps->name); @@ -403,9 +356,8 @@ static void ps_list_reset (void) } /* while (pse != NULL) */ } /* for (ps = list_head_g; ps != NULL; ps = ps->next) */ } -#endif /* HAVE_THREAD_INFO | KERNEL_LINUX */ -static int ps_config (char *key, char *value) +static int ps_config (const char *key, const char *value) { if (strcasecmp (key, "Process") == 0) { @@ -418,8 +370,9 @@ static int ps_config (char *key, char *value) return (0); } +#endif /* HAVE_THREAD_INFO | KERNEL_LINUX */ -static void ps_init (void) +static int ps_init (void) { #if HAVE_THREAD_INFO kern_return_t status; @@ -440,149 +393,79 @@ static void ps_init (void) &pset_list, &pset_list_len)) != KERN_SUCCESS) { - syslog (LOG_ERR, "host_processor_sets failed: %s\n", + ERROR ("host_processor_sets failed: %s\n", mach_error_string (status)); pset_list = NULL; pset_list_len = 0; - return; + return (-1); } /* #endif HAVE_THREAD_INFO */ #elif KERNEL_LINUX pagesize_g = sysconf(_SC_PAGESIZE); - DBG ("pagesize_g = %li; CONFIG_HZ = %i;", + DEBUG ("pagesize_g = %li; CONFIG_HZ = %i;", pagesize_g, CONFIG_HZ); #endif /* KERNEL_LINUX */ - return; -} - -static void ps_write (char *host, char *inst, char *val) -{ - rrd_update_file (host, processes_file, val, - processes_ds_def, processes_ds_num); -} - -static void ps_rss_write (char *host, char *inst, char *val) -{ - char filename[256]; - int status; - - status = snprintf (filename, 256, ps_rss_file, inst); - if ((status < 1) || (status >= 256)) - return; - - rrd_update_file (host, filename, val, ps_rss_ds_def, ps_rss_ds_num); -} - -static void ps_cputime_write (char *host, char *inst, char *val) -{ - char filename[256]; - int status; - - status = snprintf (filename, 256, ps_cputime_file, inst); - if ((status < 1) || (status >= 256)) - return; - - DBG ("host = %s; filename = %s; val = %s;", - host, filename, val); - rrd_update_file (host, filename, val, - ps_cputime_ds_def, ps_cputime_ds_num); -} - -static void ps_count_write (char *host, char *inst, char *val) -{ - char filename[256]; - int status; - - status = snprintf (filename, 256, ps_count_file, inst); - if ((status < 1) || (status >= 256)) - return; - - DBG ("host = %s; filename = %s; val = %s;", - host, filename, val); - rrd_update_file (host, filename, val, - ps_count_ds_def, ps_count_ds_num); -} - -static void ps_pagefaults_write (char *host, char *inst, char *val) -{ - char filename[256]; - int status; - - status = snprintf (filename, 256, ps_pagefaults_file, inst); - if ((status < 1) || (status >= 256)) - return; - - DBG ("host = %s; filename = %s; val = %s;", - host, filename, val); - rrd_update_file (host, filename, val, - ps_pagefaults_ds_def, ps_pagefaults_ds_num); -} + return (0); +} /* int ps_init */ -#if PROCESSES_HAVE_READ -static void ps_submit (int running, - int sleeping, - int zombies, - int stopped, - int paging, - int blocked) +static void ps_submit_state (const char *state, double value) { - char buf[BUFSIZE]; + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; - if (snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%i:%i:%i", - (unsigned int) curtime, - running, sleeping, zombies, stopped, paging, - blocked) >= BUFSIZE) - return; + values[0].gauge = value; - DBG ("running = %i; sleeping = %i; zombies = %i; stopped = %i; paging = %i; blocked = %i;", - running, sleeping, zombies, stopped, paging, blocked); + vl.values = values; + vl.values_len = 1; + vl.time = time (NULL); + strcpy (vl.host, hostname_g); + strcpy (vl.plugin, "processes"); + strcpy (vl.plugin_instance, ""); + strncpy (vl.type_instance, state, sizeof (vl.type_instance)); - plugin_submit (MODULE_NAME, "-", buf); + plugin_dispatch_values ("ps_state", &vl); } static void ps_submit_proc_list (procstat_t *ps) { - char buffer[64]; - - if (ps == NULL) - return; - - snprintf (buffer, 64, "%u:%lu", - (unsigned int) curtime, - ps->vmem_rss); - buffer[63] = '\0'; - plugin_submit ("ps_rss", ps->name, buffer); - - snprintf (buffer, 64, "%u:%u:%u", - (unsigned int) curtime, - /* Make the counter overflow */ - (unsigned int) (ps->cpu_user_counter & 0xFFFFFFFF), - (unsigned int) (ps->cpu_system_counter & 0xFFFFFFFF)); - buffer[63] = '\0'; - plugin_submit ("ps_cputime", ps->name, buffer); - - snprintf (buffer, 64, "%u:%lu:%lu", - (unsigned int) curtime, - ps->num_proc, ps->num_lwp); - buffer[63] = '\0'; - plugin_submit ("ps_count", ps->name, buffer); - - snprintf (buffer, 64, "%u:%lu:%lu", - (unsigned int) curtime, - ps->vmem_minflt_counter, ps->vmem_majflt_counter); - buffer[63] = '\0'; - plugin_submit ("ps_pagefaults", ps->name, buffer); - - DBG ("name = %s; num_proc = %lu; num_lwp = %lu; vmem_rss = %lu; " + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + vl.values = values; + vl.values_len = 2; + vl.time = time (NULL); + strcpy (vl.host, hostname_g); + strcpy (vl.plugin, "processes"); + strncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance)); + + vl.values[0].gauge = ps->vmem_rss; + vl.values_len = 1; + plugin_dispatch_values ("ps_rss", &vl); + + vl.values[0].counter = ps->cpu_user_counter; + vl.values[1].counter = ps->cpu_system_counter; + vl.values_len = 2; + plugin_dispatch_values ("ps_cputime", &vl); + + vl.values[0].gauge = ps->num_proc; + vl.values[1].gauge = ps->num_lwp; + vl.values_len = 2; + plugin_dispatch_values ("ps_count", &vl); + + vl.values[0].counter = ps->vmem_minflt_counter; + vl.values[1].counter = ps->vmem_majflt_counter; + vl.values_len = 2; + plugin_dispatch_values ("ps_pagefaults", &vl); + + DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; vmem_rss = %lu; " "vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; " "cpu_user_counter = %lu; cpu_system_counter = %lu;", ps->name, ps->num_proc, ps->num_lwp, ps->vmem_rss, - ps->vmem_minflt_counter, ps->vmem_majflt_counter, ps->cpu_user_counter, - ps->cpu_system_counter); - -} + ps->vmem_minflt_counter, ps->vmem_majflt_counter, + ps->cpu_user_counter, ps->cpu_system_counter); +} /* void ps_submit_proc_list */ #if KERNEL_LINUX static int *ps_read_tasks (int pid) @@ -600,7 +483,7 @@ static int *ps_read_tasks (int pid) if ((dh = opendir (dirname)) == NULL) { - DBG ("Failed to open directory `%s'", dirname); + DEBUG ("Failed to open directory `%s'", dirname); return (NULL); } @@ -620,7 +503,7 @@ static int *ps_read_tasks (int pid) { if (list != NULL) free (list); - syslog (LOG_ERR, "processes plugin: " + ERROR ("processes plugin: " "Failed to allocate more memory."); return (NULL); } @@ -682,20 +565,17 @@ int ps_read_process (int pid, procstat_t *ps, char *state) fields_len = strsplit (buffer, fields, 64); if (fields_len < 24) { - DBG ("`%s' has only %i fields..", - filename, fields_len); + DEBUG ("processes plugin: ps_read_process (pid = %i):" + " `%s' has only %i fields..", + (int) pid, filename, fields_len); return (-1); } - else if (fields_len != 41) - { - DBG ("WARNING: (fields_len = %i) != 41", fields_len); - } /* copy the name, strip brackets in the process */ name_len = strlen (fields[1]) - 2; if ((fields[1][0] != '(') || (fields[1][name_len + 1] != ')')) { - DBG ("No brackets found in process name: `%s'", fields[1]); + DEBUG ("No brackets found in process name: `%s'", fields[1]); return (-1); } fields[1] = fields[1] + 1; @@ -704,17 +584,21 @@ int ps_read_process (int pid, procstat_t *ps, char *state) ppid = atoi (fields[3]); - if ((tasks = ps_read_tasks (pid)) == NULL) + *state = fields[2][0]; + + if (*state == 'Z') { - /* This happends for zombied, e.g. */ - DBG ("ps_read_tasks (%i) failed.", pid); - *state = 'Z'; ps->num_lwp = 0; ps->num_proc = 0; } + else if ((tasks = ps_read_tasks (pid)) == NULL) + { + /* Kernel 2.4 or so */ + ps->num_lwp = 1; + ps->num_proc = 1; + } else { - *state = '\0'; ps->num_lwp = 0; ps->num_proc = 1; for (i = 0; tasks[i] != 0; i++) @@ -724,10 +608,10 @@ int ps_read_process (int pid, procstat_t *ps, char *state) tasks = NULL; } - /* Leave the rest at zero if this is only an LWP */ + /* Leave the rest at zero if this is only a zombi */ if (ps->num_proc == 0) { - DBG ("This is only an LWP: pid = %i; name = %s;", + DEBUG ("This is only a zombi: pid = %i; name = %s;", pid, ps->name); return (0); } @@ -747,8 +631,6 @@ int ps_read_process (int pid, procstat_t *ps, char *state) ps->cpu_system_counter = (unsigned long) cpu_system_counter; ps->vmem_rss = (unsigned long) vmem_rss; - *state = fields[2][0]; - /* success */ return (0); } /* int ps_read_process (...) */ @@ -780,7 +662,7 @@ static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_l strncpy (name, kp.kp_proc.p_comm, name_max_len - 1); name[name_max_len - 1] = '\0'; - DBG ("pid = %i; name = %s;", *pid, name); + DEBUG ("pid = %i; name = %s;", *pid, name); /* We don't do the special handling for `p_comm == "LaunchCFMApp"' as * `top' does it, because it is a lot of work and only used when @@ -790,7 +672,7 @@ static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_l } #endif /* HAVE_THREAD_INFO */ -static void ps_read (void) +static int ps_read (void) { #if HAVE_THREAD_INFO kern_return_t status; @@ -836,7 +718,7 @@ static void ps_read (void) pset_list[pset], &port_pset_priv)) != KERN_SUCCESS) { - syslog (LOG_ERR, "host_processor_set_priv failed: %s\n", + ERROR ("host_processor_set_priv failed: %s\n", mach_error_string (status)); continue; } @@ -845,7 +727,7 @@ static void ps_read (void) &task_list, &task_list_len)) != KERN_SUCCESS) { - syslog (LOG_ERR, "processor_set_tasks failed: %s\n", + ERROR ("processor_set_tasks failed: %s\n", mach_error_string (status)); mach_port_deallocate (port_task_self, port_pset_priv); continue; @@ -879,7 +761,7 @@ static void ps_read (void) &task_basic_info_len); if (status != KERN_SUCCESS) { - syslog (LOG_ERR, "task_info failed: %s", + ERROR ("task_info failed: %s", mach_error_string (status)); continue; /* with next thread_list */ } @@ -891,7 +773,7 @@ static void ps_read (void) &task_events_info_len); if (status != KERN_SUCCESS) { - syslog (LOG_ERR, "task_info failed: %s", + ERROR ("task_info failed: %s", mach_error_string (status)); continue; /* with next thread_list */ } @@ -903,7 +785,7 @@ static void ps_read (void) &task_absolutetime_info_len); if (status != KERN_SUCCESS) { - syslog (LOG_ERR, "task_info failed: %s", + ERROR ("task_info failed: %s", mach_error_string (status)); continue; /* with next thread_list */ } @@ -927,7 +809,7 @@ static void ps_read (void) * thread is nonsense, since the task/process * is dead. */ zombies++; - DBG ("task_threads failed: %s", + DEBUG ("task_threads failed: %s", mach_error_string (status)); if (task_list[task] != port_task_self) mach_port_deallocate (port_task_self, @@ -944,7 +826,7 @@ static void ps_read (void) &thread_data_len); if (status != KERN_SUCCESS) { - syslog (LOG_ERR, "thread_info failed: %s", + ERROR ("thread_info failed: %s", mach_error_string (status)); if (task_list[task] != port_task_self) mach_port_deallocate (port_task_self, @@ -976,8 +858,7 @@ static void ps_read (void) * There's only zombie tasks, which are * handled above. */ default: - syslog (LOG_WARNING, - "Unknown thread status: %s", + WARNING ("Unknown thread status: %s", thread_data.run_state); break; } /* switch (thread_data.run_state) */ @@ -987,7 +868,7 @@ static void ps_read (void) status = mach_port_deallocate (port_task_self, thread_list[thread]); if (status != KERN_SUCCESS) - syslog (LOG_ERR, "mach_port_deallocate failed: %s", + ERROR ("mach_port_deallocate failed: %s", mach_error_string (status)); } } /* for (thread_list) */ @@ -997,7 +878,7 @@ static void ps_read (void) thread_list_len * sizeof (thread_act_t))) != KERN_SUCCESS) { - syslog (LOG_ERR, "vm_deallocate failed: %s", + ERROR ("vm_deallocate failed: %s", mach_error_string (status)); } thread_list = NULL; @@ -1011,7 +892,7 @@ static void ps_read (void) status = mach_port_deallocate (port_task_self, task_list[task]); if (status != KERN_SUCCESS) - syslog (LOG_ERR, "mach_port_deallocate failed: %s", + ERROR ("mach_port_deallocate failed: %s", mach_error_string (status)); } @@ -1023,7 +904,7 @@ static void ps_read (void) (vm_address_t) task_list, task_list_len * sizeof (task_t))) != KERN_SUCCESS) { - syslog (LOG_ERR, "vm_deallocate failed: %s", + ERROR ("vm_deallocate failed: %s", mach_error_string (status)); } task_list = NULL; @@ -1032,12 +913,16 @@ static void ps_read (void) if ((status = mach_port_deallocate (port_task_self, port_pset_priv)) != KERN_SUCCESS) { - syslog (LOG_ERR, "mach_port_deallocate failed: %s", + ERROR ("mach_port_deallocate failed: %s", mach_error_string (status)); } } /* for (pset_list) */ - ps_submit (running, sleeping, zombies, stopped, -1, blocked); + ps_submit_state ("running", running); + ps_submit_state ("sleeping", sleeping); + ps_submit_state ("zombies", zombies); + ps_submit_state ("stopped", stopped); + ps_submit_state ("blocked", blocked); for (ps = list_head_g; ps != NULL; ps = ps->next) ps_submit_proc_list (ps); @@ -1067,8 +952,10 @@ static void ps_read (void) if ((proc = opendir ("/proc")) == NULL) { - syslog (LOG_ERR, "Cannot open `/proc': %s", strerror (errno)); - return; + char errbuf[1024]; + ERROR ("Cannot open `/proc': %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); } while ((ent = readdir (proc)) != NULL) @@ -1082,7 +969,7 @@ static void ps_read (void) status = ps_read_process (pid, &ps, &state); if (status != 0) { - DBG ("ps_read_process failed: %i", status); + DEBUG ("ps_read_process failed: %i", status); continue; } @@ -1118,25 +1005,29 @@ static void ps_read (void) closedir (proc); - ps_submit (running, sleeping, zombies, stopped, paging, blocked); + ps_submit_state ("running", running); + ps_submit_state ("sleeping", sleeping); + ps_submit_state ("zombies", zombies); + ps_submit_state ("stopped", stopped); + ps_submit_state ("paging", paging); + ps_submit_state ("blocked", blocked); for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next) ps_submit_proc_list (ps_ptr); #endif /* KERNEL_LINUX */ -} -#else -# define ps_read NULL + + return (0); +} /* int ps_read */ #endif /* PROCESSES_HAVE_READ */ void module_register (void) { - plugin_register (MODULE_NAME, ps_init, ps_read, ps_write); - plugin_register ("ps_rss", NULL, NULL, ps_rss_write); - plugin_register ("ps_cputime", NULL, NULL, ps_cputime_write); - plugin_register ("ps_count", NULL, NULL, ps_count_write); - plugin_register ("ps_pagefaults", NULL, NULL, ps_pagefaults_write); - cf_register (MODULE_NAME, ps_config, config_keys, config_keys_num); -} - -#undef BUFSIZE -#undef MODULE_NAME +#if PROCESSES_HAVE_READ +#if HAVE_THREAD_INFO | KERNEL_LINUX + plugin_register_config ("processes", ps_config, + config_keys, config_keys_num); +#endif + plugin_register_init ("processes", ps_init); + plugin_register_read ("processes", ps_read); +#endif /* PROCESSES_HAVE_READ */ +} /* void module_register */