rrdset2json.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "rrdset2json.h"
  3. void chart_labels2json(RRDSET *st, BUFFER *wb, size_t indentation)
  4. {
  5. if(unlikely(!st->rrdlabels))
  6. return;
  7. char tabs[11];
  8. if (indentation > 10)
  9. indentation = 10;
  10. tabs[0] = '\0';
  11. while (indentation) {
  12. strcat(tabs, "\t\t");
  13. indentation--;
  14. }
  15. rrdlabels_to_buffer(st->rrdlabels, wb, tabs, ":", "\"", ",\n", NULL, NULL, NULL, NULL);
  16. buffer_strcat(wb, "\n");
  17. }
  18. // generate JSON for the /api/v1/chart API call
  19. void rrdset2json(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used, int skip_volatile) {
  20. time_t first_entry_t = rrdset_first_entry_s(st);
  21. time_t last_entry_t = rrdset_last_entry_s(st);
  22. buffer_sprintf(
  23. wb,
  24. "\t\t{\n"
  25. "\t\t\t\"id\": \"%s\",\n"
  26. "\t\t\t\"name\": \"%s\",\n"
  27. "\t\t\t\"type\": \"%s\",\n"
  28. "\t\t\t\"family\": \"%s\",\n"
  29. "\t\t\t\"context\": \"%s\",\n"
  30. "\t\t\t\"title\": \"%s (%s)\",\n"
  31. "\t\t\t\"priority\": %ld,\n"
  32. "\t\t\t\"plugin\": \"%s\",\n"
  33. "\t\t\t\"module\": \"%s\",\n"
  34. "\t\t\t\"units\": \"%s\",\n"
  35. "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n"
  36. "\t\t\t\"chart_type\": \"%s\",\n",
  37. rrdset_id(st),
  38. rrdset_name(st),
  39. rrdset_parts_type(st),
  40. rrdset_family(st),
  41. rrdset_context(st),
  42. rrdset_title(st),
  43. rrdset_name(st),
  44. st->priority,
  45. rrdset_plugin_name(st),
  46. rrdset_module_name(st),
  47. rrdset_units(st),
  48. rrdset_name(st),
  49. rrdset_type_name(st->chart_type));
  50. if (likely(!skip_volatile))
  51. buffer_sprintf(
  52. wb,
  53. "\t\t\t\"duration\": %"PRId64",\n",
  54. (int64_t)(last_entry_t - first_entry_t + st->update_every) //st->entries * st->update_every
  55. );
  56. buffer_sprintf(
  57. wb,
  58. "\t\t\t\"first_entry\": %"PRId64",\n",
  59. (int64_t)first_entry_t //rrdset_first_entry_t(st)
  60. );
  61. if (likely(!skip_volatile))
  62. buffer_sprintf(
  63. wb,
  64. "\t\t\t\"last_entry\": %"PRId64",\n",
  65. (int64_t)last_entry_t //rrdset_last_entry_t(st)
  66. );
  67. buffer_sprintf(
  68. wb,
  69. "\t\t\t\"update_every\": %d,\n"
  70. "\t\t\t\"dimensions\": {\n",
  71. st->update_every);
  72. unsigned long memory = sizeof(RRDSET);
  73. size_t dimensions = 0;
  74. RRDDIM *rd;
  75. rrddim_foreach_read(rd, st) {
  76. if(rrddim_option_check(rd, RRDDIM_OPTION_HIDDEN) || rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) continue;
  77. memory += sizeof(RRDDIM) + rd->memsize;
  78. if (dimensions)
  79. buffer_strcat(wb, ",\n\t\t\t\t\"");
  80. else
  81. buffer_strcat(wb, "\t\t\t\t\"");
  82. buffer_strcat_jsonescape(wb, rrddim_id(rd));
  83. buffer_strcat(wb, "\": { \"name\": \"");
  84. buffer_strcat_jsonescape(wb, rrddim_name(rd));
  85. buffer_strcat(wb, "\" }");
  86. dimensions++;
  87. }
  88. rrddim_foreach_done(rd);
  89. if(dimensions_count) *dimensions_count += dimensions;
  90. if(memory_used) *memory_used += memory;
  91. buffer_sprintf(wb, "\n\t\t\t},\n\t\t\t\"chart_variables\": ");
  92. health_api_v1_chart_custom_variables2json(st, wb);
  93. buffer_strcat(wb, ",\n\t\t\t\"green\": ");
  94. buffer_rrd_value(wb, st->green);
  95. buffer_strcat(wb, ",\n\t\t\t\"red\": ");
  96. buffer_rrd_value(wb, st->red);
  97. if (likely(!skip_volatile)) {
  98. buffer_strcat(wb, ",\n\t\t\t\"alarms\": {\n");
  99. size_t alarms = 0;
  100. RRDCALC *rc;
  101. netdata_rwlock_rdlock(&st->alerts.rwlock);
  102. DOUBLE_LINKED_LIST_FOREACH_FORWARD(st->alerts.base, rc, prev, next) {
  103. buffer_sprintf(
  104. wb,
  105. "%s"
  106. "\t\t\t\t\"%s\": {\n"
  107. "\t\t\t\t\t\"id\": %u,\n"
  108. "\t\t\t\t\t\"status\": \"%s\",\n"
  109. "\t\t\t\t\t\"units\": \"%s\",\n"
  110. "\t\t\t\t\t\"update_every\": %d\n"
  111. "\t\t\t\t}",
  112. (alarms) ? ",\n" : "", rrdcalc_name(rc), rc->id, rrdcalc_status2string(rc->status), rrdcalc_units(rc),
  113. rc->update_every);
  114. alarms++;
  115. }
  116. netdata_rwlock_unlock(&st->alerts.rwlock);
  117. buffer_sprintf(wb,
  118. "\n\t\t\t}"
  119. );
  120. }
  121. buffer_strcat(wb, ",\n\t\t\t\"chart_labels\": {\n");
  122. chart_labels2json(st, wb, 2);
  123. buffer_strcat(wb, "\t\t\t}");
  124. buffer_strcat(wb, ",\n\t\t\t\"functions\": {\n");
  125. chart_functions2json(st, wb, 4, "\"", "\"");
  126. buffer_strcat(wb, "\t\t\t}");
  127. buffer_sprintf(wb,
  128. "\n\t\t}"
  129. );
  130. }