csv.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "libnetdata/libnetdata.h"
  3. #include "csv.h"
  4. void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, const char *startline, const char *separator, const char *endline, const char *betweenlines) {
  5. //netdata_log_info("RRD2CSV(): %s: BEGIN", r->st->id);
  6. long c, i;
  7. const long used = (long)r->d;
  8. // print the csv header
  9. for(c = 0, i = 0; c < used ; c++) {
  10. if(!rrdr_dimension_should_be_exposed(r->od[c], options))
  11. continue;
  12. if(!i) {
  13. buffer_strcat(wb, startline);
  14. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  15. buffer_strcat(wb, "time");
  16. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  17. }
  18. buffer_strcat(wb, separator);
  19. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  20. buffer_strcat(wb, string2str(r->dn[c]));
  21. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  22. i++;
  23. }
  24. buffer_strcat(wb, endline);
  25. if(format == DATASOURCE_CSV_MARKDOWN) {
  26. // print the --- line after header
  27. for(c = 0, i = 0; c < used ;c++) {
  28. if(!rrdr_dimension_should_be_exposed(r->od[c], options))
  29. continue;
  30. if(!i) {
  31. buffer_strcat(wb, startline);
  32. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  33. buffer_strcat(wb, ":---:");
  34. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  35. }
  36. buffer_strcat(wb, separator);
  37. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  38. buffer_strcat(wb, ":---:");
  39. if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
  40. i++;
  41. }
  42. buffer_strcat(wb, endline);
  43. }
  44. if(!i) {
  45. // no dimensions present
  46. return;
  47. }
  48. long start = 0, end = rrdr_rows(r), step = 1;
  49. if(!(options & RRDR_OPTION_REVERSED)) {
  50. start = rrdr_rows(r) - 1;
  51. end = -1;
  52. step = -1;
  53. }
  54. // for each line in the array
  55. for(i = start; i != end ;i += step) {
  56. NETDATA_DOUBLE *cn = &r->v[ i * r->d ];
  57. RRDR_VALUE_FLAGS *co = &r->o[ i * r->d ];
  58. buffer_strcat(wb, betweenlines);
  59. buffer_strcat(wb, startline);
  60. time_t now = r->t[i];
  61. if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) {
  62. // print the timestamp of the line
  63. buffer_print_netdata_double(wb, (NETDATA_DOUBLE) now);
  64. // in ms
  65. if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
  66. }
  67. else {
  68. // generate the local date time
  69. struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
  70. if(!tm) {
  71. netdata_log_error("localtime() failed."); continue; }
  72. buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
  73. }
  74. // for each dimension
  75. for(c = 0; c < used ;c++) {
  76. if(!rrdr_dimension_should_be_exposed(r->od[c], options))
  77. continue;
  78. buffer_strcat(wb, separator);
  79. NETDATA_DOUBLE n = cn[c];
  80. if(co[c] & RRDR_VALUE_EMPTY) {
  81. if(options & RRDR_OPTION_NULL2ZERO)
  82. buffer_strcat(wb, "0");
  83. else
  84. buffer_strcat(wb, "null");
  85. }
  86. else
  87. buffer_print_netdata_double(wb, n);
  88. }
  89. buffer_strcat(wb, endline);
  90. }
  91. //netdata_log_info("RRD2CSV(): %s: END", r->st->id);
  92. }