memcached plugin: Remove trailing whitespace.
[collectd.git] / src / memcached.c
index 7bdad0a..06cd536 100644 (file)
@@ -31,6 +31,7 @@
 # include <poll.h>
 # include <netdb.h>
 # include <sys/socket.h>
+# include <sys/un.h>
 # include <netinet/in.h>
 # include <netinet/tcp.h>
 
 
 static const char *config_keys[] =
 {
+       "Socket",
        "Host",
        "Port"
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
+static char *memcached_socket = NULL;
 static char *memcached_host = NULL;
 static char memcached_port[16];
 
@@ -54,66 +57,92 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */
        int fd;
        ssize_t status;
        int buffer_fill;
+    int i = 0;
 
-       const char *host;
-       const char *port;
+    if (memcached_socket != NULL) {
 
-       struct addrinfo  ai_hints;
-       struct addrinfo *ai_list, *ai_ptr;
-       int              ai_return, i = 0;
+        struct sockaddr_un serv_addr;
 
-       memset (&ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_flags    = 0;
-#ifdef AI_ADDRCONFIG
-/*     ai_hints.ai_flags   |= AI_ADDRCONFIG; */
-#endif
-       ai_hints.ai_family   = AF_INET;
-       ai_hints.ai_socktype = SOCK_STREAM;
-       ai_hints.ai_protocol = 0;
+        memset(&serv_addr, '\0', sizeof (serv_addr));
+        serv_addr.sun_family = AF_UNIX;
+        strncpy(serv_addr.sun_path, memcached_socket, sizeof (serv_addr.sun_path));
 
-       host = memcached_host;
-       if (host == NULL) {
-               host = MEMCACHED_DEF_HOST;
-       }
+        /* create our socket descriptor */
+        if ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) {
+            char errbuf[1024];
+            ERROR ("memcached: unix socket: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
+            return -1;
+        }
 
-       port = memcached_port;
-       if (strlen (port) == 0) {
-               port = MEMCACHED_DEF_PORT;
-       }
+        /* connect to the memcached daemon */
+        if (connect (fd, (struct sockaddr *) &serv_addr, SUN_LEN(&serv_addr))) {
+            shutdown(fd, SHUT_RDWR);
+            close(fd);
+            fd = -1;
+        }
 
-       if ((ai_return = getaddrinfo (host, port, NULL, &ai_list)) != 0) {
-               char errbuf[1024];
-               ERROR ("memcached: getaddrinfo (%s, %s): %s",
-                               host, port,
-                               (ai_return == EAI_SYSTEM)
-                               ? sstrerror (errno, errbuf, sizeof (errbuf))
-                               : gai_strerror (ai_return));
-               return -1;
-       }
+    } else {
 
-       fd = -1;
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
-               /* create our socket descriptor */
-               if ((fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol)) < 0) {
-                       char errbuf[1024];
-                       ERROR ("memcached: socket: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
-                       continue;
-               }
-
-               /* connect to the memcached daemon */
-               if (connect (fd, (struct sockaddr *) ai_ptr->ai_addr, ai_ptr->ai_addrlen)) {
-                       shutdown(fd, SHUT_RDWR);
-                       close(fd);
-                       fd = -1;
-                       continue;
-               }
+        const char *host;
+        const char *port;
 
-               /* A socket could be opened and connecting succeeded. We're
-                * done. */
-               break;
-       }
+        struct addrinfo  ai_hints;
+        struct addrinfo *ai_list, *ai_ptr;
+        int              ai_return = 0;
 
-       freeaddrinfo (ai_list);
+        memset (&ai_hints, '\0', sizeof (ai_hints));
+        ai_hints.ai_flags    = 0;
+#ifdef AI_ADDRCONFIG
+        /*     ai_hints.ai_flags   |= AI_ADDRCONFIG; */
+#endif
+        ai_hints.ai_family   = AF_INET;
+        ai_hints.ai_socktype = SOCK_STREAM;
+        ai_hints.ai_protocol = 0;
+
+        host = memcached_host;
+        if (host == NULL) {
+            host = MEMCACHED_DEF_HOST;
+        }
+
+        port = memcached_port;
+        if (strlen (port) == 0) {
+            port = MEMCACHED_DEF_PORT;
+        }
+
+        if ((ai_return = getaddrinfo (host, port, NULL, &ai_list)) != 0) {
+            char errbuf[1024];
+            ERROR ("memcached: getaddrinfo (%s, %s): %s",
+                   host, port,
+                   (ai_return == EAI_SYSTEM)
+                   ? sstrerror (errno, errbuf, sizeof (errbuf))
+                   : gai_strerror (ai_return));
+            return -1;
+        }
+
+        fd = -1;
+        for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
+            /* create our socket descriptor */
+            if ((fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol)) < 0) {
+                char errbuf[1024];
+                ERROR ("memcached: socket: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
+                continue;
+            }
+
+            /* connect to the memcached daemon */
+            if (connect (fd, (struct sockaddr *) ai_ptr->ai_addr, ai_ptr->ai_addrlen)) {
+                shutdown(fd, SHUT_RDWR);
+                close(fd);
+                fd = -1;
+                continue;
+            }
+
+            /* A socket could be opened and connecting succeeded. We're
+             * done. */
+            break;
+        }
+
+        freeaddrinfo (ai_list);
+    }
 
        if (fd < 0) {
                ERROR ("memcached: Could not connect to daemon.");
@@ -204,7 +233,12 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */
 
 static int memcached_config (const char *key, const char *value) /* {{{ */
 {
-       if (strcasecmp (key, "Host") == 0) {
+    if (strcasecmp (key, "Socket") == 0) {
+        if (memcached_socket != NULL) {
+            free (memcached_socket);
+        }
+        memcached_socket = strdup (value);
+    } else if (strcasecmp (key, "Host") == 0) {
                if (memcached_host != NULL) {
                        free (memcached_host);
                }
@@ -234,7 +268,6 @@ static void submit_counter (const char *type, const char *type_inst,
 
        vl.values = values;
        vl.values_len = 1;
-       vl.time = time (NULL);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
        sstrncpy (vl.type, type, sizeof (vl.type));
@@ -321,6 +354,8 @@ static int memcached_read (void) /* {{{ */
 
        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;
@@ -366,7 +401,7 @@ static int memcached_read (void) /* {{{ */
                {
                        rusage_syst = atoll(fields[2]);
                }
-       
+
                /*
                 * Number of threads of this instance
                 */
@@ -382,7 +417,7 @@ static int memcached_read (void) /* {{{ */
                {
                        submit_gauge ("memcached_items", "current", atof (fields[2]));
                }
-/*             
+/*
                else if (FIELD_IS ("total_items"))
                {
                        total_items = atoll(fields[2]);
@@ -430,6 +465,8 @@ static int memcached_read (void) /* {{{ */
                {
                        const char *name = fields[1] + 4;
                        submit_counter ("memcached_command", name, atoll (fields[2]));
+                       if (strcmp (name, "get") == 0)
+                               gets = atof (fields[2]);
                }
 
                /*
@@ -438,6 +475,7 @@ static int memcached_read (void) /* {{{ */
                else if (FIELD_IS ("get_hits"))
                {
                        submit_counter ("memcached_ops", "hits", atoll (fields[2]));
+                       hits = atof (fields[2]);
                }
                else if (FIELD_IS ("get_misses"))
                {
@@ -463,13 +501,23 @@ static int memcached_read (void) /* {{{ */
 
        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;
 }
 /* }}} */