From 8dc963f846c51d8ba173587a136231c2b3646afc Mon Sep 17 00:00:00 2001 From: Paul Sadauskas Date: Wed, 8 Jul 2009 17:36:39 -0600 Subject: [PATCH] http plugin: Make the output match the PUTVAL plain-text protocol --- src/http.c | 474 +++++++++++++++++++++++------------------------------ 1 file changed, 202 insertions(+), 272 deletions(-) diff --git a/src/http.c b/src/http.c index f4ae0ebf..0a24b60e 100644 --- a/src/http.c +++ b/src/http.c @@ -38,7 +38,7 @@ */ static const char *config_keys[] = { - "Location", "User", "Password" + "Location", "User", "Password" }; static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); @@ -61,241 +61,183 @@ static pthread_mutex_t send_lock = PTHREAD_MUTEX_INITIALIZER; static int http_init(void) /* {{{ */ { - curl = curl_easy_init (); + curl = curl_easy_init (); - if (curl == NULL) - { - ERROR ("curl plugin: curl_easy_init failed."); - return (-1); - } - - struct curl_slist *headers=NULL; - - curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION); - - headers = curl_slist_append(headers, "Accept: text/csv;q=0.8, */*;q=0.2"); - headers = curl_slist_append(headers, "Content-Type: text/csv"); - curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headers); + if (curl == NULL) + { + ERROR ("curl plugin: curl_easy_init failed."); + return (-1); + } - curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, curl_errbuf); - curl_easy_setopt (curl, CURLOPT_URL, location); + struct curl_slist *headers=NULL; - if (user != NULL) - { - size_t credentials_size; + curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION); - credentials_size = strlen (user) + 2; - if (pass != NULL) - credentials_size += strlen (pass); + headers = curl_slist_append(headers, "Accept: */*"); + headers = curl_slist_append(headers, "Content-Type: text/plain"); + curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headers); - credentials = (char *) malloc (credentials_size); - if (credentials == NULL) - { - ERROR ("curl plugin: malloc failed."); - return (-1); - } + curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, curl_errbuf); + curl_easy_setopt (curl, CURLOPT_URL, location); - ssnprintf (credentials, credentials_size, "%s:%s", - user, (pass == NULL) ? "" : pass); - curl_easy_setopt (curl, CURLOPT_USERPWD, credentials); - curl_easy_setopt (curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); - } + if (user != NULL) + { + size_t credentials_size; + + credentials_size = strlen (user) + 2; + if (pass != NULL) + credentials_size += strlen (pass); + + credentials = (char *) malloc (credentials_size); + if (credentials == NULL) + { + ERROR ("curl plugin: malloc failed."); + return (-1); + } + + ssnprintf (credentials, credentials_size, "%s:%s", + user, (pass == NULL) ? "" : pass); + curl_easy_setopt (curl, CURLOPT_USERPWD, credentials); + curl_easy_setopt (curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); + } - return (0); + return (0); } /* }}} */ static int http_value_list_to_string (char *buffer, int buffer_len, /* {{{ */ - const data_set_t *ds, const value_list_t *vl, int index) -{ - int offset = 0; - int status; - gauge_t *rates = NULL; - - assert (0 == strcmp (ds->type, vl->type)); - - memset (buffer, '\0', buffer_len); - - if ((ds->ds[index].type != DS_TYPE_COUNTER) - && (ds->ds[index].type != DS_TYPE_GAUGE)) - return (-1); - - if (ds->ds[index].type == DS_TYPE_COUNTER) - { - if (rates == NULL) - rates = uc_get_rate (ds, vl); - if (rates == NULL) - { - WARNING ("http plugin: " - "uc_get_rate failed."); - return (-1); - } - if (isnan(rates[index])) - { - /* dont output */ - return (-1); - } - status = ssnprintf (buffer + offset, - buffer_len - offset, - "%lf", rates[index]); - } - else /* if (ds->ds[index].type == DS_TYPE_GAUGE) */ - { - status = ssnprintf (buffer + offset, buffer_len - offset, - "%lf", vl->values[index].gauge); - } - - if ((status < 1) || (status >= (buffer_len - offset))) - { - sfree (rates); - return (-1); - } - - offset += status; - - sfree (rates); - return (0); -} /* }}} int http_value_list_to_string */ - -static int http_value_list_to_timestamp (char *buffer, int buffer_len, /* {{{ */ - const data_set_t *ds, const value_list_t *vl) + const data_set_t *ds, const value_list_t *vl) { - int offset = 0; - int status; - - assert (0 == strcmp (ds->type, vl->type)); + int offset = 0; + int status; + int i; + gauge_t *rates = NULL; - memset (buffer, '\0', buffer_len); + assert (0 == strcmp (ds->type, vl->type)); - status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time); - if ((status < 1) || (status >= buffer_len)) - return (-1); - offset = status; + memset (buffer, '\0', buffer_len); - return (0); -} /* }}} int http_value_list_to_timestamp */ - -static int http_value_list_to_metric_name (char *buffer, int buffer_len, /* {{{ */ - const data_set_t *ds, const value_list_t *vl) -{ - int offset = 0; - int status; - - assert (0 == strcmp (ds->type, vl->type)); - - /* hostname */ - status = ssnprintf (buffer + offset, buffer_len - offset, - "%s", vl->host); - if ((status < 1) || (status >= buffer_len - offset)) - return (-1); - offset += status; - - /* plugin */ - status = ssnprintf (buffer + offset, buffer_len - offset, - ",%s", vl->plugin); - if ((status < 1) || (status >= buffer_len - offset)) - return (-1); - offset += status; - - /* plugin_instance */ - if (strlen (vl->plugin_instance) > 0) - { - status = ssnprintf (buffer + offset, buffer_len - offset, - ",%s", vl->plugin_instance); - if ((status < 1) || (status >= buffer_len - offset)) - return (-1); - offset += status; - } - - /* type (if its the same as plugin, don't bother repeating it */ - if (0 != strcmp (vl->type, vl->plugin)) - { - status = ssnprintf (buffer + offset, buffer_len - offset, - ",%s", vl->type); - if ((status < 1) || (status >= buffer_len - offset)) - return (-1); - offset += status; - } - - /* type_instance */ - if (strlen (vl->type_instance) > 0) - { - status = ssnprintf (buffer + offset, buffer_len - offset, - ",%s", vl->type_instance); - if ((status < 1) || (status >= buffer_len - offset)) - return (-1); - offset += status; - } - - return (offset); -} /* }}} int http_value_list_to_metric_name */ + for (i = 0; i < ds->ds_num; i++) + { + if ((ds->ds[i].type != DS_TYPE_COUNTER) + && (ds->ds[i].type != DS_TYPE_GAUGE) + && (ds->ds[i].type != DS_TYPE_DERIVE) + && (ds->ds[i].type != DS_TYPE_ABSOLUTE)) + return (-1); + + if (ds->ds[i].type == DS_TYPE_GAUGE) + { + status = ssnprintf (buffer + offset, buffer_len - offset, + ":%lf", vl->values[i].gauge); + } + else if (ds->ds[i].type == DS_TYPE_COUNTER) + { + if (rates == NULL) + rates = uc_get_rate (ds, vl); + if (rates == NULL) + { + WARNING ("csv plugin: " + "uc_get_rate failed."); + return (-1); + } + status = ssnprintf (buffer + offset, + buffer_len - offset, + ":%lf", rates[i]); + } + else if (ds->ds[i].type == DS_TYPE_DERIVE) + { + status = ssnprintf (buffer + offset, + buffer_len - offset, + ":%"PRIi64, + vl->values[i].derive); + } + else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) + { + status = ssnprintf (buffer + offset, + buffer_len - offset, + ":%"PRIu64, + vl->values[i].absolute); + } + + if ((status < 1) || (status >= (buffer_len - offset))) + { + sfree (rates); + return (-1); + } + + offset += status; + } /* for ds->ds_num */ + + sfree (rates); + return (0); +} /* }}} int http_value_list_to_string */ static int http_config (const char *key, const char *value) /* {{{ */ { - if (strcasecmp ("Location", key) == 0) - { - if (location != NULL) - free (location); - location = strdup (value); - if (location != NULL) - { - int len = strlen (location); - while ((len > 0) && (location[len - 1] == '/')) - { - len--; - location[len] = '\0'; - } - if (len <= 0) - { - free (location); - location = NULL; - } - } - } - else if (strcasecmp ("User", key) == 0) - { - if (user != NULL) - free (user); - user = strdup (value); - if (user != NULL) - { - int len = strlen (user); - while ((len > 0) && (user[len - 1] == '/')) - { - len--; - user[len] = '\0'; - } - if (len <= 0) - { - free (user); - user = NULL; - } - } - } - else if (strcasecmp ("Password", key) == 0) - { - if (pass != NULL) - free (pass); - pass = strdup (value); - if (pass != NULL) - { - int len = strlen (pass); - while ((len > 0) && (pass[len - 1] == '/')) - { - len--; - pass[len] = '\0'; - } - if (len <= 0) - { - free (pass); - pass = NULL; - } - } - } - else - { - return (-1); - } - return (0); + if (strcasecmp ("Location", key) == 0) + { + if (location != NULL) + free (location); + location = strdup (value); + if (location != NULL) + { + int len = strlen (location); + while ((len > 0) && (location[len - 1] == '/')) + { + len--; + location[len] = '\0'; + } + if (len <= 0) + { + free (location); + location = NULL; + } + } + } + else if (strcasecmp ("User", key) == 0) + { + if (user != NULL) + free (user); + user = strdup (value); + if (user != NULL) + { + int len = strlen (user); + while ((len > 0) && (user[len - 1] == '/')) + { + len--; + user[len] = '\0'; + } + if (len <= 0) + { + free (user); + user = NULL; + } + } + } + else if (strcasecmp ("Password", key) == 0) + { + if (pass != NULL) + free (pass); + pass = strdup (value); + if (pass != NULL) + { + int len = strlen (pass); + while ((len > 0) && (pass[len - 1] == '/')) + { + len--; + pass[len] = '\0'; + } + if (len <= 0) + { + free (pass); + pass = NULL; + } + } + } + else + { + return (-1); + } + return (0); } /* }}} int http_config */ static void http_init_buffer (void) /* {{{ */ @@ -309,7 +251,7 @@ static int http_send_buffer (char *buffer) /* {{{ */ { int status = 0; curl_easy_setopt (curl, CURLOPT_POSTFIELDS, buffer); - status = curl_easy_perform (curl); + //status = curl_easy_perform (curl); if (status != 0) { ERROR ("http plugin: curl_easy_perform failed with staus %i: %s", @@ -321,75 +263,63 @@ static int http_send_buffer (char *buffer) /* {{{ */ static int http_flush_buffer (void) /* {{{ */ { int status = 0; - DEBUG ("http plugin: flush_buffer: send_buffer_fill = %i", - send_buffer_fill); + DEBUG ("http plugin: flushing buffer:\n%s", send_buffer); - status = http_send_buffer (send_buffer); - http_init_buffer (); + status = http_send_buffer (send_buffer); + http_init_buffer (); return (status); } /* }}} http_flush_buffer */ static int http_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */ - user_data_t __attribute__((unused)) *user_data) + user_data_t __attribute__((unused)) *user_data) { - char metric_name[512]; - int metric_prefix_len; - char value[512]; - char timestamp[512]; - - int status; - int i; + char key[1024]; + char values[512]; - if (0 != strcmp (ds->type, vl->type)) { - ERROR ("http plugin: DS type does not match value list type"); - return -1; - } + int status; - metric_prefix_len = http_value_list_to_metric_name (metric_name, - sizeof (metric_name), ds, vl); - - if (metric_prefix_len == -1) - return (-1); - - DEBUG ("http plugin: http_write: metric_name = %s", metric_name); - - if (http_value_list_to_timestamp (timestamp, sizeof (timestamp), ds, vl) != 0) - return (-1); + if (0 != strcmp (ds->type, vl->type)) { + ERROR ("http plugin: DS type does not match value list type"); + return -1; + } - for (i = 0; i < ds->ds_num; i++) - { + status = format_name( key, sizeof(key), vl->host, vl->plugin, + vl->plugin_instance, vl->type, vl->type_instance ); - if (http_value_list_to_string (value, sizeof (value), ds, vl, i) != 0) - return (-1); + if (status != 0) { + ERROR ("http plugin: error with format_name"); + return (status); + } - ssnprintf(metric_name + metric_prefix_len, sizeof (metric_name) - metric_prefix_len, - ",%s", ds->ds[i].name); + status = http_value_list_to_string (values, sizeof (values), ds, vl); - escape_string (metric_name, sizeof (metric_name)); + if (status != 0) { + ERROR ("http plugin: error with http_value_list_to_string"); + return (status); + } - pthread_mutex_lock (&send_lock); - status = ssnprintf (send_buffer + send_buffer_fill, sizeof (send_buffer) - send_buffer_fill, - "\"%s\",%s,%s\n", - metric_name, timestamp, value); - send_buffer_fill += status; + pthread_mutex_lock (&send_lock); - if ((sizeof (send_buffer) - send_buffer_fill) < 128) - { - status = http_flush_buffer(); - if (status != 0) - return status; + status = ssnprintf (send_buffer + send_buffer_fill, sizeof (send_buffer) - send_buffer_fill, + "PUTVAL %s interval=%i %u%s\n", + key, interval_g, vl->time, values); + send_buffer_fill += status; - } + if ((sizeof (send_buffer) - send_buffer_fill) < (sizeof(key) + sizeof(values))) + { + status = http_flush_buffer(); + if (status != 0) + return status; - pthread_mutex_unlock (&send_lock); + } - } /* for */ + pthread_mutex_unlock (&send_lock); - return (0); + return (0); } /* }}} int http_write */ @@ -402,11 +332,11 @@ static int http_shutdown (void) /* {{{ */ void module_register (void) /* {{{ */ { - plugin_register_init("http", http_init); - plugin_register_config ("http", http_config, - config_keys, config_keys_num); - plugin_register_write ("http", http_write, /* user_data = */ NULL); - plugin_register_shutdown("http", http_shutdown); + plugin_register_init("http", http_init); + plugin_register_config ("http", http_config, + config_keys, config_keys_num); + plugin_register_write ("http", http_write, /* user_data = */ NULL); + plugin_register_shutdown("http", http_shutdown); } /* }}} void module_register */ /* vim: set fdm=marker sw=8 ts=8 tw=78 : */ -- 2.30.2