rrd2json.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. void rrdr_buffer_print_format(BUFFER *wb, uint32_t format) {
  8. switch(format) {
  9. case DATASOURCE_JSON:
  10. buffer_strcat(wb, DATASOURCE_FORMAT_JSON);
  11. break;
  12. case DATASOURCE_DATATABLE_JSON:
  13. buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSON);
  14. break;
  15. case DATASOURCE_DATATABLE_JSONP:
  16. buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSONP);
  17. break;
  18. case DATASOURCE_JSONP:
  19. buffer_strcat(wb, DATASOURCE_FORMAT_JSONP);
  20. break;
  21. case DATASOURCE_SSV:
  22. buffer_strcat(wb, DATASOURCE_FORMAT_SSV);
  23. break;
  24. case DATASOURCE_CSV:
  25. buffer_strcat(wb, DATASOURCE_FORMAT_CSV);
  26. break;
  27. case DATASOURCE_TSV:
  28. buffer_strcat(wb, DATASOURCE_FORMAT_TSV);
  29. break;
  30. case DATASOURCE_HTML:
  31. buffer_strcat(wb, DATASOURCE_FORMAT_HTML);
  32. break;
  33. case DATASOURCE_JS_ARRAY:
  34. buffer_strcat(wb, DATASOURCE_FORMAT_JS_ARRAY);
  35. break;
  36. case DATASOURCE_SSV_COMMA:
  37. buffer_strcat(wb, DATASOURCE_FORMAT_SSV_COMMA);
  38. break;
  39. default:
  40. buffer_strcat(wb, "unknown");
  41. break;
  42. }
  43. }
  44. int rrdset2value_api_v1(
  45. RRDSET *st
  46. , BUFFER *wb
  47. , NETDATA_DOUBLE *n
  48. , const char *dimensions
  49. , size_t points
  50. , time_t after
  51. , time_t before
  52. , RRDR_GROUPING group_method
  53. , const char *group_options
  54. , time_t resampling_time
  55. , uint32_t options
  56. , time_t *db_after
  57. , time_t *db_before
  58. , size_t *db_points_read
  59. , size_t *db_points_per_tier
  60. , size_t *result_points_generated
  61. , int *value_is_null
  62. , NETDATA_DOUBLE *anomaly_rate
  63. , time_t timeout
  64. , size_t tier
  65. , QUERY_SOURCE query_source
  66. , STORAGE_PRIORITY priority
  67. ) {
  68. int ret = HTTP_RESP_INTERNAL_SERVER_ERROR;
  69. ONEWAYALLOC *owa = onewayalloc_create(0);
  70. RRDR *r = rrd2rrdr_legacy(
  71. owa,
  72. st,
  73. points,
  74. after,
  75. before,
  76. group_method,
  77. resampling_time,
  78. options,
  79. dimensions,
  80. group_options,
  81. timeout,
  82. tier,
  83. query_source,
  84. priority);
  85. if(!r) {
  86. if(value_is_null) *value_is_null = 1;
  87. ret = HTTP_RESP_INTERNAL_SERVER_ERROR;
  88. goto cleanup;
  89. }
  90. if(db_points_read)
  91. *db_points_read += r->internal.db_points_read;
  92. if(db_points_per_tier) {
  93. for(size_t t = 0; t < storage_tiers ;t++)
  94. db_points_per_tier[t] += r->internal.tier_points_read[t];
  95. }
  96. if(result_points_generated)
  97. *result_points_generated += r->internal.result_points_generated;
  98. if(rrdr_rows(r) == 0) {
  99. if(db_after) *db_after = 0;
  100. if(db_before) *db_before = 0;
  101. if(value_is_null) *value_is_null = 1;
  102. ret = HTTP_RESP_BAD_REQUEST;
  103. goto cleanup;
  104. }
  105. if(wb) {
  106. if (r->result_options & RRDR_RESULT_OPTION_RELATIVE)
  107. buffer_no_cacheable(wb);
  108. else if (r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
  109. buffer_cacheable(wb);
  110. }
  111. if(db_after) *db_after = r->after;
  112. if(db_before) *db_before = r->before;
  113. long i = (!(options & RRDR_OPTION_REVERSED))?(long)rrdr_rows(r) - 1:0;
  114. *n = rrdr2value(r, i, options, value_is_null, anomaly_rate);
  115. ret = HTTP_RESP_OK;
  116. cleanup:
  117. rrdr_free(owa, r);
  118. onewayalloc_destroy(owa);
  119. return ret;
  120. }
  121. int data_query_execute(ONEWAYALLOC *owa, BUFFER *wb, QUERY_TARGET *qt, time_t *latest_timestamp) {
  122. RRDR *r = rrd2rrdr(owa, qt);
  123. if(!r) {
  124. buffer_strcat(wb, "Cannot generate output with these parameters on this chart.");
  125. return HTTP_RESP_INTERNAL_SERVER_ERROR;
  126. }
  127. if (r->result_options & RRDR_RESULT_OPTION_CANCEL) {
  128. rrdr_free(owa, r);
  129. return HTTP_RESP_BACKEND_FETCH_FAILED;
  130. }
  131. if(r->result_options & RRDR_RESULT_OPTION_RELATIVE)
  132. buffer_no_cacheable(wb);
  133. else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
  134. buffer_cacheable(wb);
  135. if(latest_timestamp && rrdr_rows(r) > 0)
  136. *latest_timestamp = r->before;
  137. DATASOURCE_FORMAT format = qt->request.format;
  138. RRDR_OPTIONS options = qt->request.options;
  139. RRDR_GROUPING group_method = qt->request.group_method;
  140. switch(format) {
  141. case DATASOURCE_SSV:
  142. if(options & RRDR_OPTION_JSON_WRAP) {
  143. wb->contenttype = CT_APPLICATION_JSON;
  144. rrdr_json_wrapper_begin(r, wb, format, options, 1, group_method);
  145. rrdr2ssv(r, wb, options, "", " ", "");
  146. rrdr_json_wrapper_end(r, wb, format, options, 1);
  147. }
  148. else {
  149. wb->contenttype = CT_TEXT_PLAIN;
  150. rrdr2ssv(r, wb, options, "", " ", "");
  151. }
  152. break;
  153. case DATASOURCE_SSV_COMMA:
  154. if(options & RRDR_OPTION_JSON_WRAP) {
  155. wb->contenttype = CT_APPLICATION_JSON;
  156. rrdr_json_wrapper_begin(r, wb, format, options, 1, group_method);
  157. rrdr2ssv(r, wb, options, "", ",", "");
  158. rrdr_json_wrapper_end(r, wb, format, options, 1);
  159. }
  160. else {
  161. wb->contenttype = CT_TEXT_PLAIN;
  162. rrdr2ssv(r, wb, options, "", ",", "");
  163. }
  164. break;
  165. case DATASOURCE_JS_ARRAY:
  166. if(options & RRDR_OPTION_JSON_WRAP) {
  167. wb->contenttype = CT_APPLICATION_JSON;
  168. rrdr_json_wrapper_begin(r, wb, format, options, 0, group_method);
  169. rrdr2ssv(r, wb, options, "[", ",", "]");
  170. rrdr_json_wrapper_end(r, wb, format, options, 0);
  171. }
  172. else {
  173. wb->contenttype = CT_APPLICATION_JSON;
  174. rrdr2ssv(r, wb, options, "[", ",", "]");
  175. }
  176. break;
  177. case DATASOURCE_CSV:
  178. if(options & RRDR_OPTION_JSON_WRAP) {
  179. wb->contenttype = CT_APPLICATION_JSON;
  180. rrdr_json_wrapper_begin(r, wb, format, options, 1, group_method);
  181. rrdr2csv(r, wb, format, options, "", ",", "\\n", "");
  182. rrdr_json_wrapper_end(r, wb, format, options, 1);
  183. }
  184. else {
  185. wb->contenttype = CT_TEXT_PLAIN;
  186. rrdr2csv(r, wb, format, options, "", ",", "\r\n", "");
  187. }
  188. break;
  189. case DATASOURCE_CSV_MARKDOWN:
  190. if(options & RRDR_OPTION_JSON_WRAP) {
  191. wb->contenttype = CT_APPLICATION_JSON;
  192. rrdr_json_wrapper_begin(r, wb, format, options, 1, group_method);
  193. rrdr2csv(r, wb, format, options, "", "|", "\\n", "");
  194. rrdr_json_wrapper_end(r, wb, format, options, 1);
  195. }
  196. else {
  197. wb->contenttype = CT_TEXT_PLAIN;
  198. rrdr2csv(r, wb, format, options, "", "|", "\r\n", "");
  199. }
  200. break;
  201. case DATASOURCE_CSV_JSON_ARRAY:
  202. wb->contenttype = CT_APPLICATION_JSON;
  203. if(options & RRDR_OPTION_JSON_WRAP) {
  204. rrdr_json_wrapper_begin(r, wb, format, options, 0, group_method);
  205. buffer_strcat(wb, "[\n");
  206. rrdr2csv(r, wb, format, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
  207. buffer_strcat(wb, "\n]");
  208. rrdr_json_wrapper_end(r, wb, format, options, 0);
  209. }
  210. else {
  211. wb->contenttype = CT_APPLICATION_JSON;
  212. buffer_strcat(wb, "[\n");
  213. rrdr2csv(r, wb, format, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
  214. buffer_strcat(wb, "\n]");
  215. }
  216. break;
  217. case DATASOURCE_TSV:
  218. if(options & RRDR_OPTION_JSON_WRAP) {
  219. wb->contenttype = CT_APPLICATION_JSON;
  220. rrdr_json_wrapper_begin(r, wb, format, options, 1, group_method);
  221. rrdr2csv(r, wb, format, options, "", "\t", "\\n", "");
  222. rrdr_json_wrapper_end(r, wb, format, options, 1);
  223. }
  224. else {
  225. wb->contenttype = CT_TEXT_PLAIN;
  226. rrdr2csv(r, wb, format, options, "", "\t", "\r\n", "");
  227. }
  228. break;
  229. case DATASOURCE_HTML:
  230. if(options & RRDR_OPTION_JSON_WRAP) {
  231. wb->contenttype = CT_APPLICATION_JSON;
  232. rrdr_json_wrapper_begin(r, wb, format, options, 1, group_method);
  233. buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n");
  234. rrdr2csv(r, wb, format, options, "<tr><td>", "</td><td>", "</td></tr>\\n", "");
  235. buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n");
  236. rrdr_json_wrapper_end(r, wb, format, options, 1);
  237. }
  238. else {
  239. wb->contenttype = CT_TEXT_HTML;
  240. buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n");
  241. rrdr2csv(r, wb, format, options, "<tr><td>", "</td><td>", "</td></tr>\n", "");
  242. buffer_strcat(wb, "</table>\n</center>\n</html>\n");
  243. }
  244. break;
  245. case DATASOURCE_DATATABLE_JSONP:
  246. wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
  247. if(options & RRDR_OPTION_JSON_WRAP)
  248. rrdr_json_wrapper_begin(r, wb, format, options, 0, group_method);
  249. rrdr2json(r, wb, options, 1);
  250. if(options & RRDR_OPTION_JSON_WRAP)
  251. rrdr_json_wrapper_end(r, wb, format, options, 0);
  252. break;
  253. case DATASOURCE_DATATABLE_JSON:
  254. wb->contenttype = CT_APPLICATION_JSON;
  255. if(options & RRDR_OPTION_JSON_WRAP)
  256. rrdr_json_wrapper_begin(r, wb, format, options, 0, group_method);
  257. rrdr2json(r, wb, options, 1);
  258. if(options & RRDR_OPTION_JSON_WRAP)
  259. rrdr_json_wrapper_end(r, wb, format, options, 0);
  260. break;
  261. case DATASOURCE_JSONP:
  262. wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
  263. if(options & RRDR_OPTION_JSON_WRAP)
  264. rrdr_json_wrapper_begin(r, wb, format, options, 0, group_method);
  265. rrdr2json(r, wb, options, 0);
  266. if(options & RRDR_OPTION_JSON_WRAP)
  267. rrdr_json_wrapper_end(r, wb, format, options, 0);
  268. break;
  269. case DATASOURCE_JSON:
  270. default:
  271. wb->contenttype = CT_APPLICATION_JSON;
  272. if(options & RRDR_OPTION_JSON_WRAP)
  273. rrdr_json_wrapper_begin(r, wb, format, options, 0, group_method);
  274. rrdr2json(r, wb, options, 0);
  275. if(options & RRDR_OPTION_JSON_WRAP) {
  276. if(options & RRDR_OPTION_RETURN_JWAR) {
  277. rrdr_json_wrapper_anomaly_rates(r, wb, format, options, 0);
  278. rrdr2json(r, wb, options | RRDR_OPTION_INTERNAL_AR, 0);
  279. }
  280. rrdr_json_wrapper_end(r, wb, format, options, 0);
  281. }
  282. break;
  283. }
  284. rrdr_free(owa, r);
  285. return HTTP_RESP_OK;
  286. }