diff options
Diffstat (limited to 'daemon/analytics.c')
-rw-r--r-- | daemon/analytics.c | 202 |
1 files changed, 179 insertions, 23 deletions
diff --git a/daemon/analytics.c b/daemon/analytics.c index 08923a3c..bb878f70 100644 --- a/daemon/analytics.c +++ b/daemon/analytics.c @@ -4,6 +4,7 @@ struct analytics_data analytics_data; extern void analytics_exporting_connectors (BUFFER *b); +extern void analytics_exporting_connectors_ssl (BUFFER *b); extern void analytics_build_info (BUFFER *b); extern int aclk_connected; @@ -54,6 +55,12 @@ void analytics_log_data(void) debug(D_ANALYTICS, "NETDATA_HOST_ACLK_IMPLEMENTATION : [%s]", analytics_data.netdata_host_aclk_implementation); debug(D_ANALYTICS, "NETDATA_HOST_AGENT_CLAIMED : [%s]", analytics_data.netdata_host_agent_claimed); debug(D_ANALYTICS, "NETDATA_HOST_CLOUD_ENABLED : [%s]", analytics_data.netdata_host_cloud_enabled); + debug(D_ANALYTICS, "NETDATA_CONFIG_HTTPS_AVAILABLE : [%s]", analytics_data.netdata_config_https_available); + debug(D_ANALYTICS, "NETDATA_INSTALL_TYPE : [%s]", analytics_data.netdata_install_type); + debug(D_ANALYTICS, "NETDATA_PREBUILT_DISTRO : [%s]", analytics_data.netdata_prebuilt_distro); + debug(D_ANALYTICS, "NETDATA_CONFIG_IS_PRIVATE_REGISTRY : [%s]", analytics_data.netdata_config_is_private_registry); + debug(D_ANALYTICS, "NETDATA_CONFIG_USE_PRIVATE_REGISTRY: [%s]", analytics_data.netdata_config_use_private_registry); + debug(D_ANALYTICS, "NETDATA_CONFIG_OOM_SCORE : [%s]", analytics_data.netdata_config_oom_score); } /* @@ -93,6 +100,12 @@ void analytics_free_data(void) freez(analytics_data.netdata_host_aclk_implementation); freez(analytics_data.netdata_host_agent_claimed); freez(analytics_data.netdata_host_cloud_enabled); + freez(analytics_data.netdata_config_https_available); + freez(analytics_data.netdata_install_type); + freez(analytics_data.netdata_config_is_private_registry); + freez(analytics_data.netdata_config_use_private_registry); + freez(analytics_data.netdata_config_oom_score); + freez(analytics_data.netdata_prebuilt_distro); } /* @@ -137,7 +150,7 @@ void analytics_get_data(char *name, BUFFER *wb) */ void analytics_log_prometheus(void) { - if (likely(analytics_data.prometheus_hits < ANALYTICS_MAX_PROMETHEUS_HITS)) { + if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.prometheus_hits < ANALYTICS_MAX_PROMETHEUS_HITS)) { analytics_data.prometheus_hits++; char b[7]; snprintfz(b, 6, "%d", analytics_data.prometheus_hits); @@ -150,7 +163,7 @@ void analytics_log_prometheus(void) */ void analytics_log_shell(void) { - if (likely(analytics_data.shell_hits < ANALYTICS_MAX_SHELL_HITS)) { + if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.shell_hits < ANALYTICS_MAX_SHELL_HITS)) { analytics_data.shell_hits++; char b[7]; snprintfz(b, 6, "%d", analytics_data.shell_hits); @@ -163,7 +176,7 @@ void analytics_log_shell(void) */ void analytics_log_json(void) { - if (likely(analytics_data.json_hits < ANALYTICS_MAX_JSON_HITS)) { + if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.json_hits < ANALYTICS_MAX_JSON_HITS)) { analytics_data.json_hits++; char b[7]; snprintfz(b, 6, "%d", analytics_data.json_hits); @@ -176,7 +189,7 @@ void analytics_log_json(void) */ void analytics_log_dashboard(void) { - if (likely(analytics_data.dashboard_hits < ANALYTICS_MAX_DASHBOARD_HITS)) { + if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.dashboard_hits < ANALYTICS_MAX_DASHBOARD_HITS)) { analytics_data.dashboard_hits++; char b[7]; snprintfz(b, 6, "%d", analytics_data.dashboard_hits); @@ -184,6 +197,15 @@ void analytics_log_dashboard(void) } } +/* + * Called when setting the oom score + */ +void analytics_report_oom_score(long long int score){ + char b[7]; + snprintfz(b, 6, "%d", (int)score); + analytics_set_data(&analytics_data.netdata_config_oom_score, b); +} + void analytics_mirrored_hosts(void) { RRDHOST *host; @@ -217,7 +239,7 @@ void analytics_mirrored_hosts(void) void analytics_exporters(void) { //when no exporters are available, an empty string will be sent - //decide if something else is more suitable (but propably not null) + //decide if something else is more suitable (but probably not null) BUFFER *bi = buffer_create(1000); analytics_exporting_connectors(bi); analytics_set_data_str(&analytics_data.netdata_exporting_connectors, (char *)buffer_tostring(bi)); @@ -335,6 +357,67 @@ void analytics_alarms_notifications(void) buffer_free(b); } +char *get_value_from_key(char *buffer, char *key) +{ + char *s = NULL, *t = NULL; + s = t = buffer + strlen(key) + 2; + if (s) { + while (*s == '\'') + s++; + while (*++t != '\0'); + while (--t > s && *t == '\'') + *t = '\0'; + } + return s; +} + +/* + * Checks for the existence of .install_type file and reads it + */ +void analytics_get_install_type(void) +{ + char *install_type_filename; + analytics_set_data_str(&analytics_data.netdata_install_type, ""); + analytics_set_data_str(&analytics_data.netdata_prebuilt_distro, ""); + + int install_type_filename_len = (strlen(netdata_configured_user_config_dir) + strlen(".install-type") + 3); + install_type_filename = mallocz(sizeof(char) * install_type_filename_len); + snprintfz(install_type_filename, install_type_filename_len - 1, "%s/%s", netdata_configured_user_config_dir, ".install-type"); + + FILE *fp = fopen(install_type_filename, "r"); + if (fp) { + char *s, buf[256 + 1]; + size_t len = 0; + + while ((s = fgets_trim_len(buf, 256, fp, &len))) { + if (!strncmp(buf, "INSTALL_TYPE='", 14)) + analytics_set_data_str(&analytics_data.netdata_install_type, (char *)get_value_from_key(buf, "INSTALL_TYPE")); + else if (!strncmp(buf, "PREBUILT_DISTRO='", 17)) + analytics_set_data_str(&analytics_data.netdata_prebuilt_distro, (char *)get_value_from_key(buf, "PREBUILT_DISTRO")); + } + fclose(fp); + } + freez(install_type_filename); +} + +/* + * Pick up if https is actually used + */ +void analytics_https(void) +{ + BUFFER *b = buffer_create(30); +#ifdef ENABLE_HTTPS + analytics_exporting_connectors_ssl(b); + buffer_strcat(b, netdata_client_ctx && localhost->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE && localhost->rrdpush_sender_connected == 1 ? "streaming|" : "|"); + buffer_strcat(b, netdata_srv_ctx ? "web" : ""); +#else + buffer_strcat(b, "||"); +#endif + + analytics_set_data_str(&analytics_data.netdata_config_https_available, (char *)buffer_tostring(b)); + buffer_free(b); +} + void analytics_charts(void) { RRDSET *st; @@ -411,13 +494,13 @@ void analytics_misc(void) { #ifdef ENABLE_ACLK analytics_set_data(&analytics_data.netdata_host_cloud_available, "true"); -#ifdef ACLK_NG - analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "Next Generation"); -#else - analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "legacy"); -#endif + if (aclk_ng) + analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "Next Generation"); + else + analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "legacy"); #else analytics_set_data(&analytics_data.netdata_host_cloud_available, "false"); + analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, ""); #endif #ifdef ENABLE_ACLK @@ -426,17 +509,33 @@ void analytics_misc(void) else #endif analytics_set_data(&analytics_data.netdata_host_aclk_available, "false"); + + analytics_set_data(&analytics_data.netdata_config_exporting_enabled, appconfig_get_boolean(&exporting_config, CONFIG_SECTION_EXPORTING, "enabled", CONFIG_BOOLEAN_NO) ? "true" : "false"); + + analytics_set_data(&analytics_data.netdata_config_is_private_registry, "false"); + analytics_set_data(&analytics_data.netdata_config_use_private_registry, "false"); + + if (strcmp( + config_get(CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io"), + "https://registry.my-netdata.io")) + analytics_set_data(&analytics_data.netdata_config_use_private_registry, "true"); + + //do we need both registry to announce and enabled to indicate that this is a private registry ? + if (config_get_boolean(CONFIG_SECTION_REGISTRY, "enabled", CONFIG_BOOLEAN_NO) && + web_server_mode != WEB_SERVER_MODE_NONE) + analytics_set_data(&analytics_data.netdata_config_is_private_registry, "true"); } /* * Get the meta data, called from the thread once after the original delay - * These are values that won't change between agent restarts, and therefore + * These are values that won't change during agent runtime, and therefore * don't try to read them on each META event send */ void analytics_gather_immutable_meta_data(void) { analytics_misc(); analytics_exporters(); + analytics_https(); } /* @@ -490,6 +589,7 @@ void analytics_main_cleanup(void *ptr) static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; debug(D_ANALYTICS, "Cleaning up..."); + analytics_free_data(); static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; } @@ -521,7 +621,7 @@ void *analytics_main(void *ptr) analytics_gather_immutable_meta_data(); analytics_gather_mutable_meta_data(); - send_statistics("META", "-", "-"); + send_statistics("META_START", "-", "-"); analytics_log_data(); sec = 0; @@ -567,7 +667,6 @@ void set_late_global_environment() { analytics_set_data(&analytics_data.netdata_config_stream_enabled, default_rrdpush_enabled ? "true" : "false"); analytics_set_data_str(&analytics_data.netdata_config_memory_mode, (char *)rrd_memory_mode_name(default_rrd_memory_mode)); - analytics_set_data(&analytics_data.netdata_config_exporting_enabled, appconfig_get_boolean(&exporting_config, CONFIG_SECTION_EXPORTING, "enabled", CONFIG_BOOLEAN_NO) ? "true" : "false"); #ifdef DISABLE_CLOUD analytics_set_data(&analytics_data.netdata_host_cloud_enabled, "false"); @@ -607,9 +706,11 @@ void set_late_global_environment() analytics_set_data_str(&analytics_data.netdata_buildinfo, (char *)buffer_tostring(bi)); buffer_free(bi); } + + analytics_get_install_type(); } -static void get_system_timezone(void) +void get_system_timezone(void) { // avoid flood calls to stat(/etc/localtime) // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux @@ -630,7 +731,7 @@ static void get_system_timezone(void) // use the contents of /etc/timezone if (!timezone && !read_file("/etc/timezone", buffer, FILENAME_MAX)) { timezone = buffer; - info("TIMEZONE: using the contents of /etc/timezone: '%s'", timezone); + info("TIMEZONE: using the contents of /etc/timezone"); } // read the link /etc/localtime @@ -696,6 +797,46 @@ static void get_system_timezone(void) timezone = "unknown"; netdata_configured_timezone = config_get(CONFIG_SECTION_GLOBAL, "timezone", timezone); + + //get the utc offset, and the timezone as returned by strftime + //will be sent to the cloud + //Note: This will need an agent restart to get new offset on time change (dst, etc). + { + time_t t; + struct tm *tmp, tmbuf; + char zone[FILENAME_MAX + 1]; + char sign[2], hh[3], mm[3]; + + t = now_realtime_sec(); + tmp = localtime_r(&t, &tmbuf); + + if (tmp != NULL) { + if (strftime(zone, FILENAME_MAX, "%Z", tmp) == 0) { + netdata_configured_abbrev_timezone = strdupz("UTC"); + } else + netdata_configured_abbrev_timezone = strdupz(zone); + + if (strftime(zone, FILENAME_MAX, "%z", tmp) == 0) { + netdata_configured_utc_offset = 0; + } else { + sign[0] = zone[0] == '-' || zone[0] == '+' ? zone[0] : '0'; + sign[1] = '\0'; + hh[0] = isdigit(zone[1]) ? zone[1] : '0'; + hh[1] = isdigit(zone[2]) ? zone[2] : '0'; + hh[2] = '\0'; + mm[0] = isdigit(zone[3]) ? zone[3] : '0'; + mm[1] = isdigit(zone[4]) ? zone[4] : '0'; + mm[2] = '\0'; + + netdata_configured_utc_offset = (str2i(hh) * 3600) + (str2i(mm) * 60); + netdata_configured_utc_offset = + sign[0] == '-' ? -netdata_configured_utc_offset : netdata_configured_utc_offset; + } + } else { + netdata_configured_abbrev_timezone = strdupz("UTC"); + netdata_configured_utc_offset = 0; + } + } } void set_global_environment() @@ -753,6 +894,12 @@ void set_global_environment() analytics_set_data(&analytics_data.netdata_host_aclk_available, "null"); analytics_set_data(&analytics_data.netdata_host_agent_claimed, "null"); analytics_set_data(&analytics_data.netdata_host_cloud_enabled, "null"); + analytics_set_data(&analytics_data.netdata_config_https_available, "null"); + analytics_set_data(&analytics_data.netdata_install_type, "null"); + analytics_set_data(&analytics_data.netdata_config_is_private_registry, "null"); + analytics_set_data(&analytics_data.netdata_config_use_private_registry, "null"); + analytics_set_data(&analytics_data.netdata_config_oom_score, "null"); + analytics_set_data(&analytics_data.netdata_prebuilt_distro, "null"); analytics_data.prometheus_hits = 0; analytics_data.shell_hits = 0; @@ -770,8 +917,6 @@ void set_global_environment() if (clean) freez(default_port); - get_system_timezone(); - // set the path we need char path[1024 + 1], *p = getenv("PATH"); if (!p) @@ -834,7 +979,7 @@ void send_statistics(const char *action, const char *action_result, const char * sprintf( command_to_run, - "%s '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' ", + "%s '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s' ", as_script, action, action_result, @@ -870,16 +1015,27 @@ void send_statistics(const char *action, const char *action_result, const char * analytics_data.netdata_host_aclk_available, analytics_data.netdata_host_aclk_implementation, analytics_data.netdata_host_agent_claimed, - analytics_data.netdata_host_cloud_enabled); + analytics_data.netdata_host_cloud_enabled, + analytics_data.netdata_config_https_available, + analytics_data.netdata_install_type, + analytics_data.netdata_config_is_private_registry, + analytics_data.netdata_config_use_private_registry, + analytics_data.netdata_config_oom_score, + analytics_data.netdata_prebuilt_distro); info("%s '%s' '%s' '%s'", as_script, action, action_result, action_data); FILE *fp = mypopen(command_to_run, &command_pid); if (fp) { - char buffer[100 + 1]; - while (fgets(buffer, 100, fp) != NULL) - ; - mypclose(fp, command_pid); + char buffer[4 + 1]; + char *s = fgets(buffer, 4, fp); + int exit_code = mypclose(fp, command_pid); + if (exit_code) + error("Execution of anonymous statistics script returned %d.", exit_code); + if (s && strncmp(buffer, "200", 3)) + error("Execution of anonymous statistics script returned http code %s.", buffer); + } else { + error("Failed to run anonymous statistics script %s.", as_script); } freez(command_to_run); } |