rrdhost.c 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #define NETDATA_RRD_INTERNALS
  3. #include "rrd.h"
  4. static void rrdhost_streaming_sender_structures_init(RRDHOST *host);
  5. bool dbengine_enabled = false; // will become true if and when dbengine is initialized
  6. size_t storage_tiers = 3;
  7. bool use_direct_io = true;
  8. size_t storage_tiers_grouping_iterations[RRD_STORAGE_TIERS] = { 1, 60, 60, 60, 60 };
  9. RRD_BACKFILL storage_tiers_backfill[RRD_STORAGE_TIERS] = { RRD_BACKFILL_NEW, RRD_BACKFILL_NEW, RRD_BACKFILL_NEW, RRD_BACKFILL_NEW, RRD_BACKFILL_NEW };
  10. #if RRD_STORAGE_TIERS != 5
  11. #error RRD_STORAGE_TIERS is not 5 - you need to update the grouping iterations per tier
  12. #endif
  13. size_t get_tier_grouping(size_t tier) {
  14. if(unlikely(tier >= storage_tiers)) tier = storage_tiers - 1;
  15. size_t grouping = 1;
  16. // first tier is always 1 iteration of whatever update every the chart has
  17. for(size_t i = 1; i <= tier ;i++)
  18. grouping *= storage_tiers_grouping_iterations[i];
  19. return grouping;
  20. }
  21. RRDHOST *localhost = NULL;
  22. netdata_rwlock_t rrd_rwlock = NETDATA_RWLOCK_INITIALIZER;
  23. time_t rrdset_free_obsolete_time_s = 3600;
  24. time_t rrdhost_free_orphan_time_s = 3600;
  25. time_t rrdhost_free_ephemeral_time_s = 86400;
  26. bool is_storage_engine_shared(STORAGE_INSTANCE *si __maybe_unused) {
  27. #ifdef ENABLE_DBENGINE
  28. if(!rrdeng_is_legacy(si))
  29. return true;
  30. #endif
  31. return false;
  32. }
  33. RRDHOST *find_host_by_node_id(char *node_id) {
  34. uuid_t node_uuid;
  35. if (unlikely(!node_id || uuid_parse(node_id, node_uuid)))
  36. return NULL;
  37. RRDHOST *host, *ret = NULL;
  38. dfe_start_read(rrdhost_root_index, host) {
  39. if (host->node_id && !(uuid_memcmp(host->node_id, &node_uuid))) {
  40. ret = host;
  41. break;
  42. }
  43. }
  44. dfe_done(host);
  45. return ret;
  46. }
  47. // ----------------------------------------------------------------------------
  48. // RRDHOST indexes management
  49. DICTIONARY *rrdhost_root_index = NULL;
  50. static DICTIONARY *rrdhost_root_index_hostname = NULL;
  51. static inline void rrdhost_init() {
  52. if(unlikely(!rrdhost_root_index)) {
  53. rrdhost_root_index = dictionary_create_advanced(
  54. DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_VALUE_LINK_DONT_CLONE | DICT_OPTION_DONT_OVERWRITE_VALUE,
  55. &dictionary_stats_category_rrdhost, 0);
  56. }
  57. if(unlikely(!rrdhost_root_index_hostname)) {
  58. rrdhost_root_index_hostname = dictionary_create_advanced(
  59. DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_VALUE_LINK_DONT_CLONE | DICT_OPTION_DONT_OVERWRITE_VALUE,
  60. &dictionary_stats_category_rrdhost, 0);
  61. }
  62. }
  63. RRDHOST_ACQUIRED *rrdhost_find_and_acquire(const char *machine_guid) {
  64. return (RRDHOST_ACQUIRED *)dictionary_get_and_acquire_item(rrdhost_root_index, machine_guid);
  65. }
  66. RRDHOST *rrdhost_acquired_to_rrdhost(RRDHOST_ACQUIRED *rha) {
  67. if(unlikely(!rha))
  68. return NULL;
  69. return (RRDHOST *) dictionary_acquired_item_value((const DICTIONARY_ITEM *)rha);
  70. }
  71. void rrdhost_acquired_release(RRDHOST_ACQUIRED *rha) {
  72. if(unlikely(!rha))
  73. return;
  74. dictionary_acquired_item_release(rrdhost_root_index, (const DICTIONARY_ITEM *)rha);
  75. }
  76. // ----------------------------------------------------------------------------
  77. // RRDHOST index by UUID
  78. inline size_t rrdhost_hosts_available(void) {
  79. return dictionary_entries(rrdhost_root_index);
  80. }
  81. inline RRDHOST *rrdhost_find_by_guid(const char *guid) {
  82. return dictionary_get(rrdhost_root_index, guid);
  83. }
  84. static inline RRDHOST *rrdhost_index_add_by_guid(RRDHOST *host) {
  85. RRDHOST *ret_machine_guid = dictionary_set(rrdhost_root_index, host->machine_guid, host, sizeof(RRDHOST));
  86. if(ret_machine_guid == host)
  87. rrdhost_option_set(host, RRDHOST_OPTION_INDEXED_MACHINE_GUID);
  88. else {
  89. rrdhost_option_clear(host, RRDHOST_OPTION_INDEXED_MACHINE_GUID);
  90. nd_log(NDLS_DAEMON, NDLP_NOTICE,
  91. "RRDHOST: host with machine guid '%s' is already indexed. Not adding it again.",
  92. host->machine_guid);
  93. }
  94. return host;
  95. }
  96. static void rrdhost_index_del_by_guid(RRDHOST *host) {
  97. if(rrdhost_option_check(host, RRDHOST_OPTION_INDEXED_MACHINE_GUID)) {
  98. if(!dictionary_del(rrdhost_root_index, host->machine_guid))
  99. nd_log(NDLS_DAEMON, NDLP_NOTICE,
  100. "RRDHOST: failed to delete machine guid '%s' from index",
  101. host->machine_guid);
  102. rrdhost_option_clear(host, RRDHOST_OPTION_INDEXED_MACHINE_GUID);
  103. }
  104. }
  105. // ----------------------------------------------------------------------------
  106. // RRDHOST index by hostname
  107. inline RRDHOST *rrdhost_find_by_hostname(const char *hostname) {
  108. if(unlikely(!strcmp(hostname, "localhost")))
  109. return localhost;
  110. return dictionary_get(rrdhost_root_index_hostname, hostname);
  111. }
  112. static inline void rrdhost_index_del_hostname(RRDHOST *host) {
  113. if(unlikely(!host->hostname)) return;
  114. if(rrdhost_option_check(host, RRDHOST_OPTION_INDEXED_HOSTNAME)) {
  115. if(!dictionary_del(rrdhost_root_index_hostname, rrdhost_hostname(host)))
  116. nd_log(NDLS_DAEMON, NDLP_NOTICE,
  117. "RRDHOST: failed to delete hostname '%s' from index",
  118. rrdhost_hostname(host));
  119. rrdhost_option_clear(host, RRDHOST_OPTION_INDEXED_HOSTNAME);
  120. }
  121. }
  122. static inline RRDHOST *rrdhost_index_add_hostname(RRDHOST *host) {
  123. if(!host->hostname) return host;
  124. RRDHOST *ret_hostname = dictionary_set(rrdhost_root_index_hostname, rrdhost_hostname(host), host, sizeof(RRDHOST));
  125. if(ret_hostname == host)
  126. rrdhost_option_set(host, RRDHOST_OPTION_INDEXED_HOSTNAME);
  127. else {
  128. //have the same hostname but it's not the same host
  129. //keep the new one only if the old one is orphan or archived
  130. if (rrdhost_flag_check(ret_hostname, RRDHOST_FLAG_ORPHAN) || rrdhost_flag_check(ret_hostname, RRDHOST_FLAG_ARCHIVED)) {
  131. rrdhost_index_del_hostname(ret_hostname);
  132. rrdhost_index_add_hostname(host);
  133. }
  134. }
  135. return host;
  136. }
  137. // ----------------------------------------------------------------------------
  138. // RRDHOST - internal helpers
  139. static inline void rrdhost_init_hostname(RRDHOST *host, const char *hostname, bool add_to_index) {
  140. if(unlikely(hostname && !*hostname)) hostname = NULL;
  141. if(host->hostname && hostname && !strcmp(rrdhost_hostname(host), hostname))
  142. return;
  143. rrdhost_index_del_hostname(host);
  144. STRING *old = host->hostname;
  145. host->hostname = string_strdupz(hostname?hostname:"localhost");
  146. string_freez(old);
  147. if(add_to_index)
  148. rrdhost_index_add_hostname(host);
  149. }
  150. static inline void rrdhost_init_os(RRDHOST *host, const char *os) {
  151. if(host->os && os && !strcmp(rrdhost_os(host), os))
  152. return;
  153. STRING *old = host->os;
  154. host->os = string_strdupz(os?os:"unknown");
  155. string_freez(old);
  156. }
  157. static inline void rrdhost_init_timezone(RRDHOST *host, const char *timezone, const char *abbrev_timezone, int32_t utc_offset) {
  158. if (host->timezone && timezone && !strcmp(rrdhost_timezone(host), timezone) && host->abbrev_timezone && abbrev_timezone &&
  159. !strcmp(rrdhost_abbrev_timezone(host), abbrev_timezone) && host->utc_offset == utc_offset)
  160. return;
  161. STRING *old = host->timezone;
  162. host->timezone = string_strdupz((timezone && *timezone)?timezone:"unknown");
  163. string_freez(old);
  164. old = (void *)host->abbrev_timezone;
  165. host->abbrev_timezone = string_strdupz((abbrev_timezone && *abbrev_timezone) ? abbrev_timezone : "UTC");
  166. string_freez(old);
  167. host->utc_offset = utc_offset;
  168. }
  169. void set_host_properties(RRDHOST *host, int update_every, RRD_MEMORY_MODE memory_mode,
  170. const char *registry_hostname, const char *os, const char *tzone,
  171. const char *abbrev_tzone, int32_t utc_offset, const char *prog_name,
  172. const char *prog_version)
  173. {
  174. host->rrd_update_every = update_every;
  175. host->rrd_memory_mode = memory_mode;
  176. rrdhost_init_os(host, os);
  177. rrdhost_init_timezone(host, tzone, abbrev_tzone, utc_offset);
  178. host->program_name = string_strdupz((prog_name && *prog_name) ? prog_name : "unknown");
  179. host->program_version = string_strdupz((prog_version && *prog_version) ? prog_version : "unknown");
  180. host->registry_hostname = string_strdupz((registry_hostname && *registry_hostname) ? registry_hostname : rrdhost_hostname(host));
  181. }
  182. // ----------------------------------------------------------------------------
  183. // RRDHOST - add a host
  184. static void rrdhost_initialize_rrdpush_sender(RRDHOST *host,
  185. unsigned int rrdpush_enabled,
  186. char *rrdpush_destination,
  187. char *rrdpush_api_key,
  188. char *rrdpush_send_charts_matching
  189. ) {
  190. if(rrdhost_flag_check(host, RRDHOST_FLAG_RRDPUSH_SENDER_INITIALIZED)) return;
  191. if(rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key) {
  192. rrdhost_flag_set(host, RRDHOST_FLAG_RRDPUSH_SENDER_INITIALIZED);
  193. rrdhost_streaming_sender_structures_init(host);
  194. #ifdef ENABLE_HTTPS
  195. host->sender->ssl = NETDATA_SSL_UNSET_CONNECTION;
  196. #endif
  197. host->rrdpush_send_destination = strdupz(rrdpush_destination);
  198. rrdpush_destinations_init(host);
  199. host->rrdpush_send_api_key = strdupz(rrdpush_api_key);
  200. host->rrdpush_send_charts_matching = simple_pattern_create(rrdpush_send_charts_matching, NULL,
  201. SIMPLE_PATTERN_EXACT, true);
  202. rrdhost_option_set(host, RRDHOST_OPTION_SENDER_ENABLED);
  203. }
  204. else
  205. rrdhost_option_clear(host, RRDHOST_OPTION_SENDER_ENABLED);
  206. }
  207. static RRDHOST *rrdhost_create(
  208. const char *hostname,
  209. const char *registry_hostname,
  210. const char *guid,
  211. const char *os,
  212. const char *timezone,
  213. const char *abbrev_timezone,
  214. int32_t utc_offset,
  215. const char *prog_name,
  216. const char *prog_version,
  217. int update_every,
  218. long entries,
  219. RRD_MEMORY_MODE memory_mode,
  220. unsigned int health_enabled,
  221. unsigned int rrdpush_enabled,
  222. char *rrdpush_destination,
  223. char *rrdpush_api_key,
  224. char *rrdpush_send_charts_matching,
  225. bool rrdpush_enable_replication,
  226. time_t rrdpush_seconds_to_replicate,
  227. time_t rrdpush_replication_step,
  228. struct rrdhost_system_info *system_info,
  229. int is_localhost,
  230. bool archived
  231. ) {
  232. if(memory_mode == RRD_MEMORY_MODE_DBENGINE && !dbengine_enabled) {
  233. nd_log(NDLS_DAEMON, NDLP_ERR,
  234. "memory mode 'dbengine' is not enabled, but host '%s' is configured for it. Falling back to 'alloc'",
  235. hostname);
  236. memory_mode = RRD_MEMORY_MODE_ALLOC;
  237. }
  238. #ifdef ENABLE_DBENGINE
  239. int is_legacy = (memory_mode == RRD_MEMORY_MODE_DBENGINE) && is_legacy_child(guid);
  240. #else
  241. int is_legacy = 1;
  242. #endif
  243. int is_in_multihost = (memory_mode == RRD_MEMORY_MODE_DBENGINE && !is_legacy);
  244. RRDHOST *host = callocz(1, sizeof(RRDHOST));
  245. __atomic_add_fetch(&netdata_buffers_statistics.rrdhost_allocations_size, sizeof(RRDHOST), __ATOMIC_RELAXED);
  246. strncpyz(host->machine_guid, guid, GUID_LEN + 1);
  247. set_host_properties(host, (update_every > 0)?update_every:1, memory_mode, registry_hostname, os,
  248. timezone, abbrev_timezone, utc_offset,
  249. prog_name,
  250. prog_version);
  251. rrdhost_init_hostname(host, hostname, false);
  252. host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries);
  253. host->health.health_enabled = ((memory_mode == RRD_MEMORY_MODE_NONE)) ? 0 : health_enabled;
  254. netdata_mutex_init(&host->aclk_state_lock);
  255. netdata_mutex_init(&host->receiver_lock);
  256. if (likely(!archived)) {
  257. rrd_functions_host_init(host);
  258. host->last_connected = now_realtime_sec();
  259. host->rrdlabels = rrdlabels_create();
  260. rrdhost_initialize_rrdpush_sender(
  261. host, rrdpush_enabled, rrdpush_destination, rrdpush_api_key, rrdpush_send_charts_matching);
  262. }
  263. if(rrdpush_enable_replication)
  264. rrdhost_option_set(host, RRDHOST_OPTION_REPLICATION);
  265. else
  266. rrdhost_option_clear(host, RRDHOST_OPTION_REPLICATION);
  267. host->rrdpush_seconds_to_replicate = rrdpush_seconds_to_replicate;
  268. host->rrdpush_replication_step = rrdpush_replication_step;
  269. host->rrdpush_receiver_replication_percent = 100.0;
  270. switch(memory_mode) {
  271. default:
  272. case RRD_MEMORY_MODE_ALLOC:
  273. case RRD_MEMORY_MODE_RAM:
  274. if(host->rrdpush_seconds_to_replicate > (time_t) host->rrd_history_entries * (time_t) host->rrd_update_every)
  275. host->rrdpush_seconds_to_replicate = (time_t) host->rrd_history_entries * (time_t) host->rrd_update_every;
  276. break;
  277. case RRD_MEMORY_MODE_DBENGINE:
  278. break;
  279. }
  280. host->system_info = system_info;
  281. rrdset_index_init(host);
  282. if(config_get_boolean(CONFIG_SECTION_DB, "delete obsolete charts files", 1))
  283. rrdhost_option_set(host, RRDHOST_OPTION_DELETE_OBSOLETE_CHARTS);
  284. if(config_get_boolean(CONFIG_SECTION_DB, "delete orphan hosts files", 1) && !is_localhost)
  285. rrdhost_option_set(host, RRDHOST_OPTION_DELETE_ORPHAN_HOST);
  286. char filename[FILENAME_MAX + 1];
  287. if(is_localhost)
  288. host->cache_dir = strdupz(netdata_configured_cache_dir);
  289. else {
  290. // this is not localhost - append our GUID to localhost path
  291. if (is_in_multihost) { // don't append to cache dir in multihost
  292. host->cache_dir = strdupz(netdata_configured_cache_dir);
  293. }
  294. else {
  295. snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid);
  296. host->cache_dir = strdupz(filename);
  297. }
  298. if(host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE && is_legacy)
  299. {
  300. int r = mkdir(host->cache_dir, 0775);
  301. if(r != 0 && errno != EEXIST)
  302. nd_log(NDLS_DAEMON, NDLP_CRIT,
  303. "Host '%s': cannot create directory '%s'",
  304. rrdhost_hostname(host), host->cache_dir);
  305. }
  306. }
  307. // this is also needed for custom host variables - not only health
  308. if(!host->rrdvars)
  309. host->rrdvars = rrdvariables_create();
  310. if (likely(!uuid_parse(host->machine_guid, host->host_uuid)))
  311. sql_load_node_id(host);
  312. else
  313. error_report("Host machine GUID %s is not valid", host->machine_guid);
  314. rrdcalc_rrdhost_index_init(host);
  315. if (host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
  316. #ifdef ENABLE_DBENGINE
  317. char dbenginepath[FILENAME_MAX + 1];
  318. int ret;
  319. snprintfz(dbenginepath, FILENAME_MAX, "%s/dbengine", host->cache_dir);
  320. ret = mkdir(dbenginepath, 0775);
  321. if (ret != 0 && errno != EEXIST)
  322. nd_log(NDLS_DAEMON, NDLP_CRIT,
  323. "Host '%s': cannot create directory '%s'",
  324. rrdhost_hostname(host), dbenginepath);
  325. else
  326. ret = 0; // succeed
  327. if (is_legacy) {
  328. // initialize legacy dbengine instance as needed
  329. host->db[0].mode = RRD_MEMORY_MODE_DBENGINE;
  330. host->db[0].eng = storage_engine_get(host->db[0].mode);
  331. host->db[0].tier_grouping = get_tier_grouping(0);
  332. ret = rrdeng_init(
  333. (struct rrdengine_instance **)&host->db[0].si,
  334. dbenginepath,
  335. default_rrdeng_disk_quota_mb,
  336. 0); // may fail here for legacy dbengine initialization
  337. if(ret == 0) {
  338. rrdeng_readiness_wait((struct rrdengine_instance *)host->db[0].si);
  339. // assign the rest of the shared storage instances to it
  340. // to allow them collect its metrics too
  341. for(size_t tier = 1; tier < storage_tiers ; tier++) {
  342. host->db[tier].mode = RRD_MEMORY_MODE_DBENGINE;
  343. host->db[tier].eng = storage_engine_get(host->db[tier].mode);
  344. host->db[tier].si = (STORAGE_INSTANCE *) multidb_ctx[tier];
  345. host->db[tier].tier_grouping = get_tier_grouping(tier);
  346. }
  347. }
  348. }
  349. else {
  350. for(size_t tier = 0; tier < storage_tiers ; tier++) {
  351. host->db[tier].mode = RRD_MEMORY_MODE_DBENGINE;
  352. host->db[tier].eng = storage_engine_get(host->db[tier].mode);
  353. host->db[tier].si = (STORAGE_INSTANCE *)multidb_ctx[tier];
  354. host->db[tier].tier_grouping = get_tier_grouping(tier);
  355. }
  356. }
  357. if (ret) { // check legacy or multihost initialization success
  358. nd_log(NDLS_DAEMON, NDLP_CRIT,
  359. "Host '%s': cannot initialize host with machine guid '%s'. Failed to initialize DB engine at '%s'.",
  360. rrdhost_hostname(host), host->machine_guid, host->cache_dir);
  361. rrd_wrlock();
  362. rrdhost_free___while_having_rrd_wrlock(host, true);
  363. rrd_unlock();
  364. return NULL;
  365. }
  366. #else
  367. fatal("RRD_MEMORY_MODE_DBENGINE is not supported in this platform.");
  368. #endif
  369. }
  370. else {
  371. host->db[0].mode = host->rrd_memory_mode;
  372. host->db[0].eng = storage_engine_get(host->db[0].mode);
  373. host->db[0].si = NULL;
  374. host->db[0].tier_grouping = get_tier_grouping(0);
  375. #ifdef ENABLE_DBENGINE
  376. // the first tier is reserved for the non-dbengine modes
  377. for(size_t tier = 1; tier < storage_tiers ; tier++) {
  378. host->db[tier].mode = RRD_MEMORY_MODE_DBENGINE;
  379. host->db[tier].eng = storage_engine_get(host->db[tier].mode);
  380. host->db[tier].si = (STORAGE_INSTANCE *) multidb_ctx[tier];
  381. host->db[tier].tier_grouping = get_tier_grouping(tier);
  382. }
  383. #endif
  384. }
  385. // ------------------------------------------------------------------------
  386. // init new ML host and update system_info to let upstreams know
  387. // about ML functionality
  388. //
  389. if (is_localhost && host->system_info) {
  390. host->system_info->ml_capable = ml_capable();
  391. host->system_info->ml_enabled = ml_enabled(host);
  392. host->system_info->mc_version = enable_metric_correlations ? metric_correlations_version : 0;
  393. }
  394. // ------------------------------------------------------------------------
  395. // link it and add it to the index
  396. rrd_wrlock();
  397. RRDHOST *t = rrdhost_index_add_by_guid(host);
  398. if(t != host) {
  399. nd_log(NDLS_DAEMON, NDLP_NOTICE,
  400. "Host '%s': cannot add host with machine guid '%s' to index. It already exists as host '%s' with machine guid '%s'.",
  401. rrdhost_hostname(host), host->machine_guid, rrdhost_hostname(t), t->machine_guid);
  402. if (!is_localhost)
  403. rrdhost_free___while_having_rrd_wrlock(host, true);
  404. rrd_unlock();
  405. return NULL;
  406. }
  407. rrdhost_index_add_hostname(host);
  408. if(is_localhost)
  409. DOUBLE_LINKED_LIST_PREPEND_ITEM_UNSAFE(localhost, host, prev, next);
  410. else
  411. DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(localhost, host, prev, next);
  412. rrd_unlock();
  413. // ------------------------------------------------------------------------
  414. nd_log(NDLS_DAEMON, NDLP_INFO,
  415. "Host '%s' (at registry as '%s') with guid '%s' initialized"
  416. ", os '%s'"
  417. ", timezone '%s'"
  418. ", program_name '%s'"
  419. ", program_version '%s'"
  420. ", update every %d"
  421. ", memory mode %s"
  422. ", history entries %d"
  423. ", streaming %s"
  424. " (to '%s' with api key '%s')"
  425. ", health %s"
  426. ", cache_dir '%s'"
  427. ", alarms default handler '%s'"
  428. ", alarms default recipient '%s'"
  429. , rrdhost_hostname(host)
  430. , rrdhost_registry_hostname(host)
  431. , host->machine_guid
  432. , rrdhost_os(host)
  433. , rrdhost_timezone(host)
  434. , rrdhost_program_name(host)
  435. , rrdhost_program_version(host)
  436. , host->rrd_update_every
  437. , rrd_memory_mode_name(host->rrd_memory_mode)
  438. , host->rrd_history_entries
  439. , rrdhost_has_rrdpush_sender_enabled(host)?"enabled":"disabled"
  440. , host->rrdpush_send_destination?host->rrdpush_send_destination:""
  441. , host->rrdpush_send_api_key?host->rrdpush_send_api_key:""
  442. , host->health.health_enabled?"enabled":"disabled"
  443. , host->cache_dir
  444. , string2str(host->health.health_default_exec)
  445. , string2str(host->health.health_default_recipient)
  446. );
  447. if(!archived) {
  448. metaqueue_host_update_info(host);
  449. rrdhost_load_rrdcontext_data(host);
  450. // rrdhost_flag_set(host, RRDHOST_FLAG_METADATA_INFO | RRDHOST_FLAG_METADATA_UPDATE);
  451. ml_host_new(host);
  452. } else
  453. rrdhost_flag_set(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD | RRDHOST_FLAG_ARCHIVED | RRDHOST_FLAG_ORPHAN);
  454. return host;
  455. }
  456. static void rrdhost_update(RRDHOST *host
  457. , const char *hostname
  458. , const char *registry_hostname
  459. , const char *guid
  460. , const char *os
  461. , const char *timezone
  462. , const char *abbrev_timezone
  463. , int32_t utc_offset
  464. , const char *prog_name
  465. , const char *prog_version
  466. , int update_every
  467. , long history
  468. , RRD_MEMORY_MODE mode
  469. , unsigned int health_enabled
  470. , unsigned int rrdpush_enabled
  471. , char *rrdpush_destination
  472. , char *rrdpush_api_key
  473. , char *rrdpush_send_charts_matching
  474. , bool rrdpush_enable_replication
  475. , time_t rrdpush_seconds_to_replicate
  476. , time_t rrdpush_replication_step
  477. , struct rrdhost_system_info *system_info
  478. )
  479. {
  480. UNUSED(guid);
  481. spinlock_lock(&host->rrdhost_update_lock);
  482. host->health.health_enabled = (mode == RRD_MEMORY_MODE_NONE) ? 0 : health_enabled;
  483. {
  484. struct rrdhost_system_info *old = host->system_info;
  485. host->system_info = system_info;
  486. rrdhost_flag_set(host, RRDHOST_FLAG_METADATA_INFO | RRDHOST_FLAG_METADATA_CLAIMID | RRDHOST_FLAG_METADATA_UPDATE);
  487. rrdhost_system_info_free(old);
  488. }
  489. rrdhost_init_os(host, os);
  490. rrdhost_init_timezone(host, timezone, abbrev_timezone, utc_offset);
  491. string_freez(host->registry_hostname);
  492. host->registry_hostname = string_strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname);
  493. if(strcmp(rrdhost_hostname(host), hostname) != 0) {
  494. nd_log(NDLS_DAEMON, NDLP_WARNING,
  495. "Host '%s' has been renamed to '%s'. If this is not intentional it may mean multiple hosts are using the same machine_guid.",
  496. rrdhost_hostname(host), hostname);
  497. rrdhost_init_hostname(host, hostname, true);
  498. } else {
  499. rrdhost_index_add_hostname(host);
  500. }
  501. if(strcmp(rrdhost_program_name(host), prog_name) != 0) {
  502. nd_log(NDLS_DAEMON, NDLP_NOTICE,
  503. "Host '%s' switched program name from '%s' to '%s'",
  504. rrdhost_hostname(host), rrdhost_program_name(host),
  505. prog_name);
  506. STRING *t = host->program_name;
  507. host->program_name = string_strdupz(prog_name);
  508. string_freez(t);
  509. }
  510. if(strcmp(rrdhost_program_version(host), prog_version) != 0) {
  511. nd_log(NDLS_DAEMON, NDLP_NOTICE,
  512. "Host '%s' switched program version from '%s' to '%s'",
  513. rrdhost_hostname(host), rrdhost_program_version(host),
  514. prog_version);
  515. STRING *t = host->program_version;
  516. host->program_version = string_strdupz(prog_version);
  517. string_freez(t);
  518. }
  519. if(host->rrd_update_every != update_every)
  520. nd_log(NDLS_DAEMON, NDLP_WARNING,
  521. "Host '%s' has an update frequency of %d seconds, but the wanted one is %d seconds. "
  522. "Restart netdata here to apply the new settings.",
  523. rrdhost_hostname(host), host->rrd_update_every, update_every);
  524. if(host->rrd_memory_mode != mode)
  525. nd_log(NDLS_DAEMON, NDLP_WARNING,
  526. "Host '%s' has memory mode '%s', but the wanted one is '%s'. "
  527. "Restart netdata here to apply the new settings.",
  528. rrdhost_hostname(host),
  529. rrd_memory_mode_name(host->rrd_memory_mode),
  530. rrd_memory_mode_name(mode));
  531. else if(host->rrd_memory_mode != RRD_MEMORY_MODE_DBENGINE && host->rrd_history_entries < history)
  532. nd_log(NDLS_DAEMON, NDLP_WARNING,
  533. "Host '%s' has history of %d entries, but the wanted one is %ld entries. "
  534. "Restart netdata here to apply the new settings.",
  535. rrdhost_hostname(host),
  536. host->rrd_history_entries,
  537. history);
  538. if(!host->rrdvars)
  539. host->rrdvars = rrdvariables_create();
  540. host->last_connected = now_realtime_sec();
  541. if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED)) {
  542. rrdhost_flag_clear(host, RRDHOST_FLAG_ARCHIVED);
  543. rrd_functions_host_init(host);
  544. if(!host->rrdlabels)
  545. host->rrdlabels = rrdlabels_create();
  546. if (!host->rrdset_root_index)
  547. rrdset_index_init(host);
  548. rrdhost_initialize_rrdpush_sender(host,
  549. rrdpush_enabled,
  550. rrdpush_destination,
  551. rrdpush_api_key,
  552. rrdpush_send_charts_matching);
  553. rrdcalc_rrdhost_index_init(host);
  554. if(rrdpush_enable_replication)
  555. rrdhost_option_set(host, RRDHOST_OPTION_REPLICATION);
  556. else
  557. rrdhost_option_clear(host, RRDHOST_OPTION_REPLICATION);
  558. host->rrdpush_seconds_to_replicate = rrdpush_seconds_to_replicate;
  559. host->rrdpush_replication_step = rrdpush_replication_step;
  560. ml_host_new(host);
  561. rrdhost_load_rrdcontext_data(host);
  562. nd_log(NDLS_DAEMON, NDLP_DEBUG,
  563. "Host %s is not in archived mode anymore",
  564. rrdhost_hostname(host));
  565. }
  566. spinlock_unlock(&host->rrdhost_update_lock);
  567. }
  568. RRDHOST *rrdhost_find_or_create(
  569. const char *hostname
  570. , const char *registry_hostname
  571. , const char *guid
  572. , const char *os
  573. , const char *timezone
  574. , const char *abbrev_timezone
  575. , int32_t utc_offset
  576. , const char *prog_name
  577. , const char *prog_version
  578. , int update_every
  579. , long history
  580. , RRD_MEMORY_MODE mode
  581. , unsigned int health_enabled
  582. , unsigned int rrdpush_enabled
  583. , char *rrdpush_destination
  584. , char *rrdpush_api_key
  585. , char *rrdpush_send_charts_matching
  586. , bool rrdpush_enable_replication
  587. , time_t rrdpush_seconds_to_replicate
  588. , time_t rrdpush_replication_step
  589. , struct rrdhost_system_info *system_info
  590. , bool archived
  591. ) {
  592. RRDHOST *host = rrdhost_find_by_guid(guid);
  593. if (unlikely(host && host->rrd_memory_mode != mode && rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED))) {
  594. if (likely(!archived && rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD)))
  595. return host;
  596. /* If a legacy memory mode instantiates all dbengine state must be discarded to avoid inconsistencies */
  597. nd_log(NDLS_DAEMON, NDLP_INFO,
  598. "Archived host '%s' has memory mode '%s', but the wanted one is '%s'. Discarding archived state.",
  599. rrdhost_hostname(host),
  600. rrd_memory_mode_name(host->rrd_memory_mode),
  601. rrd_memory_mode_name(mode));
  602. rrd_wrlock();
  603. rrdhost_free___while_having_rrd_wrlock(host, true);
  604. host = NULL;
  605. rrd_unlock();
  606. }
  607. if(!host) {
  608. host = rrdhost_create(
  609. hostname
  610. , registry_hostname
  611. , guid
  612. , os
  613. , timezone
  614. , abbrev_timezone
  615. , utc_offset
  616. , prog_name
  617. , prog_version
  618. , update_every
  619. , history
  620. , mode
  621. , health_enabled
  622. , rrdpush_enabled
  623. , rrdpush_destination
  624. , rrdpush_api_key
  625. , rrdpush_send_charts_matching
  626. , rrdpush_enable_replication
  627. , rrdpush_seconds_to_replicate
  628. , rrdpush_replication_step
  629. , system_info
  630. , 0
  631. , archived
  632. );
  633. }
  634. else {
  635. if (likely(!rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD)))
  636. rrdhost_update(host
  637. , hostname
  638. , registry_hostname
  639. , guid
  640. , os
  641. , timezone
  642. , abbrev_timezone
  643. , utc_offset
  644. , prog_name
  645. , prog_version
  646. , update_every
  647. , history
  648. , mode
  649. , health_enabled
  650. , rrdpush_enabled
  651. , rrdpush_destination
  652. , rrdpush_api_key
  653. , rrdpush_send_charts_matching
  654. , rrdpush_enable_replication
  655. , rrdpush_seconds_to_replicate
  656. , rrdpush_replication_step
  657. , system_info);
  658. }
  659. return host;
  660. }
  661. inline int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected_host, time_t now_s) {
  662. if(host != protected_host
  663. && host != localhost
  664. && rrdhost_receiver_replicating_charts(host) == 0
  665. && rrdhost_sender_replicating_charts(host) == 0
  666. && rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN)
  667. && !rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD)
  668. && !host->receiver
  669. && host->child_disconnected_time
  670. && host->child_disconnected_time + rrdhost_free_orphan_time_s < now_s)
  671. return 1;
  672. return 0;
  673. }
  674. // ----------------------------------------------------------------------------
  675. // RRDHOST global / startup initialization
  676. #ifdef ENABLE_DBENGINE
  677. struct dbengine_initialization {
  678. netdata_thread_t thread;
  679. char path[FILENAME_MAX + 1];
  680. int disk_space_mb;
  681. size_t tier;
  682. int ret;
  683. };
  684. void *dbengine_tier_init(void *ptr) {
  685. struct dbengine_initialization *dbi = ptr;
  686. dbi->ret = rrdeng_init(NULL, dbi->path, dbi->disk_space_mb, dbi->tier);
  687. return ptr;
  688. }
  689. #endif
  690. void dbengine_init(char *hostname) {
  691. #ifdef ENABLE_DBENGINE
  692. use_direct_io = config_get_boolean(CONFIG_SECTION_DB, "dbengine use direct io", use_direct_io);
  693. unsigned read_num = (unsigned)config_get_number(CONFIG_SECTION_DB, "dbengine pages per extent", MAX_PAGES_PER_EXTENT);
  694. if (read_num > 0 && read_num <= MAX_PAGES_PER_EXTENT)
  695. rrdeng_pages_per_extent = read_num;
  696. else {
  697. nd_log(NDLS_DAEMON, NDLP_WARNING,
  698. "Invalid dbengine pages per extent %u given. Using %u.",
  699. read_num, rrdeng_pages_per_extent);
  700. config_set_number(CONFIG_SECTION_DB, "dbengine pages per extent", rrdeng_pages_per_extent);
  701. }
  702. storage_tiers = config_get_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  703. if(storage_tiers < 1) {
  704. nd_log(NDLS_DAEMON, NDLP_WARNING,
  705. "At least 1 storage tier is required. Assuming 1.");
  706. storage_tiers = 1;
  707. config_set_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  708. }
  709. if(storage_tiers > RRD_STORAGE_TIERS) {
  710. nd_log(NDLS_DAEMON, NDLP_WARNING,
  711. "Up to %d storage tier are supported. Assuming %d.",
  712. RRD_STORAGE_TIERS, RRD_STORAGE_TIERS);
  713. storage_tiers = RRD_STORAGE_TIERS;
  714. config_set_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  715. }
  716. bool parallel_initialization = (storage_tiers <= (size_t)get_netdata_cpus()) ? true : false;
  717. parallel_initialization = config_get_boolean(CONFIG_SECTION_DB, "dbengine parallel initialization", parallel_initialization);
  718. struct dbengine_initialization tiers_init[RRD_STORAGE_TIERS] = {};
  719. bool tiers_adjusted = false;
  720. size_t created_tiers = 0;
  721. char dbenginepath[FILENAME_MAX + 1];
  722. char dbengineconfig[200 + 1];
  723. int divisor = 1;
  724. for(size_t tier = 0; tier < storage_tiers ;tier++) {
  725. if(tier > 0)
  726. divisor *= 2;
  727. int disk_space_mb = default_multidb_disk_quota_mb / divisor;
  728. size_t grouping_iterations = storage_tiers_grouping_iterations[tier];
  729. RRD_BACKFILL backfill = storage_tiers_backfill[tier];
  730. if(tier > 0) {
  731. snprintfz(dbengineconfig, sizeof(dbengineconfig) - 1, "dbengine tier %zu multihost disk space MB", tier);
  732. disk_space_mb = config_get_number(CONFIG_SECTION_DB, dbengineconfig, disk_space_mb);
  733. snprintfz(dbengineconfig, sizeof(dbengineconfig) - 1, "dbengine tier %zu update every iterations", tier);
  734. grouping_iterations = config_get_number(CONFIG_SECTION_DB, dbengineconfig, grouping_iterations);
  735. if(grouping_iterations < 2) {
  736. grouping_iterations = 2;
  737. config_set_number(CONFIG_SECTION_DB, dbengineconfig, grouping_iterations);
  738. nd_log(NDLS_DAEMON, NDLP_WARNING,
  739. "DBENGINE on '%s': 'dbegnine tier %zu update every iterations' cannot be less than 2. Assuming 2.",
  740. hostname, tier);
  741. }
  742. snprintfz(dbengineconfig, sizeof(dbengineconfig) - 1, "dbengine tier %zu backfill", tier);
  743. const char *bf = config_get(CONFIG_SECTION_DB, dbengineconfig, backfill == RRD_BACKFILL_NEW ? "new" : backfill == RRD_BACKFILL_FULL ? "full" : "none");
  744. if(strcmp(bf, "new") == 0) backfill = RRD_BACKFILL_NEW;
  745. else if(strcmp(bf, "full") == 0) backfill = RRD_BACKFILL_FULL;
  746. else if(strcmp(bf, "none") == 0) backfill = RRD_BACKFILL_NONE;
  747. else {
  748. nd_log(NDLS_DAEMON, NDLP_WARNING, "DBENGINE: unknown backfill value '%s', assuming 'new'", bf);
  749. config_set(CONFIG_SECTION_DB, dbengineconfig, "new");
  750. backfill = RRD_BACKFILL_NEW;
  751. }
  752. }
  753. storage_tiers_grouping_iterations[tier] = grouping_iterations;
  754. storage_tiers_backfill[tier] = backfill;
  755. if(tier > 0 && get_tier_grouping(tier) > 65535) {
  756. storage_tiers_grouping_iterations[tier] = 1;
  757. nd_log(NDLS_DAEMON, NDLP_WARNING,
  758. "DBENGINE on '%s': dbengine tier %zu gives aggregation of more than 65535 points of tier 0. "
  759. "Disabling tiers %zu and above",
  760. hostname, tier, tier);
  761. storage_tiers = tier;
  762. tiers_adjusted = true;
  763. break;
  764. }
  765. if(tier == 0)
  766. snprintfz(dbenginepath, FILENAME_MAX, "%s/dbengine", netdata_configured_cache_dir);
  767. else
  768. snprintfz(dbenginepath, FILENAME_MAX, "%s/dbengine-tier%zu", netdata_configured_cache_dir, tier);
  769. int ret = mkdir(dbenginepath, 0775);
  770. if (ret != 0 && errno != EEXIST) {
  771. nd_log(NDLS_DAEMON, NDLP_CRIT, "DBENGINE on '%s': cannot create directory '%s'", hostname, dbenginepath);
  772. break;
  773. }
  774. internal_error(true, "DBENGINE tier %zu grouping iterations is set to %zu", tier, storage_tiers_grouping_iterations[tier]);
  775. tiers_init[tier].disk_space_mb = disk_space_mb;
  776. tiers_init[tier].tier = tier;
  777. strncpyz(tiers_init[tier].path, dbenginepath, FILENAME_MAX);
  778. tiers_init[tier].ret = 0;
  779. if(parallel_initialization) {
  780. char tag[NETDATA_THREAD_TAG_MAX + 1];
  781. snprintfz(tag, NETDATA_THREAD_TAG_MAX, "DBENGINIT[%zu]", tier);
  782. netdata_thread_create(&tiers_init[tier].thread, tag, NETDATA_THREAD_OPTION_JOINABLE,
  783. dbengine_tier_init, &tiers_init[tier]);
  784. }
  785. else
  786. dbengine_tier_init(&tiers_init[tier]);
  787. }
  788. if (tiers_adjusted)
  789. config_set_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  790. for(size_t tier = 0; tier < storage_tiers ;tier++) {
  791. void *ptr;
  792. if(parallel_initialization)
  793. netdata_thread_join(tiers_init[tier].thread, &ptr);
  794. if(tiers_init[tier].ret != 0) {
  795. nd_log(NDLS_DAEMON, NDLP_ERR,
  796. "DBENGINE on '%s': Failed to initialize multi-host database tier %zu on path '%s'",
  797. hostname, tiers_init[tier].tier, tiers_init[tier].path);
  798. }
  799. else if(created_tiers == tier)
  800. created_tiers++;
  801. }
  802. if(created_tiers && created_tiers < storage_tiers) {
  803. nd_log(NDLS_DAEMON, NDLP_WARNING,
  804. "DBENGINE on '%s': Managed to create %zu tiers instead of %zu. Continuing with %zu available.",
  805. hostname, created_tiers, storage_tiers, created_tiers);
  806. storage_tiers = created_tiers;
  807. }
  808. else if(!created_tiers)
  809. fatal("DBENGINE on '%s', failed to initialize databases at '%s'.", hostname, netdata_configured_cache_dir);
  810. for(size_t tier = 0; tier < storage_tiers ;tier++)
  811. rrdeng_readiness_wait(multidb_ctx[tier]);
  812. dbengine_enabled = true;
  813. #else
  814. storage_tiers = config_get_number(CONFIG_SECTION_DB, "storage tiers", 1);
  815. if(storage_tiers != 1) {
  816. nd_log(NDLS_DAEMON, NDLP_WARNING,
  817. "DBENGINE is not available on '%s', so only 1 database tier can be supported.",
  818. hostname);
  819. storage_tiers = 1;
  820. config_set_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  821. }
  822. dbengine_enabled = false;
  823. #endif
  824. }
  825. int rrd_init(char *hostname, struct rrdhost_system_info *system_info, bool unittest) {
  826. rrdhost_init();
  827. if (unlikely(sql_init_meta_database(DB_CHECK_NONE, system_info ? 0 : 1))) {
  828. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
  829. set_late_global_environment(system_info);
  830. fatal("Failed to initialize SQLite");
  831. }
  832. nd_log(NDLS_DAEMON, NDLP_DEBUG,
  833. "Skipping SQLITE metadata initialization since memory mode is not dbengine");
  834. }
  835. if (unlikely(sql_init_context_database(system_info ? 0 : 1))) {
  836. error_report("Failed to initialize context metadata database");
  837. }
  838. if (unlikely(unittest)) {
  839. dbengine_enabled = true;
  840. }
  841. else {
  842. rrdpush_init();
  843. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE || rrdpush_receiver_needs_dbengine()) {
  844. nd_log(NDLS_DAEMON, NDLP_DEBUG,
  845. "DBENGINE: Initializing ...");
  846. dbengine_init(hostname);
  847. }
  848. else
  849. storage_tiers = 1;
  850. if (!dbengine_enabled) {
  851. if (storage_tiers > 1) {
  852. nd_log(NDLS_DAEMON, NDLP_WARNING,
  853. "dbengine is not enabled, but %zu tiers have been requested. Resetting tiers to 1",
  854. storage_tiers);
  855. storage_tiers = 1;
  856. }
  857. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
  858. nd_log(NDLS_DAEMON, NDLP_WARNING,
  859. "dbengine is not enabled, but it has been given as the default db mode. "
  860. "Resetting db mode to alloc");
  861. default_rrd_memory_mode = RRD_MEMORY_MODE_ALLOC;
  862. }
  863. }
  864. }
  865. if(!unittest)
  866. metadata_sync_init();
  867. localhost = rrdhost_create(
  868. hostname
  869. , registry_get_this_machine_hostname()
  870. , registry_get_this_machine_guid()
  871. , os_type
  872. , netdata_configured_timezone
  873. , netdata_configured_abbrev_timezone
  874. , netdata_configured_utc_offset
  875. , program_name
  876. , program_version
  877. , default_rrd_update_every
  878. , default_rrd_history_entries
  879. , default_rrd_memory_mode
  880. , health_plugin_enabled()
  881. , default_rrdpush_enabled
  882. , default_rrdpush_destination
  883. , default_rrdpush_api_key
  884. , default_rrdpush_send_charts_matching
  885. , default_rrdpush_enable_replication
  886. , default_rrdpush_seconds_to_replicate
  887. , default_rrdpush_replication_step
  888. , system_info
  889. , 1
  890. , 0
  891. );
  892. if (unlikely(!localhost))
  893. return 1;
  894. dyncfg_host_init(localhost);
  895. if(!unittest) {
  896. health_plugin_init();
  897. }
  898. // we register this only on localhost
  899. // for the other nodes, the origin server should register it
  900. rrd_function_add_inline(localhost, NULL, "streaming", 10,
  901. RRDFUNCTIONS_PRIORITY_DEFAULT + 1, RRDFUNCTIONS_STREAMING_HELP, "top",
  902. HTTP_ACCESS_SIGNED_ID | HTTP_ACCESS_SAME_SPACE | HTTP_ACCESS_SENSITIVE_DATA,
  903. rrdhost_function_streaming);
  904. rrd_function_add_inline(localhost, NULL, "netdata-api-calls", 10,
  905. RRDFUNCTIONS_PRIORITY_DEFAULT + 2, RRDFUNCTIONS_PROGRESS_HELP, "top",
  906. HTTP_ACCESS_SIGNED_ID | HTTP_ACCESS_SAME_SPACE | HTTP_ACCESS_SENSITIVE_DATA,
  907. rrdhost_function_progress);
  908. if (likely(system_info)) {
  909. detect_machine_guid_change(&localhost->host_uuid);
  910. sql_aclk_sync_init();
  911. web_client_api_v1_management_init();
  912. }
  913. return 0;
  914. }
  915. // ----------------------------------------------------------------------------
  916. // RRDHOST - free
  917. void rrdhost_system_info_free(struct rrdhost_system_info *system_info) {
  918. if(likely(system_info)) {
  919. __atomic_sub_fetch(&netdata_buffers_statistics.rrdhost_allocations_size, sizeof(struct rrdhost_system_info), __ATOMIC_RELAXED);
  920. freez(system_info->cloud_provider_type);
  921. freez(system_info->cloud_instance_type);
  922. freez(system_info->cloud_instance_region);
  923. freez(system_info->host_os_name);
  924. freez(system_info->host_os_id);
  925. freez(system_info->host_os_id_like);
  926. freez(system_info->host_os_version);
  927. freez(system_info->host_os_version_id);
  928. freez(system_info->host_os_detection);
  929. freez(system_info->host_cores);
  930. freez(system_info->host_cpu_freq);
  931. freez(system_info->host_ram_total);
  932. freez(system_info->host_disk_space);
  933. freez(system_info->container_os_name);
  934. freez(system_info->container_os_id);
  935. freez(system_info->container_os_id_like);
  936. freez(system_info->container_os_version);
  937. freez(system_info->container_os_version_id);
  938. freez(system_info->container_os_detection);
  939. freez(system_info->kernel_name);
  940. freez(system_info->kernel_version);
  941. freez(system_info->architecture);
  942. freez(system_info->virtualization);
  943. freez(system_info->virt_detection);
  944. freez(system_info->container);
  945. freez(system_info->container_detection);
  946. freez(system_info->is_k8s_node);
  947. freez(system_info->install_type);
  948. freez(system_info->prebuilt_arch);
  949. freez(system_info->prebuilt_dist);
  950. freez(system_info);
  951. }
  952. }
  953. static void rrdhost_streaming_sender_structures_init(RRDHOST *host)
  954. {
  955. if (host->sender)
  956. return;
  957. host->sender = callocz(1, sizeof(*host->sender));
  958. __atomic_add_fetch(&netdata_buffers_statistics.rrdhost_senders, sizeof(*host->sender), __ATOMIC_RELAXED);
  959. host->sender->host = host;
  960. host->sender->buffer = cbuffer_new(CBUFFER_INITIAL_SIZE, 1024 * 1024, &netdata_buffers_statistics.cbuffers_streaming);
  961. host->sender->capabilities = stream_our_capabilities(host, true);
  962. host->sender->rrdpush_sender_pipe[PIPE_READ] = -1;
  963. host->sender->rrdpush_sender_pipe[PIPE_WRITE] = -1;
  964. host->sender->rrdpush_sender_socket = -1;
  965. host->sender->disabled_capabilities = STREAM_CAP_NONE;
  966. if(!default_rrdpush_compression_enabled)
  967. host->sender->disabled_capabilities |= STREAM_CAP_COMPRESSIONS_AVAILABLE;
  968. spinlock_init(&host->sender->spinlock);
  969. replication_init_sender(host->sender);
  970. }
  971. static void rrdhost_streaming_sender_structures_free(RRDHOST *host)
  972. {
  973. rrdhost_option_clear(host, RRDHOST_OPTION_SENDER_ENABLED);
  974. if (unlikely(!host->sender))
  975. return;
  976. rrdpush_sender_thread_stop(host, STREAM_HANDSHAKE_DISCONNECT_HOST_CLEANUP, true); // stop a possibly running thread
  977. cbuffer_free(host->sender->buffer);
  978. rrdpush_compressor_destroy(&host->sender->compressor);
  979. replication_cleanup_sender(host->sender);
  980. __atomic_sub_fetch(&netdata_buffers_statistics.rrdhost_senders, sizeof(*host->sender), __ATOMIC_RELAXED);
  981. freez(host->sender);
  982. host->sender = NULL;
  983. rrdhost_flag_clear(host, RRDHOST_FLAG_RRDPUSH_SENDER_INITIALIZED);
  984. }
  985. void rrdhost_free___while_having_rrd_wrlock(RRDHOST *host, bool force) {
  986. if(!host) return;
  987. if (netdata_exit || force) {
  988. nd_log(NDLS_DAEMON, NDLP_DEBUG,
  989. "RRD: 'host:%s' freeing memory...",
  990. rrdhost_hostname(host));
  991. // ------------------------------------------------------------------------
  992. // first remove it from the indexes, so that it will not be discoverable
  993. rrdhost_index_del_hostname(host);
  994. rrdhost_index_del_by_guid(host);
  995. if (host->prev)
  996. DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(localhost, host, prev, next);
  997. }
  998. // ------------------------------------------------------------------------
  999. // clean up streaming chart slots
  1000. rrdhost_pluginsd_send_chart_slots_free(host);
  1001. rrdhost_pluginsd_receive_chart_slots_free(host);
  1002. // ------------------------------------------------------------------------
  1003. // clean up streaming
  1004. rrdhost_streaming_sender_structures_free(host);
  1005. if (netdata_exit || force)
  1006. stop_streaming_receiver(host, STREAM_HANDSHAKE_DISCONNECT_HOST_CLEANUP);
  1007. // ------------------------------------------------------------------------
  1008. // clean up alarms
  1009. rrdcalc_delete_all(host);
  1010. // ------------------------------------------------------------------------
  1011. // release its children resources
  1012. #ifdef ENABLE_DBENGINE
  1013. for(size_t tier = 0; tier < storage_tiers ;tier++) {
  1014. if(host->db[tier].mode == RRD_MEMORY_MODE_DBENGINE
  1015. && host->db[tier].si
  1016. && !is_storage_engine_shared(host->db[tier].si))
  1017. rrdeng_prepare_exit((struct rrdengine_instance *)host->db[tier].si);
  1018. }
  1019. #endif
  1020. // delete all the RRDSETs of the host
  1021. rrdset_index_destroy(host);
  1022. rrdcalc_rrdhost_index_destroy(host);
  1023. // cleanup ML resources
  1024. ml_host_delete(host);
  1025. freez(host->exporting_flags);
  1026. health_alarm_log_free(host);
  1027. #ifdef ENABLE_DBENGINE
  1028. for(size_t tier = 0; tier < storage_tiers ;tier++) {
  1029. if(host->db[tier].mode == RRD_MEMORY_MODE_DBENGINE
  1030. && host->db[tier].si
  1031. && !is_storage_engine_shared(host->db[tier].si))
  1032. rrdeng_exit((struct rrdengine_instance *)host->db[tier].si);
  1033. }
  1034. #endif
  1035. if (!netdata_exit && !force) {
  1036. nd_log(NDLS_DAEMON, NDLP_DEBUG,
  1037. "RRD: 'host:%s' is now in archive mode...",
  1038. rrdhost_hostname(host));
  1039. rrdhost_flag_set(host, RRDHOST_FLAG_ARCHIVED | RRDHOST_FLAG_ORPHAN);
  1040. return;
  1041. }
  1042. // ------------------------------------------------------------------------
  1043. // free it
  1044. pthread_mutex_destroy(&host->aclk_state_lock);
  1045. freez(host->aclk_state.claimed_id);
  1046. freez(host->aclk_state.prev_claimed_id);
  1047. rrdlabels_destroy(host->rrdlabels);
  1048. string_freez(host->os);
  1049. string_freez(host->timezone);
  1050. string_freez(host->abbrev_timezone);
  1051. string_freez(host->program_name);
  1052. string_freez(host->program_version);
  1053. rrdhost_system_info_free(host->system_info);
  1054. freez(host->cache_dir);
  1055. freez(host->rrdpush_send_api_key);
  1056. freez(host->rrdpush_send_destination);
  1057. rrdpush_destinations_free(host);
  1058. string_freez(host->health.health_default_exec);
  1059. string_freez(host->health.health_default_recipient);
  1060. string_freez(host->registry_hostname);
  1061. simple_pattern_free(host->rrdpush_send_charts_matching);
  1062. freez(host->node_id);
  1063. rrd_functions_host_destroy(host);
  1064. rrdvariables_destroy(host->rrdvars);
  1065. if (host == localhost)
  1066. health_plugin_destroy();
  1067. rrdhost_destroy_rrdcontexts(host);
  1068. string_freez(host->hostname);
  1069. __atomic_sub_fetch(&netdata_buffers_statistics.rrdhost_allocations_size, sizeof(RRDHOST), __ATOMIC_RELAXED);
  1070. freez(host);
  1071. }
  1072. void rrdhost_free_all(void) {
  1073. rrd_wrlock();
  1074. /* Make sure child-hosts are released before the localhost. */
  1075. while(localhost && localhost->next)
  1076. rrdhost_free___while_having_rrd_wrlock(localhost->next, true);
  1077. if(localhost)
  1078. rrdhost_free___while_having_rrd_wrlock(localhost, true);
  1079. rrd_unlock();
  1080. }
  1081. void rrd_finalize_collection_for_all_hosts(void) {
  1082. RRDHOST *host;
  1083. dfe_start_reentrant(rrdhost_root_index, host) {
  1084. rrdhost_finalize_collection(host);
  1085. }
  1086. dfe_done(host);
  1087. }
  1088. struct rrdhost_system_info *rrdhost_labels_to_system_info(RRDLABELS *labels) {
  1089. struct rrdhost_system_info *info = callocz(1, sizeof(struct rrdhost_system_info));
  1090. info->hops = 1;
  1091. rrdlabels_get_value_strdup_or_null(labels, &info->cloud_provider_type, "_cloud_provider_type");
  1092. rrdlabels_get_value_strdup_or_null(labels, &info->cloud_instance_type, "_cloud_instance_type");
  1093. rrdlabels_get_value_strdup_or_null(labels, &info->cloud_instance_region, "_cloud_instance_region");
  1094. rrdlabels_get_value_strdup_or_null(labels, &info->host_os_name, "_os_name");
  1095. rrdlabels_get_value_strdup_or_null(labels, &info->host_os_version, "_os_version");
  1096. rrdlabels_get_value_strdup_or_null(labels, &info->kernel_version, "_kernel_version");
  1097. rrdlabels_get_value_strdup_or_null(labels, &info->host_cores, "_system_cores");
  1098. rrdlabels_get_value_strdup_or_null(labels, &info->host_cpu_freq, "_system_cpu_freq");
  1099. rrdlabels_get_value_strdup_or_null(labels, &info->host_ram_total, "_system_ram_total");
  1100. rrdlabels_get_value_strdup_or_null(labels, &info->host_disk_space, "_system_disk_space");
  1101. rrdlabels_get_value_strdup_or_null(labels, &info->architecture, "_architecture");
  1102. rrdlabels_get_value_strdup_or_null(labels, &info->virtualization, "_virtualization");
  1103. rrdlabels_get_value_strdup_or_null(labels, &info->container, "_container");
  1104. rrdlabels_get_value_strdup_or_null(labels, &info->container_detection, "_container_detection");
  1105. rrdlabels_get_value_strdup_or_null(labels, &info->virt_detection, "_virt_detection");
  1106. rrdlabels_get_value_strdup_or_null(labels, &info->is_k8s_node, "_is_k8s_node");
  1107. rrdlabels_get_value_strdup_or_null(labels, &info->install_type, "_install_type");
  1108. rrdlabels_get_value_strdup_or_null(labels, &info->prebuilt_arch, "_prebuilt_arch");
  1109. rrdlabels_get_value_strdup_or_null(labels, &info->prebuilt_dist, "_prebuilt_dist");
  1110. return info;
  1111. }
  1112. static void rrdhost_load_auto_labels(void) {
  1113. RRDLABELS *labels = localhost->rrdlabels;
  1114. if (localhost->system_info->cloud_provider_type)
  1115. rrdlabels_add(labels, "_cloud_provider_type", localhost->system_info->cloud_provider_type, RRDLABEL_SRC_AUTO);
  1116. if (localhost->system_info->cloud_instance_type)
  1117. rrdlabels_add(labels, "_cloud_instance_type", localhost->system_info->cloud_instance_type, RRDLABEL_SRC_AUTO);
  1118. if (localhost->system_info->cloud_instance_region)
  1119. rrdlabels_add(labels, "_cloud_instance_region", localhost->system_info->cloud_instance_region, RRDLABEL_SRC_AUTO);
  1120. if (localhost->system_info->host_os_name)
  1121. rrdlabels_add(labels, "_os_name", localhost->system_info->host_os_name, RRDLABEL_SRC_AUTO);
  1122. if (localhost->system_info->host_os_version)
  1123. rrdlabels_add(labels, "_os_version", localhost->system_info->host_os_version, RRDLABEL_SRC_AUTO);
  1124. if (localhost->system_info->kernel_version)
  1125. rrdlabels_add(labels, "_kernel_version", localhost->system_info->kernel_version, RRDLABEL_SRC_AUTO);
  1126. if (localhost->system_info->host_cores)
  1127. rrdlabels_add(labels, "_system_cores", localhost->system_info->host_cores, RRDLABEL_SRC_AUTO);
  1128. if (localhost->system_info->host_cpu_freq)
  1129. rrdlabels_add(labels, "_system_cpu_freq", localhost->system_info->host_cpu_freq, RRDLABEL_SRC_AUTO);
  1130. if (localhost->system_info->host_ram_total)
  1131. rrdlabels_add(labels, "_system_ram_total", localhost->system_info->host_ram_total, RRDLABEL_SRC_AUTO);
  1132. if (localhost->system_info->host_disk_space)
  1133. rrdlabels_add(labels, "_system_disk_space", localhost->system_info->host_disk_space, RRDLABEL_SRC_AUTO);
  1134. if (localhost->system_info->architecture)
  1135. rrdlabels_add(labels, "_architecture", localhost->system_info->architecture, RRDLABEL_SRC_AUTO);
  1136. if (localhost->system_info->virtualization)
  1137. rrdlabels_add(labels, "_virtualization", localhost->system_info->virtualization, RRDLABEL_SRC_AUTO);
  1138. if (localhost->system_info->container)
  1139. rrdlabels_add(labels, "_container", localhost->system_info->container, RRDLABEL_SRC_AUTO);
  1140. if (localhost->system_info->container_detection)
  1141. rrdlabels_add(labels, "_container_detection", localhost->system_info->container_detection, RRDLABEL_SRC_AUTO);
  1142. if (localhost->system_info->virt_detection)
  1143. rrdlabels_add(labels, "_virt_detection", localhost->system_info->virt_detection, RRDLABEL_SRC_AUTO);
  1144. if (localhost->system_info->is_k8s_node)
  1145. rrdlabels_add(labels, "_is_k8s_node", localhost->system_info->is_k8s_node, RRDLABEL_SRC_AUTO);
  1146. if (localhost->system_info->install_type)
  1147. rrdlabels_add(labels, "_install_type", localhost->system_info->install_type, RRDLABEL_SRC_AUTO);
  1148. if (localhost->system_info->prebuilt_arch)
  1149. rrdlabels_add(labels, "_prebuilt_arch", localhost->system_info->prebuilt_arch, RRDLABEL_SRC_AUTO);
  1150. if (localhost->system_info->prebuilt_dist)
  1151. rrdlabels_add(labels, "_prebuilt_dist", localhost->system_info->prebuilt_dist, RRDLABEL_SRC_AUTO);
  1152. add_aclk_host_labels();
  1153. // The source should be CONF, but when it is set, these labels are exported by default ('send configured labels' in exporting.conf).
  1154. // Their export seems to break exporting to Graphite, see https://github.com/netdata/netdata/issues/14084.
  1155. int is_ephemeral = appconfig_get_boolean(&netdata_config, CONFIG_SECTION_GLOBAL, "is ephemeral node", CONFIG_BOOLEAN_NO);
  1156. rrdlabels_add(labels, "_is_ephemeral", is_ephemeral ? "true" : "false", RRDLABEL_SRC_AUTO);
  1157. int has_unstable_connection = appconfig_get_boolean(&netdata_config, CONFIG_SECTION_GLOBAL, "has unstable connection", CONFIG_BOOLEAN_NO);
  1158. rrdlabels_add(labels, "_has_unstable_connection", has_unstable_connection ? "true" : "false", RRDLABEL_SRC_AUTO);
  1159. rrdlabels_add(labels, "_is_parent", (localhost->connected_children_count > 0) ? "true" : "false", RRDLABEL_SRC_AUTO);
  1160. rrdlabels_add(labels, "_hostname", string2str(localhost->hostname), RRDLABEL_SRC_AUTO);
  1161. rrdlabels_add(labels, "_os", string2str(localhost->os), RRDLABEL_SRC_AUTO);
  1162. if (localhost->rrdpush_send_destination)
  1163. rrdlabels_add(labels, "_streams_to", localhost->rrdpush_send_destination, RRDLABEL_SRC_AUTO);
  1164. }
  1165. void rrdhost_set_is_parent_label(void) {
  1166. int count = __atomic_load_n(&localhost->connected_children_count, __ATOMIC_RELAXED);
  1167. if (count == 0 || count == 1) {
  1168. RRDLABELS *labels = localhost->rrdlabels;
  1169. rrdlabels_add(labels, "_is_parent", (count) ? "true" : "false", RRDLABEL_SRC_AUTO);
  1170. //queue a node info
  1171. #ifdef ENABLE_ACLK
  1172. if (netdata_cloud_enabled) {
  1173. aclk_queue_node_info(localhost, false);
  1174. }
  1175. #endif
  1176. }
  1177. }
  1178. static void rrdhost_load_config_labels(void) {
  1179. int status = config_load(NULL, 1, CONFIG_SECTION_HOST_LABEL);
  1180. if(!status) {
  1181. char *filename = CONFIG_DIR "/" CONFIG_FILENAME;
  1182. nd_log(NDLS_DAEMON, NDLP_WARNING,
  1183. "RRDLABEL: Cannot reload the configuration file '%s', using labels in memory",
  1184. filename);
  1185. }
  1186. struct section *co = appconfig_get_section(&netdata_config, CONFIG_SECTION_HOST_LABEL);
  1187. if(co) {
  1188. config_section_wrlock(co);
  1189. struct config_option *cv;
  1190. for(cv = co->values; cv ; cv = cv->next) {
  1191. rrdlabels_add(localhost->rrdlabels, cv->name, cv->value, RRDLABEL_SRC_CONFIG);
  1192. cv->flags |= CONFIG_VALUE_USED;
  1193. }
  1194. config_section_unlock(co);
  1195. }
  1196. }
  1197. static void rrdhost_load_kubernetes_labels(void) {
  1198. char label_script[sizeof(char) * (strlen(netdata_configured_primary_plugins_dir) + strlen("get-kubernetes-labels.sh") + 2)];
  1199. sprintf(label_script, "%s/%s", netdata_configured_primary_plugins_dir, "get-kubernetes-labels.sh");
  1200. if (unlikely(access(label_script, R_OK) != 0)) {
  1201. nd_log(NDLS_DAEMON, NDLP_ERR,
  1202. "Kubernetes pod label fetching script %s not found.",
  1203. label_script);
  1204. return;
  1205. }
  1206. pid_t pid;
  1207. FILE *fp_child_input;
  1208. FILE *fp_child_output = netdata_popen(label_script, &pid, &fp_child_input);
  1209. if(!fp_child_output) return;
  1210. char buffer[1000 + 1];
  1211. while (fgets(buffer, 1000, fp_child_output) != NULL)
  1212. rrdlabels_add_pair(localhost->rrdlabels, buffer, RRDLABEL_SRC_AUTO|RRDLABEL_SRC_K8S);
  1213. // Non-zero exit code means that all the script output is error messages. We've shown already any message that didn't include a ':'
  1214. // Here we'll inform with an ERROR that the script failed, show whatever (if anything) was added to the list of labels, free the memory and set the return to null
  1215. int rc = netdata_pclose(fp_child_input, fp_child_output, pid);
  1216. if(rc)
  1217. nd_log(NDLS_DAEMON, NDLP_ERR,
  1218. "%s exited abnormally. Failed to get kubernetes labels.",
  1219. label_script);
  1220. }
  1221. void reload_host_labels(void) {
  1222. if(!localhost->rrdlabels)
  1223. localhost->rrdlabels = rrdlabels_create();
  1224. rrdlabels_unmark_all(localhost->rrdlabels);
  1225. // priority is important here
  1226. rrdhost_load_config_labels();
  1227. rrdhost_load_kubernetes_labels();
  1228. rrdhost_load_auto_labels();
  1229. rrdhost_flag_set(localhost,RRDHOST_FLAG_METADATA_LABELS | RRDHOST_FLAG_METADATA_UPDATE);
  1230. rrdpush_send_host_labels(localhost);
  1231. }
  1232. void rrdhost_finalize_collection(RRDHOST *host) {
  1233. nd_log(NDLS_DAEMON, NDLP_DEBUG,
  1234. "RRD: 'host:%s' stopping data collection...",
  1235. rrdhost_hostname(host));
  1236. RRDSET *st;
  1237. rrdset_foreach_read(st, host)
  1238. rrdset_finalize_collection(st, true);
  1239. rrdset_foreach_done(st);
  1240. }
  1241. // ----------------------------------------------------------------------------
  1242. // RRDHOST - set system info from environment variables
  1243. // system_info fields must be heap allocated or NULL
  1244. int rrdhost_set_system_info_variable(struct rrdhost_system_info *system_info, char *name, char *value) {
  1245. int res = 0;
  1246. if (!strcmp(name, "NETDATA_PROTOCOL_VERSION"))
  1247. return res;
  1248. else if(!strcmp(name, "NETDATA_INSTANCE_CLOUD_TYPE")){
  1249. freez(system_info->cloud_provider_type);
  1250. system_info->cloud_provider_type = strdupz(value);
  1251. }
  1252. else if(!strcmp(name, "NETDATA_INSTANCE_CLOUD_INSTANCE_TYPE")){
  1253. freez(system_info->cloud_instance_type);
  1254. system_info->cloud_instance_type = strdupz(value);
  1255. }
  1256. else if(!strcmp(name, "NETDATA_INSTANCE_CLOUD_INSTANCE_REGION")){
  1257. freez(system_info->cloud_instance_region);
  1258. system_info->cloud_instance_region = strdupz(value);
  1259. }
  1260. else if(!strcmp(name, "NETDATA_CONTAINER_OS_NAME")){
  1261. freez(system_info->container_os_name);
  1262. system_info->container_os_name = strdupz(value);
  1263. }
  1264. else if(!strcmp(name, "NETDATA_CONTAINER_OS_ID")){
  1265. freez(system_info->container_os_id);
  1266. system_info->container_os_id = strdupz(value);
  1267. }
  1268. else if(!strcmp(name, "NETDATA_CONTAINER_OS_ID_LIKE")){
  1269. freez(system_info->container_os_id_like);
  1270. system_info->container_os_id_like = strdupz(value);
  1271. }
  1272. else if(!strcmp(name, "NETDATA_CONTAINER_OS_VERSION")){
  1273. freez(system_info->container_os_version);
  1274. system_info->container_os_version = strdupz(value);
  1275. }
  1276. else if(!strcmp(name, "NETDATA_CONTAINER_OS_VERSION_ID")){
  1277. freez(system_info->container_os_version_id);
  1278. system_info->container_os_version_id = strdupz(value);
  1279. }
  1280. else if(!strcmp(name, "NETDATA_CONTAINER_OS_DETECTION")){
  1281. freez(system_info->container_os_detection);
  1282. system_info->container_os_detection = strdupz(value);
  1283. }
  1284. else if(!strcmp(name, "NETDATA_HOST_OS_NAME")){
  1285. freez(system_info->host_os_name);
  1286. system_info->host_os_name = strdupz(value);
  1287. json_fix_string(system_info->host_os_name);
  1288. }
  1289. else if(!strcmp(name, "NETDATA_HOST_OS_ID")){
  1290. freez(system_info->host_os_id);
  1291. system_info->host_os_id = strdupz(value);
  1292. }
  1293. else if(!strcmp(name, "NETDATA_HOST_OS_ID_LIKE")){
  1294. freez(system_info->host_os_id_like);
  1295. system_info->host_os_id_like = strdupz(value);
  1296. }
  1297. else if(!strcmp(name, "NETDATA_HOST_OS_VERSION")){
  1298. freez(system_info->host_os_version);
  1299. system_info->host_os_version = strdupz(value);
  1300. }
  1301. else if(!strcmp(name, "NETDATA_HOST_OS_VERSION_ID")){
  1302. freez(system_info->host_os_version_id);
  1303. system_info->host_os_version_id = strdupz(value);
  1304. }
  1305. else if(!strcmp(name, "NETDATA_HOST_OS_DETECTION")){
  1306. freez(system_info->host_os_detection);
  1307. system_info->host_os_detection = strdupz(value);
  1308. }
  1309. else if(!strcmp(name, "NETDATA_SYSTEM_KERNEL_NAME")){
  1310. freez(system_info->kernel_name);
  1311. system_info->kernel_name = strdupz(value);
  1312. }
  1313. else if(!strcmp(name, "NETDATA_SYSTEM_CPU_LOGICAL_CPU_COUNT")){
  1314. freez(system_info->host_cores);
  1315. system_info->host_cores = strdupz(value);
  1316. }
  1317. else if(!strcmp(name, "NETDATA_SYSTEM_CPU_FREQ")){
  1318. freez(system_info->host_cpu_freq);
  1319. system_info->host_cpu_freq = strdupz(value);
  1320. }
  1321. else if(!strcmp(name, "NETDATA_SYSTEM_TOTAL_RAM")){
  1322. freez(system_info->host_ram_total);
  1323. system_info->host_ram_total = strdupz(value);
  1324. }
  1325. else if(!strcmp(name, "NETDATA_SYSTEM_TOTAL_DISK_SIZE")){
  1326. freez(system_info->host_disk_space);
  1327. system_info->host_disk_space = strdupz(value);
  1328. }
  1329. else if(!strcmp(name, "NETDATA_SYSTEM_KERNEL_VERSION")){
  1330. freez(system_info->kernel_version);
  1331. system_info->kernel_version = strdupz(value);
  1332. }
  1333. else if(!strcmp(name, "NETDATA_SYSTEM_ARCHITECTURE")){
  1334. freez(system_info->architecture);
  1335. system_info->architecture = strdupz(value);
  1336. }
  1337. else if(!strcmp(name, "NETDATA_SYSTEM_VIRTUALIZATION")){
  1338. freez(system_info->virtualization);
  1339. system_info->virtualization = strdupz(value);
  1340. }
  1341. else if(!strcmp(name, "NETDATA_SYSTEM_VIRT_DETECTION")){
  1342. freez(system_info->virt_detection);
  1343. system_info->virt_detection = strdupz(value);
  1344. }
  1345. else if(!strcmp(name, "NETDATA_SYSTEM_CONTAINER")){
  1346. freez(system_info->container);
  1347. system_info->container = strdupz(value);
  1348. }
  1349. else if(!strcmp(name, "NETDATA_SYSTEM_CONTAINER_DETECTION")){
  1350. freez(system_info->container_detection);
  1351. system_info->container_detection = strdupz(value);
  1352. }
  1353. else if(!strcmp(name, "NETDATA_HOST_IS_K8S_NODE")){
  1354. freez(system_info->is_k8s_node);
  1355. system_info->is_k8s_node = strdupz(value);
  1356. }
  1357. else if (!strcmp(name, "NETDATA_SYSTEM_CPU_VENDOR"))
  1358. return res;
  1359. else if (!strcmp(name, "NETDATA_SYSTEM_CPU_MODEL"))
  1360. return res;
  1361. else if (!strcmp(name, "NETDATA_SYSTEM_CPU_DETECTION"))
  1362. return res;
  1363. else if (!strcmp(name, "NETDATA_SYSTEM_RAM_DETECTION"))
  1364. return res;
  1365. else if (!strcmp(name, "NETDATA_SYSTEM_DISK_DETECTION"))
  1366. return res;
  1367. else if (!strcmp(name, "NETDATA_CONTAINER_IS_OFFICIAL_IMAGE"))
  1368. return res;
  1369. else {
  1370. res = 1;
  1371. }
  1372. return res;
  1373. }
  1374. static NETDATA_DOUBLE rrdhost_sender_replication_completion_unsafe(RRDHOST *host, time_t now, size_t *instances) {
  1375. size_t charts = rrdhost_sender_replicating_charts(host);
  1376. NETDATA_DOUBLE completion;
  1377. if(!charts || !host->sender || !host->sender->replication.oldest_request_after_t)
  1378. completion = 100.0;
  1379. else if(!host->sender->replication.latest_completed_before_t || host->sender->replication.latest_completed_before_t < host->sender->replication.oldest_request_after_t)
  1380. completion = 0.0;
  1381. else {
  1382. time_t total = now - host->sender->replication.oldest_request_after_t;
  1383. time_t current = host->sender->replication.latest_completed_before_t - host->sender->replication.oldest_request_after_t;
  1384. completion = (NETDATA_DOUBLE) current * 100.0 / (NETDATA_DOUBLE) total;
  1385. }
  1386. *instances = charts;
  1387. return completion;
  1388. }
  1389. bool rrdhost_matches_window(RRDHOST *host, time_t after, time_t before, time_t now) {
  1390. time_t first_time_s, last_time_s;
  1391. rrdhost_retention(host, now, rrdhost_is_online(host), &first_time_s, &last_time_s);
  1392. return query_matches_retention(after, before, first_time_s, last_time_s, 0);
  1393. }
  1394. bool rrdhost_state_cloud_emulation(RRDHOST *host) {
  1395. return rrdhost_is_online(host);
  1396. }
  1397. void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s) {
  1398. memset(s, 0, sizeof(*s));
  1399. s->host = host;
  1400. s->now = now;
  1401. RRDHOST_FLAGS flags = __atomic_load_n(&host->flags, __ATOMIC_RELAXED);
  1402. // --- dyncfg ---
  1403. s->dyncfg.status = dyncfg_available_for_rrdhost(host) ? RRDHOST_DYNCFG_STATUS_AVAILABLE : RRDHOST_DYNCFG_STATUS_UNAVAILABLE;
  1404. // --- db ---
  1405. bool online = rrdhost_is_online(host);
  1406. rrdhost_retention(host, now, online, &s->db.first_time_s, &s->db.last_time_s);
  1407. s->db.metrics = host->rrdctx.metrics;
  1408. s->db.instances = host->rrdctx.instances;
  1409. s->db.contexts = dictionary_entries(host->rrdctx.contexts);
  1410. if(!s->db.first_time_s || !s->db.last_time_s || !s->db.metrics || !s->db.instances || !s->db.contexts ||
  1411. (flags & (RRDHOST_FLAG_PENDING_CONTEXT_LOAD)))
  1412. s->db.status = RRDHOST_DB_STATUS_INITIALIZING;
  1413. else
  1414. s->db.status = RRDHOST_DB_STATUS_QUERYABLE;
  1415. s->db.mode = host->rrd_memory_mode;
  1416. // --- ingest ---
  1417. s->ingest.since = MAX(host->child_connect_time, host->child_disconnected_time);
  1418. s->ingest.reason = (online) ? STREAM_HANDSHAKE_NEVER : host->rrdpush_last_receiver_exit_reason;
  1419. netdata_mutex_lock(&host->receiver_lock);
  1420. s->ingest.hops = (host->system_info ? host->system_info->hops : (host == localhost) ? 0 : 1);
  1421. bool has_receiver = false;
  1422. if (host->receiver) {
  1423. has_receiver = true;
  1424. s->ingest.replication.instances = rrdhost_receiver_replicating_charts(host);
  1425. s->ingest.replication.completion = host->rrdpush_receiver_replication_percent;
  1426. s->ingest.replication.in_progress = s->ingest.replication.instances > 0;
  1427. s->ingest.capabilities = host->receiver->capabilities;
  1428. s->ingest.peers = socket_peers(host->receiver->fd);
  1429. #ifdef ENABLE_HTTPS
  1430. s->ingest.ssl = SSL_connection(&host->receiver->ssl);
  1431. #endif
  1432. }
  1433. netdata_mutex_unlock(&host->receiver_lock);
  1434. if (online) {
  1435. if(s->db.status == RRDHOST_DB_STATUS_INITIALIZING)
  1436. s->ingest.status = RRDHOST_INGEST_STATUS_INITIALIZING;
  1437. else if (host == localhost || rrdhost_option_check(host, RRDHOST_OPTION_VIRTUAL_HOST)) {
  1438. s->ingest.status = RRDHOST_INGEST_STATUS_ONLINE;
  1439. s->ingest.since = netdata_start_time;
  1440. }
  1441. else if (s->ingest.replication.in_progress)
  1442. s->ingest.status = RRDHOST_INGEST_STATUS_REPLICATING;
  1443. else
  1444. s->ingest.status = RRDHOST_INGEST_STATUS_ONLINE;
  1445. }
  1446. else {
  1447. if (!s->ingest.since) {
  1448. s->ingest.status = RRDHOST_INGEST_STATUS_ARCHIVED;
  1449. s->ingest.since = s->db.last_time_s;
  1450. }
  1451. else
  1452. s->ingest.status = RRDHOST_INGEST_STATUS_OFFLINE;
  1453. }
  1454. if(host == localhost)
  1455. s->ingest.type = RRDHOST_INGEST_TYPE_LOCALHOST;
  1456. else if(has_receiver || rrdhost_flag_set(host, RRDHOST_FLAG_RRDPUSH_RECEIVER_DISCONNECTED))
  1457. s->ingest.type = RRDHOST_INGEST_TYPE_CHILD;
  1458. else if(rrdhost_option_check(host, RRDHOST_OPTION_VIRTUAL_HOST))
  1459. s->ingest.type = RRDHOST_INGEST_TYPE_VIRTUAL;
  1460. else
  1461. s->ingest.type = RRDHOST_INGEST_TYPE_ARCHIVED;
  1462. s->ingest.id = host->rrdpush_receiver_connection_counter;
  1463. if(!s->ingest.since)
  1464. s->ingest.since = netdata_start_time;
  1465. if(s->ingest.status == RRDHOST_INGEST_STATUS_ONLINE)
  1466. s->db.liveness = RRDHOST_DB_LIVENESS_LIVE;
  1467. else
  1468. s->db.liveness = RRDHOST_DB_LIVENESS_STALE;
  1469. // --- stream ---
  1470. if (!host->sender) {
  1471. s->stream.status = RRDHOST_STREAM_STATUS_DISABLED;
  1472. s->stream.hops = s->ingest.hops + 1;
  1473. }
  1474. else {
  1475. sender_lock(host->sender);
  1476. s->stream.since = host->sender->last_state_since_t;
  1477. s->stream.peers = socket_peers(host->sender->rrdpush_sender_socket);
  1478. #ifdef ENABLE_HTTPS
  1479. s->stream.ssl = SSL_connection(&host->sender->ssl);
  1480. #endif
  1481. memcpy(s->stream.sent_bytes_on_this_connection_per_type,
  1482. host->sender->sent_bytes_on_this_connection_per_type,
  1483. MIN(sizeof(s->stream.sent_bytes_on_this_connection_per_type),
  1484. sizeof(host->sender->sent_bytes_on_this_connection_per_type)));
  1485. if (rrdhost_flag_check(host, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED)) {
  1486. s->stream.hops = host->sender->hops;
  1487. s->stream.reason = STREAM_HANDSHAKE_NEVER;
  1488. s->stream.capabilities = host->sender->capabilities;
  1489. s->stream.replication.completion = rrdhost_sender_replication_completion_unsafe(host, now, &s->stream.replication.instances);
  1490. s->stream.replication.in_progress = s->stream.replication.instances > 0;
  1491. if(s->stream.replication.in_progress)
  1492. s->stream.status = RRDHOST_STREAM_STATUS_REPLICATING;
  1493. else
  1494. s->stream.status = RRDHOST_STREAM_STATUS_ONLINE;
  1495. s->stream.compression = host->sender->compressor.initialized;
  1496. }
  1497. else {
  1498. s->stream.status = RRDHOST_STREAM_STATUS_OFFLINE;
  1499. s->stream.hops = s->ingest.hops + 1;
  1500. s->stream.reason = host->sender->exit.reason;
  1501. }
  1502. sender_unlock(host->sender);
  1503. }
  1504. s->stream.id = host->rrdpush_sender_connection_counter;
  1505. if(!s->stream.since)
  1506. s->stream.since = netdata_start_time;
  1507. // --- ml ---
  1508. if(ml_host_get_host_status(host, &s->ml.metrics)) {
  1509. s->ml.type = RRDHOST_ML_TYPE_SELF;
  1510. if(s->ingest.status == RRDHOST_INGEST_STATUS_OFFLINE || s->ingest.status == RRDHOST_INGEST_STATUS_ARCHIVED)
  1511. s->ml.status = RRDHOST_ML_STATUS_OFFLINE;
  1512. else
  1513. s->ml.status = RRDHOST_ML_STATUS_RUNNING;
  1514. }
  1515. else if(stream_has_capability(&s->ingest, STREAM_CAP_DATA_WITH_ML)) {
  1516. s->ml.type = RRDHOST_ML_TYPE_RECEIVED;
  1517. s->ml.status = RRDHOST_ML_STATUS_RUNNING;
  1518. }
  1519. else {
  1520. // does not receive ML, does not run ML
  1521. s->ml.type = RRDHOST_ML_TYPE_DISABLED;
  1522. s->ml.status = RRDHOST_ML_STATUS_DISABLED;
  1523. }
  1524. // --- health ---
  1525. if(host->health.health_enabled) {
  1526. if(flags & RRDHOST_FLAG_PENDING_HEALTH_INITIALIZATION)
  1527. s->health.status = RRDHOST_HEALTH_STATUS_INITIALIZING;
  1528. else {
  1529. s->health.status = RRDHOST_HEALTH_STATUS_RUNNING;
  1530. RRDCALC *rc;
  1531. foreach_rrdcalc_in_rrdhost_read(host, rc) {
  1532. if (unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec))
  1533. continue;
  1534. switch (rc->status) {
  1535. default:
  1536. case RRDCALC_STATUS_REMOVED:
  1537. break;
  1538. case RRDCALC_STATUS_CLEAR:
  1539. s->health.alerts.clear++;
  1540. break;
  1541. case RRDCALC_STATUS_WARNING:
  1542. s->health.alerts.warning++;
  1543. break;
  1544. case RRDCALC_STATUS_CRITICAL:
  1545. s->health.alerts.critical++;
  1546. break;
  1547. case RRDCALC_STATUS_UNDEFINED:
  1548. s->health.alerts.undefined++;
  1549. break;
  1550. case RRDCALC_STATUS_UNINITIALIZED:
  1551. s->health.alerts.uninitialized++;
  1552. break;
  1553. }
  1554. }
  1555. foreach_rrdcalc_in_rrdhost_done(rc);
  1556. }
  1557. }
  1558. else
  1559. s->health.status = RRDHOST_HEALTH_STATUS_DISABLED;
  1560. }