summaryrefslogtreecommitdiffstats
path: root/web/api/web_api_v1.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/api/web_api_v1.c')
-rw-r--r--web/api/web_api_v1.c109
1 files changed, 91 insertions, 18 deletions
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 8cf89d38..cb73f7c0 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -422,6 +422,7 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
char *chart_labels_filter = NULL;
int group = RRDR_GROUPING_AVERAGE;
+ int show_dimensions = 0;
uint32_t format = DATASOURCE_JSON;
uint32_t options = 0x00000000;
@@ -447,6 +448,7 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
buffer_strcat(dimensions, "|");
buffer_strcat(dimensions, value);
}
+ else if(!strcmp(name, "show_dimensions")) show_dimensions = 1;
else if(!strcmp(name, "after")) after_str = value;
else if(!strcmp(name, "before")) before_str = value;
else if(!strcmp(name, "points")) points_str = value;
@@ -512,6 +514,7 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
fix_google_param(outFileName);
RRDSET *st = NULL;
+ ONEWAYALLOC *owa = onewayalloc_create(0);
if((!chart || !*chart) && (!context)) {
buffer_sprintf(w->response.data, "No chart id is given at the request.");
@@ -519,8 +522,10 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
}
struct context_param *context_param_list = NULL;
+
if (context && !chart) {
RRDSET *st1;
+
uint32_t context_hash = simple_hash(context);
rrdhost_rdlock(host);
@@ -532,14 +537,14 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
(!chart_label_key || rrdset_contains_label_keylist(st1, chart_label_key)) &&
(!chart_labels_filter ||
rrdset_matches_label_keys(st1, chart_labels_filter, words, hash_key_list, &word_count, MAX_CHART_LABELS_FILTER)))
- build_context_param_list(&context_param_list, st1);
+ build_context_param_list(owa, &context_param_list, st1);
}
rrdhost_unlock(host);
if (likely(context_param_list && context_param_list->rd)) // Just set the first one
st = context_param_list->rd->rrdset;
else {
if (!chart_label_key && !chart_labels_filter)
- sql_build_context_param_list(&context_param_list, host, context, NULL);
+ sql_build_context_param_list(owa, &context_param_list, host, context, NULL);
}
}
else {
@@ -549,14 +554,14 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
if (likely(st))
st->last_accessed_time = now_realtime_sec();
else
- sql_build_context_param_list(&context_param_list, host, NULL, chart);
+ sql_build_context_param_list(owa, &context_param_list, host, NULL, chart);
}
if (!st) {
if (likely(context_param_list && context_param_list->rd && context_param_list->rd->rrdset))
st = context_param_list->rd->rrdset;
else {
- free_context_param_list(&context_param_list);
+ free_context_param_list(owa, &context_param_list);
context_param_list = NULL;
}
}
@@ -589,6 +594,18 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
long group_time = (group_time_str && *group_time_str)?str2l(group_time_str):0;
int max_anomaly_rates = (max_anomaly_rates_str && *max_anomaly_rates_str) ? str2i(max_anomaly_rates_str) : 0;
+ if (timeout) {
+ struct timeval now;
+ now_realtime_timeval(&now);
+ int inqueue = (int)dt_usec(&w->tv_in, &now) / 1000;
+ timeout -= inqueue;
+ if (timeout <= 0) {
+ buffer_flush(w->response.data);
+ buffer_strcat(w->response.data, "Query timeout exceeded");
+ return HTTP_RESP_BACKEND_FETCH_FAILED;
+ }
+ }
+
debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'"
, w->id
, chart
@@ -630,12 +647,18 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
buffer_strcat(w->response.data, "(");
}
- ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format,
- points, after, before, group, group_time,
- options, &last_timestamp_in_data, context_param_list,
- chart_label_key, max_anomaly_rates, timeout);
+ QUERY_PARAMS query_params = {
+ .context_param_list = context_param_list,
+ .timeout = timeout,
+ .max_anomaly_rates = max_anomaly_rates,
+ .show_dimensions = show_dimensions,
+ .chart_label_key = chart_label_key,
+ .wb = w->response.data};
+
+ ret = rrdset2anything_api_v1(owa, st, &query_params, dimensions, format,
+ points, after, before, group, group_time, options, &last_timestamp_in_data);
- free_context_param_list(&context_param_list);
+ free_context_param_list(owa, &context_param_list);
if(format == DATASOURCE_DATATABLE_JSONP) {
if(google_timestamp < last_timestamp_in_data)
@@ -652,7 +675,8 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
else if(format == DATASOURCE_JSONP)
buffer_strcat(w->response.data, ");");
- cleanup:
+cleanup:
+ onewayalloc_destroy(owa);
buffer_free(dimensions);
return ret;
}
@@ -899,23 +923,27 @@ static inline void web_client_api_request_v1_info_mirrored_hosts(BUFFER *wb) {
netdata_mutex_lock(&host->receiver_lock);
buffer_sprintf(
- wb, "\t\t{ \"guid\": \"%s\", \"reachable\": %s, \"hops\": %d, \"claim_id\": ", host->machine_guid,
- (host->receiver || host == localhost) ? "true" : "false", host->system_info ? host->system_info->hops : (host == localhost) ? 0 : 1);
+ wb, "\t\t{ \"guid\": \"%s\", \"hostname\": \"%s\", \"reachable\": %s, \"hops\": %d"
+ , host->machine_guid
+ , host->hostname
+ , (host->receiver || host == localhost) ? "true" : "false"
+ , host->system_info ? host->system_info->hops : (host == localhost) ? 0 : 1
+ );
netdata_mutex_unlock(&host->receiver_lock);
rrdhost_aclk_state_lock(host);
if (host->aclk_state.claimed_id)
- buffer_sprintf(wb, "\"%s\", ", host->aclk_state.claimed_id);
+ buffer_sprintf(wb, ", \"claim_id\": \"%s\"", host->aclk_state.claimed_id);
else
- buffer_strcat(wb, "null, ");
+ buffer_strcat(wb, ", \"claim_id\": null");
rrdhost_aclk_state_unlock(host);
if (host->node_id) {
char node_id_str[GUID_LEN + 1];
uuid_unparse_lower(*host->node_id, node_id_str);
- buffer_sprintf(wb, "\"node_id\": \"%s\" }", node_id_str);
+ buffer_sprintf(wb, ", \"node_id\": \"%s\" }", node_id_str);
} else
- buffer_strcat(wb, "\"node_id\": null }");
+ buffer_strcat(wb, ", \"node_id\": null }");
count++;
}
@@ -1295,6 +1323,50 @@ static int web_client_api_request_v1_aclk_state(RRDHOST *host, struct web_client
return HTTP_RESP_OK;
}
+int web_client_api_request_v1_metric_correlations(RRDHOST *host, struct web_client *w, char *url) {
+ if (!netdata_ready)
+ return HTTP_RESP_BACKEND_FETCH_FAILED;
+
+ long long baseline_after = 0, baseline_before = 0, highlight_after = 0, highlight_before = 0, max_points = 0;
+
+ while (url) {
+ char *value = mystrsep(&url, "&");
+ if (!value || !*value)
+ continue;
+
+ char *name = mystrsep(&value, "=");
+ if (!name || !*name)
+ continue;
+ if (!value || !*value)
+ continue;
+
+ if (!strcmp(name, "baseline_after"))
+ baseline_after = (long long) strtoul(value, NULL, 0);
+ else if (!strcmp(name, "baseline_before"))
+ baseline_before = (long long) strtoul(value, NULL, 0);
+ else if (!strcmp(name, "highlight_after"))
+ highlight_after = (long long) strtoul(value, NULL, 0);
+ else if (!strcmp(name, "highlight_before"))
+ highlight_before = (long long) strtoul(value, NULL, 0);
+ else if (!strcmp(name, "max_points"))
+ max_points = (long long) strtoul(value, NULL, 0);
+
+ }
+
+ BUFFER *wb = w->response.data;
+ buffer_flush(wb);
+ wb->contenttype = CT_APPLICATION_JSON;
+ buffer_no_cacheable(wb);
+
+ if (!highlight_after || !highlight_before)
+ buffer_strcat(wb, "{\"error\": \"Missing or invalid required highlight after and before parameters.\" }");
+ else {
+ metric_correlations(host, wb, baseline_after, baseline_before, highlight_after, highlight_before, max_points);
+ }
+
+ return HTTP_RESP_OK;
+}
+
static struct api_command {
const char *command;
uint32_t hash;
@@ -1326,8 +1398,9 @@ static struct api_command {
{ "ml_info", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_ml_info },
#endif
- { "manage/health", 0, WEB_CLIENT_ACL_MGMT, web_client_api_request_v1_mgmt_health },
- { "aclk", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_aclk_state },
+ { "manage/health", 0, WEB_CLIENT_ACL_MGMT, web_client_api_request_v1_mgmt_health },
+ { "aclk", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_aclk_state },
+ { "metric_correlations", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_metric_correlations },
// terminator
{ NULL, 0, WEB_CLIENT_ACL_NONE, NULL },
};