rrdset2json.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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->state || !st->state->chart_labels))
  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->state->chart_labels, 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. rrdset_rdlock(st);
  21. time_t first_entry_t = rrdset_first_entry_t_nolock(st);
  22. time_t last_entry_t = rrdset_last_entry_t_nolock(st);
  23. buffer_sprintf(
  24. wb,
  25. "\t\t{\n"
  26. "\t\t\t\"id\": \"%s\",\n"
  27. "\t\t\t\"name\": \"%s\",\n"
  28. "\t\t\t\"type\": \"%s\",\n"
  29. "\t\t\t\"family\": \"%s\",\n"
  30. "\t\t\t\"context\": \"%s\",\n"
  31. "\t\t\t\"title\": \"%s (%s)\",\n"
  32. "\t\t\t\"priority\": %ld,\n"
  33. "\t\t\t\"plugin\": \"%s\",\n"
  34. "\t\t\t\"module\": \"%s\",\n"
  35. "\t\t\t\"units\": \"%s\",\n"
  36. "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n"
  37. "\t\t\t\"chart_type\": \"%s\",\n",
  38. st->id,
  39. st->name,
  40. st->type,
  41. st->family,
  42. st->context,
  43. st->title,
  44. st->name,
  45. st->priority,
  46. st->plugin_name ? st->plugin_name : "",
  47. st->module_name ? st->module_name : "",
  48. st->units,
  49. st->name,
  50. rrdset_type_name(st->chart_type));
  51. if (likely(!skip_volatile))
  52. buffer_sprintf(
  53. wb,
  54. "\t\t\t\"duration\": %"PRId64",\n",
  55. (int64_t)(last_entry_t - first_entry_t + st->update_every) //st->entries * st->update_every
  56. );
  57. buffer_sprintf(
  58. wb,
  59. "\t\t\t\"first_entry\": %"PRId64",\n",
  60. (int64_t)first_entry_t //rrdset_first_entry_t(st)
  61. );
  62. if (likely(!skip_volatile))
  63. buffer_sprintf(
  64. wb,
  65. "\t\t\t\"last_entry\": %"PRId64",\n",
  66. (int64_t)last_entry_t //rrdset_last_entry_t(st)
  67. );
  68. buffer_sprintf(
  69. wb,
  70. "\t\t\t\"update_every\": %d,\n"
  71. "\t\t\t\"dimensions\": {\n",
  72. st->update_every);
  73. unsigned long memory = sizeof(RRDSET) + st->memsize;
  74. size_t dimensions = 0;
  75. RRDDIM *rd;
  76. rrddim_foreach_read(rd, st) {
  77. if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN) || rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) continue;
  78. memory += sizeof(RRDDIM) + rd->memsize;
  79. if (dimensions)
  80. buffer_strcat(wb, ",\n\t\t\t\t\"");
  81. else
  82. buffer_strcat(wb, "\t\t\t\t\"");
  83. buffer_strcat_jsonescape(wb, rd->id);
  84. buffer_strcat(wb, "\": { \"name\": \"");
  85. buffer_strcat_jsonescape(wb, rd->name);
  86. buffer_strcat(wb, "\" }");
  87. dimensions++;
  88. }
  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. for (rc = st->alarms; rc; rc = rc->rrdset_next) {
  102. buffer_sprintf(
  103. wb,
  104. "%s"
  105. "\t\t\t\t\"%s\": {\n"
  106. "\t\t\t\t\t\"id\": %u,\n"
  107. "\t\t\t\t\t\"status\": \"%s\",\n"
  108. "\t\t\t\t\t\"units\": \"%s\",\n"
  109. "\t\t\t\t\t\"update_every\": %d\n"
  110. "\t\t\t\t}",
  111. (alarms) ? ",\n" : "", rc->name, rc->id, rrdcalc_status2string(rc->status), rc->units,
  112. rc->update_every);
  113. alarms++;
  114. }
  115. buffer_sprintf(wb,
  116. "\n\t\t\t}"
  117. );
  118. }
  119. buffer_strcat(wb, ",\n\t\t\t\"chart_labels\": {\n");
  120. chart_labels2json(st, wb, 2);
  121. buffer_strcat(wb, "\t\t\t}\n");
  122. buffer_sprintf(wb,
  123. "\n\t\t}"
  124. );
  125. rrdset_unlock(st);
  126. }