rrd2json.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "web/api/web_api_v1.h"
  3. #include "database/storage_engine.h"
  4. void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) {
  5. rrdset2json(st, wb, NULL, NULL, 0);
  6. }
  7. const char *rrdr_format_to_string(DATASOURCE_FORMAT format) {
  8. switch(format) {
  9. case DATASOURCE_JSON:
  10. return DATASOURCE_FORMAT_JSON;
  11. case DATASOURCE_JSON2:
  12. return DATASOURCE_FORMAT_JSON2;
  13. case DATASOURCE_DATATABLE_JSON:
  14. return DATASOURCE_FORMAT_DATATABLE_JSON;
  15. case DATASOURCE_DATATABLE_JSONP:
  16. return DATASOURCE_FORMAT_DATATABLE_JSONP;
  17. case DATASOURCE_JSONP:
  18. return DATASOURCE_FORMAT_JSONP;
  19. case DATASOURCE_SSV:
  20. return DATASOURCE_FORMAT_SSV;
  21. case DATASOURCE_CSV:
  22. return DATASOURCE_FORMAT_CSV;
  23. case DATASOURCE_TSV:
  24. return DATASOURCE_FORMAT_TSV;
  25. case DATASOURCE_HTML:
  26. return DATASOURCE_FORMAT_HTML;
  27. case DATASOURCE_JS_ARRAY:
  28. return DATASOURCE_FORMAT_JS_ARRAY;
  29. case DATASOURCE_SSV_COMMA:
  30. return DATASOURCE_FORMAT_SSV_COMMA;
  31. default:
  32. return "unknown";
  33. }
  34. }
  35. int rrdset2value_api_v1(
  36. RRDSET *st
  37. , BUFFER *wb
  38. , NETDATA_DOUBLE *n
  39. , const char *dimensions
  40. , size_t points
  41. , time_t after
  42. , time_t before
  43. , RRDR_TIME_GROUPING group_method
  44. , const char *group_options
  45. , time_t resampling_time
  46. , uint32_t options
  47. , time_t *db_after
  48. , time_t *db_before
  49. , size_t *db_points_read
  50. , size_t *db_points_per_tier
  51. , size_t *result_points_generated
  52. , int *value_is_null
  53. , NETDATA_DOUBLE *anomaly_rate
  54. , time_t timeout
  55. , size_t tier
  56. , QUERY_SOURCE query_source
  57. , STORAGE_PRIORITY priority
  58. ) {
  59. int ret = HTTP_RESP_INTERNAL_SERVER_ERROR;
  60. ONEWAYALLOC *owa = onewayalloc_create(0);
  61. RRDR *r = rrd2rrdr_legacy(
  62. owa,
  63. st,
  64. points,
  65. after,
  66. before,
  67. group_method,
  68. resampling_time,
  69. options,
  70. dimensions,
  71. group_options,
  72. timeout,
  73. tier,
  74. query_source,
  75. priority);
  76. if(!r) {
  77. if(value_is_null) *value_is_null = 1;
  78. ret = HTTP_RESP_INTERNAL_SERVER_ERROR;
  79. goto cleanup;
  80. }
  81. if(db_points_read)
  82. *db_points_read += r->stats.db_points_read;
  83. if(db_points_per_tier) {
  84. for(size_t t = 0; t < storage_tiers ;t++)
  85. db_points_per_tier[t] += r->internal.qt->db.tiers[t].points;
  86. }
  87. if(result_points_generated)
  88. *result_points_generated += r->stats.result_points_generated;
  89. if(rrdr_rows(r) == 0) {
  90. if(db_after) *db_after = 0;
  91. if(db_before) *db_before = 0;
  92. if(value_is_null) *value_is_null = 1;
  93. ret = HTTP_RESP_BAD_REQUEST;
  94. goto cleanup;
  95. }
  96. if(wb) {
  97. if (r->view.flags & RRDR_RESULT_FLAG_RELATIVE)
  98. buffer_no_cacheable(wb);
  99. else if (r->view.flags & RRDR_RESULT_FLAG_ABSOLUTE)
  100. buffer_cacheable(wb);
  101. }
  102. if(db_after) *db_after = r->view.after;
  103. if(db_before) *db_before = r->view.before;
  104. long i = (!(options & RRDR_OPTION_REVERSED))?(long)rrdr_rows(r) - 1:0;
  105. *n = rrdr2value(r, i, options, value_is_null, anomaly_rate);
  106. ret = HTTP_RESP_OK;
  107. cleanup:
  108. rrdr_free(owa, r);
  109. onewayalloc_destroy(owa);
  110. return ret;
  111. }
  112. static inline void buffer_json_member_add_key_only(BUFFER *wb, const char *key) {
  113. buffer_print_json_comma_newline_spacing(wb);
  114. buffer_print_json_key(wb, key);
  115. buffer_fast_strcat(wb, ":", 1);
  116. wb->json.stack[wb->json.depth].count++;
  117. }
  118. static inline void buffer_json_member_add_string_open(BUFFER *wb, const char *key) {
  119. buffer_json_member_add_key_only(wb, key);
  120. buffer_strcat(wb, wb->json.value_quote);
  121. }
  122. static inline void buffer_json_member_add_string_close(BUFFER *wb) {
  123. buffer_strcat(wb, wb->json.value_quote);
  124. }
  125. int data_query_execute(ONEWAYALLOC *owa, BUFFER *wb, QUERY_TARGET *qt, time_t *latest_timestamp) {
  126. wrapper_begin_t wrapper_begin = rrdr_json_wrapper_begin;
  127. wrapper_end_t wrapper_end = rrdr_json_wrapper_end;
  128. if(qt->request.version == 2) {
  129. wrapper_begin = rrdr_json_wrapper_begin2;
  130. wrapper_end = rrdr_json_wrapper_end2;
  131. }
  132. RRDR *r = rrd2rrdr(owa, qt);
  133. if(!r) {
  134. buffer_strcat(wb, "Cannot generate output with these parameters on this chart.");
  135. return HTTP_RESP_INTERNAL_SERVER_ERROR;
  136. }
  137. if (r->view.flags & RRDR_RESULT_FLAG_CANCEL) {
  138. rrdr_free(owa, r);
  139. return HTTP_RESP_BACKEND_FETCH_FAILED;
  140. }
  141. if(r->view.flags & RRDR_RESULT_FLAG_RELATIVE)
  142. buffer_no_cacheable(wb);
  143. else if(r->view.flags & RRDR_RESULT_FLAG_ABSOLUTE)
  144. buffer_cacheable(wb);
  145. if(latest_timestamp && rrdr_rows(r) > 0)
  146. *latest_timestamp = r->view.before;
  147. DATASOURCE_FORMAT format = qt->request.format;
  148. RRDR_OPTIONS options = qt->window.options;
  149. switch(format) {
  150. case DATASOURCE_SSV:
  151. if(options & RRDR_OPTION_JSON_WRAP) {
  152. wb->content_type = CT_APPLICATION_JSON;
  153. wrapper_begin(r, wb);
  154. buffer_json_member_add_string_open(wb, "result");
  155. rrdr2ssv(r, wb, options, "", " ", "");
  156. buffer_json_member_add_string_close(wb);
  157. wrapper_end(r, wb);
  158. }
  159. else {
  160. wb->content_type = CT_TEXT_PLAIN;
  161. rrdr2ssv(r, wb, options, "", " ", "");
  162. }
  163. break;
  164. case DATASOURCE_SSV_COMMA:
  165. if(options & RRDR_OPTION_JSON_WRAP) {
  166. wb->content_type = CT_APPLICATION_JSON;
  167. wrapper_begin(r, wb);
  168. buffer_json_member_add_string_open(wb, "result");
  169. rrdr2ssv(r, wb, options, "", ",", "");
  170. buffer_json_member_add_string_close(wb);
  171. wrapper_end(r, wb);
  172. }
  173. else {
  174. wb->content_type = CT_TEXT_PLAIN;
  175. rrdr2ssv(r, wb, options, "", ",", "");
  176. }
  177. break;
  178. case DATASOURCE_JS_ARRAY:
  179. if(options & RRDR_OPTION_JSON_WRAP) {
  180. wb->content_type = CT_APPLICATION_JSON;
  181. wrapper_begin(r, wb);
  182. buffer_json_member_add_array(wb, "result");
  183. rrdr2ssv(r, wb, options, "", ",", "");
  184. buffer_json_array_close(wb);
  185. wrapper_end(r, wb);
  186. }
  187. else {
  188. wb->content_type = CT_APPLICATION_JSON;
  189. rrdr2ssv(r, wb, options, "[", ",", "]");
  190. }
  191. break;
  192. case DATASOURCE_CSV:
  193. if(options & RRDR_OPTION_JSON_WRAP) {
  194. wb->content_type = CT_APPLICATION_JSON;
  195. wrapper_begin(r, wb);
  196. buffer_json_member_add_string_open(wb, "result");
  197. rrdr2csv(r, wb, format, options, "", ",", "\\n", "");
  198. buffer_json_member_add_string_close(wb);
  199. wrapper_end(r, wb);
  200. }
  201. else {
  202. wb->content_type = CT_TEXT_PLAIN;
  203. rrdr2csv(r, wb, format, options, "", ",", "\r\n", "");
  204. }
  205. break;
  206. case DATASOURCE_CSV_MARKDOWN:
  207. if(options & RRDR_OPTION_JSON_WRAP) {
  208. wb->content_type = CT_APPLICATION_JSON;
  209. wrapper_begin(r, wb);
  210. buffer_json_member_add_string_open(wb, "result");
  211. rrdr2csv(r, wb, format, options, "", "|", "\\n", "");
  212. buffer_json_member_add_string_close(wb);
  213. wrapper_end(r, wb);
  214. }
  215. else {
  216. wb->content_type = CT_TEXT_PLAIN;
  217. rrdr2csv(r, wb, format, options, "", "|", "\r\n", "");
  218. }
  219. break;
  220. case DATASOURCE_CSV_JSON_ARRAY:
  221. wb->content_type = CT_APPLICATION_JSON;
  222. if(options & RRDR_OPTION_JSON_WRAP) {
  223. wrapper_begin(r, wb);
  224. buffer_json_member_add_array(wb, "result");
  225. rrdr2csv(r, wb, format, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
  226. buffer_json_array_close(wb);
  227. wrapper_end(r, wb);
  228. }
  229. else {
  230. wb->content_type = CT_APPLICATION_JSON;
  231. buffer_strcat(wb, "[\n");
  232. rrdr2csv(r, wb, format, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
  233. buffer_strcat(wb, "\n]");
  234. }
  235. break;
  236. case DATASOURCE_TSV:
  237. if(options & RRDR_OPTION_JSON_WRAP) {
  238. wb->content_type = CT_APPLICATION_JSON;
  239. wrapper_begin(r, wb);
  240. buffer_json_member_add_string_open(wb, "result");
  241. rrdr2csv(r, wb, format, options, "", "\t", "\\n", "");
  242. buffer_json_member_add_string_close(wb);
  243. wrapper_end(r, wb);
  244. }
  245. else {
  246. wb->content_type = CT_TEXT_PLAIN;
  247. rrdr2csv(r, wb, format, options, "", "\t", "\r\n", "");
  248. }
  249. break;
  250. case DATASOURCE_HTML:
  251. if(options & RRDR_OPTION_JSON_WRAP) {
  252. wb->content_type = CT_APPLICATION_JSON;
  253. wrapper_begin(r, wb);
  254. buffer_json_member_add_string_open(wb, "result");
  255. buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n");
  256. rrdr2csv(r, wb, format, options, "<tr><td>", "</td><td>", "</td></tr>\\n", "");
  257. buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n");
  258. buffer_json_member_add_string_close(wb);
  259. wrapper_end(r, wb);
  260. }
  261. else {
  262. wb->content_type = CT_TEXT_HTML;
  263. buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n");
  264. rrdr2csv(r, wb, format, options, "<tr><td>", "</td><td>", "</td></tr>\n", "");
  265. buffer_strcat(wb, "</table>\n</center>\n</html>\n");
  266. }
  267. break;
  268. case DATASOURCE_DATATABLE_JSONP:
  269. wb->content_type = CT_APPLICATION_X_JAVASCRIPT;
  270. if(options & RRDR_OPTION_JSON_WRAP) {
  271. wrapper_begin(r, wb);
  272. buffer_json_member_add_key_only(wb, "result");
  273. }
  274. rrdr2json(r, wb, options, 1);
  275. if(options & RRDR_OPTION_JSON_WRAP)
  276. wrapper_end(r, wb);
  277. break;
  278. case DATASOURCE_DATATABLE_JSON:
  279. wb->content_type = CT_APPLICATION_JSON;
  280. if(options & RRDR_OPTION_JSON_WRAP) {
  281. wrapper_begin(r, wb);
  282. buffer_json_member_add_key_only(wb, "result");
  283. }
  284. rrdr2json(r, wb, options, 1);
  285. if(options & RRDR_OPTION_JSON_WRAP)
  286. wrapper_end(r, wb);
  287. break;
  288. case DATASOURCE_JSONP:
  289. wb->content_type = CT_APPLICATION_X_JAVASCRIPT;
  290. if(options & RRDR_OPTION_JSON_WRAP) {
  291. wrapper_begin(r, wb);
  292. buffer_json_member_add_key_only(wb, "result");
  293. }
  294. rrdr2json(r, wb, options, 0);
  295. if(options & RRDR_OPTION_JSON_WRAP)
  296. wrapper_end(r, wb);
  297. break;
  298. case DATASOURCE_JSON:
  299. default:
  300. wb->content_type = CT_APPLICATION_JSON;
  301. if(options & RRDR_OPTION_JSON_WRAP) {
  302. wrapper_begin(r, wb);
  303. buffer_json_member_add_key_only(wb, "result");
  304. }
  305. rrdr2json(r, wb, options, 0);
  306. if(options & RRDR_OPTION_JSON_WRAP) {
  307. if (options & RRDR_OPTION_RETURN_JWAR) {
  308. buffer_json_member_add_key_only(wb, "anomaly_rates");
  309. rrdr2json(r, wb, options | RRDR_OPTION_INTERNAL_AR, false);
  310. }
  311. wrapper_end(r, wb);
  312. }
  313. break;
  314. case DATASOURCE_JSON2:
  315. wb->content_type = CT_APPLICATION_JSON;
  316. wrapper_begin(r, wb);
  317. rrdr2json_v2(r, wb);
  318. wrapper_end(r, wb);
  319. break;
  320. }
  321. rrdr_free(owa, r);
  322. return HTTP_RESP_OK;
  323. }