X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fmemcached.c;h=2d999ce4e15be392dc9a3faed8dfca34395fee4c;hb=10c85e89cbd077980ae297b17a23bbc42ce5d3d5;hp=d7fb19fa03efbc3815637db7c7a280cc2db585f4;hpb=0735ed714d0d3302df01348e37fd21e3cb33818e;p=collectd.git diff --git a/src/memcached.c b/src/memcached.c index d7fb19fa..2d999ce4 100644 --- a/src/memcached.c +++ b/src/memcached.c @@ -1,6 +1,8 @@ /** - * collectd - src/memcached.c - * Copyright (C) 2007 Antony Dovgal, heavily based on hddtemp.c + * collectd - src/memcached.c, based on src/hddtemp.c + * Copyright (C) 2007 Antony Dovgal + * Copyright (C) 2007-2009 Florian Forster + * Copyright (C) 2009 Doug MacEachern * * 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 @@ -18,7 +20,8 @@ * * Authors: * Antony Dovgal - * + * Florian octo Forster + * Doug MacEachern **/ #include "collectd.h" @@ -31,11 +34,6 @@ # include # include # include -# include /* for basename */ - -#if HAVE_LINUX_MAJOR_H -# include -#endif #define MEMCACHED_DEF_HOST "127.0.0.1" #define MEMCACHED_DEF_PORT "11211" @@ -45,10 +43,9 @@ static const char *config_keys[] = { "Host", - "Port", - NULL + "Port" }; -static int config_keys_num = 2; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); static char *memcached_host = NULL; static char memcached_port[16]; @@ -85,7 +82,7 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */ port = MEMCACHED_DEF_PORT; } - if ((ai_return = getaddrinfo (host, port, NULL, &ai_list)) != 0) { + if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0) { char errbuf[1024]; ERROR ("memcached: getaddrinfo (%s, %s): %s", host, port, @@ -106,7 +103,6 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */ /* connect to the memcached daemon */ if (connect (fd, (struct sockaddr *) ai_ptr->ai_addr, ai_ptr->ai_addrlen)) { - char errbuf[1024]; shutdown(fd, SHUT_RDWR); close(fd); fd = -1; @@ -132,17 +128,29 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */ { struct pollfd p; - int n; + int status; + memset (&p, 0, sizeof (p)); p.fd = fd; - p.events = POLLIN|POLLERR|POLLHUP; + p.events = POLLIN | POLLERR | POLLHUP; p.revents = 0; - n = poll(&p, 1, 3); - - if (n <= 0) { - ERROR ("memcached: poll() failed or timed out"); - return -1; + status = poll (&p, /* nfds = */ 1, /* timeout = */ 1000 * interval_g); + if (status <= 0) + { + if (status == 0) + { + ERROR ("memcached: poll(2) timed out after %i seconds.", interval_g); + } + else + { + char errbuf[1024]; + ERROR ("memcached: poll(2) failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + } + shutdown (fd, SHUT_RDWR); + close (fd); + return (-1); } } @@ -205,11 +213,10 @@ static int memcached_config (const char *key, const char *value) /* {{{ */ } else if (strcasecmp (key, "Port") == 0) { int port = (int) (atof (value)); if ((port > 0) && (port <= 65535)) { - snprintf (memcached_port, sizeof (memcached_port), "%i", port); + ssnprintf (memcached_port, sizeof (memcached_port), "%i", port); } else { - strncpy (memcached_port, value, sizeof (memcached_port)); + sstrncpy (memcached_port, value, sizeof (memcached_port)); } - memcached_port[sizeof (memcached_port) - 1] = '\0'; } else { return -1; } @@ -218,183 +225,265 @@ static int memcached_config (const char *key, const char *value) /* {{{ */ } /* }}} */ -#if 0 -static void memcached_submit_items(double curr_items, unsigned long long total_items) /* {{{ */ -{ - value_t values[2]; - value_list_t vl = VALUE_LIST_INIT; - - values[0].gauge = curr_items; - values[1].counter = total_items; - - vl.values = values; - vl.values_len = 2; - vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "memcached"); - - plugin_dispatch_values ("memcached_items", &vl); -} -/* }}} */ -#endif - -static void memcached_submit_connections(double curr_connections, unsigned long long total_connections) /* {{{ */ +static void submit_counter (const char *type, const char *type_inst, + counter_t value) /* {{{ */ { - value_t values[2]; + value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = curr_connections; - values[1].counter = total_connections; + values[0].counter = value; vl.values = values; - vl.values_len = 2; - vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "memcached"); - - plugin_dispatch_values ("memcached_connections", &vl); -} + vl.values_len = 1; + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin)); + sstrncpy (vl.type, type, sizeof (vl.type)); + if (type_inst != NULL) + sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} /* void memcached_submit_cmd */ /* }}} */ -static void memcached_submit_bytes(unsigned long long bytes_read, unsigned long long bytes_written) /* {{{ */ +static void submit_counter2 (const char *type, const char *type_inst, + counter_t value0, counter_t value1) /* {{{ */ { value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - values[0].counter = bytes_read; - values[1].counter = bytes_written; + values[0].counter = value0; + values[1].counter = value1; vl.values = values; vl.values_len = 2; vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "memcached"); - - plugin_dispatch_values ("memcached_bytes", &vl); -} + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin)); + sstrncpy (vl.type, type, sizeof (vl.type)); + if (type_inst != NULL) + sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} /* void memcached_submit_cmd */ /* }}} */ -static void memcached_submit_cmd(unsigned long long cmd_get, unsigned long long cmd_set, unsigned long long get_hits, unsigned long long get_misses) /* {{{ */ +static void submit_gauge (const char *type, const char *type_inst, + gauge_t value) /* {{{ */ { - value_t values[4]; + value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].counter = cmd_get; - values[1].counter = cmd_set; - values[2].counter = get_hits; - values[3].counter = get_misses; + values[0].gauge = value; vl.values = values; - vl.values_len = 4; + vl.values_len = 1; vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "memcached"); + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin)); + sstrncpy (vl.type, type, sizeof (vl.type)); + if (type_inst != NULL) + sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); - plugin_dispatch_values ("memcached_cmd", &vl); + plugin_dispatch_values (&vl); } /* }}} */ -static void memcached_submit_rusage(unsigned long long rusage_user, unsigned long long rusage_system) /* {{{ */ +static void submit_gauge2 (const char *type, const char *type_inst, + gauge_t value0, gauge_t value1) /* {{{ */ { value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - values[0].counter = rusage_user; - values[1].counter = rusage_system; + values[0].gauge = value0; + values[1].gauge = value1; vl.values = values; vl.values_len = 2; vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "memcached"); + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin)); + sstrncpy (vl.type, type, sizeof (vl.type)); + if (type_inst != NULL) + sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); - plugin_dispatch_values ("memcached_rusage", &vl); + plugin_dispatch_values (&vl); } /* }}} */ static int memcached_read (void) /* {{{ */ { char buf[1024]; - char *lines[128]; char *fields[3]; char *ptr; + char *line; char *saveptr; int fields_num; - int lines_num = 0; - int i; - unsigned long long total_connections = 0, bytes_read = 0, bytes_written = 0, cmd_get = 0, cmd_set = 0, get_hits = 0, get_misses = 0, rusage_user = 0, rusage_system = 0; - double curr_connections = 0; + + gauge_t bytes_used = NAN; + gauge_t bytes_total = NAN; + gauge_t hits = NAN; + gauge_t gets = NAN; + counter_t rusage_user = 0; + counter_t rusage_syst = 0; + counter_t octets_rx = 0; + counter_t octets_tx = 0; /* get data from daemon */ if (memcached_query_daemon (buf, sizeof (buf)) < 0) { return -1; } +#define FIELD_IS(cnst) \ + (((sizeof(cnst) - 1) == name_len) && (strcmp (cnst, fields[1]) == 0)) + ptr = buf; saveptr = NULL; - while ((lines[lines_num] = strtok_r (ptr, "\n\r", &saveptr)) != NULL) { - ptr = NULL; - lines_num++; + while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL) + { + int name_len; - if (lines_num >= 127) break; - } + ptr = NULL; -#define FIELD_IS(cnst) \ - (sizeof(cnst) - 1) == name_len && memcmp(cnst, fields[1], sizeof(cnst)) == 0 + fields_num = strsplit(line, fields, 3); + if (fields_num != 3) + continue; - for (i = 0; i < lines_num; i++) { - int name_len; + name_len = strlen(fields[1]); + if (name_len == 0) + continue; - fields_num = strsplit(lines[i], fields, 3); - if (fields_num != 3) continue; + /* + * For an explanation on these fields please refer to + * + */ + + /* + * CPU time consumed by the memcached process + */ + if (FIELD_IS ("rusage_user")) + { + rusage_user = atoll (fields[2]); + } + else if (FIELD_IS ("rusage_system")) + { + rusage_syst = atoll(fields[2]); + } + + /* + * Number of threads of this instance + */ + else if (FIELD_IS ("threads")) + { + submit_gauge2 ("ps_count", NULL, NAN, atof (fields[2])); + } - name_len = strlen(fields[1]); - if (name_len == 0) continue; - - if (FIELD_IS("rusage_user")) { - rusage_user = atoll(fields[2]); - } else if (FIELD_IS("rusage_system")) { - rusage_system = atoll(fields[2]); -/* } else if (FIELD_IS("curr_items")) { - curr_items = atof(fields[2]); - } else if (FIELD_IS("total_items")) { + /* + * Number of items stored + */ + else if (FIELD_IS ("curr_items")) + { + submit_gauge ("memcached_items", "current", atof (fields[2])); + } +/* + else if (FIELD_IS ("total_items")) + { total_items = atoll(fields[2]); - } else if (FIELD_IS("bytes")) { - bytes = atof(fields[2]); */ - } else if (FIELD_IS("curr_connections")) { - curr_connections = atof(fields[2]); - } else if (FIELD_IS("total_connections")) { + } + */ + + /* + * Number of bytes used and available (total - used) + */ + else if (FIELD_IS ("bytes")) + { + bytes_used = atof (fields[2]); + } + else if (FIELD_IS ("limit_maxbytes")) + { + bytes_total = atof(fields[2]); + } + + /* + * Connections + */ + else if (FIELD_IS ("curr_connections")) + { + submit_gauge ("memcached_connections", "current", atof (fields[2])); + } +/* + else if (FIELD_IS("total_connections")) + { total_connections = atoll(fields[2]); -/* } else if (FIELD_IS("connection_structures")) { - connection_structures = atof(fields[2]); */ - } else if (FIELD_IS("cmd_get")) { - cmd_get = atoll(fields[2]); - } else if (FIELD_IS("cmd_set")) { - cmd_set = atoll(fields[2]); - } else if (FIELD_IS("get_hits")) { - get_hits = atoll(fields[2]); - } else if (FIELD_IS("get_misses")) { - get_misses = atoll(fields[2]); -/* } else if (FIELD_IS("evictions")) { - evictions = atoll(fields[2]); */ - } else if (FIELD_IS("bytes_read")) { - bytes_read = atoll(fields[2]); - } else if (FIELD_IS("bytes_written")) { - bytes_written = atoll(fields[2]); -/* } else if (FIELD_IS("limit_maxbytes")) { - limit_maxbytes = atof(fields[2]); - } else if (FIELD_IS("threads")) { - threads = atof(fields[2]); */ } - } +*/ -#if 0 - memcached_submit_items(curr_items, total_items); -#endif - memcached_submit_connections(curr_connections, total_connections); - memcached_submit_bytes(bytes_read, bytes_written); - memcached_submit_cmd(cmd_get, cmd_set, get_hits, get_misses); - memcached_submit_rusage(rusage_user, rusage_system); +/* + * ``Number of connection structures allocated by the server'' + else if (FIELD_IS ("connection_structures")) + { + connection_structures = atof(fields[2]); + } + */ + + /* + * Commands + */ + else if ((name_len > 4) && (strncmp (fields[1], "cmd_", 4) == 0)) + { + const char *name = fields[1] + 4; + submit_counter ("memcached_command", name, atoll (fields[2])); + if (strcmp (name, "get") == 0) + gets = atof (fields[2]); + } + + /* + * Operations on the cache, i. e. cache hits, cache misses and evictions of items + */ + else if (FIELD_IS ("get_hits")) + { + submit_counter ("memcached_ops", "hits", atoll (fields[2])); + hits = atof (fields[2]); + } + else if (FIELD_IS ("get_misses")) + { + submit_counter ("memcached_ops", "misses", atoll (fields[2])); + } + else if (FIELD_IS ("evictions")) + { + submit_counter ("memcached_ops", "evictions", atoll (fields[2])); + } + + /* + * Network traffic + */ + else if (FIELD_IS ("bytes_read")) + { + octets_rx = atoll (fields[2]); + } + else if (FIELD_IS ("bytes_written")) + { + octets_tx = atoll (fields[2]); + } + } /* while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL) */ + + if (!isnan (bytes_used) && !isnan (bytes_total) && (bytes_used <= bytes_total)) + submit_gauge2 ("df", "cache", bytes_used, bytes_total - bytes_used); + + if ((rusage_user != 0) || (rusage_syst != 0)) + submit_counter2 ("ps_cputime", NULL, rusage_user, rusage_syst); + + if ((octets_rx != 0) || (octets_tx != 0)) + submit_counter2 ("memcached_octets", NULL, octets_rx, octets_tx); + + if (!isnan (gets) && !isnan (hits)) + { + gauge_t rate = NAN; + + if (gets != 0.0) + rate = 100.0 * hits / gets; + + submit_gauge ("percent", "hitratio", rate); + } return 0; }