summaryrefslogtreecommitdiffstats
path: root/src/rrd2json.c
diff options
context:
space:
mode:
authorCosta Tsaousis <costa@tsaousis.gr>2018-10-11 21:27:56 +0300
committerGitHub <noreply@github.com>2018-10-11 21:27:56 +0300
commit2cc264eff5925769a4ae082e9b23f31c00ef23ec (patch)
tree2f20f7d6ec77b894e5067c81522611f26fa37722 /src/rrd2json.c
parent6606b3131d20eac229644472abd2d2534ddc05fb (diff)
modularize C source code (#4372)
* modularize cgroups and cmake; #4339 * modularized freeipmi.plugin * added comment about referencing parent files * modularized apps.plugin * modularized proc and diskspace * minor fixes * modularized plugins: checks, freebsd, idlejitter, nfacct, tc, macos, plugins.d * minor fixes 2 * modularized statsd * modularized cgroup-network * moved cgroup-network-helper.sh and cgroup-name.sh to cgroup.plugin * modularized health plugin * move rrd related info to rrd.h * added libnetdata * do not corrupt config.h * use dir-objects instead of static libraries * fixed cmake for new structure * use absolute paths to fix LGTM * enable automake subdir-objects and prettify its output * use relative files at the src directory for all plugins * fix compiler warning * synced automake and cmake * added config.h to cmake * abstracted basic os functions in libnetdata/os * fix zfs_common * removed apps.plugin dependency on freebsd plugin * health removed from plugins * modularized the registry * modularized the rest of it * include streaming files in cmake * use libnetdata as library * enable silent-rules only when they are available
Diffstat (limited to 'src/rrd2json.c')
-rw-r--r--src/rrd2json.c2061
1 files changed, 0 insertions, 2061 deletions
diff --git a/src/rrd2json.c b/src/rrd2json.c
deleted file mode 100644
index 7920cb85e5..0000000000
--- a/src/rrd2json.c
+++ /dev/null
@@ -1,2061 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "common.h"
-
-void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used)
-{
- rrdset_rdlock(st);
-
- buffer_sprintf(wb,
- "\t\t{\n"
- "\t\t\t\"id\": \"%s\",\n"
- "\t\t\t\"name\": \"%s\",\n"
- "\t\t\t\"type\": \"%s\",\n"
- "\t\t\t\"family\": \"%s\",\n"
- "\t\t\t\"context\": \"%s\",\n"
- "\t\t\t\"title\": \"%s (%s)\",\n"
- "\t\t\t\"priority\": %ld,\n"
- "\t\t\t\"plugin\": \"%s\",\n"
- "\t\t\t\"module\": \"%s\",\n"
- "\t\t\t\"enabled\": %s,\n"
- "\t\t\t\"units\": \"%s\",\n"
- "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n"
- "\t\t\t\"chart_type\": \"%s\",\n"
- "\t\t\t\"duration\": %ld,\n"
- "\t\t\t\"first_entry\": %ld,\n"
- "\t\t\t\"last_entry\": %ld,\n"
- "\t\t\t\"update_every\": %d,\n"
- "\t\t\t\"dimensions\": {\n"
- , st->id
- , st->name
- , st->type
- , st->family
- , st->context
- , st->title, st->name
- , st->priority
- , st->plugin_name?st->plugin_name:""
- , st->module_name?st->module_name:""
- , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?"true":"false"
- , st->units
- , st->name
- , rrdset_type_name(st->chart_type)
- , st->entries * st->update_every
- , rrdset_first_entry_t(st)
- , rrdset_last_entry_t(st)
- , st->update_every
- );
-
- unsigned long memory = st->memsize;
-
- size_t dimensions = 0;
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) continue;
-
- memory += rd->memsize;
-
- buffer_sprintf(
- wb
- , "%s"
- "\t\t\t\t\"%s\": { \"name\": \"%s\" }"
- , dimensions ? ",\n" : ""
- , rd->id
- , rd->name
- );
-
- dimensions++;
- }
-
- if(dimensions_count) *dimensions_count += dimensions;
- if(memory_used) *memory_used += memory;
-
- buffer_strcat(wb, "\n\t\t\t},\n\t\t\t\"green\": ");
- buffer_rrd_value(wb, st->green);
- buffer_strcat(wb, ",\n\t\t\t\"red\": ");
- buffer_rrd_value(wb, st->red);
-
- buffer_strcat(wb, ",\n\t\t\t\"alarms\": {\n");
- size_t alarms = 0;
- RRDCALC *rc;
- for(rc = st->alarms; rc ; rc = rc->rrdset_next) {
-
- buffer_sprintf(
- wb
- , "%s"
- "\t\t\t\t\"%s\": {\n"
- "\t\t\t\t\t\"id\": %u,\n"
- "\t\t\t\t\t\"status\": \"%s\",\n"
- "\t\t\t\t\t\"units\": \"%s\",\n"
- "\t\t\t\t\t\"update_every\": %d\n"
- "\t\t\t\t}"
- , (alarms) ? ",\n" : ""
- , rc->name
- , rc->id
- , rrdcalc_status2string(rc->status)
- , rc->units
- , rc->update_every
- );
-
- alarms++;
- }
-
- buffer_sprintf(wb,
- "\n\t\t\t}\n\t\t}"
- );
-
- rrdset_unlock(st);
-}
-
-void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) {
- rrd_stats_api_v1_chart_with_data(st, wb, NULL, NULL);
-}
-
-void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) {
- static char *custom_dashboard_info_js_filename = NULL;
- size_t c, dimensions = 0, memory = 0, alarms = 0;
- RRDSET *st;
-
- time_t now = now_realtime_sec();
-
- if(unlikely(!custom_dashboard_info_js_filename))
- custom_dashboard_info_js_filename = config_get(CONFIG_SECTION_WEB, "custom dashboard_info.js", "");
-
- buffer_sprintf(wb, "{\n"
- "\t\"hostname\": \"%s\""
- ",\n\t\"version\": \"%s\""
- ",\n\t\"os\": \"%s\""
- ",\n\t\"timezone\": \"%s\""
- ",\n\t\"update_every\": %d"
- ",\n\t\"history\": %ld"
- ",\n\t\"custom_info\": \"%s\""
- ",\n\t\"charts\": {"
- , host->hostname
- , host->program_version
- , host->os
- , host->timezone
- , host->rrd_update_every
- , host->rrd_history_entries
- , custom_dashboard_info_js_filename
- );
-
- c = 0;
- rrdhost_rdlock(host);
- rrdset_foreach_read(st, host) {
- if(rrdset_is_available_for_viewers(st)) {
- if(c) buffer_strcat(wb, ",");
- buffer_strcat(wb, "\n\t\t\"");
- buffer_strcat(wb, st->id);
- buffer_strcat(wb, "\": ");
- rrd_stats_api_v1_chart_with_data(st, wb, &dimensions, &memory);
-
- c++;
- st->last_accessed_time = now;
- }
- }
-
- RRDCALC *rc;
- for(rc = host->alarms; rc ; rc = rc->next) {
- if(rc->rrdset)
- alarms++;
- }
- rrdhost_unlock(host);
-
- buffer_sprintf(wb
- , "\n\t}"
- ",\n\t\"charts_count\": %zu"
- ",\n\t\"dimensions_count\": %zu"
- ",\n\t\"alarms_count\": %zu"
- ",\n\t\"rrd_memory_bytes\": %zu"
- ",\n\t\"hosts_count\": %zu"
- ",\n\t\"hosts\": ["
- , c
- , dimensions
- , alarms
- , memory
- , rrd_hosts_available
- );
-
- if(unlikely(rrd_hosts_available > 1)) {
- rrd_rdlock();
-
- size_t found = 0;
- RRDHOST *h;
- rrdhost_foreach_read(h) {
- if(!rrdhost_should_be_removed(h, host, now)) {
- buffer_sprintf(wb
- , "%s\n\t\t{"
- "\n\t\t\t\"hostname\": \"%s\""
- "\n\t\t}"
- , (found > 0) ? "," : ""
- , h->hostname
- );
-
- found++;
- }
- }
-
- rrd_unlock();
- }
- else {
- buffer_sprintf(wb
- , "\n\t\t{"
- "\n\t\t\t\"hostname\": \"%s\""
- "\n\t\t}"
- , host->hostname
- );
- }
-
- buffer_sprintf(wb, "\n\t]\n}\n");
-}
-
-// ----------------------------------------------------------------------------
-// BASH
-// /api/v1/allmetrics?format=bash
-
-static inline size_t shell_name_copy(char *d, const char *s, size_t usable) {
- size_t n;
-
- for(n = 0; *s && n < usable ; d++, s++, n++) {
- register char c = *s;
-
- if(unlikely(!isalnum(c))) *d = '_';
- else *d = (char)toupper(c);
- }
- *d = '\0';
-
- return n;
-}
-
-#define SHELL_ELEMENT_MAX 100
-
-void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) {
- rrdhost_rdlock(host);
-
- // for each chart
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- calculated_number total = 0.0;
- char chart[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(chart, st->name?st->name:st->id, SHELL_ELEMENT_MAX);
-
- buffer_sprintf(wb, "\n# chart: %s (name: %s)\n", st->id, st->name);
- if(rrdset_is_available_for_viewers(st)) {
- rrdset_rdlock(st);
-
- // for each dimension
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rd->collections_counter) {
- char dimension[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(dimension, rd->name?rd->name:rd->id, SHELL_ELEMENT_MAX);
-
- calculated_number n = rd->last_stored_value;
-
- if(isnan(n) || isinf(n))
- buffer_sprintf(wb, "NETDATA_%s_%s=\"\" # %s\n", chart, dimension, st->units);
- else {
- if(rd->multiplier < 0 || rd->divisor < 0) n = -n;
- n = calculated_number_round(n);
- if(!rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) total += n;
- buffer_sprintf(wb, "NETDATA_%s_%s=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, dimension, n, st->units);
- }
- }
- }
-
- total = calculated_number_round(total);
- buffer_sprintf(wb, "NETDATA_%s_VISIBLETOTAL=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, total, st->units);
- rrdset_unlock(st);
- }
- }
-
- buffer_strcat(wb, "\n# NETDATA ALARMS RUNNING\n");
-
- RRDCALC *rc;
- for(rc = host->alarms; rc ;rc = rc->next) {
- if(!rc->rrdset) continue;
-
- char chart[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(chart, rc->rrdset->name?rc->rrdset->name:rc->rrdset->id, SHELL_ELEMENT_MAX);
-
- char alarm[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(alarm, rc->name, SHELL_ELEMENT_MAX);
-
- calculated_number n = rc->value;
-
- if(isnan(n) || isinf(n))
- buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"\" # %s\n", chart, alarm, rc->units);
- else {
- n = calculated_number_round(n);
- buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, alarm, n, rc->units);
- }
-
- buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_STATUS=\"%s\"\n", chart, alarm, rrdcalc_status2string(rc->status));
- }
-
- rrdhost_unlock(host);
-}
-
-// ----------------------------------------------------------------------------
-
-void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb) {
- rrdhost_rdlock(host);
-
- buffer_strcat(wb, "{");
-
- size_t chart_counter = 0;
- size_t dimension_counter = 0;
-
- // for each chart
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- if(rrdset_is_available_for_viewers(st)) {
- rrdset_rdlock(st);
-
- buffer_sprintf(wb, "%s\n"
- "\t\"%s\": {\n"
- "\t\t\"name\":\"%s\",\n"
- "\t\t\"context\":\"%s\",\n"
- "\t\t\"units\":\"%s\",\n"
- "\t\t\"last_updated\": %ld,\n"
- "\t\t\"dimensions\": {"
- , chart_counter?",":""
- , st->id
- , st->name
- , st->context
- , st->units
- , rrdset_last_entry_t(st)
- );
-
- chart_counter++;
- dimension_counter = 0;
-
- // for each dimension
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rd->collections_counter) {
-
- buffer_sprintf(wb, "%s\n"
- "\t\t\t\"%s\": {\n"
- "\t\t\t\t\"name\": \"%s\",\n"
- "\t\t\t\t\"value\": "
- , dimension_counter?",":""
- , rd->id
- , rd->name
- );
-
- if(isnan(rd->last_stored_value))
- buffer_strcat(wb, "null");
- else
- buffer_sprintf(wb, CALCULATED_NUMBER_FORMAT, rd->last_stored_value);
-
- buffer_strcat(wb, "\n\t\t\t}");
-
- dimension_counter++;
- }
- }
-
- buffer_strcat(wb, "\n\t\t}\n\t}");
- rrdset_unlock(st);
- }
- }
-
- buffer_strcat(wb, "\n}");
- rrdhost_unlock(host);
-}
-
-// ----------------------------------------------------------------------------
-
-// RRDR dimension options
-#define RRDR_EMPTY 0x01 // the dimension contains / the value is empty (null)
-#define RRDR_RESET 0x02 // the dimension contains / the value is reset
-#define RRDR_HIDDEN 0x04 // the dimension contains / the value is hidden
-#define RRDR_NONZERO 0x08 // the dimension contains / the value is non-zero
-#define RRDR_SELECTED 0x10 // the dimension is selected
-
-// RRDR result options
-#define RRDR_RESULT_OPTION_ABSOLUTE 0x00000001
-#define RRDR_RESULT_OPTION_RELATIVE 0x00000002
-
-typedef struct rrdresult {
- RRDSET *st; // the chart this result refers to
-
- uint32_t result_options; // RRDR_RESULT_OPTION_*
-
- int d; // the number of dimensions
- long n; // the number of values in the arrays
- long rows; // the number of rows used
-
- uint8_t *od; // the options for the dimensions
-
- time_t *t; // array of n timestamps
- calculated_number *v; // array n x d values
- uint8_t *o; // array n x d options
-
- long c; // current line ( -1 ~ n ), ( -1 = none, use rrdr_rows() to get number of rows )
-
- long group; // how many collected values were grouped for each row
- int update_every; // what is the suggested update frequency in seconds
-
- calculated_number min;
- calculated_number max;
-
- time_t before;
- time_t after;
-
- int has_st_lock; // if st is read locked by us
-} RRDR;
-
-#define rrdr_rows(r) ((r)->rows)
-
-/*
-static void rrdr_dump(RRDR *r)
-{
- long c, i;
- RRDDIM *d;
-
- fprintf(stderr, "\nCHART %s (%s)\n", r->st->id, r->st->name);
-
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
- fprintf(stderr, "DIMENSION %s (%s), %s%s%s%s\n"
- , d->id
- , d->name
- , (r->od[c] & RRDR_EMPTY)?"EMPTY ":""
- , (r->od[c] & RRDR_RESET)?"RESET ":""
- , (r->od[c] & RRDR_HIDDEN)?"HIDDEN ":""
- , (r->od[c] & RRDR_NONZERO)?"NONZERO ":""
- );
- }
-
- if(r->rows <= 0) {
- fprintf(stderr, "RRDR does not have any values in it.\n");
- return;
- }
-
- fprintf(stderr, "RRDR includes %d values in it:\n", r->rows);
-
- // for each line in the array
- for(i = 0; i < r->rows ;i++) {
- calculated_number *cn = &r->v[ i * r->d ];
- uint8_t *co = &r->o[ i * r->d ];
-
- // print the id and the timestamp of the line
- fprintf(stderr, "%ld %ld ", i + 1, r->t[i]);
-
- // for each dimension
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
-
- if(co[c] & RRDR_EMPTY)
- fprintf(stderr, "null ");
- else
- fprintf(stderr, CALCULATED_NUMBER_FORMAT " %s%s%s%s "
- , cn[c]
- , (co[c] & RRDR_EMPTY)?"E":" "
- , (co[c] & RRDR_RESET)?"R":" "
- , (co[c] & RRDR_HIDDEN)?"H":" "
- , (co[c] & RRDR_NONZERO)?"N":" "
- );
- }
-
- fprintf(stderr, "\n");
- }
-}
-*/
-
-void rrdr_disable_not_selected_dimensions(RRDR *r, uint32_t options, const char *dims) {
- rrdset_check_rdlock(r->st);
-
- if(unlikely(!dims || !*dims || (dims[0] == '*' && dims[1] == '\0'))) return;
-
- int match_ids = 0, match_names = 0;
-
- if(unlikely(options & RRDR_OPTION_MATCH_IDS))
- match_ids = 1;
- if(unlikely(options & RRDR_OPTION_MATCH_NAMES))
- match_names = 1;
-
- if(likely(!match_ids && !match_names))
- match_ids = match_names = 1;
-
- SIMPLE_PATTERN *pattern = simple_pattern_create(dims, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT);
-
- RRDDIM *d;
- long c, dims_selected = 0, dims_not_hidden_not_zero = 0;
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
- if( (match_ids && simple_pattern_matches(pattern, d->id))
- || (match_names && simple_pattern_matches(pattern, d->name))
- ) {
- r->od[c] |= RRDR_SELECTED;
- if(unlikely(r->od[c] & RRDR_HIDDEN)) r->od[c] &= ~RRDR_HIDDEN;
- dims_selected++;
-
- // since the user needs this dimension
- // make it appear as NONZERO, to return it
- // even if the dimension has only zeros
- // unless option non_zero is set
- if(unlikely(!(options & RRDR_OPTION_NONZERO)))
- r->od[c] |= RRDR_NONZERO;
-
- // count the visible dimensions
- if(likely(r->od[c] & RRDR_NONZERO))
- dims_not_hidden_not_zero++;
- }
- else {
- r->od[c] |= RRDR_HIDDEN;
- if(unlikely(r->od[c] & RRDR_SELECTED)) r->od[c] &= ~RRDR_SELECTED;
- }
- }
- simple_pattern_free(pattern);
-
- // check if all dimensions are hidden
- if(unlikely(!dims_not_hidden_not_zero && dims_selected)) {
- // there are a few selected dimensions
- // but they are all zero
- // enable the selected ones
- // to avoid returning an empty chart
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next)
- if(unlikely(r->od[c] & RRDR_SELECTED))
- r->od[c] |= RRDR_NONZERO;
- }
-}
-
-void rrdr_buffer_print_format(BUFFER *wb, uint32_t format)
-{
- switch(format) {
- case DATASOURCE_JSON:
- buffer_strcat(wb, DATASOURCE_FORMAT_JSON);
- break;
-
- case DATASOURCE_DATATABLE_JSON:
- buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSON);
- break;
-
- case DATASOURCE_DATATABLE_JSONP:
- buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSONP);
- break;
-
- case DATASOURCE_JSONP:
- buffer_strcat(wb, DATASOURCE_FORMAT_JSONP);
- break;
-
- case DATASOURCE_SSV:
- buffer_strcat(wb, DATASOURCE_FORMAT_SSV);
- break;
-
- case DATASOURCE_CSV:
- buffer_strcat(wb, DATASOURCE_FORMAT_CSV);
- break;
-
- case DATASOURCE_TSV:
- buffer_strcat(wb, DATASOURCE_FORMAT_TSV);
- break;
-
- case DATASOURCE_HTML:
- buffer_strcat(wb, DATASOURCE_FORMAT_HTML);
- break;
-
- case DATASOURCE_JS_ARRAY:
- buffer_strcat(wb, DATASOURCE_FORMAT_JS_ARRAY);
- break;
-
- case DATASOURCE_SSV_COMMA:
- buffer_strcat(wb, DATASOURCE_FORMAT_SSV_COMMA);
- break;
-
- default:
- buffer_strcat(wb, "unknown");
- break;
- }
-}
-
-uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims)
-{
- rrdset_check_rdlock(r->st);
-
- (void)dims;
-
- if(options & RRDR_OPTION_NONZERO) {
- long i;
-
- // commented due to #1514
-
- //if(dims && *dims) {
- // the caller wants specific dimensions
- // disable NONZERO option
- // to make sure we don't accidentally prevent
- // the specific dimensions from being returned
- // i = 0;
- //}
- //else {
- // find how many dimensions are not zero
- long c;
- RRDDIM *rd;
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
- i++;
- }
- //}
-
- // if with nonzero we get i = 0 (no dimensions will be returned)
- // disable nonzero to show all dimensions
- if(!i) options &= ~RRDR_OPTION_NONZERO;
- }
-
- return options;
-}
-
-void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
-{
- rrdset_check_rdlock(r->st);
-
- long rows = rrdr_rows(r);
- long c, i;
- RRDDIM *rd;
-
- //info("JSONWRAPPER(): %s: BEGIN", r->st->id);
- char kq[2] = "", // key quote
- sq[2] = ""; // string quote
-
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- }
-
- buffer_sprintf(wb, "{\n"
- " %sapi%s: 1,\n"
- " %sid%s: %s%s%s,\n"
- " %sname%s: %s%s%s,\n"
- " %sview_update_every%s: %d,\n"
- " %supdate_every%s: %d,\n"
- " %sfirst_entry%s: %u,\n"
- " %slast_entry%s: %u,\n"
- " %sbefore%s: %u,\n"
- " %safter%s: %u,\n"
- " %sdimension_names%s: ["
- , kq, kq
- , kq, kq, sq, r->st->id, sq
- , kq, kq, sq, r->st->name, sq
- , kq, kq, r->update_every
- , kq, kq, r->st->update_every
- , kq, kq, (uint32_t)rrdset_first_entry_t(r->st)
- , kq, kq, (uint32_t)rrdset_last_entry_t(r->st)
- , kq, kq, (uint32_t)r->before
- , kq, kq, (uint32_t)r->after
- , kq, kq);
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- buffer_strcat(wb, sq);
- buffer_strcat(wb, rd->name);
- buffer_strcat(wb, sq);
- i++;
- }
- if(!i) {
-#ifdef NETDATA_INTERNAL_CHECKS
- error("RRDR is empty for %s (RRDR has %d dimensions, options is 0x%08x)", r->st->id, r->d, options);
-#endif
- rows = 0;
- buffer_strcat(wb, sq);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, sq);
- }
-
- buffer_sprintf(wb, "],\n"
- " %sdimension_ids%s: ["
- , kq, kq);
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- buffer_strcat(wb, sq);
- buffer_strcat(wb, rd->id);
- buffer_strcat(wb, sq);
- i++;
- }
- if(!i) {
- rows = 0;
- buffer_strcat(wb, sq);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, sq);
- }
-
- buffer_sprintf(wb, "],\n"
- " %slatest_values%s: ["
- , kq, kq);
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- i++;
-
- storage_number n = rd->values[rrdset_last_slot(r->st)];
-
- if(!does_storage_number_exist(n))
- buffer_strcat(wb, "null");
- else
- buffer_rrd_value(wb, unpack_storage_number(n));
- }
- if(!i) {
- rows = 0;
- buffer_strcat(wb, "null");
- }
-
- buffer_sprintf(wb, "],\n"
- " %sview_latest_values%s: ["
- , kq, kq);
-
- i = 0;
- if(rows) {
- calculated_number total = 1;
-
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- total = 0;
- for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- calculated_number *cn = &r->v[ (0) * r->d ];
- calculated_number n = cn[c];
-
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- total += n;
- }
- // prevent a division by zero
- if(total == 0) total = 1;
- }
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- i++;
-
- calculated_number *cn = &r->v[ (0) * r->d ];
- uint8_t *co = &r->o[ (0) * r->d ];
- calculated_number n = cn[c];
-
- if(co[c] & RRDR_EMPTY) {
- if(options & RRDR_OPTION_NULL2ZERO)
- buffer_strcat(wb, "0");
- else
- buffer_strcat(wb, "null");
- }
- else {
- if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- if(unlikely(options & RRDR_OPTION_PERCENTAGE))
- n = n * 100 / total;
-
- buffer_rrd_value(wb, n);
- }
- }
- }
- if(!i) {
- rows = 0;
- buffer_strcat(wb, "null");
- }
-
- buffer_sprintf(wb, "],\n"
- " %sdimensions%s: %ld,\n"
- " %spoints%s: %ld,\n"
- " %sformat%s: %s"
- , kq, kq, i
- , kq, kq, rows
- , kq, kq, sq
- );
-
- rrdr_buffer_print_format(wb, format);
-
- buffer_sprintf(wb, "%s,\n"
- " %sresult%s: "
- , sq
- , kq, kq
- );
-
- if(string_value) buffer_strcat(wb, sq);
- //info("JSONWRAPPER(): %s: END", r->st->id);
-}
-
-void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
-{
- (void)format;
-
- char kq[2] = "", // key quote
- sq[2] = ""; // string quote
-
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- }
-
- if(string_value) buffer_strcat(wb, sq);
-
- buffer_sprintf(wb, ",\n %smin%s: ", kq, kq);
- buffer_rrd_value(wb, r->min);
- buffer_sprintf(wb, ",\n %smax%s: ", kq, kq);
- buffer_rrd_value(wb, r->max);
- buffer_strcat(wb, "\n}\n");
-}
-
-#define JSON_DATES_JS 1
-#define JSON_DATES_TIMESTAMP 2
-
-static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
-{
- rrdset_check_rdlock(r->st);
-
- //info("RRD2JSON(): %s: BEGIN", r->st->id);
- int row_annotations = 0, dates, dates_with_new = 0;
- char kq[2] = "", // key quote
- sq[2] = "", // string quote
- pre_label[101] = "", // before each label
- post_label[101] = "", // after each label
- pre_date[101] = "", // the beginning of line, to the date
- post_date[101] = "", // closing the date
- pre_value[101] = "", // before each value
- post_value[101] = "", // after each value
- post_line[101] = "", // at the end of each row
- normal_annotation[201] = "", // default row annotation
- overflow_annotation[201] = "", // overflow row annotation
- data_begin[101] = "", // between labels and values
- finish[101] = ""; // at the end of everything
-
- if(datatable) {
- dates = JSON_DATES_JS;
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- }
- row_annotations = 1;
- snprintfz(pre_date, 100, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
- snprintfz(post_date, 100, "%s}", sq);
- snprintfz(pre_label, 100, ",\n {%sid%s:%s%s,%slabel%s:%s", kq, kq, sq, sq, kq, kq, sq);
- snprintfz(post_label, 100, "%s,%spattern%s:%s%s,%stype%s:%snumber%s}", sq, kq, kq, sq, sq, kq, kq, sq, sq);
- snprintfz(pre_value, 100, ",{%sv%s:", kq, kq);
- strcpy(post_value, "}");
- strcpy(post_line, "]}");
- snprintfz(data_begin, 100, "\n ],\n %srows%s:\n [\n", kq, kq);
- strcpy(finish, "\n ]\n}");
-
- snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
- snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
-
- buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
-
- // remove the valueobjects flag
- // google wants its own keys
- if(options & RRDR_OPTION_OBJECTSROWS)
- options &= ~RRDR_OPTION_OBJECTSROWS;
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- if(options & RRDR_OPTION_GOOGLE_JSON) {
- dates = JSON_DATES_JS;
- dates_with_new = 1;
- }
- else {
- dates = JSON_DATES_TIMESTAMP;
- dates_with_new = 0;
- }
- if( options & RRDR_OPTION_OBJECTSROWS )
- strcpy(pre_date, " { ");
- else
- strcpy(pre_date, " [ ");
- strcpy(pre_label, ", \"");
- strcpy(post_label, "\"");
- strcpy(pre_value, ", ");
- if( options & RRDR_OPTION_OBJECTSROWS )
- strcpy(post_line, "}");
- else
- strcpy(post_line, "]");
- snprintfz(data_begin, 100, "],\n %sdata%s:\n [\n", kq, kq);
- strcpy(finish, "\n ]\n}");
-
- buffer_sprintf(wb, "{\n %slabels%s: [", kq, kq);
- buffer_sprintf(wb, "%stime%s", sq, sq);
- }
-
- // -------------------------------------------------------------------------
- // print the JSON header
-
- long c, i;
- RRDDIM *rd;
-
- // print the header lines
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- buffer_strcat(wb, pre_label);
- buffer_strcat(wb, rd->name);
- buffer_strcat(wb, post_label);
- i++;
- }
- if(!i) {
- buffer_strcat(wb, pre_label);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, post_label);
- }
-
- // print the begin of row data
- buffer_strcat(wb, data_begin);
-
- // if all dimensions are hidden, print a null
- if(!i) {
- buffer_strcat(wb, finish);
- return;
- }
-
- long start = 0, end = rrdr_rows(r), step = 1;
- if((options & RRDR_OPTION_REVERSED)) {
- start = rrdr_rows(r) - 1;
- end = -1;
- step = -1;
- }
-
- // for each line in the array
- calculated_number total = 1;
- for(i = start; i != end ;i += step) {
- calculated_number *cn = &r->v[ i * r->d ];
- uint8_t *co = &r->o[ i * r->d ];
-
- time_t now = r->t[i];
-
- if(dates == JSON_DATES_JS) {
- // generate the local date time
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
- if(!tm) { error("localtime_r() failed."); continue; }
-
- if(likely(i != start)) buffer_strcat(wb, ",\n");
- buffer_strcat(wb, pre_date);
-
- if( options & RRDR_OPTION_OBJECTSROWS )
- buffer_sprintf(wb, "%stime%s: ", kq, kq);
-
- if(dates_with_new)
- buffer_strcat(wb, "new ");
-
- buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
-
- buffer_strcat(wb, post_date);
-
- if(row_annotations) {
- // google supports one annotation per row
- int annotation_found = 0;
- for(c = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
- if(co[c] & RRDR_RESET) {
- buffer_strcat(wb, overflow_annotation);
- annotation_found = 1;