From 89f3604407aff8f4cb2ed958252c61e23c767e24 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 9 Jun 2022 06:52:39 +0200 Subject: Adding upstream version 1.35.0. Signed-off-by: Daniel Baumann --- web/api/web_api_v1.c | 109 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 18 deletions(-) (limited to 'web/api/web_api_v1.c') diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c index 8cf89d38d..cb73f7c02 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 }, }; -- cgit v1.2.3