static int dsnames_to_json(char *buffer, size_t buffer_size, /* {{{ */ const data_set_t *ds) { size_t offset = 0; memset(buffer, 0, buffer_size); #define BUFFER_ADD(...) \ do { \ int status; \ status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \ if (status < 1) \ return (-1); \ else if (((size_t)status) >= (buffer_size - offset)) \ return (-ENOMEM); \ else \ offset += ((size_t)status); \ } while (0) BUFFER_ADD("["); for (size_t i = 0; i < ds->ds_num; i++) { if (i > 0) BUFFER_ADD(","); BUFFER_ADD("\"%s\"", ds->ds[i].name); } /* for ds->ds_num */ BUFFER_ADD("]"); #undef BUFFER_ADD DEBUG("format_json: dsnames_to_json: buffer = %s;", buffer); return (0); } /* }}} int dsnames_to_json */
static int gr_format_values (char *ret, size_t ret_len, int ds_num, const data_set_t *ds, const value_list_t *vl, gauge_t const *rates) { size_t offset = 0; int status; assert (0 == strcmp (ds->type, vl->type)); memset (ret, 0, ret_len); #define BUFFER_ADD(...) do { \ status = ssnprintf (ret + offset, ret_len - offset, \ __VA_ARGS__); \ if (status < 1) \ { \ return (-1); \ } \ else if (((size_t) status) >= (ret_len - offset)) \ { \ return (-1); \ } \ else \ offset += ((size_t) status); \ } while (0) if (ds->ds[ds_num].type == DS_TYPE_GAUGE) BUFFER_ADD (GAUGE_FORMAT, vl->values[ds_num].gauge); else if (rates != NULL) BUFFER_ADD ("%f", rates[ds_num]); else if (ds->ds[ds_num].type == DS_TYPE_COUNTER) BUFFER_ADD ("%llu", vl->values[ds_num].counter); else if (ds->ds[ds_num].type == DS_TYPE_DERIVE) BUFFER_ADD ("%"PRIi64, vl->values[ds_num].derive); else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE) BUFFER_ADD ("%"PRIu64, vl->values[ds_num].absolute); else { ERROR ("gr_format_values plugin: Unknown data source type: %i", ds->ds[ds_num].type); return (-1); } #undef BUFFER_ADD return (0); }
static int kairosdb_escape_string(char *buffer, size_t buffer_size, /* {{{ */ const char *string) { size_t dst_pos; if ((buffer == NULL) || (string == NULL)) return -EINVAL; if (buffer_size < 3) return -ENOMEM; dst_pos = 0; #define BUFFER_ADD(c) \ do { \ if (dst_pos >= (buffer_size - 1)) { \ buffer[buffer_size - 1] = '\0'; \ return -ENOMEM; \ } \ buffer[dst_pos] = (c); \ dst_pos++; \ } while (0) /* Escape special characters */ /* authorize -_. and alpha num but also escapes " */ BUFFER_ADD('"'); for (size_t src_pos = 0; string[src_pos] != 0; src_pos++) { if (isalnum(string[src_pos]) || 0x2d == string[src_pos] || 0x2e == string[src_pos] || 0x5f == string[src_pos]) BUFFER_ADD(tolower(string[src_pos])); } /* for */ BUFFER_ADD('"'); buffer[dst_pos] = 0; #undef BUFFER_ADD return 0; } /* }}} int kairosdb_escape_string */
static int escape_string (char *buffer, size_t buffer_size, /* {{{ */ const char *string) { size_t src_pos; size_t dst_pos; if ((buffer == NULL) || (string == NULL)) return (-EINVAL); if (buffer_size < 3) return (-ENOMEM); dst_pos = 0; #define BUFFER_ADD(c) do { \ if (dst_pos >= (buffer_size - 1)) { \ buffer[buffer_size - 1] = 0; \ return (-ENOMEM); \ } \ buffer[dst_pos] = (c); \ dst_pos++; \ } while (0) /* Escape special characters */ BUFFER_ADD ('"'); for (src_pos = 0; string[src_pos] != 0; src_pos++) { if ((string[src_pos] == '"') || (string[src_pos] == '\\')) { BUFFER_ADD ('\\'); BUFFER_ADD (string[src_pos]); } else if (string[src_pos] <= 0x001F) BUFFER_ADD ('?'); else BUFFER_ADD (string[src_pos]); } /* for */ BUFFER_ADD ('"'); buffer[dst_pos] = 0; #undef BUFFER_ADD return (0); } /* }}} int buffer_add_string */
static int ceph_cb_number(void *ctx, const char *number_val, yajl_len_t number_len) { yajl_struct *state = (yajl_struct*) ctx; char buffer[number_len+1]; char key[2 * DATA_MAX_NAME_LEN]; _Bool latency_type = 0; size_t i; int status; memcpy(buffer, number_val, number_len); buffer[sizeof(buffer) - 1] = 0; memset (key, 0, sizeof (key)); for (i = 0; i < state->depth; i++) { if (state->stack[i] == NULL) continue; if (strlen (key) != 0) BUFFER_ADD (key, "."); BUFFER_ADD (key, state->stack[i]); } /* Special case for latency metrics. */ if ((strcmp ("avgcount", state->key) == 0) || (strcmp ("sum", state->key) == 0)) { latency_type = 1; /* Super-special case for filestore.journal_wr_bytes.avgcount: For * some reason, Ceph schema encodes this as a count/sum pair while all * other "Bytes" data (excluding used/capacity bytes for OSD space) uses * a single "Derive" type. To spare further confusion, keep this KPI as * the same type of other "Bytes". Instead of keeping an "average" or * "rate", use the "sum" in the pair and assign that to the derive * value. */ if (convert_special_metrics && (state->depth >= 2) && (strcmp("filestore", state->stack[state->depth - 2]) == 0) && (strcmp("journal_wr_bytes", state->stack[state->depth - 1]) == 0) && (strcmp("avgcount", state->key) == 0)) { DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes"); return CEPH_CB_CONTINUE; } } else /* not a latency type */ { BUFFER_ADD (key, "."); BUFFER_ADD (key, state->key); } status = state->handler(state->handler_arg, buffer, key); if((status == RETRY_AVGCOUNT) && latency_type) { /* Add previously skipped part of the key, either "avgcount" or "sum", * and try again. */ BUFFER_ADD (key, "."); BUFFER_ADD (key, state->key); status = state->handler(state->handler_arg, buffer, key); } if (status != 0) { ERROR("ceph plugin: JSON handler failed with status %d.", status); return CEPH_CB_ABORT; } return CEPH_CB_CONTINUE; }
static int values_to_json (char *buffer, size_t buffer_size, /* {{{ */ const data_set_t *ds, const value_list_t *vl, int store_rates) { size_t offset = 0; int i; gauge_t *rates = NULL; memset (buffer, 0, buffer_size); #define BUFFER_ADD(...) do { \ int status; \ status = ssnprintf (buffer + offset, buffer_size - offset, \ __VA_ARGS__); \ if (status < 1) \ { \ sfree(rates); \ return (-1); \ } \ else if (((size_t) status) >= (buffer_size - offset)) \ { \ sfree(rates); \ return (-ENOMEM); \ } \ else \ offset += ((size_t) status); \ } while (0) BUFFER_ADD ("["); for (i = 0; i < ds->ds_num; i++) { if (i > 0) BUFFER_ADD (","); if (ds->ds[i].type == DS_TYPE_GAUGE) { if(isfinite (vl->values[i].gauge)) BUFFER_ADD ("%g", vl->values[i].gauge); else BUFFER_ADD ("null"); } else if (store_rates) { if (rates == NULL) rates = uc_get_rate (ds, vl); if (rates == NULL) { WARNING ("utils_format_json: uc_get_rate failed."); sfree(rates); return (-1); } if(isfinite (rates[i])) BUFFER_ADD ("%g", rates[i]); else BUFFER_ADD ("null"); } else if (ds->ds[i].type == DS_TYPE_COUNTER) BUFFER_ADD ("%llu", vl->values[i].counter); else if (ds->ds[i].type == DS_TYPE_DERIVE) BUFFER_ADD ("%"PRIi64, vl->values[i].derive); else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) BUFFER_ADD ("%"PRIu64, vl->values[i].absolute); else { ERROR ("format_json: Unknown data source type: %i", ds->ds[i].type); sfree (rates); return (-1); } } /* for ds->ds_num */ BUFFER_ADD ("]"); #undef BUFFER_ADD DEBUG ("format_json: values_to_json: buffer = %s;", buffer); sfree(rates); return (0); } /* }}} int values_to_json */
int value_list_to_json (char *buffer, size_t buffer_size, /* {{{ */ const data_set_t *ds, const value_list_t *vl, int store_rates) { char temp[512]; size_t offset = 0; int status; memset (buffer, 0, buffer_size); #define BUFFER_ADD(...) do { \ status = ssnprintf (buffer + offset, buffer_size - offset, \ __VA_ARGS__); \ if (status < 1) \ return (-1); \ else if (((size_t) status) >= (buffer_size - offset)) \ return (-ENOMEM); \ else \ offset += ((size_t) status); \ } while (0) BUFFER_ADD ("{"); status = values_to_json (temp, sizeof (temp), ds, vl, store_rates); if (status != 0) return (status); BUFFER_ADD ("\"values\":%s", temp); status = dstypes_to_json (temp, sizeof (temp), ds, vl); if (status != 0) return (status); BUFFER_ADD (",\"dstypes\":%s", temp); status = dsnames_to_json (temp, sizeof (temp), ds, vl); if (status != 0) return (status); BUFFER_ADD (",\"dsnames\":%s", temp); BUFFER_ADD (",\"time\":%lu", (unsigned long) vl->time); BUFFER_ADD (",\"interval\":%i", vl->interval); #define BUFFER_ADD_KEYVAL(key, value) do { \ status = escape_string (temp, sizeof (temp), (value)); \ if (status != 0) \ return (status); \ BUFFER_ADD (",\"%s\":%s", (key), temp); \ } while (0) BUFFER_ADD_KEYVAL ("host", vl->host); BUFFER_ADD_KEYVAL ("plugin", vl->plugin); BUFFER_ADD_KEYVAL ("plugin_instance", vl->plugin_instance); BUFFER_ADD_KEYVAL ("type", vl->type); BUFFER_ADD_KEYVAL ("type_instance", vl->type_instance); BUFFER_ADD ("}"); #undef BUFFER_ADD_KEYVAL #undef BUFFER_ADD DEBUG ("format_json: value_list_to_json: buffer = %s;", buffer); return (0); } /* }}} int value_list_to_json */
static int value_list_to_json(char *buffer, size_t buffer_size, /* {{{ */ const data_set_t *ds, const value_list_t *vl, int store_rates) { char temp[512]; size_t offset = 0; int status; memset(buffer, 0, buffer_size); #define BUFFER_ADD(...) \ do { \ status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \ if (status < 1) \ return (-1); \ else if (((size_t)status) >= (buffer_size - offset)) \ return (-ENOMEM); \ else \ offset += ((size_t)status); \ } while (0) /* All value lists have a leading comma. The first one will be replaced with * a square bracket in `format_json_finalize'. */ BUFFER_ADD(",{"); status = values_to_json(temp, sizeof(temp), ds, vl, store_rates); if (status != 0) return (status); BUFFER_ADD("\"values\":%s", temp); status = dstypes_to_json(temp, sizeof(temp), ds); if (status != 0) return (status); BUFFER_ADD(",\"dstypes\":%s", temp); status = dsnames_to_json(temp, sizeof(temp), ds); if (status != 0) return (status); BUFFER_ADD(",\"dsnames\":%s", temp); BUFFER_ADD(",\"time\":%.3f", CDTIME_T_TO_DOUBLE(vl->time)); BUFFER_ADD(",\"interval\":%.3f", CDTIME_T_TO_DOUBLE(vl->interval)); #define BUFFER_ADD_KEYVAL(key, value) \ do { \ status = json_escape_string(temp, sizeof(temp), (value)); \ if (status != 0) \ return (status); \ BUFFER_ADD(",\"%s\":%s", (key), temp); \ } while (0) BUFFER_ADD_KEYVAL("host", vl->host); BUFFER_ADD_KEYVAL("plugin", vl->plugin); BUFFER_ADD_KEYVAL("plugin_instance", vl->plugin_instance); BUFFER_ADD_KEYVAL("type", vl->type); BUFFER_ADD_KEYVAL("type_instance", vl->type_instance); if (vl->meta != NULL) { char meta_buffer[buffer_size]; memset(meta_buffer, 0, sizeof(meta_buffer)); status = meta_data_to_json(meta_buffer, sizeof(meta_buffer), vl->meta); if (status != 0) return (status); BUFFER_ADD(",\"meta\":%s", meta_buffer); } /* if (vl->meta != NULL) */ BUFFER_ADD("}"); #undef BUFFER_ADD_KEYVAL #undef BUFFER_ADD DEBUG("format_json: value_list_to_json: buffer = %s;", buffer); return (0); } /* }}} int value_list_to_json */
static int meta_data_keys_to_json(char *buffer, size_t buffer_size, /* {{{ */ meta_data_t *meta, char **keys, size_t keys_num) { size_t offset = 0; int status; buffer[0] = 0; #define BUFFER_ADD(...) \ do { \ status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \ if (status < 1) \ return (-1); \ else if (((size_t)status) >= (buffer_size - offset)) \ return (-ENOMEM); \ else \ offset += ((size_t)status); \ } while (0) for (size_t i = 0; i < keys_num; ++i) { int type; char *key = keys[i]; type = meta_data_type(meta, key); if (type == MD_TYPE_STRING) { char *value = NULL; if (meta_data_get_string(meta, key, &value) == 0) { char temp[512] = ""; status = json_escape_string(temp, sizeof(temp), value); sfree(value); if (status != 0) return status; BUFFER_ADD(",\"%s\":%s", key, temp); } } else if (type == MD_TYPE_SIGNED_INT) { int64_t value = 0; if (meta_data_get_signed_int(meta, key, &value) == 0) BUFFER_ADD(",\"%s\":%" PRIi64, key, value); } else if (type == MD_TYPE_UNSIGNED_INT) { uint64_t value = 0; if (meta_data_get_unsigned_int(meta, key, &value) == 0) BUFFER_ADD(",\"%s\":%" PRIu64, key, value); } else if (type == MD_TYPE_DOUBLE) { double value = 0.0; if (meta_data_get_double(meta, key, &value) == 0) BUFFER_ADD(",\"%s\":%f", key, value); } else if (type == MD_TYPE_BOOLEAN) { _Bool value = 0; if (meta_data_get_boolean(meta, key, &value) == 0) BUFFER_ADD(",\"%s\":%s", key, value ? "true" : "false"); } } /* for (keys) */ if (offset == 0) return (ENOENT); buffer[0] = '{'; /* replace leading ',' */ BUFFER_ADD("}"); #undef BUFFER_ADD return (0); } /* }}} int meta_data_keys_to_json */
static int values_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */ const data_set_t *ds, const value_list_t *vl, int store_rates, size_t ds_idx) { size_t offset = 0; gauge_t *rates = NULL; memset(buffer, 0, buffer_size); #define BUFFER_ADD(...) \ do { \ int status; \ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \ if (status < 1) { \ sfree(rates); \ return -1; \ } else if (((size_t)status) >= (buffer_size - offset)) { \ sfree(rates); \ return -ENOMEM; \ } else \ offset += ((size_t)status); \ } while (0) if (ds->ds[ds_idx].type == DS_TYPE_GAUGE) { if (isfinite(vl->values[ds_idx].gauge)) { BUFFER_ADD("[["); BUFFER_ADD("%" PRIu64, CDTIME_T_TO_MS(vl->time)); BUFFER_ADD(","); BUFFER_ADD(JSON_GAUGE_FORMAT, vl->values[ds_idx].gauge); } else { DEBUG("utils_format_kairosdb: invalid vl->values[ds_idx].gauge for " "%s|%s|%s|%s|%s", vl->plugin, vl->plugin_instance, vl->type, vl->type_instance, ds->ds[ds_idx].name); return -1; } } else if (store_rates) { if (rates == NULL) rates = uc_get_rate(ds, vl); if (rates == NULL) { WARNING("utils_format_kairosdb: uc_get_rate failed for %s|%s|%s|%s|%s", vl->plugin, vl->plugin_instance, vl->type, vl->type_instance, ds->ds[ds_idx].name); return -1; } if (isfinite(rates[ds_idx])) { BUFFER_ADD("[["); BUFFER_ADD("%" PRIu64, CDTIME_T_TO_MS(vl->time)); BUFFER_ADD(","); BUFFER_ADD(JSON_GAUGE_FORMAT, rates[ds_idx]); } else { WARNING("utils_format_kairosdb: invalid rates[ds_idx] for %s|%s|%s|%s|%s", vl->plugin, vl->plugin_instance, vl->type, vl->type_instance, ds->ds[ds_idx].name); sfree(rates); return -1; } } else if (ds->ds[ds_idx].type == DS_TYPE_COUNTER) { BUFFER_ADD("[["); BUFFER_ADD("%" PRIu64, CDTIME_T_TO_MS(vl->time)); BUFFER_ADD(","); BUFFER_ADD("%" PRIu64, (uint64_t)vl->values[ds_idx].counter); } else if (ds->ds[ds_idx].type == DS_TYPE_DERIVE) { BUFFER_ADD("[["); BUFFER_ADD("%" PRIu64, CDTIME_T_TO_MS(vl->time)); BUFFER_ADD(","); BUFFER_ADD("%" PRIi64, vl->values[ds_idx].derive); } else if (ds->ds[ds_idx].type == DS_TYPE_ABSOLUTE) { BUFFER_ADD("[["); BUFFER_ADD("%" PRIu64, CDTIME_T_TO_MS(vl->time)); BUFFER_ADD(","); BUFFER_ADD("%" PRIu64, vl->values[ds_idx].absolute); } else { ERROR("format_kairosdb: Unknown data source type: %i", ds->ds[ds_idx].type); sfree(rates); return -1; } BUFFER_ADD("]]"); #undef BUFFER_ADD DEBUG("format_kairosdb: values_to_kairosdb: buffer = %s;", buffer); sfree(rates); return 0; } /* }}} int values_to_kairosdb */
static int value_list_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */ const data_set_t *ds, const value_list_t *vl, int store_rates, char const *const *http_attrs, size_t http_attrs_num, int data_ttl, char const *metrics_prefix) { char temp[512]; size_t offset = 0; int status; memset(buffer, 0, buffer_size); #define BUFFER_ADD(...) \ do { \ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \ if (status < 1) \ return -1; \ else if (((size_t)status) >= (buffer_size - offset)) \ return -ENOMEM; \ else \ offset += ((size_t)status); \ } while (0) #define BUFFER_ADD_KEYVAL(key, value) \ do { \ status = kairosdb_escape_string(temp, sizeof(temp), (value)); \ if (status != 0) \ return status; \ BUFFER_ADD(",\"%s\": %s", (key), temp); \ } while (0) for (size_t i = 0; i < ds->ds_num; i++) { /* All value lists have a leading comma. The first one will be replaced with * a square bracket in `format_kairosdb_finalize'. */ BUFFER_ADD(",{\"name\":\""); if (metrics_prefix != NULL) { BUFFER_ADD("%s.", metrics_prefix); } BUFFER_ADD("%s", vl->plugin); status = values_to_kairosdb(temp, sizeof(temp), ds, vl, store_rates, i); if (status != 0) return status; BUFFER_ADD("\", \"datapoints\": %s", temp); /* * Now adds meta data to metric as tags */ memset(temp, 0, sizeof(temp)); if (data_ttl != 0) BUFFER_ADD(", \"ttl\": %i", data_ttl); BUFFER_ADD(", \"tags\":\{"); BUFFER_ADD("\"host\": \"%s\"", vl->host); for (size_t j = 0; j < http_attrs_num; j += 2) { BUFFER_ADD(", \"%s\":", http_attrs[j]); BUFFER_ADD(" \"%s\"", http_attrs[j + 1]); } if (strlen(vl->plugin_instance)) BUFFER_ADD_KEYVAL("plugin_instance", vl->plugin_instance); BUFFER_ADD_KEYVAL("type", vl->type); if (strlen(vl->type_instance)) BUFFER_ADD_KEYVAL("type_instance", vl->type_instance); if (ds->ds_num != 1) BUFFER_ADD_KEYVAL("ds", ds->ds[i].name); BUFFER_ADD("}}"); } /* for ds->ds_num */ #undef BUFFER_ADD_KEYVAL #undef BUFFER_ADD DEBUG("format_kairosdb: value_list_to_kairosdb: buffer = %s;", buffer); return 0; } /* }}} int value_list_to_kairosdb */
int format_values_extremon (char *ret, size_t ret_len, const data_set_t *ds, const value_list_t *vl, _Bool store_rates) { size_t offset = 0; int status=0; int i; gauge_t* rates = NULL; assert (0 == strcmp (ds->type, vl->type)); assert (vl->plugin != NULL); assert (vl->type != NULL); memset (ret, 0, ret_len); #define BUFFER_ADD(...) do { \ status = ssnprintf (ret + offset, ret_len - offset, \ __VA_ARGS__); \ if (status < 1) \ { \ sfree (rates); \ return (-1); \ } \ else if (((size_t) status) >= (ret_len - offset)) \ { \ sfree (rates); \ return (-1); \ } \ else \ offset += ((size_t) status); \ } while (0) for(i=0;i<ds->ds_num;i++) { if((vl->plugin_instance==NULL) || (strlen (vl->plugin_instance)= 0)) { if ((vl->type_instance==NULL) || (strlen(vl->type_instance)==0)) BUFFER_ADD("%s.%s.%s.",vl->host,vl->plugin,vl->type); else BUFFER_ADD("%s.%s.%s.%s.",vl->host,vl->plugin,vl->type, vl->type_instance); } else { if((vl->type_instance == NULL) || (strlen(vl->type_instance) == 0)) BUFFER_ADD("%s.%s.%s.%s.", vl->host,vl->plugin, vl->plugin_instance, vl->type); else BUFFER_ADD("%s.%s.%s.%s.%s.", vl->host,vl->plugin, vl->plugin_instance,vl->type, vl->type_instance); } if(ds->ds[i].type==DS_TYPE_GAUGE) BUFFER_ADD ("%s=%f\n", ds->ds[i].name,vl->values[i].gauge); else if(store_rates) { if(rates==NULL) rates=uc_get_rate (ds, vl); if(rates==NULL) { WARNING ("format_values_extremon : uc_get_rate failed."); return (-1); } BUFFER_ADD ("%s=%g\n", ds->ds[i].name,rates[i]); } else if(ds->ds[i].type==DS_TYPE_COUNTER) BUFFER_ADD ("%s=%llu\n", ds->ds[i].name,vl->values[i].counter); } #undef BUFFER_ADD sfree (rates); return (0); }