|
@@ -0,0 +1,231 @@
|
|
|
+#include "common.h"
|
|
|
+
|
|
|
+int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type) {
|
|
|
+ if(!url || !*url) {
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ buffer_sprintf(w->response.data, "Incomplete request.");
|
|
|
+ return 400;
|
|
|
+ }
|
|
|
+
|
|
|
+ RRDSET *st = NULL;
|
|
|
+
|
|
|
+ char *args = strchr(url, '?');
|
|
|
+ if(args) {
|
|
|
+ *args='\0';
|
|
|
+ args = &args[1];
|
|
|
+ }
|
|
|
+
|
|
|
+ // get the name of the data to show
|
|
|
+ char *tok = mystrsep(&url, "/");
|
|
|
+ if(!tok) tok = "";
|
|
|
+
|
|
|
+ // do we have such a data set?
|
|
|
+ if(*tok) {
|
|
|
+ debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
|
|
|
+ st = rrdset_find_byname(host, tok);
|
|
|
+ if(!st) st = rrdset_find(host, tok);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!st) {
|
|
|
+ // we don't have it
|
|
|
+ // try to send a file with that name
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ return(mysendfile(w, tok));
|
|
|
+ }
|
|
|
+
|
|
|
+ // we have it
|
|
|
+ debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok);
|
|
|
+
|
|
|
+ // how many entries does the client want?
|
|
|
+ int lines = (int)st->entries;
|
|
|
+ int group_count = 1;
|
|
|
+ time_t after = 0, before = 0;
|
|
|
+ int group_method = GROUP_AVERAGE;
|
|
|
+ int nonzero = 0;
|
|
|
+
|
|
|
+ if(url) {
|
|
|
+ // parse the lines required
|
|
|
+ tok = mystrsep(&url, "/");
|
|
|
+ if(tok) lines = str2i(tok);
|
|
|
+ if(lines < 1) lines = 1;
|
|
|
+ }
|
|
|
+ if(url) {
|
|
|
+ // parse the group count required
|
|
|
+ tok = mystrsep(&url, "/");
|
|
|
+ if(tok && *tok) group_count = str2i(tok);
|
|
|
+ if(group_count < 1) group_count = 1;
|
|
|
+ //if(group_count > save_history / 20) group_count = save_history / 20;
|
|
|
+ }
|
|
|
+ if(url) {
|
|
|
+ // parse the grouping method required
|
|
|
+ tok = mystrsep(&url, "/");
|
|
|
+ if(tok && *tok) {
|
|
|
+ if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
|
|
|
+ else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
|
|
|
+ else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
|
|
|
+ else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(url) {
|
|
|
+ // parse after time
|
|
|
+ tok = mystrsep(&url, "/");
|
|
|
+ if(tok && *tok) after = str2ul(tok);
|
|
|
+ if(after < 0) after = 0;
|
|
|
+ }
|
|
|
+ if(url) {
|
|
|
+ // parse before time
|
|
|
+ tok = mystrsep(&url, "/");
|
|
|
+ if(tok && *tok) before = str2ul(tok);
|
|
|
+ if(before < 0) before = 0;
|
|
|
+ }
|
|
|
+ if(url) {
|
|
|
+ // parse nonzero
|
|
|
+ tok = mystrsep(&url, "/");
|
|
|
+ if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ w->response.data->contenttype = CT_APPLICATION_JSON;
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+
|
|
|
+ char *google_version = "0.6";
|
|
|
+ char *google_reqId = "0";
|
|
|
+ char *google_sig = "0";
|
|
|
+ char *google_out = "json";
|
|
|
+ char *google_responseHandler = "google.visualization.Query.setResponse";
|
|
|
+ char *google_outFileName = NULL;
|
|
|
+ time_t last_timestamp_in_data = 0;
|
|
|
+ if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) {
|
|
|
+
|
|
|
+ w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
|
|
|
+
|
|
|
+ while(args) {
|
|
|
+ tok = mystrsep(&args, "&");
|
|
|
+ if(tok && *tok) {
|
|
|
+ char *name = mystrsep(&tok, "=");
|
|
|
+ if(name && *name && strcmp(name, "tqx") == 0) {
|
|
|
+ char *key = mystrsep(&tok, ":");
|
|
|
+ char *value = mystrsep(&tok, ";");
|
|
|
+ if(key && value && *key && *value) {
|
|
|
+ if(strcmp(key, "version") == 0)
|
|
|
+ google_version = value;
|
|
|
+
|
|
|
+ else if(strcmp(key, "reqId") == 0)
|
|
|
+ google_reqId = value;
|
|
|
+
|
|
|
+ else if(strcmp(key, "sig") == 0)
|
|
|
+ google_sig = value;
|
|
|
+
|
|
|
+ else if(strcmp(key, "out") == 0)
|
|
|
+ google_out = value;
|
|
|
+
|
|
|
+ else if(strcmp(key, "responseHandler") == 0)
|
|
|
+ google_responseHandler = value;
|
|
|
+
|
|
|
+ else if(strcmp(key, "outFileName") == 0)
|
|
|
+ google_outFileName = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
|
|
|
+ w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName
|
|
|
+ );
|
|
|
+
|
|
|
+ if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
|
|
|
+ last_timestamp_in_data = strtoul(google_sig, NULL, 0);
|
|
|
+
|
|
|
+ // check the client wants json
|
|
|
+ if(strcmp(google_out, "json") != 0) {
|
|
|
+ buffer_sprintf(w->response.data,
|
|
|
+ "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
|
|
|
+ google_responseHandler, google_version, google_reqId, google_out);
|
|
|
+ return 200;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
|
|
|
+ buffer_sprintf(w->response.data,
|
|
|
+ "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
|
|
|
+ google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
|
|
|
+ }
|
|
|
+
|
|
|
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).",
|
|
|
+ w->id, st->name, st->id, lines, group_count, group_method, after, before);
|
|
|
+
|
|
|
+ time_t timestamp_in_data = rrd_stats_json(datasource_type, st, w->response.data, lines, group_count, group_method, (unsigned long)after, (unsigned long)before, nonzero);
|
|
|
+
|
|
|
+ if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
|
|
|
+ if(timestamp_in_data > last_timestamp_in_data)
|
|
|
+ buffer_strcat(w->response.data, "});");
|
|
|
+
|
|
|
+ else {
|
|
|
+ // the client already has the latest data
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ buffer_sprintf(w->response.data,
|
|
|
+ "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
|
|
|
+ google_responseHandler, google_version, google_reqId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 200;
|
|
|
+}
|
|
|
+
|
|
|
+inline int web_client_api_old_data_request_json(RRDHOST *host, struct web_client *w, char *url) {
|
|
|
+ return web_client_api_old_data_request(host, w, url, DATASOURCE_JSON);
|
|
|
+}
|
|
|
+
|
|
|
+inline int web_client_api_old_data_request_jsonp(RRDHOST *host, struct web_client *w, char *url) {
|
|
|
+ return web_client_api_old_data_request(host, w, url, DATASOURCE_DATATABLE_JSONP);
|
|
|
+}
|
|
|
+
|
|
|
+inline int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url) {
|
|
|
+ // get the name of the data to show
|
|
|
+ char *tok = mystrsep(&url, "/?&");
|
|
|
+ if(tok && *tok) {
|
|
|
+ debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
|
|
|
+
|
|
|
+ // do we have such a data set?
|
|
|
+ RRDSET *st = rrdset_find_byname(host, tok);
|
|
|
+ if(!st) st = rrdset_find(host, tok);
|
|
|
+ if(!st) {
|
|
|
+ // we don't have it
|
|
|
+ // try to send a file with that name
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ return mysendfile(w, tok);
|
|
|
+ }
|
|
|
+
|
|
|
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
|
|
|
+ w->response.data->contenttype = CT_APPLICATION_JSON;
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ rrd_stats_graph_json(st, url, w->response.data);
|
|
|
+ return 200;
|
|
|
+ }
|
|
|
+
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ buffer_strcat(w->response.data, "Graph name?\r\n");
|
|
|
+ return 400;
|
|
|
+}
|
|
|
+
|
|
|
+inline int web_client_api_old_list_request(RRDHOST *host, struct web_client *w, char *url) {
|
|
|
+ (void)url;
|
|
|
+
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ RRDSET *st;
|
|
|
+
|
|
|
+ rrdhost_rdlock(host);
|
|
|
+ rrdset_foreach_read(st, host) buffer_sprintf(w->response.data, "%s\n", st->name);
|
|
|
+ rrdhost_unlock(host);
|
|
|
+
|
|
|
+ return 200;
|
|
|
+}
|
|
|
+
|
|
|
+inline int web_client_api_old_all_json(RRDHOST *host, struct web_client *w, char *url) {
|
|
|
+ (void)url;
|
|
|
+
|
|
|
+ w->response.data->contenttype = CT_APPLICATION_JSON;
|
|
|
+ buffer_flush(w->response.data);
|
|
|
+ rrd_stats_all_json(host, w->response.data);
|
|
|
+ return 200;
|
|
|
+}
|