123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include "json_wrapper.h"
- void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, int string_value,
- struct context_param *context_param_list, char *chart_label_key)
- {
- RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL;
- int should_lock = (!context_param_list || !(context_param_list->flags & CONTEXT_FLAGS_ARCHIVE));
- uint8_t context_mode = (!context_param_list || (context_param_list->flags & CONTEXT_FLAGS_CONTEXT));
- if (should_lock)
- 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] = '"';
- }
- if (should_lock)
- rrdset_rdlock(r->st);
- 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, context_mode && temp_rd?r->st->context:r->st->id, sq
- , kq, kq, sq, context_mode && temp_rd?r->st->context:r->st->name, sq
- , kq, kq, r->update_every
- , kq, kq, r->st->update_every
- , kq, kq, (uint32_t) (context_param_list ? context_param_list->first_entry_t : rrdset_first_entry_t_nolock(r->st))
- , kq, kq, (uint32_t) (context_param_list ? context_param_list->last_entry_t : rrdset_last_entry_t_nolock(r->st))
- , kq, kq, (uint32_t)r->before
- , kq, kq, (uint32_t)r->after
- , kq, kq);
- if (should_lock)
- rrdset_unlock(r->st);
- for(c = 0, i = 0, rd = temp_rd?temp_rd:r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_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 = temp_rd?temp_rd:r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_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_strcat(wb, "],\n");
- // Composite charts
- if (context_mode && temp_rd) {
- buffer_sprintf(
- wb,
- " %schart_ids%s: [",
- kq, kq);
- for (c = 0, i = 0, rd = temp_rd ; rd && c < r->d; c++, rd = rd->next) {
- if (unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN))
- continue;
- if (unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO)))
- continue;
- if (i)
- buffer_strcat(wb, ", ");
- buffer_strcat(wb, sq);
- buffer_strcat(wb, rd->rrdset->id);
- buffer_strcat(wb, sq);
- i++;
- }
- if (!i) {
- rows = 0;
- buffer_strcat(wb, sq);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, sq);
- }
- buffer_strcat(wb, "],\n");
- if (chart_label_key) {
- buffer_sprintf(wb, " %schart_labels%s: { ", kq, kq);
- SIMPLE_PATTERN *pattern = simple_pattern_create(chart_label_key, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT);
- SIMPLE_PATTERN *original_pattern = pattern;
- char *label_key = NULL;
- int keys = 0;
- while (pattern && (label_key = simple_pattern_iterate(&pattern))) {
- uint32_t key_hash = simple_hash(label_key);
- struct label *current_label;
- if (keys)
- buffer_strcat(wb, ", ");
- buffer_sprintf(wb, "%s%s%s : [", kq, label_key, kq);
- keys++;
- for (c = 0, i = 0, rd = temp_rd; rd && c < r->d; c++, rd = rd->next) {
- if (unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN))
- continue;
- if (unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO)))
- continue;
- if (i)
- buffer_strcat(wb, ", ");
- current_label = rrdset_lookup_label_key(rd->rrdset, label_key, key_hash);
- if (current_label) {
- buffer_strcat(wb, sq);
- buffer_strcat(wb, current_label->value);
- buffer_strcat(wb, sq);
- } else
- buffer_strcat(wb, "null");
- i++;
- }
- if (!i) {
- rows = 0;
- buffer_strcat(wb, sq);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, sq);
- }
- buffer_strcat(wb, "]");
- }
- buffer_strcat(wb, "},\n");
- simple_pattern_free(original_pattern);
- }
- }
- buffer_sprintf(wb, " %slatest_values%s: ["
- , kq, kq);
- for(c = 0, i = 0, rd = temp_rd?temp_rd:r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue;
- if(i) buffer_strcat(wb, ", ");
- i++;
- calculated_number value = rd->last_stored_value;
- if (NAN == value)
- buffer_strcat(wb, "null");
- else
- buffer_rrd_value(wb, value);
- /*
- 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 = temp_rd?temp_rd:r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- calculated_number *cn = &r->v[ (rrdr_rows(r) - 1) * 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 = temp_rd?temp_rd:r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue;
- if(i) buffer_strcat(wb, ", ");
- i++;
- calculated_number *cn = &r->v[ (rrdr_rows(r) - 1) * r->d ];
- RRDR_VALUE_FLAGS *co = &r->o[ (rrdr_rows(r) - 1) * r->d ];
- calculated_number n = cn[c];
- if(co[c] & RRDR_VALUE_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);
- if((options & RRDR_OPTION_CUSTOM_VARS) && (options & RRDR_OPTION_JSON_WRAP)) {
- buffer_sprintf(wb, "%s,\n %schart_variables%s: ", sq, kq, kq);
- health_api_v1_chart_custom_variables2json(r->st, wb);
- }
- else
- buffer_sprintf(wb, "%s", sq);
- buffer_sprintf(wb, ",\n %sresult%s: ", 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");
- }
|