analytics.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "common.h"
  3. #include "buildinfo.h"
  4. struct analytics_data analytics_data;
  5. extern void analytics_exporting_connectors (BUFFER *b);
  6. extern void analytics_exporting_connectors_ssl (BUFFER *b);
  7. extern void analytics_build_info (BUFFER *b);
  8. extern int aclk_connected;
  9. struct collector {
  10. const char *plugin;
  11. const char *module;
  12. };
  13. struct array_printer {
  14. int c;
  15. BUFFER *both;
  16. };
  17. /*
  18. * Debug logging
  19. */
  20. void analytics_log_data(void)
  21. {
  22. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_STREAM_ENABLED : [%s]", analytics_data.netdata_config_stream_enabled);
  23. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_MEMORY_MODE : [%s]", analytics_data.netdata_config_memory_mode);
  24. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_EXPORTING_ENABLED : [%s]", analytics_data.netdata_config_exporting_enabled);
  25. netdata_log_debug(D_ANALYTICS, "NETDATA_EXPORTING_CONNECTORS : [%s]", analytics_data.netdata_exporting_connectors);
  26. netdata_log_debug(D_ANALYTICS, "NETDATA_ALLMETRICS_PROMETHEUS_USED : [%s]", analytics_data.netdata_allmetrics_prometheus_used);
  27. netdata_log_debug(D_ANALYTICS, "NETDATA_ALLMETRICS_SHELL_USED : [%s]", analytics_data.netdata_allmetrics_shell_used);
  28. netdata_log_debug(D_ANALYTICS, "NETDATA_ALLMETRICS_JSON_USED : [%s]", analytics_data.netdata_allmetrics_json_used);
  29. netdata_log_debug(D_ANALYTICS, "NETDATA_DASHBOARD_USED : [%s]", analytics_data.netdata_dashboard_used);
  30. netdata_log_debug(D_ANALYTICS, "NETDATA_COLLECTORS : [%s]", analytics_data.netdata_collectors);
  31. netdata_log_debug(D_ANALYTICS, "NETDATA_COLLECTORS_COUNT : [%s]", analytics_data.netdata_collectors_count);
  32. netdata_log_debug(D_ANALYTICS, "NETDATA_BUILDINFO : [%s]", analytics_data.netdata_buildinfo);
  33. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_PAGE_CACHE_SIZE : [%s]", analytics_data.netdata_config_page_cache_size);
  34. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_MULTIDB_DISK_QUOTA : [%s]", analytics_data.netdata_config_multidb_disk_quota);
  35. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_HTTPS_ENABLED : [%s]", analytics_data.netdata_config_https_enabled);
  36. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_WEB_ENABLED : [%s]", analytics_data.netdata_config_web_enabled);
  37. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_RELEASE_CHANNEL : [%s]", analytics_data.netdata_config_release_channel);
  38. netdata_log_debug(D_ANALYTICS, "NETDATA_MIRRORED_HOST_COUNT : [%s]", analytics_data.netdata_mirrored_host_count);
  39. netdata_log_debug(D_ANALYTICS, "NETDATA_MIRRORED_HOSTS_REACHABLE : [%s]", analytics_data.netdata_mirrored_hosts_reachable);
  40. netdata_log_debug(D_ANALYTICS, "NETDATA_MIRRORED_HOSTS_UNREACHABLE : [%s]", analytics_data.netdata_mirrored_hosts_unreachable);
  41. netdata_log_debug(D_ANALYTICS, "NETDATA_NOTIFICATION_METHODS : [%s]", analytics_data.netdata_notification_methods);
  42. netdata_log_debug(D_ANALYTICS, "NETDATA_ALARMS_NORMAL : [%s]", analytics_data.netdata_alarms_normal);
  43. netdata_log_debug(D_ANALYTICS, "NETDATA_ALARMS_WARNING : [%s]", analytics_data.netdata_alarms_warning);
  44. netdata_log_debug(D_ANALYTICS, "NETDATA_ALARMS_CRITICAL : [%s]", analytics_data.netdata_alarms_critical);
  45. netdata_log_debug(D_ANALYTICS, "NETDATA_CHARTS_COUNT : [%s]", analytics_data.netdata_charts_count);
  46. netdata_log_debug(D_ANALYTICS, "NETDATA_METRICS_COUNT : [%s]", analytics_data.netdata_metrics_count);
  47. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_IS_PARENT : [%s]", analytics_data.netdata_config_is_parent);
  48. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_HOSTS_AVAILABLE : [%s]", analytics_data.netdata_config_hosts_available);
  49. netdata_log_debug(D_ANALYTICS, "NETDATA_HOST_CLOUD_AVAILABLE : [%s]", analytics_data.netdata_host_cloud_available);
  50. netdata_log_debug(D_ANALYTICS, "NETDATA_HOST_ACLK_AVAILABLE : [%s]", analytics_data.netdata_host_aclk_available);
  51. netdata_log_debug(D_ANALYTICS, "NETDATA_HOST_ACLK_PROTOCOL : [%s]", analytics_data.netdata_host_aclk_protocol);
  52. netdata_log_debug(D_ANALYTICS, "NETDATA_HOST_ACLK_IMPLEMENTATION : [%s]", analytics_data.netdata_host_aclk_implementation);
  53. netdata_log_debug(D_ANALYTICS, "NETDATA_HOST_AGENT_CLAIMED : [%s]", analytics_data.netdata_host_agent_claimed);
  54. netdata_log_debug(D_ANALYTICS, "NETDATA_HOST_CLOUD_ENABLED : [%s]", analytics_data.netdata_host_cloud_enabled);
  55. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_HTTPS_AVAILABLE : [%s]", analytics_data.netdata_config_https_available);
  56. netdata_log_debug(D_ANALYTICS, "NETDATA_INSTALL_TYPE : [%s]", analytics_data.netdata_install_type);
  57. netdata_log_debug(D_ANALYTICS, "NETDATA_PREBUILT_DISTRO : [%s]", analytics_data.netdata_prebuilt_distro);
  58. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_IS_PRIVATE_REGISTRY : [%s]", analytics_data.netdata_config_is_private_registry);
  59. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_USE_PRIVATE_REGISTRY: [%s]", analytics_data.netdata_config_use_private_registry);
  60. netdata_log_debug(D_ANALYTICS, "NETDATA_CONFIG_OOM_SCORE : [%s]", analytics_data.netdata_config_oom_score);
  61. }
  62. /*
  63. * Free data
  64. */
  65. void analytics_free_data(void)
  66. {
  67. freez(analytics_data.netdata_config_stream_enabled);
  68. freez(analytics_data.netdata_config_memory_mode);
  69. freez(analytics_data.netdata_config_exporting_enabled);
  70. freez(analytics_data.netdata_exporting_connectors);
  71. freez(analytics_data.netdata_allmetrics_prometheus_used);
  72. freez(analytics_data.netdata_allmetrics_shell_used);
  73. freez(analytics_data.netdata_allmetrics_json_used);
  74. freez(analytics_data.netdata_dashboard_used);
  75. freez(analytics_data.netdata_collectors);
  76. freez(analytics_data.netdata_collectors_count);
  77. freez(analytics_data.netdata_buildinfo);
  78. freez(analytics_data.netdata_config_page_cache_size);
  79. freez(analytics_data.netdata_config_multidb_disk_quota);
  80. freez(analytics_data.netdata_config_https_enabled);
  81. freez(analytics_data.netdata_config_web_enabled);
  82. freez(analytics_data.netdata_config_release_channel);
  83. freez(analytics_data.netdata_mirrored_host_count);
  84. freez(analytics_data.netdata_mirrored_hosts_reachable);
  85. freez(analytics_data.netdata_mirrored_hosts_unreachable);
  86. freez(analytics_data.netdata_notification_methods);
  87. freez(analytics_data.netdata_alarms_normal);
  88. freez(analytics_data.netdata_alarms_warning);
  89. freez(analytics_data.netdata_alarms_critical);
  90. freez(analytics_data.netdata_charts_count);
  91. freez(analytics_data.netdata_metrics_count);
  92. freez(analytics_data.netdata_config_is_parent);
  93. freez(analytics_data.netdata_config_hosts_available);
  94. freez(analytics_data.netdata_host_cloud_available);
  95. freez(analytics_data.netdata_host_aclk_available);
  96. freez(analytics_data.netdata_host_aclk_protocol);
  97. freez(analytics_data.netdata_host_aclk_implementation);
  98. freez(analytics_data.netdata_host_agent_claimed);
  99. freez(analytics_data.netdata_host_cloud_enabled);
  100. freez(analytics_data.netdata_config_https_available);
  101. freez(analytics_data.netdata_install_type);
  102. freez(analytics_data.netdata_config_is_private_registry);
  103. freez(analytics_data.netdata_config_use_private_registry);
  104. freez(analytics_data.netdata_config_oom_score);
  105. freez(analytics_data.netdata_prebuilt_distro);
  106. freez(analytics_data.netdata_fail_reason);
  107. }
  108. /*
  109. * Set a numeric/boolean data with a value
  110. */
  111. void analytics_set_data(char **name, char *value)
  112. {
  113. if (*name) {
  114. analytics_data.data_length -= strlen(*name);
  115. freez(*name);
  116. }
  117. *name = strdupz(value);
  118. analytics_data.data_length += strlen(*name);
  119. }
  120. /*
  121. * Set a string data with a value
  122. */
  123. void analytics_set_data_str(char **name, const char *value)
  124. {
  125. size_t value_string_len;
  126. if (*name) {
  127. analytics_data.data_length -= strlen(*name);
  128. freez(*name);
  129. }
  130. value_string_len = strlen(value) + 4;
  131. *name = mallocz(sizeof(char) * value_string_len);
  132. snprintfz(*name, value_string_len - 1, "\"%s\"", value);
  133. analytics_data.data_length += strlen(*name);
  134. }
  135. /*
  136. * Log hits on the allmetrics page, with prometheus parameter
  137. */
  138. void analytics_log_prometheus(void)
  139. {
  140. if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.prometheus_hits < ANALYTICS_MAX_PROMETHEUS_HITS)) {
  141. analytics_data.prometheus_hits++;
  142. char b[21];
  143. snprintfz(b, 20, "%zu", analytics_data.prometheus_hits);
  144. analytics_set_data(&analytics_data.netdata_allmetrics_prometheus_used, b);
  145. }
  146. }
  147. /*
  148. * Log hits on the allmetrics page, with shell parameter (or default)
  149. */
  150. void analytics_log_shell(void)
  151. {
  152. if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.shell_hits < ANALYTICS_MAX_SHELL_HITS)) {
  153. analytics_data.shell_hits++;
  154. char b[21];
  155. snprintfz(b, 20, "%zu", analytics_data.shell_hits);
  156. analytics_set_data(&analytics_data.netdata_allmetrics_shell_used, b);
  157. }
  158. }
  159. /*
  160. * Log hits on the allmetrics page, with json parameter
  161. */
  162. void analytics_log_json(void)
  163. {
  164. if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.json_hits < ANALYTICS_MAX_JSON_HITS)) {
  165. analytics_data.json_hits++;
  166. char b[21];
  167. snprintfz(b, 20, "%zu", analytics_data.json_hits);
  168. analytics_set_data(&analytics_data.netdata_allmetrics_json_used, b);
  169. }
  170. }
  171. /*
  172. * Log hits on the dashboard, (when calling HELLO).
  173. */
  174. void analytics_log_dashboard(void)
  175. {
  176. if (netdata_anonymous_statistics_enabled == 1 && likely(analytics_data.dashboard_hits < ANALYTICS_MAX_DASHBOARD_HITS)) {
  177. analytics_data.dashboard_hits++;
  178. char b[21];
  179. snprintfz(b, 20, "%zu", analytics_data.dashboard_hits);
  180. analytics_set_data(&analytics_data.netdata_dashboard_used, b);
  181. }
  182. }
  183. /*
  184. * Called when setting the oom score
  185. */
  186. void analytics_report_oom_score(long long int score){
  187. char b[21];
  188. snprintfz(b, 20, "%lld", score);
  189. analytics_set_data(&analytics_data.netdata_config_oom_score, b);
  190. }
  191. void analytics_mirrored_hosts(void)
  192. {
  193. RRDHOST *host;
  194. size_t count = 0;
  195. size_t reachable = 0;
  196. size_t unreachable = 0;
  197. char b[21];
  198. rrd_rdlock();
  199. rrdhost_foreach_read(host)
  200. {
  201. if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED))
  202. continue;
  203. ((host == localhost || !rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN)) ? reachable++ : unreachable++);
  204. count++;
  205. }
  206. rrd_unlock();
  207. snprintfz(b, 20, "%zu", count);
  208. analytics_set_data(&analytics_data.netdata_mirrored_host_count, b);
  209. snprintfz(b, 20, "%zu", reachable);
  210. analytics_set_data(&analytics_data.netdata_mirrored_hosts_reachable, b);
  211. snprintfz(b, 20, "%zu", unreachable);
  212. analytics_set_data(&analytics_data.netdata_mirrored_hosts_unreachable, b);
  213. }
  214. void analytics_exporters(void)
  215. {
  216. //when no exporters are available, an empty string will be sent
  217. //decide if something else is more suitable (but probably not null)
  218. BUFFER *bi = buffer_create(1000, NULL);
  219. analytics_exporting_connectors(bi);
  220. analytics_set_data_str(&analytics_data.netdata_exporting_connectors, (char *)buffer_tostring(bi));
  221. buffer_free(bi);
  222. }
  223. int collector_counter_callb(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data) {
  224. struct array_printer *ap = (struct array_printer *)data;
  225. struct collector *col = (struct collector *)entry;
  226. BUFFER *bt = ap->both;
  227. if (likely(ap->c)) {
  228. buffer_strcat(bt, ",");
  229. }
  230. buffer_strcat(bt, "{");
  231. buffer_strcat(bt, " \"plugin\": \"");
  232. buffer_strcat(bt, col->plugin);
  233. buffer_strcat(bt, "\", \"module\":\"");
  234. buffer_strcat(bt, col->module);
  235. buffer_strcat(bt, "\" }");
  236. (ap->c)++;
  237. return 0;
  238. }
  239. /*
  240. * Create a JSON array of available collectors, same as in api/v1/info
  241. */
  242. void analytics_collectors(void)
  243. {
  244. RRDSET *st;
  245. DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED);
  246. char name[500];
  247. BUFFER *bt = buffer_create(1000, NULL);
  248. rrdset_foreach_read(st, localhost) {
  249. if(!rrdset_is_available_for_viewers(st))
  250. continue;
  251. struct collector col = {
  252. .plugin = rrdset_plugin_name(st),
  253. .module = rrdset_module_name(st)
  254. };
  255. snprintfz(name, 499, "%s:%s", col.plugin, col.module);
  256. dictionary_set(dict, name, &col, sizeof(struct collector));
  257. }
  258. rrdset_foreach_done(st);
  259. struct array_printer ap;
  260. ap.c = 0;
  261. ap.both = bt;
  262. dictionary_walkthrough_read(dict, collector_counter_callb, &ap);
  263. dictionary_destroy(dict);
  264. analytics_set_data(&analytics_data.netdata_collectors, (char *)buffer_tostring(ap.both));
  265. {
  266. char b[21];
  267. snprintfz(b, 20, "%d", ap.c);
  268. analytics_set_data(&analytics_data.netdata_collectors_count, b);
  269. }
  270. buffer_free(bt);
  271. }
  272. /*
  273. * Run alarm-notify.sh script using the dump_methods parameter
  274. * SEND_CUSTOM is always available
  275. */
  276. void analytics_alarms_notifications(void)
  277. {
  278. char *script;
  279. script = mallocz(
  280. sizeof(char) * (strlen(netdata_configured_primary_plugins_dir) + strlen("alarm-notify.sh dump_methods") + 2));
  281. sprintf(script, "%s/%s", netdata_configured_primary_plugins_dir, "alarm-notify.sh");
  282. if (unlikely(access(script, R_OK) != 0)) {
  283. netdata_log_info("Alarm notify script %s not found.", script);
  284. freez(script);
  285. return;
  286. }
  287. strcat(script, " dump_methods");
  288. pid_t command_pid;
  289. netdata_log_debug(D_ANALYTICS, "Executing %s", script);
  290. BUFFER *b = buffer_create(1000, NULL);
  291. int cnt = 0;
  292. FILE *fp_child_input;
  293. FILE *fp_child_output = netdata_popen(script, &command_pid, &fp_child_input);
  294. if (fp_child_output) {
  295. char line[200 + 1];
  296. while (fgets(line, 200, fp_child_output) != NULL) {
  297. char *end = line;
  298. while (*end && *end != '\n')
  299. end++;
  300. *end = '\0';
  301. if (likely(cnt))
  302. buffer_strcat(b, "|");
  303. buffer_strcat(b, line);
  304. cnt++;
  305. }
  306. netdata_pclose(fp_child_input, fp_child_output, command_pid);
  307. }
  308. freez(script);
  309. analytics_set_data_str(&analytics_data.netdata_notification_methods, (char *)buffer_tostring(b));
  310. buffer_free(b);
  311. }
  312. static void analytics_get_install_type(struct rrdhost_system_info *system_info)
  313. {
  314. if (system_info->install_type == NULL) {
  315. analytics_set_data_str(&analytics_data.netdata_install_type, "unknown");
  316. } else {
  317. analytics_set_data_str(&analytics_data.netdata_install_type, system_info->install_type);
  318. }
  319. if (system_info->prebuilt_dist != NULL) {
  320. analytics_set_data_str(&analytics_data.netdata_prebuilt_distro, system_info->prebuilt_dist);
  321. }
  322. }
  323. /*
  324. * Pick up if https is actually used
  325. */
  326. void analytics_https(void)
  327. {
  328. BUFFER *b = buffer_create(30, NULL);
  329. #ifdef ENABLE_HTTPS
  330. analytics_exporting_connectors_ssl(b);
  331. buffer_strcat(b, netdata_ssl_streaming_sender_ctx &&
  332. rrdhost_flag_check(localhost, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED) &&
  333. SSL_connection(&localhost->sender->ssl) ? "streaming|" : "|");
  334. buffer_strcat(b, netdata_ssl_web_server_ctx ? "web" : "");
  335. #else
  336. buffer_strcat(b, "||");
  337. #endif
  338. analytics_set_data_str(&analytics_data.netdata_config_https_available, (char *)buffer_tostring(b));
  339. buffer_free(b);
  340. }
  341. void analytics_charts(void)
  342. {
  343. RRDSET *st;
  344. size_t c = 0;
  345. rrdset_foreach_read(st, localhost)
  346. if(rrdset_is_available_for_viewers(st)) c++;
  347. rrdset_foreach_done(st);
  348. analytics_data.charts_count = c;
  349. {
  350. char b[21];
  351. snprintfz(b, 20, "%zu", c);
  352. analytics_set_data(&analytics_data.netdata_charts_count, b);
  353. }
  354. }
  355. void analytics_metrics(void)
  356. {
  357. RRDSET *st;
  358. size_t dimensions = 0;
  359. rrdset_foreach_read(st, localhost) {
  360. if (rrdset_is_available_for_viewers(st)) {
  361. RRDDIM *rd;
  362. rrddim_foreach_read(rd, st) {
  363. if (rrddim_option_check(rd, RRDDIM_OPTION_HIDDEN) || rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE))
  364. continue;
  365. dimensions++;
  366. }
  367. rrddim_foreach_done(rd);
  368. }
  369. }
  370. rrdset_foreach_done(st);
  371. analytics_data.metrics_count = dimensions;
  372. {
  373. char b[21];
  374. snprintfz(b, 20, "%zu", dimensions);
  375. analytics_set_data(&analytics_data.netdata_metrics_count, b);
  376. }
  377. }
  378. void analytics_alarms(void)
  379. {
  380. size_t alarm_warn = 0, alarm_crit = 0, alarm_normal = 0;
  381. char b[21];
  382. RRDCALC *rc;
  383. foreach_rrdcalc_in_rrdhost_read(localhost, rc) {
  384. if (unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec))
  385. continue;
  386. switch (rc->status) {
  387. case RRDCALC_STATUS_WARNING:
  388. alarm_warn++;
  389. break;
  390. case RRDCALC_STATUS_CRITICAL:
  391. alarm_crit++;
  392. break;
  393. default:
  394. alarm_normal++;
  395. }
  396. }
  397. foreach_rrdcalc_in_rrdhost_done(rc);
  398. snprintfz(b, 20, "%zu", alarm_normal);
  399. analytics_set_data(&analytics_data.netdata_alarms_normal, b);
  400. snprintfz(b, 20, "%zu", alarm_warn);
  401. analytics_set_data(&analytics_data.netdata_alarms_warning, b);
  402. snprintfz(b, 20, "%zu", alarm_crit);
  403. analytics_set_data(&analytics_data.netdata_alarms_critical, b);
  404. }
  405. /*
  406. * Misc attributes to get (run from start)
  407. */
  408. void analytics_misc(void)
  409. {
  410. #ifdef ENABLE_ACLK
  411. analytics_set_data(&analytics_data.netdata_host_cloud_available, "true");
  412. analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "Next Generation");
  413. #else
  414. analytics_set_data(&analytics_data.netdata_host_cloud_available, "false");
  415. analytics_set_data_str(&analytics_data.netdata_host_aclk_implementation, "");
  416. #endif
  417. analytics_data.exporting_enabled = appconfig_get_boolean(&exporting_config, CONFIG_SECTION_EXPORTING, "enabled", CONFIG_BOOLEAN_NO);
  418. analytics_set_data(&analytics_data.netdata_config_exporting_enabled, analytics_data.exporting_enabled ? "true" : "false");
  419. analytics_set_data(&analytics_data.netdata_config_is_private_registry, "false");
  420. analytics_set_data(&analytics_data.netdata_config_use_private_registry, "false");
  421. if (strcmp(
  422. config_get(CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io"),
  423. "https://registry.my-netdata.io"))
  424. analytics_set_data(&analytics_data.netdata_config_use_private_registry, "true");
  425. //do we need both registry to announce and enabled to indicate that this is a private registry ?
  426. if (config_get_boolean(CONFIG_SECTION_REGISTRY, "enabled", CONFIG_BOOLEAN_NO) &&
  427. web_server_mode != WEB_SERVER_MODE_NONE)
  428. analytics_set_data(&analytics_data.netdata_config_is_private_registry, "true");
  429. }
  430. void analytics_aclk(void)
  431. {
  432. #ifdef ENABLE_ACLK
  433. if (aclk_connected) {
  434. analytics_set_data(&analytics_data.netdata_host_aclk_available, "true");
  435. analytics_set_data_str(&analytics_data.netdata_host_aclk_protocol, "New");
  436. }
  437. else
  438. #endif
  439. analytics_set_data(&analytics_data.netdata_host_aclk_available, "false");
  440. }
  441. /*
  442. * Get the meta data, called from the thread once after the original delay
  443. * These are values that won't change during agent runtime, and therefore
  444. * don't try to read them on each META event send
  445. */
  446. void analytics_gather_immutable_meta_data(void)
  447. {
  448. analytics_misc();
  449. analytics_exporters();
  450. analytics_https();
  451. }
  452. /*
  453. * Get the meta data, called from the thread on every heartbeat, and right before the EXIT event
  454. * These are values that can change between agent restarts, and therefore
  455. * try to read them on each META event send
  456. */
  457. void analytics_gather_mutable_meta_data(void)
  458. {
  459. analytics_collectors();
  460. analytics_alarms();
  461. analytics_charts();
  462. analytics_metrics();
  463. analytics_aclk();
  464. analytics_mirrored_hosts();
  465. analytics_alarms_notifications();
  466. analytics_set_data(
  467. &analytics_data.netdata_config_is_parent, (rrdhost_hosts_available() > 1 || configured_as_parent()) ? "true" : "false");
  468. char *claim_id = get_agent_claimid();
  469. analytics_set_data(&analytics_data.netdata_host_agent_claimed, claim_id ? "true" : "false");
  470. freez(claim_id);
  471. {
  472. char b[21];
  473. snprintfz(b, 20, "%zu", analytics_data.prometheus_hits);
  474. analytics_set_data(&analytics_data.netdata_allmetrics_prometheus_used, b);
  475. snprintfz(b, 20, "%zu", analytics_data.shell_hits);
  476. analytics_set_data(&analytics_data.netdata_allmetrics_shell_used, b);
  477. snprintfz(b, 20, "%zu", analytics_data.json_hits);
  478. analytics_set_data(&analytics_data.netdata_allmetrics_json_used, b);
  479. snprintfz(b, 20, "%zu", analytics_data.dashboard_hits);
  480. analytics_set_data(&analytics_data.netdata_dashboard_used, b);
  481. snprintfz(b, 20, "%zu", rrdhost_hosts_available());
  482. analytics_set_data(&analytics_data.netdata_config_hosts_available, b);
  483. }
  484. }
  485. void analytics_main_cleanup(void *ptr)
  486. {
  487. struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
  488. static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
  489. netdata_log_debug(D_ANALYTICS, "Cleaning up...");
  490. analytics_free_data();
  491. static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
  492. }
  493. /*
  494. * The analytics thread. Sleep for ANALYTICS_INIT_SLEEP_SEC,
  495. * gather the data, and then go to a loop where every ANALYTICS_HEARTBEAT
  496. * it will send a new META event after gathering data that could be changed
  497. * while the agent is running
  498. */
  499. void *analytics_main(void *ptr)
  500. {
  501. netdata_thread_cleanup_push(analytics_main_cleanup, ptr);
  502. unsigned int sec = 0;
  503. heartbeat_t hb;
  504. heartbeat_init(&hb);
  505. usec_t step_ut = USEC_PER_SEC;
  506. netdata_log_debug(D_ANALYTICS, "Analytics thread starts");
  507. //first delay after agent start
  508. while (service_running(SERVICE_ANALYTICS) && likely(sec <= ANALYTICS_INIT_SLEEP_SEC)) {
  509. heartbeat_next(&hb, step_ut);
  510. sec++;
  511. }
  512. if (unlikely(!service_running(SERVICE_ANALYTICS)))
  513. goto cleanup;
  514. analytics_gather_immutable_meta_data();
  515. analytics_gather_mutable_meta_data();
  516. send_statistics("META_START", "-", "-");
  517. analytics_log_data();
  518. sec = 0;
  519. while (1) {
  520. heartbeat_next(&hb, step_ut * 2);
  521. sec += 2;
  522. if (unlikely(!service_running(SERVICE_ANALYTICS)))
  523. break;
  524. if (likely(sec < ANALYTICS_HEARTBEAT))
  525. continue;
  526. analytics_gather_mutable_meta_data();
  527. send_statistics("META", "-", "-");
  528. analytics_log_data();
  529. sec = 0;
  530. }
  531. cleanup:
  532. netdata_thread_cleanup_pop(1);
  533. return NULL;
  534. }
  535. static const char *verify_required_directory(const char *dir)
  536. {
  537. if (chdir(dir) == -1)
  538. fatal("Cannot change directory to '%s'", dir);
  539. DIR *d = opendir(dir);
  540. if (!d)
  541. fatal("Cannot examine the contents of directory '%s'", dir);
  542. closedir(d);
  543. return dir;
  544. }
  545. static const char *verify_or_create_required_directory(const char *dir) {
  546. int result;
  547. result = mkdir(dir, 0755);
  548. if (result != 0 && errno != EEXIST)
  549. fatal("Cannot create required directory '%s'", dir);
  550. return verify_required_directory(dir);
  551. }
  552. /*
  553. * This is called after the rrdinit
  554. * These values will be sent on the START event
  555. */
  556. void set_late_global_environment(struct rrdhost_system_info *system_info)
  557. {
  558. analytics_set_data(&analytics_data.netdata_config_stream_enabled, default_rrdpush_enabled ? "true" : "false");
  559. analytics_set_data_str(&analytics_data.netdata_config_memory_mode, (char *)rrd_memory_mode_name(default_rrd_memory_mode));
  560. #ifdef DISABLE_CLOUD
  561. analytics_set_data(&analytics_data.netdata_host_cloud_enabled, "false");
  562. #else
  563. analytics_set_data(
  564. &analytics_data.netdata_host_cloud_enabled,
  565. appconfig_get_boolean_ondemand(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", netdata_cloud_enabled) ? "true" : "false");
  566. #endif
  567. #ifdef ENABLE_DBENGINE
  568. {
  569. char b[16];
  570. snprintfz(b, 15, "%d", default_rrdeng_page_cache_mb);
  571. analytics_set_data(&analytics_data.netdata_config_page_cache_size, b);
  572. snprintfz(b, 15, "%d", default_multidb_disk_quota_mb);
  573. analytics_set_data(&analytics_data.netdata_config_multidb_disk_quota, b);
  574. }
  575. #endif
  576. #ifdef ENABLE_HTTPS
  577. analytics_set_data(&analytics_data.netdata_config_https_enabled, "true");
  578. #else
  579. analytics_set_data(&analytics_data.netdata_config_https_enabled, "false");
  580. #endif
  581. if (web_server_mode == WEB_SERVER_MODE_NONE)
  582. analytics_set_data(&analytics_data.netdata_config_web_enabled, "false");
  583. else
  584. analytics_set_data(&analytics_data.netdata_config_web_enabled, "true");
  585. analytics_set_data_str(&analytics_data.netdata_config_release_channel, (char *)get_release_channel());
  586. {
  587. BUFFER *bi = buffer_create(1000, NULL);
  588. analytics_build_info(bi);
  589. analytics_set_data_str(&analytics_data.netdata_buildinfo, (char *)buffer_tostring(bi));
  590. buffer_free(bi);
  591. }
  592. analytics_get_install_type(system_info);
  593. }
  594. void get_system_timezone(void)
  595. {
  596. // avoid flood calls to stat(/etc/localtime)
  597. // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
  598. const char *tz = getenv("TZ");
  599. if (!tz || !*tz)
  600. setenv("TZ", config_get(CONFIG_SECTION_ENV_VARS, "TZ", ":/etc/localtime"), 0);
  601. char buffer[FILENAME_MAX + 1] = "";
  602. const char *timezone = NULL;
  603. ssize_t ret;
  604. // use the TZ variable
  605. if (tz && *tz && *tz != ':') {
  606. timezone = tz;
  607. netdata_log_info("TIMEZONE: using TZ variable '%s'", timezone);
  608. }
  609. // use the contents of /etc/timezone
  610. if (!timezone && !read_file("/etc/timezone", buffer, FILENAME_MAX)) {
  611. timezone = buffer;
  612. netdata_log_info("TIMEZONE: using the contents of /etc/timezone");
  613. }
  614. // read the link /etc/localtime
  615. if (!timezone) {
  616. ret = readlink("/etc/localtime", buffer, FILENAME_MAX);
  617. if (ret > 0) {
  618. buffer[ret] = '\0';
  619. char *cmp = "/usr/share/zoneinfo/";
  620. size_t cmp_len = strlen(cmp);
  621. char *s = strstr(buffer, cmp);
  622. if (s && s[cmp_len]) {
  623. timezone = &s[cmp_len];
  624. netdata_log_info("TIMEZONE: using the link of /etc/localtime: '%s'", timezone);
  625. }
  626. } else
  627. buffer[0] = '\0';
  628. }
  629. // find the timezone from strftime()
  630. if (!timezone) {
  631. time_t t;
  632. struct tm *tmp, tmbuf;
  633. t = now_realtime_sec();
  634. tmp = localtime_r(&t, &tmbuf);
  635. if (tmp != NULL) {
  636. if (strftime(buffer, FILENAME_MAX, "%Z", tmp) == 0)
  637. buffer[0] = '\0';
  638. else {
  639. buffer[FILENAME_MAX] = '\0';
  640. timezone = buffer;
  641. netdata_log_info("TIMEZONE: using strftime(): '%s'", timezone);
  642. }
  643. }
  644. }
  645. if (timezone && *timezone) {
  646. // make sure it does not have illegal characters
  647. // netdata_log_info("TIMEZONE: fixing '%s'", timezone);
  648. size_t len = strlen(timezone);
  649. char tmp[len + 1];
  650. char *d = tmp;
  651. *d = '\0';
  652. while (*timezone) {
  653. if (isalnum(*timezone) || *timezone == '_' || *timezone == '/')
  654. *d++ = *timezone++;
  655. else
  656. timezone++;
  657. }
  658. *d = '\0';
  659. strncpyz(buffer, tmp, len);
  660. timezone = buffer;
  661. netdata_log_info("TIMEZONE: fixed as '%s'", timezone);
  662. }
  663. if (!timezone || !*timezone)
  664. timezone = "unknown";
  665. netdata_configured_timezone = config_get(CONFIG_SECTION_GLOBAL, "timezone", timezone);
  666. //get the utc offset, and the timezone as returned by strftime
  667. //will be sent to the cloud
  668. //Note: This will need an agent restart to get new offset on time change (dst, etc).
  669. {
  670. time_t t;
  671. struct tm *tmp, tmbuf;
  672. char zone[FILENAME_MAX + 1];
  673. char sign[2], hh[3], mm[3];
  674. t = now_realtime_sec();
  675. tmp = localtime_r(&t, &tmbuf);
  676. if (tmp != NULL) {
  677. if (strftime(zone, FILENAME_MAX, "%Z", tmp) == 0) {
  678. netdata_configured_abbrev_timezone = strdupz("UTC");
  679. } else
  680. netdata_configured_abbrev_timezone = strdupz(zone);
  681. if (strftime(zone, FILENAME_MAX, "%z", tmp) == 0) {
  682. netdata_configured_utc_offset = 0;
  683. } else {
  684. sign[0] = zone[0] == '-' || zone[0] == '+' ? zone[0] : '0';
  685. sign[1] = '\0';
  686. hh[0] = isdigit(zone[1]) ? zone[1] : '0';
  687. hh[1] = isdigit(zone[2]) ? zone[2] : '0';
  688. hh[2] = '\0';
  689. mm[0] = isdigit(zone[3]) ? zone[3] : '0';
  690. mm[1] = isdigit(zone[4]) ? zone[4] : '0';
  691. mm[2] = '\0';
  692. netdata_configured_utc_offset = (str2i(hh) * 3600) + (str2i(mm) * 60);
  693. netdata_configured_utc_offset =
  694. sign[0] == '-' ? -netdata_configured_utc_offset : netdata_configured_utc_offset;
  695. }
  696. } else {
  697. netdata_configured_abbrev_timezone = strdupz("UTC");
  698. netdata_configured_utc_offset = 0;
  699. }
  700. }
  701. }
  702. void set_global_environment()
  703. {
  704. {
  705. char b[16];
  706. snprintfz(b, 15, "%d", default_rrd_update_every);
  707. setenv("NETDATA_UPDATE_EVERY", b, 1);
  708. }
  709. setenv("NETDATA_VERSION", program_version, 1);
  710. setenv("NETDATA_HOSTNAME", netdata_configured_hostname, 1);
  711. setenv("NETDATA_CONFIG_DIR", verify_required_directory(netdata_configured_user_config_dir), 1);
  712. setenv("NETDATA_USER_CONFIG_DIR", verify_required_directory(netdata_configured_user_config_dir), 1);
  713. setenv("NETDATA_STOCK_CONFIG_DIR", verify_required_directory(netdata_configured_stock_config_dir), 1);
  714. setenv("NETDATA_PLUGINS_DIR", verify_required_directory(netdata_configured_primary_plugins_dir), 1);
  715. setenv("NETDATA_WEB_DIR", verify_required_directory(netdata_configured_web_dir), 1);
  716. setenv("NETDATA_CACHE_DIR", verify_or_create_required_directory(netdata_configured_cache_dir), 1);
  717. setenv("NETDATA_LIB_DIR", verify_or_create_required_directory(netdata_configured_varlib_dir), 1);
  718. setenv("NETDATA_LOCK_DIR", verify_or_create_required_directory(netdata_configured_lock_dir), 1);
  719. setenv("NETDATA_LOG_DIR", verify_or_create_required_directory(netdata_configured_log_dir), 1);
  720. setenv("HOME", verify_or_create_required_directory(netdata_configured_home_dir), 1);
  721. setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1);
  722. {
  723. BUFFER *user_plugins_dirs = buffer_create(FILENAME_MAX, NULL);
  724. for (size_t i = 1; i < PLUGINSD_MAX_DIRECTORIES && plugin_directories[i]; i++) {
  725. if (i > 1)
  726. buffer_strcat(user_plugins_dirs, " ");
  727. buffer_strcat(user_plugins_dirs, plugin_directories[i]);
  728. }
  729. setenv("NETDATA_USER_PLUGINS_DIRS", buffer_tostring(user_plugins_dirs), 1);
  730. buffer_free(user_plugins_dirs);
  731. }
  732. analytics_data.data_length = 0;
  733. analytics_set_data(&analytics_data.netdata_config_stream_enabled, "null");
  734. analytics_set_data(&analytics_data.netdata_config_memory_mode, "null");
  735. analytics_set_data(&analytics_data.netdata_config_exporting_enabled, "null");
  736. analytics_set_data(&analytics_data.netdata_exporting_connectors, "null");
  737. analytics_set_data(&analytics_data.netdata_allmetrics_prometheus_used, "null");
  738. analytics_set_data(&analytics_data.netdata_allmetrics_shell_used, "null");
  739. analytics_set_data(&analytics_data.netdata_allmetrics_json_used, "null");
  740. analytics_set_data(&analytics_data.netdata_dashboard_used, "null");
  741. analytics_set_data(&analytics_data.netdata_collectors, "null");
  742. analytics_set_data(&analytics_data.netdata_collectors_count, "null");
  743. analytics_set_data(&analytics_data.netdata_buildinfo, "null");
  744. analytics_set_data(&analytics_data.netdata_config_page_cache_size, "null");
  745. analytics_set_data(&analytics_data.netdata_config_multidb_disk_quota, "null");
  746. analytics_set_data(&analytics_data.netdata_config_https_enabled, "null");
  747. analytics_set_data(&analytics_data.netdata_config_web_enabled, "null");
  748. analytics_set_data(&analytics_data.netdata_config_release_channel, "null");
  749. analytics_set_data(&analytics_data.netdata_mirrored_host_count, "null");
  750. analytics_set_data(&analytics_data.netdata_mirrored_hosts_reachable, "null");
  751. analytics_set_data(&analytics_data.netdata_mirrored_hosts_unreachable, "null");
  752. analytics_set_data(&analytics_data.netdata_notification_methods, "null");
  753. analytics_set_data(&analytics_data.netdata_alarms_normal, "null");
  754. analytics_set_data(&analytics_data.netdata_alarms_warning, "null");
  755. analytics_set_data(&analytics_data.netdata_alarms_critical, "null");
  756. analytics_set_data(&analytics_data.netdata_charts_count, "null");
  757. analytics_set_data(&analytics_data.netdata_metrics_count, "null");
  758. analytics_set_data(&analytics_data.netdata_config_is_parent, "null");
  759. analytics_set_data(&analytics_data.netdata_config_hosts_available, "null");
  760. analytics_set_data(&analytics_data.netdata_host_cloud_available, "null");
  761. analytics_set_data(&analytics_data.netdata_host_aclk_implementation, "null");
  762. analytics_set_data(&analytics_data.netdata_host_aclk_available, "null");
  763. analytics_set_data(&analytics_data.netdata_host_aclk_protocol, "null");
  764. analytics_set_data(&analytics_data.netdata_host_agent_claimed, "null");
  765. analytics_set_data(&analytics_data.netdata_host_cloud_enabled, "null");
  766. analytics_set_data(&analytics_data.netdata_config_https_available, "null");
  767. analytics_set_data(&analytics_data.netdata_install_type, "null");
  768. analytics_set_data(&analytics_data.netdata_config_is_private_registry, "null");
  769. analytics_set_data(&analytics_data.netdata_config_use_private_registry, "null");
  770. analytics_set_data(&analytics_data.netdata_config_oom_score, "null");
  771. analytics_set_data(&analytics_data.netdata_prebuilt_distro, "null");
  772. analytics_set_data(&analytics_data.netdata_fail_reason, "null");
  773. analytics_data.prometheus_hits = 0;
  774. analytics_data.shell_hits = 0;
  775. analytics_data.json_hits = 0;
  776. analytics_data.dashboard_hits = 0;
  777. analytics_data.charts_count = 0;
  778. analytics_data.metrics_count = 0;
  779. analytics_data.exporting_enabled = false;
  780. char *default_port = appconfig_get(&netdata_config, CONFIG_SECTION_WEB, "default port", NULL);
  781. int clean = 0;
  782. if (!default_port) {
  783. default_port = strdupz("19999");
  784. clean = 1;
  785. }
  786. setenv("NETDATA_LISTEN_PORT", default_port, 1);
  787. if (clean)
  788. freez(default_port);
  789. // set the path we need
  790. char path[1024 + 1], *p = getenv("PATH");
  791. if (!p)
  792. p = "/bin:/usr/bin";
  793. snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin");
  794. setenv("PATH", config_get(CONFIG_SECTION_ENV_VARS, "PATH", path), 1);
  795. // python options
  796. p = getenv("PYTHONPATH");
  797. if (!p)
  798. p = "";
  799. setenv("PYTHONPATH", config_get(CONFIG_SECTION_ENV_VARS, "PYTHONPATH", p), 1);
  800. // disable buffering for python plugins
  801. setenv("PYTHONUNBUFFERED", "1", 1);
  802. // switch to standard locale for plugins
  803. setenv("LC_ALL", "C", 1);
  804. }
  805. void send_statistics(const char *action, const char *action_result, const char *action_data)
  806. {
  807. static char *as_script;
  808. if (netdata_anonymous_statistics_enabled == -1) {
  809. char *optout_file = mallocz(
  810. sizeof(char) *
  811. (strlen(netdata_configured_user_config_dir) + strlen(".opt-out-from-anonymous-statistics") + 2));
  812. sprintf(optout_file, "%s/%s", netdata_configured_user_config_dir, ".opt-out-from-anonymous-statistics");
  813. if (likely(access(optout_file, R_OK) != 0)) {
  814. as_script = mallocz(
  815. sizeof(char) *
  816. (strlen(netdata_configured_primary_plugins_dir) + strlen("anonymous-statistics.sh") + 2));
  817. sprintf(as_script, "%s/%s", netdata_configured_primary_plugins_dir, "anonymous-statistics.sh");
  818. if (unlikely(access(as_script, R_OK) != 0)) {
  819. netdata_anonymous_statistics_enabled = 0;
  820. netdata_log_info("Anonymous statistics script %s not found.", as_script);
  821. freez(as_script);
  822. } else {
  823. netdata_anonymous_statistics_enabled = 1;
  824. }
  825. } else {
  826. netdata_anonymous_statistics_enabled = 0;
  827. as_script = NULL;
  828. }
  829. freez(optout_file);
  830. }
  831. if (!netdata_anonymous_statistics_enabled)
  832. return;
  833. if (!action)
  834. return;
  835. if (!action_result)
  836. action_result = "";
  837. if (!action_data)
  838. action_data = "";
  839. char *command_to_run = mallocz(
  840. sizeof(char) * (strlen(action) + strlen(action_result) + strlen(action_data) + strlen(as_script) +
  841. analytics_data.data_length + (ANALYTICS_NO_OF_ITEMS * 3) + 15));
  842. pid_t command_pid;
  843. sprintf(
  844. command_to_run,
  845. "%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' ",
  846. as_script,
  847. action,
  848. action_result,
  849. action_data,
  850. analytics_data.netdata_config_stream_enabled,
  851. analytics_data.netdata_config_memory_mode,
  852. analytics_data.netdata_config_exporting_enabled,
  853. analytics_data.netdata_exporting_connectors,
  854. analytics_data.netdata_allmetrics_prometheus_used,
  855. analytics_data.netdata_allmetrics_shell_used,
  856. analytics_data.netdata_allmetrics_json_used,
  857. analytics_data.netdata_dashboard_used,
  858. analytics_data.netdata_collectors,
  859. analytics_data.netdata_collectors_count,
  860. analytics_data.netdata_buildinfo,
  861. analytics_data.netdata_config_page_cache_size,
  862. analytics_data.netdata_config_multidb_disk_quota,
  863. analytics_data.netdata_config_https_enabled,
  864. analytics_data.netdata_config_web_enabled,
  865. analytics_data.netdata_config_release_channel,
  866. analytics_data.netdata_mirrored_host_count,
  867. analytics_data.netdata_mirrored_hosts_reachable,
  868. analytics_data.netdata_mirrored_hosts_unreachable,
  869. analytics_data.netdata_notification_methods,
  870. analytics_data.netdata_alarms_normal,
  871. analytics_data.netdata_alarms_warning,
  872. analytics_data.netdata_alarms_critical,
  873. analytics_data.netdata_charts_count,
  874. analytics_data.netdata_metrics_count,
  875. analytics_data.netdata_config_is_parent,
  876. analytics_data.netdata_config_hosts_available,
  877. analytics_data.netdata_host_cloud_available,
  878. analytics_data.netdata_host_aclk_available,
  879. analytics_data.netdata_host_aclk_protocol,
  880. analytics_data.netdata_host_aclk_implementation,
  881. analytics_data.netdata_host_agent_claimed,
  882. analytics_data.netdata_host_cloud_enabled,
  883. analytics_data.netdata_config_https_available,
  884. analytics_data.netdata_install_type,
  885. analytics_data.netdata_config_is_private_registry,
  886. analytics_data.netdata_config_use_private_registry,
  887. analytics_data.netdata_config_oom_score,
  888. analytics_data.netdata_prebuilt_distro,
  889. analytics_data.netdata_fail_reason);
  890. netdata_log_info("%s '%s' '%s' '%s'", as_script, action, action_result, action_data);
  891. FILE *fp_child_input;
  892. FILE *fp_child_output = netdata_popen(command_to_run, &command_pid, &fp_child_input);
  893. if (fp_child_output) {
  894. char buffer[4 + 1];
  895. char *s = fgets(buffer, 4, fp_child_output);
  896. int exit_code = netdata_pclose(fp_child_input, fp_child_output, command_pid);
  897. if (exit_code)
  898. netdata_log_error("Execution of anonymous statistics script returned %d.", exit_code);
  899. if (s && strncmp(buffer, "200", 3))
  900. netdata_log_error("Execution of anonymous statistics script returned http code %s.", buffer);
  901. } else {
  902. netdata_log_error("Failed to run anonymous statistics script %s.", as_script);
  903. }
  904. freez(command_to_run);
  905. }