123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include "libnetdata/libnetdata.h"
- #include "csv.h"
- void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, const char *startline, const char *separator, const char *endline, const char *betweenlines) {
- //info("RRD2CSV(): %s: BEGIN", r->st->id);
- QUERY_TARGET *qt = r->internal.qt;
- long c, i;
- const long used = qt->query.used;
- // print the csv header
- for(c = 0, i = 0; c < used ; c++) {
- if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue;
- if(unlikely(!(r->od[c] & RRDR_DIMENSION_QUERIED))) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue;
- if(!i) {
- buffer_strcat(wb, startline);
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- buffer_strcat(wb, "time");
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- }
- buffer_strcat(wb, separator);
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- buffer_strcat(wb, string2str(qt->query.array[c].dimension.name));
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- i++;
- }
- buffer_strcat(wb, endline);
- if(format == DATASOURCE_CSV_MARKDOWN) {
- // print the --- line after header
- for(c = 0, i = 0; c < used ;c++) {
- if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue;
- if(unlikely(!(r->od[c] & RRDR_DIMENSION_QUERIED))) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue;
- if(!i) {
- buffer_strcat(wb, startline);
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- buffer_strcat(wb, ":---:");
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- }
- buffer_strcat(wb, separator);
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- buffer_strcat(wb, ":---:");
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- i++;
- }
- buffer_strcat(wb, endline);
- }
- if(!i) {
- // no dimensions present
- 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
- NETDATA_DOUBLE total = 1;
- for(i = start; i != end ;i += step) {
- NETDATA_DOUBLE *cn = &r->v[ i * r->d ];
- RRDR_VALUE_FLAGS *co = &r->o[ i * r->d ];
- buffer_strcat(wb, betweenlines);
- buffer_strcat(wb, startline);
- time_t now = r->t[i];
- if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) {
- // print the timestamp of the line
- buffer_rrd_value(wb, (NETDATA_DOUBLE)now);
- // in ms
- if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
- }
- else {
- // generate the local date time
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
- if(!tm) { error("localtime() failed."); continue; }
- buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
- }
- int set_min_max = 0;
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- total = 0;
- for(c = 0; c < used ;c++) {
- if(unlikely(!(r->od[c] & RRDR_DIMENSION_QUERIED))) continue;
- NETDATA_DOUBLE 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;
- set_min_max = 1;
- }
- // for each dimension
- for(c = 0; c < used ;c++) {
- if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue;
- if(unlikely(!(r->od[c] & RRDR_DIMENSION_QUERIED))) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue;
- buffer_strcat(wb, separator);
- NETDATA_DOUBLE 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;
- if(unlikely(set_min_max)) {
- r->min = r->max = n;
- set_min_max = 0;
- }
- if(n < r->min) r->min = n;
- if(n > r->max) r->max = n;
- }
- buffer_rrd_value(wb, n);
- }
- }
- buffer_strcat(wb, endline);
- }
- //info("RRD2CSV(): %s: END", r->st->id);
- }
|