0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-05-05 17:50:18 +00:00
netdata_netdata/web/api/formatters/json_wrapper.c
Valentin Rakush 92642269f1 Add alarm variables to the response of chart and data ()
##### Summary
Implements feature  

Now requests like 

http://localhost:19999/api/v1/chart?chart=example.random
http://localhost:19999/api/v1/data?chart=example.random&options=jsonwrap&options=showcustomvars

- return chart variables in their responses. Chart variables include only those with options set to RRDVAR_OPTION_CUSTOM_CHART_VAR
- for /api/v1/data requests chart variables are returned when parameter options=jsonwrap and options=showcustomvars

##### Component Name
[/database](https://github.com/netdata/netdata/tree/master/database/)
[/web/api/formatters](https://github.com/netdata/netdata/tree/master/web/api/formatters)
2019-08-20 11:11:43 +02:00

220 lines
6.9 KiB
C

// 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) {
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_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 = 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_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_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 = 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 = 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");
}