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.c263
1 files changed, 228 insertions, 35 deletions
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 3efac5669..73ac15d30 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -2,6 +2,8 @@
#include "web_api_v1.h"
+char *api_secret;
+
static struct {
const char *name;
uint32_t hash;
@@ -33,6 +35,7 @@ static struct {
, {"match_names" , 0 , RRDR_OPTION_MATCH_NAMES}
, {"match-names" , 0 , RRDR_OPTION_MATCH_NAMES}
, {"showcustomvars" , 0 , RRDR_OPTION_CUSTOM_VARS}
+ , {"allow_past" , 0 , RRDR_OPTION_ALLOW_PAST}
, { NULL, 0, 0}
};
@@ -194,10 +197,8 @@ inline uint32_t web_client_api_request_v1_data_google_format(char *name) {
return DATASOURCE_JSON;
}
-
-inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) {
+int web_client_api_request_v1_alarms_select (char *url) {
int all = 0;
-
while(url) {
char *value = mystrsep(&url, "&");
if (!value || !*value) continue;
@@ -206,6 +207,12 @@ inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w,
else if(!strcmp(value, "active")) all = 0;
}
+ return all;
+}
+
+inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) {
+ int all = web_client_api_request_v1_alarms_select(url);
+
buffer_flush(w->response.data);
w->response.data->contenttype = CT_APPLICATION_JSON;
health_alarms2json(host, w->response.data, all);
@@ -213,6 +220,16 @@ inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w,
return HTTP_RESP_OK;
}
+inline int web_client_api_request_v1_alarms_values(RRDHOST *host, struct web_client *w, char *url) {
+ int all = web_client_api_request_v1_alarms_select(url);
+
+ buffer_flush(w->response.data);
+ w->response.data->contenttype = CT_APPLICATION_JSON;
+ health_alarms_values2json(host, w->response.data, all);
+ buffer_no_cacheable(w->response.data);
+ return HTTP_RESP_OK;
+}
+
inline int web_client_api_request_v1_alarm_count(RRDHOST *host, struct web_client *w, char *url) {
RRDCALC_STATUS status = RRDCALC_STATUS_RAISED;
BUFFER *contexts = NULL;
@@ -333,7 +350,19 @@ inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w,
buffer_flush(w->response.data);
w->response.data->contenttype = CT_APPLICATION_JSON;
- charts2json(host, w->response.data);
+ charts2json(host, w->response.data, 0, 0);
+ return HTTP_RESP_OK;
+}
+
+inline int web_client_api_request_v1_archivedcharts(RRDHOST *host __maybe_unused, struct web_client *w, char *url) {
+ (void)url;
+
+ buffer_flush(w->response.data);
+ w->response.data->contenttype = CT_APPLICATION_JSON;
+#ifdef ENABLE_DBENGINE
+ if (host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
+ sql_rrdset2json(host, w->response.data);
+#endif
return HTTP_RESP_OK;
}
@@ -372,7 +401,9 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
, *before_str = NULL
, *after_str = NULL
, *group_time_str = NULL
- , *points_str = NULL;
+ , *points_str = NULL
+ , *context = NULL
+ , *chart_label_key = NULL;
int group = RRDR_GROUPING_AVERAGE;
uint32_t format = DATASOURCE_JSON;
@@ -391,7 +422,9 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
// name and value are now the parameters
// they are not null and not empty
- if(!strcmp(name, "chart")) chart = value;
+ if(!strcmp(name, "context")) context = value;
+ else if(!strcmp(name, "chart_label_key")) chart_label_key = value;
+ else if(!strcmp(name, "chart")) chart = value;
else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
if(!dimensions) dimensions = buffer_create(100);
buffer_strcat(dimensions, "|");
@@ -457,23 +490,59 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
fix_google_param(responseHandler);
fix_google_param(outFileName);
- if(!chart || !*chart) {
+ RRDSET *st = NULL;
+
+ if((!chart || !*chart) && (!context)) {
buffer_sprintf(w->response.data, "No chart id is given at the request.");
goto cleanup;
}
- RRDSET *st = rrdset_find(host, chart);
- if(!st) st = rrdset_find_byname(host, chart);
- if(!st) {
- buffer_strcat(w->response.data, "Chart is not found: ");
- buffer_strcat_htmlescape(w->response.data, chart);
+ struct context_param *context_param_list = NULL;
+ if (context && !chart) {
+ RRDSET *st1;
+ uint32_t context_hash = simple_hash(context);
+
+ rrdhost_rdlock(host);
+ rrdset_foreach_read(st1, host) {
+ if (st1->hash_context == context_hash && !strcmp(st1->context, context) &&
+ (!chart_label_key || rrdset_contains_label_keylist(st1, chart_label_key)))
+ build_context_param_list(&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 {
+ st = rrdset_find(host, chart);
+ if (!st)
+ st = rrdset_find_byname(host, chart);
+ if (likely(st))
+ st->last_accessed_time = now_realtime_sec();
+ }
+
+ if (!st && !context_param_list) {
+ if (context && !chart) {
+ if (!chart_label_key) {
+ buffer_strcat(w->response.data, "Context is not found: ");
+ buffer_strcat_htmlescape(w->response.data, context);
+ } else {
+ buffer_strcat(w->response.data, "Context: ");
+ buffer_strcat_htmlescape(w->response.data, context);
+ buffer_strcat(w->response.data, " or chart label key: ");
+ buffer_strcat_htmlescape(w->response.data, chart_label_key);
+ buffer_strcat(w->response.data, " not found");
+ }
+ }
+ else {
+ buffer_strcat(w->response.data, "Chart is not found: ");
+ buffer_strcat_htmlescape(w->response.data, chart);
+ }
ret = HTTP_RESP_NOT_FOUND;
goto cleanup;
}
- st->last_accessed_time = now_realtime_sec();
long long before = (before_str && *before_str)?str2l(before_str):0;
- long long after = (after_str && *after_str) ?str2l(after_str):0;
+ long long after = (after_str && *after_str) ?str2l(after_str):-600;
int points = (points_str && *points_str)?str2i(points_str):0;
long group_time = (group_time_str && *group_time_str)?str2l(group_time_str):0;
@@ -515,7 +584,9 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
}
ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, group_time
- , options, &last_timestamp_in_data);
+ , options, &last_timestamp_in_data, context_param_list, chart_label_key);
+
+ free_context_param_list(&context_param_list);
if(format == DATASOURCE_DATATABLE_JSONP) {
if(google_timestamp < last_timestamp_in_data)
@@ -596,6 +667,9 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
int redirects = 0;
*/
+ // Don't cache registry responses
+ buffer_no_cacheable(w->response.data);
+
while(url) {
char *value = mystrsep(&url, "&");
if (!value || !*value) continue;
@@ -749,44 +823,119 @@ static inline void web_client_api_request_v1_info_summary_alarm_statuses(RRDHOST
}
static inline void web_client_api_request_v1_info_mirrored_hosts(BUFFER *wb) {
- RRDHOST *rc;
+ RRDHOST *host;
int count = 0;
+
+ buffer_strcat(wb, "\t\"mirrored_hosts\": [\n");
rrd_rdlock();
- rrdhost_foreach_read(rc) {
- if(count > 0) buffer_strcat(wb, ",\n");
- buffer_sprintf(wb, "\t\t\"%s\"", rc->hostname);
+ rrdhost_foreach_read(host) {
+ if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED))
+ continue;
+ if (count > 0)
+ buffer_strcat(wb, ",\n");
+
+ buffer_sprintf(wb, "\t\t\"%s\"", host->hostname);
+ count++;
+ }
+
+ buffer_strcat(wb, "\n\t],\n\t\"mirrored_hosts_status\": [\n");
+ count = 0;
+ rrdhost_foreach_read(host)
+ {
+ if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED))
+ continue;
+ if (count > 0)
+ buffer_strcat(wb, ",\n");
+
+ netdata_mutex_lock(&host->receiver_lock);
+ buffer_sprintf(
+ wb, "\t\t{ \"guid\": \"%s\", \"reachable\": %s, \"claim_id\": ", host->machine_guid,
+ (host->receiver || host == localhost) ? "true" : "false");
+ 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);
+ else
+ buffer_strcat(wb, "null }");
+ rrdhost_aclk_state_unlock(host);
+
count++;
}
- buffer_strcat(wb, "\n");
rrd_unlock();
+
+ buffer_strcat(wb, "\n\t],\n");
}
-inline int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, char *url) {
- (void)url;
- if (!netdata_ready) return HTTP_RESP_BACKEND_FETCH_FAILED;
+inline void host_labels2json(RRDHOST *host, BUFFER *wb, size_t indentation) {
+ char tabs[11];
- BUFFER *wb = w->response.data;
- buffer_flush(wb);
- wb->contenttype = CT_APPLICATION_JSON;
+ if (indentation > 10)
+ indentation = 10;
+
+ tabs[0] = '\0';
+ while (indentation) {
+ strcat(tabs, "\t");
+ indentation--;
+ }
+
+ int count = 0;
+ rrdhost_rdlock(host);
+ netdata_rwlock_rdlock(&host->labels.labels_rwlock);
+ for (struct label *label = host->labels.head; label; label = label->next) {
+ if(count > 0) buffer_strcat(wb, ",\n");
+ buffer_strcat(wb, tabs);
+
+ char value[CONFIG_MAX_VALUE * 2 + 1];
+ sanitize_json_string(value, label->value, CONFIG_MAX_VALUE * 2);
+ buffer_sprintf(wb, "\"%s\": \"%s\"", label->key, value);
+ count++;
+ }
+ buffer_strcat(wb, "\n");
+ netdata_rwlock_unlock(&host->labels.labels_rwlock);
+ rrdhost_unlock(host);
+}
+
+extern int aclk_connected;
+inline int web_client_api_request_v1_info_fill_buffer(RRDHOST *host, BUFFER *wb)
+{
buffer_strcat(wb, "{\n");
buffer_sprintf(wb, "\t\"version\": \"%s\",\n", host->program_version);
buffer_sprintf(wb, "\t\"uid\": \"%s\",\n", host->machine_guid);
- buffer_strcat(wb, "\t\"mirrored_hosts\": [\n");
web_client_api_request_v1_info_mirrored_hosts(wb);
- buffer_strcat(wb, "\t],\n");
buffer_strcat(wb, "\t\"alarms\": {\n");
web_client_api_request_v1_info_summary_alarm_statuses(host, wb);
buffer_strcat(wb, "\t},\n");
- buffer_sprintf(wb, "\t\"os_name\": %s,\n", (host->system_info->os_name) ? host->system_info->os_name : "\"\"");
- buffer_sprintf(wb, "\t\"os_id\": \"%s\",\n", (host->system_info->os_id) ? host->system_info->os_id : "");
- buffer_sprintf(wb, "\t\"os_id_like\": \"%s\",\n", (host->system_info->os_id_like) ? host->system_info->os_id_like : "");
- buffer_sprintf(wb, "\t\"os_version\": \"%s\",\n", (host->system_info->os_version) ? host->system_info->os_version : "");
- buffer_sprintf(wb, "\t\"os_version_id\": \"%s\",\n", (host->system_info->os_version_id) ? host->system_info->os_version_id : "");
- buffer_sprintf(wb, "\t\"os_detection\": \"%s\",\n", (host->system_info->os_detection) ? host->system_info->os_detection : "");
+ buffer_sprintf(wb, "\t\"os_name\": \"%s\",\n", (host->system_info->host_os_name) ? host->system_info->host_os_name : "");
+ buffer_sprintf(wb, "\t\"os_id\": \"%s\",\n", (host->system_info->host_os_id) ? host->system_info->host_os_id : "");
+ buffer_sprintf(wb, "\t\"os_id_like\": \"%s\",\n", (host->system_info->host_os_id_like) ? host->system_info->host_os_id_like : "");
+ buffer_sprintf(wb, "\t\"os_version\": \"%s\",\n", (host->system_info->host_os_version) ? host->system_info->host_os_version : "");
+ buffer_sprintf(wb, "\t\"os_version_id\": \"%s\",\n", (host->system_info->host_os_version_id) ? host->system_info->host_os_version_id : "");
+ buffer_sprintf(wb, "\t\"os_detection\": \"%s\",\n", (host->system_info->host_os_detection) ? host->system_info->host_os_detection : "");
+ buffer_sprintf(wb, "\t\"cores_total\": \"%s\",\n", (host->system_info->host_cores) ? host->system_info->host_cores : "");
+ buffer_sprintf(wb, "\t\"total_disk_space\": \"%s\",\n", (host->system_info->host_disk_space) ? host->system_info->host_disk_space : "");
+ buffer_sprintf(wb, "\t\"cpu_freq\": \"%s\",\n", (host->system_info->host_cpu_freq) ? host->system_info->host_cpu_freq : "");
+ buffer_sprintf(wb, "\t\"ram_total\": \"%s\",\n", (host->system_info->host_ram_total) ? host->system_info->host_ram_total : "");
+
+ if (host->system_info->container_os_name)
+ buffer_sprintf(wb, "\t\"container_os_name\": \"%s\",\n", host->system_info->container_os_name);
+ if (host->system_info->container_os_id)
+ buffer_sprintf(wb, "\t\"container_os_id\": \"%s\",\n", host->system_info->container_os_id);
+ if (host->system_info->container_os_id_like)
+ buffer_sprintf(wb, "\t\"container_os_id_like\": \"%s\",\n", host->system_info->container_os_id_like);
+ if (host->system_info->container_os_version)
+ buffer_sprintf(wb, "\t\"container_os_version\": \"%s\",\n", host->system_info->container_os_version);
+ if (host->system_info->container_os_version_id)
+ buffer_sprintf(wb, "\t\"container_os_version_id\": \"%s\",\n", host->system_info->container_os_version_id);
+ if (host->system_info->container_os_detection)
+ buffer_sprintf(wb, "\t\"container_os_detection\": \"%s\",\n", host->system_info->container_os_detection);
+ if (host->system_info->is_k8s_node)
+ buffer_sprintf(wb, "\t\"is_k8s_node\": \"%s\",\n", host->system_info->is_k8s_node);
+
buffer_sprintf(wb, "\t\"kernel_name\": \"%s\",\n", (host->system_info->kernel_name) ? host->system_info->kernel_name : "");
buffer_sprintf(wb, "\t\"kernel_version\": \"%s\",\n", (host->system_info->kernel_version) ? host->system_info->kernel_version : "");
buffer_sprintf(wb, "\t\"architecture\": \"%s\",\n", (host->system_info->architecture) ? host->system_info->architecture : "");
@@ -795,11 +944,53 @@ inline int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, c
buffer_sprintf(wb, "\t\"container\": \"%s\",\n", (host->system_info->container) ? host->system_info->container : "");
buffer_sprintf(wb, "\t\"container_detection\": \"%s\",\n", (host->system_info->container_detection) ? host->system_info->container_detection : "");
+ buffer_strcat(wb, "\t\"host_labels\": {\n");
+ host_labels2json(host, wb, 2);
+ buffer_strcat(wb, "\t},\n");
+
buffer_strcat(wb, "\t\"collectors\": [");
chartcollectors2json(host, wb);
- buffer_strcat(wb, "\n\t]\n");
+ buffer_strcat(wb, "\n\t],\n");
+
+#ifdef DISABLE_CLOUD
+ buffer_strcat(wb, "\t\"cloud-enabled\": false,\n");
+#else
+ buffer_sprintf(wb, "\t\"cloud-enabled\": %s,\n",
+ appconfig_get_boolean(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", 1) ? "true" : "false");
+#endif
+
+#ifdef ENABLE_ACLK
+ buffer_strcat(wb, "\t\"cloud-available\": true,\n");
+#else
+ buffer_strcat(wb, "\t\"cloud-available\": false,\n");
+#endif
+ char *agent_id = is_agent_claimed();
+ if (agent_id == NULL)
+ buffer_strcat(wb, "\t\"agent-claimed\": false,\n");
+ else {
+ buffer_strcat(wb, "\t\"agent-claimed\": true,\n");
+ freez(agent_id);
+ }
+#ifdef ENABLE_ACLK
+ if (aclk_connected)
+ buffer_strcat(wb, "\t\"aclk-available\": true\n");
+ else
+#endif
+ buffer_strcat(wb, "\t\"aclk-available\": false\n"); // Intentionally valid with/without #ifdef above
buffer_strcat(wb, "}");
+ return 0;
+}
+
+inline int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, char *url) {
+ (void)url;
+ if (!netdata_ready) return HTTP_RESP_BACKEND_FETCH_FAILED;
+ BUFFER *wb = w->response.data;
+ buffer_flush(wb);
+ wb->contenttype = CT_APPLICATION_JSON;
+
+ web_client_api_request_v1_info_fill_buffer(host, wb);
+
buffer_no_cacheable(wb);
return HTTP_RESP_OK;
}
@@ -814,6 +1005,7 @@ static struct api_command {
{ "data", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_data },
{ "chart", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_chart },
{ "charts", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_charts },
+ { "archivedcharts", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_archivedcharts },
// registry checks the ACL by itself, so we allow everything
{ "registry", 0, WEB_CLIENT_ACL_NOCHECK, web_client_api_request_v1_registry },
@@ -822,6 +1014,7 @@ static struct api_command {
{ "badge.svg", 0, WEB_CLIENT_ACL_DASHBOARD|WEB_CLIENT_ACL_BADGE, web_client_api_request_v1_badge },
{ "alarms", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarms },
+ { "alarms_values", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarms_values },
{ "alarm_log", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_log },
{ "alarm_variables", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_variables },
{ "alarm_count", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_count },