12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include "common.h"
- #include "buildinfo.h"
- 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;
- struct collector {
- const char *plugin;
- const char *module;
- };
- struct array_printer {
- int c;
- BUFFER *both;
- };
- /*
- * Debug logging
- */
- void analytics_log_data(void)
- {
- debug(D_ANALYTICS, "NETDATA_CONFIG_STREAM_ENABLED : [%s]", analytics_data.netdata_config_stream_enabled);
- debug(D_ANALYTICS, "NETDATA_CONFIG_MEMORY_MODE : [%s]", analytics_data.netdata_config_memory_mode);
- debug(D_ANALYTICS, "NETDATA_CONFIG_EXPORTING_ENABLED : [%s]", analytics_data.netdata_config_exporting_enabled);
- debug(D_ANALYTICS, "NETDATA_EXPORTING_CONNECTORS : [%s]", analytics_data.netdata_exporting_connectors);
- debug(D_ANALYTICS, "NETDATA_ALLMETRICS_PROMETHEUS_USED : [%s]", analytics_data.netdata_allmetrics_prometheus_used);
- debug(D_ANALYTICS, "NETDATA_ALLMETRICS_SHELL_USED : [%s]", analytics_data.netdata_allmetrics_shell_used);
- debug(D_ANALYTICS, "NETDATA_ALLMETRICS_JSON_USED : [%s]", analytics_data.netdata_allmetrics_json_used);
- debug(D_ANALYTICS, "NETDATA_DASHBOARD_USED : [%s]", analytics_data.netdata_dashboard_used);
- debug(D_ANALYTICS, "NETDATA_COLLECTORS : [%s]", analytics_data.netdata_collectors);
- debug(D_ANALYTICS, "NETDATA_COLLECTORS_COUNT : [%s]", analytics_data.netdata_collectors_count);
- debug(D_ANALYTICS, "NETDATA_BUILDINFO : [%s]", analytics_data.netdata_buildinfo);
- debug(D_ANALYTICS, "NETDATA_CONFIG_PAGE_CACHE_SIZE : [%s]", analytics_data.netdata_config_page_cache_size);
- debug(D_ANALYTICS, "NETDATA_CONFIG_MULTIDB_DISK_QUOTA : [%s]", analytics_data.netdata_config_multidb_disk_quota);
- debug(D_ANALYTICS, "NETDATA_CONFIG_HTTPS_ENABLED : [%s]", analytics_data.netdata_config_https_enabled);
- debug(D_ANALYTICS, "NETDATA_CONFIG_WEB_ENABLED : [%s]", analytics_data.netdata_config_web_enabled);
- debug(D_ANALYTICS, "NETDATA_CONFIG_RELEASE_CHANNEL : [%s]", analytics_data.netdata_config_release_channel);
- debug(D_ANALYTICS, "NETDATA_MIRRORED_HOST_COUNT : [%s]", analytics_data.netdata_mirrored_host_count);
- debug(D_ANALYTICS, "NETDATA_MIRRORED_HOSTS_REACHABLE : [%s]", analytics_data.netdata_mirrored_hosts_reachable);
- debug(D_ANALYTICS, "NETDATA_MIRRORED_HOSTS_UNREACHABLE : [%s]", analytics_data.netdata_mirrored_hosts_unreachable);
- debug(D_ANALYTICS, "NETDATA_NOTIFICATION_METHODS : [%s]", analytics_data.netdata_notification_methods);
- debug(D_ANALYTICS, "NETDATA_ALARMS_NORMAL : [%s]", analytics_data.netdata_alarms_normal);
- debug(D_ANALYTICS, "NETDATA_ALARMS_WARNING : [%s]", analytics_data.netdata_alarms_warning);
- debug(D_ANALYTICS, "NETDATA_ALARMS_CRITICAL : [%s]", analytics_data.netdata_alarms_critical);
- debug(D_ANALYTICS, "NETDATA_CHARTS_COUNT : [%s]", analytics_data.netdata_charts_count);
- debug(D_ANALYTICS, "NETDATA_METRICS_COUNT : [%s]", analytics_data.netdata_metrics_count);
- debug(D_ANALYTICS, "NETDATA_CONFIG_IS_PARENT : [%s]", analytics_data.netdata_config_is_parent);
- debug(D_ANALYTICS, "NETDATA_CONFIG_HOSTS_AVAILABLE : [%s]", analytics_data.netdata_config_hosts_available);
- debug(D_ANALYTICS, "NETDATA_HOST_CLOUD_AVAILABLE : [%s]", analytics_data.netdata_host_cloud_available);
- debug(D_ANALYTICS, "NETDATA_HOST_ACLK_AVAILABLE : [%s]", analytics_data.netdata_host_aclk_available);
- debug(D_ANALYTICS, "NETDATA_HOST_ACLK_PROTOCOL : [%s]", analytics_data.netdata_host_aclk_protocol);
- 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);
- }
- /*
- * Free data
- */
- void analytics_free_data(void)
- {
- freez(analytics_data.netdata_config_stream_enabled);
- freez(analytics_data.netdata_config_memory_mode);
- freez(analytics_data.netdata_config_exporting_enabled);
- freez(analytics_data.netdata_exporting_connectors);
- freez(analytics_data.netdata_allmetrics_prometheus_used);
- freez(analytics_data.netdata_allmetrics_shell_used);
- freez(analytics_data.netdata_allmetrics_json_used);
- freez(analytics_data.netdata_dashboard_used);
- freez(analytics_data.netdata_collectors);
- freez(analytics_data.netdata_collectors_count);
- freez(analytics_data.netdata_buildinfo);
- freez(analytics_data.netdata_config_page_cache_size);
- freez(analytics_data.netdata_config_multidb_disk_quota);
- freez(analytics_data.netdata_config_https_enabled);
- freez(analytics_data.netdata_config_web_enabled);
- freez(analytics_data.netdata_config_release_channel);
- freez(analytics_data.netdata_mirrored_host_count);
- freez(analytics_data.netdata_mirrored_hosts_reachable);
- freez(analytics_data.netdata_mirrored_hosts_unreachable);
- freez(analytics_data.netdata_notification_methods);
- freez(analytics_data.netdata_alarms_normal);
- freez(analytics_data.netdata_alarms_warning);
- freez(analytics_data.netdata_alarms_critical);
- freez(analytics_data.netdata_charts_count);
- freez(analytics_data.netdata_metrics_count);
- freez(analytics_data.netdata_config_is_parent);
- freez(analytics_data.netdata_config_hosts_available);
- freez(analytics_data.netdata_host_cloud_available);
- freez(analytics_data.netdata_host_aclk_available);
- freez(analytics_data.netdata_host_aclk_protocol);
- 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);
- }
- /*
- * Set a numeric/boolean data with a value
- */
- void analytics_set_data(char **name, char *value)
- {
- if (*name) {
- analytics_data.data_length -= strlen(*name);
- freez(*name);
- }
- *name = strdupz(value);
- analytics_data.data_length += strlen(*name);
- }
- /*
- * Set a string data with a value
- */
- void analytics_set_data_str(char **name, char *value)
- {
- size_t value_string_len;
- if (*name) {
- analytics_data.data_length -= strlen(*name);
- freez(*name);
- }
- value_string_len = strlen(value) + 4;
- *name = mallocz(sizeof(char) * value_string_len);
- snprintfz(*name, value_string_len - 1, "\"%s\"", value);
- analytics_data.data_length += strlen(*name);
- }
- /*
- * Log hits on the allmetrics page, with prometheus parameter
- */
- void analytics_log_prometheus(void)
- {
- if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.prometheus_hits < ANALYTICS_MAX_PROMETHEUS_HITS)) {
- analytics_data.prometheus_hits++;
- char b[21];
- snprintfz(b, 20, "%zu", analytics_data.prometheus_hits);
- analytics_set_data(&analytics_data.netdata_allmetrics_prometheus_used, b);
- }
- }
- /*
- * Log hits on the allmetrics page, with shell parameter (or default)
- */
- void analytics_log_shell(void)
- {
- if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.shell_hits < ANALYTICS_MAX_SHELL_HITS)) {
- analytics_data.shell_hits++;
- char b[21];
- snprintfz(b, 20, "%zu", analytics_data.shell_hits);
- analytics_set_data(&analytics_data.netdata_allmetrics_shell_used, b);
- }
- }
- /*
- * Log hits on the allmetrics page, with json parameter
- */
- void analytics_log_json(void)
- {
- if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.json_hits < ANALYTICS_MAX_JSON_HITS)) {
- analytics_data.json_hits++;
- char b[21];
- snprintfz(b, 20, "%zu", analytics_data.json_hits);
- analytics_set_data(&analytics_data.netdata_allmetrics_json_used, b);
- }
- }
- /*
- * Log hits on the dashboard, (when calling HELLO).
- */
- void analytics_log_dashboard(void)
- {
- if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.dashboard_hits < ANALYTICS_MAX_DASHBOARD_HITS)) {
- analytics_data.dashboard_hits++;
- char b[21];
- snprintfz(b, 20, "%zu", analytics_data.dashboard_hits);
- analytics_set_data(&analytics_data.netdata_dashboard_used, b);
- }
- }
- /*
- * Called when setting the oom score
- */
- void analytics_report_oom_score(long long int score){
- char b[21];
- snprintfz(b, 20, "%lld", score);
- analytics_set_data(&analytics_data.netdata_config_oom_score, b);
- }
- void analytics_mirrored_hosts(void)
- {
- RRDHOST *host;
- size_t count = 0;
- size_t reachable = 0;
- size_t unreachable = 0;
- char b[21];
- rrd_rdlock();
- rrdhost_foreach_read(host)
- {
- if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED))
- continue;
- ((host == localhost || !rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN)) ? reachable++ : unreachable++);
- count++;
- }
- rrd_unlock();
- snprintfz(b, 20, "%zu", count);
- analytics_set_data(&analytics_data.netdata_mirrored_host_count, b);
- snprintfz(b, 20, "%zu", reachable);
- analytics_set_data(&analytics_data.netdata_mirrored_hosts_reachable, b);
- snprintfz(b, 20, "%zu", unreachable);
- analytics_set_data(&analytics_data.netdata_mirrored_hosts_unreachable, b);
- }
- void analytics_exporters(void)
- {
- //when no exporters are available, an empty string will be sent
- //decide if something else is more suitable (but probably not null)
- BUFFER *bi = buffer_create(1000, NULL);
- analytics_exporting_connectors(bi);
- analytics_set_data_str(&analytics_data.netdata_exporting_connectors, (char *)buffer_tostring(bi));
- buffer_free(bi);
- }
- int collector_counter_callb(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data) {
- struct array_printer *ap = (struct array_printer *)data;
- struct collector *col = (struct collector *)entry;
- BUFFER *bt = ap->both;
- if (likely(ap->c)) {
- buffer_strcat(bt, ",");
- }
- buffer_strcat(bt, "{");
- buffer_strcat(bt, " \"plugin\": \"");
- buffer_strcat(bt, col->plugin);
- buffer_strcat(bt, "\", \"module\":\"");
- buffer_strcat(bt, col->module);
- buffer_strcat(bt, "\" }");
- (ap->c)++;
- return 0;
- }
- /*
- * Create a JSON array of available collectors, same as in api/v1/info
- */
- void analytics_collectors(void)
- {
- RRDSET *st;
- DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED);
- char name[500];
- BUFFER *bt = buffer_create(1000, NULL);
- rrdset_foreach_read(st, localhost) {
- if(!rrdset_is_available_for_viewers(st))
- continue;
- struct collector col = {
- .plugin = rrdset_plugin_name(st),
- .module = rrdset_module_name(st)
- };
- snprintfz(name, 499, "%s:%s", col.plugin, col.module);
- dictionary_set(dict, name, &col, sizeof(struct collector));
- }
- rrdset_foreach_done(st);
- struct array_printer ap;
- ap.c = 0;
- ap.both = bt;
- dictionary_walkthrough_read(dict, collector_counter_callb, &ap);
- dictionary_destroy(dict);
- analytics_set_data(&analytics_data.netdata_collectors, (char *)buffer_tostring(ap.both));
- {
- char b[21];
- snprintfz(b, 20, "%d", ap.c);
- analytics_set_data(&analytics_data.netdata_collectors_count, b);
- }
- buffer_free(bt);
- }
- /*
- * Run alarm-notify.sh script using the dump_methods parameter
- * SEND_CUSTOM is always available
- */
- void analytics_alarms_notifications(void)
- {
- char *script;
- script = mallocz(
- sizeof(char) * (strlen(netdata_configured_primary_plugins_dir) + strlen("alarm-notify.sh dump_methods") + 2));
- sprintf(script, "%s/%s", netdata_configured_primary_plugins_dir, "alarm-notify.sh");
- if (unlikely(access(script, R_OK) != 0)) {
- info("Alarm notify script %s not found.", script);
- freez(script);
- return;
- }
- strcat(script, " dump_methods");
- pid_t command_pid;
- debug(D_ANALYTICS, "Executing %s", script);
- BUFFER *b = buffer_create(1000, NULL);
- int cnt = 0;
- FILE *fp_child_input;
- FILE *fp_child_output = netdata_popen(script, &command_pid, &fp_child_input);
- if (fp_child_output) {
- char line[200 + 1];
- while (fgets(line, 200, fp_child_output) != NULL) {
- char *end = line;
- while (*end && *end != '\n')
- end++;
- *end = '\0';
- if (likely(cnt))
- buffer_strcat(b, "|");
- buffer_strcat(b, line);
- cnt++;
- }
- netdata_pclose(fp_child_input, fp_child_output, command_pid);
- }
- freez(script);
- analytics_set_data_str(&analytics_data.netdata_notification_methods, (char *)buffer_tostring(b));
- buffer_free(b);
- }
- static void analytics_get_install_type(struct rrdhost_system_info *system_info)
- {
- if (system_info->install_type == NULL) {
- analytics_set_data_str(&analytics_data.netdata_install_type, "unknown");
- } else {
- analytics_set_data_str(&analytics_data.netdata_install_type, system_info->install_type);
- }
- if (system_info->prebuilt_dist != NULL) {
- analytics_set_data_str(&analytics_data.netdata_prebuilt_distro, system_info->prebuilt_dist);
- }
- }
- /*
- * Pick up if https is actually used
- */
- void analytics_https(void)
- {
- BUFFER *b = buffer_create(30, NULL);
- #ifdef ENABLE_HTTPS
- analytics_exporting_connectors_ssl(b);
- buffer_strcat(b, netdata_ssl_streaming_sender_ctx &&
- rrdhost_flag_check(localhost, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED) &&
- SSL_connection(&localhost->sender->ssl) ? "streaming|" : "|");
- buffer_strcat(b, netdata_ssl_web_server_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;
- size_t c = 0;
- rrdset_foreach_read(st, localhost)
- if(rrdset_is_available_for_viewers(st)) c++;
- rrdset_foreach_done(st);
- analytics_data.charts_count = c;
- {
- char b[21];
- snprintfz(b, 20, "%zu", c);
- analytics_set_data(&analytics_data.netdata_charts_count, b);
- }
- }
- void analytics_metrics(void)
- {
- RRDSET *st;
- size_t dimensions = 0;
- rrdset_foreach_read(st, localhost) {
- if (rrdset_is_available_for_viewers(st)) {
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if (rrddim_option_check(rd, RRDDIM_OPTION_HIDDEN) || rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE))
- continue;
- dimensions++;
- }
- rrddim_foreach_done(rd);
- }
- }
- rrdset_foreach_done(st);
- analytics_data.metrics_count = dimensions;
- {
- char b[21];
- snprintfz(b, 20, "%zu", dimensions);
- analytics_set_data(&analytics_data.netdata_metrics_count, b);
- }
- }
- void analytics_alarms(void)
- {
- size_t alarm_warn = 0, alarm_crit = 0, alarm_normal = 0;
- char b[21];
- RRDCALC *rc;
- foreach_rrdcalc_in_rrdhost_read(localhost, rc) {
- if (unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec))
- continue;
- switch (rc->status) {
- case RRDCALC_STATUS_WARNING:
- alarm_warn++;
- break;
- case RRDCALC_STATUS_CRITICAL:
- alarm_crit++;
- break;
- default:
- alarm_normal++;
- }
- }
- foreach_rrdcalc_in_rrdhost_done(rc);
- snprintfz(b, 20, "%zu", alarm_normal);
- analytics_set_data(&analytics_data.netdata_alarms_normal, b);
- snprintfz(b, 20, "%zu", alarm_warn);
- analytics_set_data(&analytics_data.netdata_alarms_warning, b);
- snprintfz(b, 20, "%zu", alarm_crit);
- analytics_set_data(&analytics_data.netdata_alarms_critical, b);
- }
- /*
- * Misc attributes to get (run from start)
- */
- void analytics_misc(void)
- {
- #ifdef ENABLE_ACLK
- analytics_set_data(&analytics_data.netdata_host_cloud_available, "true");
- analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "Next Generation");
- #else
- analytics_set_data(&analytics_data.netdata_host_cloud_available, "false");
- analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "");
- #endif
- analytics_data.exporting_enabled = appconfig_get_boolean(&exporting_config, CONFIG_SECTION_EXPORTING, "enabled", CONFIG_BOOLEAN_NO);
- analytics_set_data(&analytics_data.netdata_config_exporting_enabled, analytics_data.exporting_enabled ? "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");
- }
- void analytics_aclk(void)
- {
- #ifdef ENABLE_ACLK
- if (aclk_connected) {
- analytics_set_data(&analytics_data.netdata_host_aclk_available, "true");
- analytics_set_data_str(&analytics_data.netdata_host_aclk_protocol, "New");
- }
- else
- #endif
- analytics_set_data(&analytics_data.netdata_host_aclk_available, "false");
- }
- /*
- * Get the meta data, called from the thread once after the original delay
- * 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();
- }
- /*
- * Get the meta data, called from the thread on every heartbeat, and right before the EXIT event
- * These are values that can change between agent restarts, and therefore
- * try to read them on each META event send
- */
- void analytics_gather_mutable_meta_data(void)
- {
- analytics_collectors();
- analytics_alarms();
- analytics_charts();
- analytics_metrics();
- analytics_aclk();
- analytics_mirrored_hosts();
- analytics_alarms_notifications();
- analytics_set_data(
- &analytics_data.netdata_config_is_parent, (rrdhost_hosts_available() > 1 || configured_as_parent()) ? "true" : "false");
- char *claim_id = get_agent_claimid();
- analytics_set_data(&analytics_data.netdata_host_agent_claimed, claim_id ? "true" : "false");
- freez(claim_id);
- {
- char b[21];
- snprintfz(b, 20, "%zu", analytics_data.prometheus_hits);
- analytics_set_data(&analytics_data.netdata_allmetrics_prometheus_used, b);
- snprintfz(b, 20, "%zu", analytics_data.shell_hits);
- analytics_set_data(&analytics_data.netdata_allmetrics_shell_used, b);
- snprintfz(b, 20, "%zu", analytics_data.json_hits);
- analytics_set_data(&analytics_data.netdata_allmetrics_json_used, b);
- snprintfz(b, 20, "%zu", analytics_data.dashboard_hits);
- analytics_set_data(&analytics_data.netdata_dashboard_used, b);
- snprintfz(b, 20, "%zu", rrdhost_hosts_available());
- analytics_set_data(&analytics_data.netdata_config_hosts_available, b);
- }
- }
- void analytics_main_cleanup(void *ptr)
- {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
- debug(D_ANALYTICS, "Cleaning up...");
- analytics_free_data();
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
- }
- /*
- * The analytics thread. Sleep for ANALYTICS_INIT_SLEEP_SEC,
- * gather the data, and then go to a loop where every ANALYTICS_HEARTBEAT
- * it will send a new META event after gathering data that could be changed
- * while the agent is running
- */
- void *analytics_main(void *ptr)
- {
- netdata_thread_cleanup_push(analytics_main_cleanup, ptr);
- unsigned int sec = 0;
- heartbeat_t hb;
- heartbeat_init(&hb);
- usec_t step_ut = USEC_PER_SEC;
- debug(D_ANALYTICS, "Analytics thread starts");
- //first delay after agent start
- while (service_running(SERVICE_ANALYTICS) && likely(sec <= ANALYTICS_INIT_SLEEP_SEC)) {
- heartbeat_next(&hb, step_ut);
- sec++;
- }
- if (unlikely(!service_running(SERVICE_ANALYTICS)))
- goto cleanup;
- analytics_gather_immutable_meta_data();
- analytics_gather_mutable_meta_data();
- send_statistics("META_START", "-", "-");
- analytics_log_data();
- sec = 0;
- while (1) {
- heartbeat_next(&hb, step_ut * 2);
- sec += 2;
- if (unlikely(!service_running(SERVICE_ANALYTICS)))
- break;
- if (likely(sec < ANALYTICS_HEARTBEAT))
- continue;
- analytics_gather_mutable_meta_data();
- send_statistics("META", "-", "-");
- analytics_log_data();
- sec = 0;
- }
- cleanup:
- netdata_thread_cleanup_pop(1);
- return NULL;
- }
- static const char *verify_required_directory(const char *dir)
- {
- if (chdir(dir) == -1)
- fatal("Cannot change directory to '%s'", dir);
- DIR *d = opendir(dir);
- if (!d)
- fatal("Cannot examine the contents of directory '%s'", dir);
- closedir(d);
- return dir;
- }
- /*
- * This is called after the rrdinit
- * These values will be sent on the START event
- */
- void set_late_global_environment(struct rrdhost_system_info *system_info)
- {
- 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));
- #ifdef DISABLE_CLOUD
- analytics_set_data(&analytics_data.netdata_host_cloud_enabled, "false");
- #else
- analytics_set_data(
- &analytics_data.netdata_host_cloud_enabled,
- appconfig_get_boolean(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", CONFIG_BOOLEAN_YES) ? "true" : "false");
- #endif
- #ifdef ENABLE_DBENGINE
- {
- char b[16];
- snprintfz(b, 15, "%d", default_rrdeng_page_cache_mb);
- analytics_set_data(&analytics_data.netdata_config_page_cache_size, b);
- snprintfz(b, 15, "%d", default_multidb_disk_quota_mb);
- analytics_set_data(&analytics_data.netdata_config_multidb_disk_quota, b);
- }
- #endif
- #ifdef ENABLE_HTTPS
- analytics_set_data(&analytics_data.netdata_config_https_enabled, "true");
- #else
- analytics_set_data(&analytics_data.netdata_config_https_enabled, "false");
- #endif
- if (web_server_mode == WEB_SERVER_MODE_NONE)
- analytics_set_data(&analytics_data.netdata_config_web_enabled, "false");
- else
- analytics_set_data(&analytics_data.netdata_config_web_enabled, "true");
- analytics_set_data_str(&analytics_data.netdata_config_release_channel, (char *)get_release_channel());
- {
- BUFFER *bi = buffer_create(1000, NULL);
- analytics_build_info(bi);
- analytics_set_data_str(&analytics_data.netdata_buildinfo, (char *)buffer_tostring(bi));
- buffer_free(bi);
- }
- analytics_get_install_type(system_info);
- }
- 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
- const char *tz = getenv("TZ");
- if (!tz || !*tz)
- setenv("TZ", config_get(CONFIG_SECTION_ENV_VARS, "TZ", ":/etc/localtime"), 0);
- char buffer[FILENAME_MAX + 1] = "";
- const char *timezone = NULL;
- ssize_t ret;
- // use the TZ variable
- if (tz && *tz && *tz != ':') {
- timezone = tz;
- info("TIMEZONE: using TZ variable '%s'", timezone);
- }
- // 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");
- }
- // read the link /etc/localtime
- if (!timezone) {
- ret = readlink("/etc/localtime", buffer, FILENAME_MAX);
- if (ret > 0) {
- buffer[ret] = '\0';
- char *cmp = "/usr/share/zoneinfo/";
- size_t cmp_len = strlen(cmp);
- char *s = strstr(buffer, cmp);
- if (s && s[cmp_len]) {
- timezone = &s[cmp_len];
- info("TIMEZONE: using the link of /etc/localtime: '%s'", timezone);
- }
- } else
- buffer[0] = '\0';
- }
- // find the timezone from strftime()
- if (!timezone) {
- time_t t;
- struct tm *tmp, tmbuf;
- t = now_realtime_sec();
- tmp = localtime_r(&t, &tmbuf);
- if (tmp != NULL) {
- if (strftime(buffer, FILENAME_MAX, "%Z", tmp) == 0)
- buffer[0] = '\0';
- else {
- buffer[FILENAME_MAX] = '\0';
- timezone = buffer;
- info("TIMEZONE: using strftime(): '%s'", timezone);
- }
- }
- }
- if (timezone && *timezone) {
- // make sure it does not have illegal characters
- // info("TIMEZONE: fixing '%s'", timezone);
- size_t len = strlen(timezone);
- char tmp[len + 1];
- char *d = tmp;
- *d = '\0';
- while (*timezone) {
- if (isalnum(*timezone) || *timezone == '_' || *timezone == '/')
- *d++ = *timezone++;
- else
- timezone++;
- }
- *d = '\0';
- strncpyz(buffer, tmp, len);
- timezone = buffer;
- info("TIMEZONE: fixed as '%s'", timezone);
- }
- if (!timezone || !*timezone)
- 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()
- {
- {
- char b[16];
- snprintfz(b, 15, "%d", default_rrd_update_every);
- setenv("NETDATA_UPDATE_EVERY", b, 1);
- }
- setenv("NETDATA_VERSION", program_version, 1);
- setenv("NETDATA_HOSTNAME", netdata_configured_hostname, 1);
- setenv("NETDATA_CONFIG_DIR", verify_required_directory(netdata_configured_user_config_dir), 1);
- setenv("NETDATA_USER_CONFIG_DIR", verify_required_directory(netdata_configured_user_config_dir), 1);
- setenv("NETDATA_STOCK_CONFIG_DIR", verify_required_directory(netdata_configured_stock_config_dir), 1);
- setenv("NETDATA_PLUGINS_DIR", verify_required_directory(netdata_configured_primary_plugins_dir), 1);
- setenv("NETDATA_WEB_DIR", verify_required_directory(netdata_configured_web_dir), 1);
- setenv("NETDATA_CACHE_DIR", verify_required_directory(netdata_configured_cache_dir), 1);
- setenv("NETDATA_LIB_DIR", verify_required_directory(netdata_configured_varlib_dir), 1);
- setenv("NETDATA_LOCK_DIR", netdata_configured_lock_dir, 1);
- setenv("NETDATA_LOG_DIR", verify_required_directory(netdata_configured_log_dir), 1);
- setenv("HOME", verify_required_directory(netdata_configured_home_dir), 1);
- setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1);
- {
- BUFFER *user_plugins_dirs = buffer_create(FILENAME_MAX, NULL);
- for (size_t i = 1; i < PLUGINSD_MAX_DIRECTORIES && plugin_directories[i]; i++) {
- if (i > 1)
- buffer_strcat(user_plugins_dirs, " ");
- buffer_strcat(user_plugins_dirs, plugin_directories[i]);
- }
- setenv("NETDATA_USER_PLUGINS_DIRS", buffer_tostring(user_plugins_dirs), 1);
- buffer_free(user_plugins_dirs);
- }
- analytics_data.data_length = 0;
- analytics_set_data(&analytics_data.netdata_config_stream_enabled, "null");
- analytics_set_data(&analytics_data.netdata_config_memory_mode, "null");
- analytics_set_data(&analytics_data.netdata_config_exporting_enabled, "null");
- analytics_set_data(&analytics_data.netdata_exporting_connectors, "null");
- analytics_set_data(&analytics_data.netdata_allmetrics_prometheus_used, "null");
- analytics_set_data(&analytics_data.netdata_allmetrics_shell_used, "null");
- analytics_set_data(&analytics_data.netdata_allmetrics_json_used, "null");
- analytics_set_data(&analytics_data.netdata_dashboard_used, "null");
- analytics_set_data(&analytics_data.netdata_collectors, "null");
- analytics_set_data(&analytics_data.netdata_collectors_count, "null");
- analytics_set_data(&analytics_data.netdata_buildinfo, "null");
- analytics_set_data(&analytics_data.netdata_config_page_cache_size, "null");
- analytics_set_data(&analytics_data.netdata_config_multidb_disk_quota, "null");
- analytics_set_data(&analytics_data.netdata_config_https_enabled, "null");
- analytics_set_data(&analytics_data.netdata_config_web_enabled, "null");
- analytics_set_data(&analytics_data.netdata_config_release_channel, "null");
- analytics_set_data(&analytics_data.netdata_mirrored_host_count, "null");
- analytics_set_data(&analytics_data.netdata_mirrored_hosts_reachable, "null");
- analytics_set_data(&analytics_data.netdata_mirrored_hosts_unreachable, "null");
- analytics_set_data(&analytics_data.netdata_notification_methods, "null");
- analytics_set_data(&analytics_data.netdata_alarms_normal, "null");
- analytics_set_data(&analytics_data.netdata_alarms_warning, "null");
- analytics_set_data(&analytics_data.netdata_alarms_critical, "null");
- analytics_set_data(&analytics_data.netdata_charts_count, "null");
- analytics_set_data(&analytics_data.netdata_metrics_count, "null");
- analytics_set_data(&analytics_data.netdata_config_is_parent, "null");
- analytics_set_data(&analytics_data.netdata_config_hosts_available, "null");
- analytics_set_data(&analytics_data.netdata_host_cloud_available, "null");
- analytics_set_data(&analytics_data.netdata_host_aclk_implementation, "null");
- analytics_set_data(&analytics_data.netdata_host_aclk_available, "null");
- analytics_set_data(&analytics_data.netdata_host_aclk_protocol, "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;
- analytics_data.json_hits = 0;
- analytics_data.dashboard_hits = 0;
- analytics_data.charts_count = 0;
- analytics_data.metrics_count = 0;
- analytics_data.exporting_enabled = false;
- char *default_port = appconfig_get(&netdata_config, CONFIG_SECTION_WEB, "default port", NULL);
- int clean = 0;
- if (!default_port) {
- default_port = strdupz("19999");
- clean = 1;
- }
- setenv("NETDATA_LISTEN_PORT", default_port, 1);
- if (clean)
- freez(default_port);
- // set the path we need
- char path[1024 + 1], *p = getenv("PATH");
- if (!p)
- p = "/bin:/usr/bin";
- snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin");
- setenv("PATH", config_get(CONFIG_SECTION_ENV_VARS, "PATH", path), 1);
- // python options
- p = getenv("PYTHONPATH");
- if (!p)
- p = "";
- setenv("PYTHONPATH", config_get(CONFIG_SECTION_ENV_VARS, "PYTHONPATH", p), 1);
- // disable buffering for python plugins
- setenv("PYTHONUNBUFFERED", "1", 1);
- // switch to standard locale for plugins
- setenv("LC_ALL", "C", 1);
- }
- void send_statistics(const char *action, const char *action_result, const char *action_data)
- {
- static char *as_script;
- if (netdata_anonymous_statistics_enabled == -1) {
- char *optout_file = mallocz(
- sizeof(char) *
- (strlen(netdata_configured_user_config_dir) + strlen(".opt-out-from-anonymous-statistics") + 2));
- sprintf(optout_file, "%s/%s", netdata_configured_user_config_dir, ".opt-out-from-anonymous-statistics");
- if (likely(access(optout_file, R_OK) != 0)) {
- as_script = mallocz(
- sizeof(char) *
- (strlen(netdata_configured_primary_plugins_dir) + strlen("anonymous-statistics.sh") + 2));
- sprintf(as_script, "%s/%s", netdata_configured_primary_plugins_dir, "anonymous-statistics.sh");
- if (unlikely(access(as_script, R_OK) != 0)) {
- netdata_anonymous_statistics_enabled = 0;
- info("Anonymous statistics script %s not found.", as_script);
- freez(as_script);
- } else {
- netdata_anonymous_statistics_enabled = 1;
- }
- } else {
- netdata_anonymous_statistics_enabled = 0;
- as_script = NULL;
- }
- freez(optout_file);
- }
- if (!netdata_anonymous_statistics_enabled)
- return;
- if (!action)
- return;
- if (!action_result)
- action_result = "";
- if (!action_data)
- action_data = "";
- char *command_to_run = mallocz(
- sizeof(char) * (strlen(action) + strlen(action_result) + strlen(action_data) + strlen(as_script) +
- analytics_data.data_length + (ANALYTICS_NO_OF_ITEMS * 3) + 15));
- pid_t command_pid;
- 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' ",
- as_script,
- action,
- action_result,
- action_data,
- analytics_data.netdata_config_stream_enabled,
- analytics_data.netdata_config_memory_mode,
- analytics_data.netdata_config_exporting_enabled,
- analytics_data.netdata_exporting_connectors,
- analytics_data.netdata_allmetrics_prometheus_used,
- analytics_data.netdata_allmetrics_shell_used,
- analytics_data.netdata_allmetrics_json_used,
- analytics_data.netdata_dashboard_used,
- analytics_data.netdata_collectors,
- analytics_data.netdata_collectors_count,
- analytics_data.netdata_buildinfo,
- analytics_data.netdata_config_page_cache_size,
- analytics_data.netdata_config_multidb_disk_quota,
- analytics_data.netdata_config_https_enabled,
- analytics_data.netdata_config_web_enabled,
- analytics_data.netdata_config_release_channel,
- analytics_data.netdata_mirrored_host_count,
- analytics_data.netdata_mirrored_hosts_reachable,
- analytics_data.netdata_mirrored_hosts_unreachable,
- analytics_data.netdata_notification_methods,
- analytics_data.netdata_alarms_normal,
- analytics_data.netdata_alarms_warning,
- analytics_data.netdata_alarms_critical,
- analytics_data.netdata_charts_count,
- analytics_data.netdata_metrics_count,
- analytics_data.netdata_config_is_parent,
- analytics_data.netdata_config_hosts_available,
- analytics_data.netdata_host_cloud_available,
- analytics_data.netdata_host_aclk_available,
- analytics_data.netdata_host_aclk_protocol,
- analytics_data.netdata_host_aclk_implementation,
- analytics_data.netdata_host_agent_claimed,
- 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_child_input;
- FILE *fp_child_output = netdata_popen(command_to_run, &command_pid, &fp_child_input);
- if (fp_child_output) {
- char buffer[4 + 1];
- char *s = fgets(buffer, 4, fp_child_output);
- int exit_code = netdata_pclose(fp_child_input, fp_child_output, 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);
- }
|