daemon status improvements 3 (#19707)
* spawn an init spawn server while netdata runs; then stop it and run the final one * stop the old one before dropping permissions * remove the leading dot from spawn server filenames * save the status file on every step during startup * minor update * add clarity about the double use of the function
Costa Tsaousis committed
Feb 25, 2025 at 12:15 UTC
728e36596bbecffe9fc41f758ee5c088dc10c901
10 files changed
+93
-87
src/claim/claim-with-api.c
+1
-1
@@ -372,7 +372,7 @@ bool claim_agent(const char *url, const char *token, const char *rooms, const ch
372
bool done = false, can_retry = true;
373
size_t retries = 0;
374
do {
375
- done = send_curl_request(registry_get_this_machine_guid(), registry_get_this_machine_hostname(), token, rooms, url, proxy, insecure, &can_retry);
375
+ done = send_curl_request(registry_get_this_machine_guid(true), registry_get_this_machine_hostname(), token, rooms, url, proxy, insecure, &can_retry);
376
if (done) break;
377
sleep_usec(300 * USEC_PER_MS + 100 * retries * USEC_PER_MS);
378
retries++;
src/claim/cloud-conf.c
+1
-1
@@ -79,7 +79,7 @@ void cloud_conf_init_after_registry(void) {
79
80
// for machine guid and hostname we have to use inicfg_set() for that they will be saved uncommented
81
if(!machine_guid || !*machine_guid)
82
- inicfg_set(&cloud_config, CONFIG_SECTION_GLOBAL, "machine_guid", registry_get_this_machine_guid());
82
+ inicfg_set(&cloud_config, CONFIG_SECTION_GLOBAL, "machine_guid", registry_get_this_machine_guid(true));
83
84
if(!hostname || !*hostname)
85
inicfg_set(&cloud_config, CONFIG_SECTION_GLOBAL, "hostname", registry_get_this_machine_hostname());
src/daemon/daemon-status-file.c
+13
-5
@@ -263,7 +263,7 @@ static DAEMON_STATUS_FILE daemon_status_file_get(DAEMON_STATUS status) {
263
else if(!UUIDiszero(last_session_status.host_id))
264
session_status.host_id = last_session_status.host_id;
265
else {
266
- const char *machine_guid = registry_get_this_machine_guid();
266
+ const char *machine_guid = registry_get_this_machine_guid(false);
267
if(machine_guid && *machine_guid) {
268
if (uuid_parse_flexi(machine_guid, session_status.host_id.uuid) != 0)
269
session_status.host_id = UUID_ZERO;
@@ -296,8 +296,7 @@ static DAEMON_STATUS_FILE daemon_status_file_get(DAEMON_STATUS status) {
296
if(!session_status.os_id_like && last_session_status.os_id_like)
297
session_status.os_id_like = strdupz(last_session_status.os_id_like);
298
299
- if(status == DAEMON_STATUS_RUNNING)
300
- get_daemon_status_fields_from_system_info(&session_status);
299
+ get_daemon_status_fields_from_system_info(&session_status);
300
301
session_status.exit_reason = exit_initiated;
302
session_status.profile = nd_profile_detect_and_configure(false);
@@ -373,7 +372,7 @@ DAEMON_STATUS_FILE daemon_status_file_load(void) {
372
char current_filename[FILENAME_MAX];
373
time_t newest_mtime = 0, current_mtime;
374
376
- // Check primary directory first
375
+ // Check the primary directory first
376
if(check_status_file(netdata_configured_cache_dir, current_filename, sizeof(current_filename), ¤t_mtime)) {
377
strncpyz(newest_filename, current_filename, sizeof(newest_filename) - 1);
378
newest_mtime = current_mtime;
@@ -675,6 +674,13 @@ bool daemon_status_file_was_incomplete_shutdown(void) {
674
return last_session_status.status == DAEMON_STATUS_EXITING;
675
}
676
677
+void daemon_status_file_startup_step(const char *step) {
678
+ freez((char *)session_status.fatal.function);
679
+ session_status.fatal.function = strdupz(step);
680
+ if(step != NULL)
681
+ daemon_status_file_save(DAEMON_STATUS_NONE);
682
+}
683
+
684
// --------------------------------------------------------------------------------------------------------------------
685
// ng_log() hook for receiving fatal message information
686
@@ -682,7 +688,8 @@ void daemon_status_file_register_fatal(const char *filename, const char *functio
688
static SPINLOCK spinlock = SPINLOCK_INITIALIZER;
689
spinlock_lock(&spinlock);
690
685
- if(session_status.fatal.filename || session_status.fatal.function || session_status.fatal.message || session_status.fatal.stack_trace) {
691
+ // do not check the function, because it may have a startup step in it
692
+ if(session_status.fatal.filename || session_status.fatal.message || session_status.fatal.stack_trace) {
693
spinlock_unlock(&spinlock);
694
freez((void *)filename);
695
freez((void *)function);
@@ -692,6 +699,7 @@ void daemon_status_file_register_fatal(const char *filename, const char *functio
699
}
700
701
session_status.fatal.filename = filename;
702
+ freez((char *)session_status.fatal.function); // it may have a startup step
703
session_status.fatal.function = function;
704
session_status.fatal.message = message;
705
session_status.fatal.stack_trace = stack_trace;
src/daemon/daemon-status-file.h
+1
@@ -79,6 +79,7 @@ void daemon_status_file_check_crash(void);
79
80
bool daemon_status_file_has_last_crashed(void);
81
bool daemon_status_file_was_incomplete_shutdown(void);
82
+void daemon_status_file_startup_step(const char *step);
83
84
void daemon_status_file_register_fatal(const char *filename, const char *function, const char *message, const char *stack_trace, long line);
85
src/daemon/main.c
+69
-68
@@ -184,15 +184,16 @@ int help(int exitcode) {
184
be set in this procedure to be called in all the relevant code paths.
185
*/
186
187
-#define delta_startup_time(msg) \
188
- { \
189
- usec_t now_ut = now_monotonic_usec(); \
190
- if(prev_msg) \
187
+#define delta_startup_time(msg) \
188
+ { \
189
+ usec_t now_ut = now_monotonic_usec(); \
190
+ if(prev_msg) \
191
netdata_log_info("NETDATA STARTUP: in %7llu ms, %s - next: %s", (now_ut - last_ut) / USEC_PER_MS, prev_msg, msg); \
192
- else \
193
- netdata_log_info("NETDATA STARTUP: next: %s", msg); \
194
- last_ut = now_ut; \
195
- prev_msg = msg; \
192
+ else \
193
+ netdata_log_info("NETDATA STARTUP: next: %s", msg); \
194
+ last_ut = now_ut; \
195
+ prev_msg = msg; \
196
+ daemon_status_file_startup_step("startup(" msg ")"); \
197
}
198
199
int buffer_unittest(void);
@@ -782,18 +783,21 @@ int netdata_main(int argc, char **argv) {
783
784
nd_profile_setup();
785
786
+ // start a temporary spawn server
787
+ netdata_main_spawn_server_init("init", argc, (const char **)argv);
788
+
789
// status and crash/update/exit detection
790
exit_initiated_reset();
791
daemon_status_file_check_crash();
792
793
+ // ----------------------------------------------------------------------------------------------------------------
794
+ delta_startup_time("initialize environment");
795
+
796
netdata_conf_ssl();
797
791
- // Get execution path before switching user to avoid permission issues
798
+ // Get the execution path before switching user to avoid permission issues
799
get_netdata_execution_path();
800
794
- // ----------------------------------------------------------------------------------------------------------------
795
- // data collection plugins
796
-
801
// prepare configuration environment variables for the plugins
802
set_environment_for_plugins_and_scripts();
803
@@ -802,13 +806,13 @@ int netdata_main(int argc, char **argv) {
806
fatal("Cannot cd to '%s'", netdata_configured_user_config_dir);
807
808
// ----------------------------------------------------------------------------------------------------------------
805
- // analytics
809
+ delta_startup_time("initialize analytics");
810
811
analytics_reset();
812
get_system_timezone();
813
814
// ----------------------------------------------------------------------------------------------------------------
811
- // pulse (internal netdata instrumentation)
815
+ delta_startup_time("initialize pulse");
816
817
#ifdef NETDATA_INTERNAL_CHECKS
818
pulse_enabled = true;
@@ -823,29 +827,23 @@ int netdata_main(int argc, char **argv) {
827
workers_utilization_enable();
828
829
// ----------------------------------------------------------------------------------------------------------------
826
- // streaming, replication, functions initialization
830
+ delta_startup_time("initialize streaming and replication");
831
832
replication_initialize();
833
rrd_functions_inflight_init();
834
831
- // --------------------------------------------------------------------
832
- // alerts SILENCERS
835
+ // ----------------------------------------------------------------------------------------------------------------
836
+ delta_startup_time("initialize silencers");
837
838
health_set_silencers_filename();
839
health_initialize_global_silencers();
840
837
- // --------------------------------------------------------------------
838
- // setup process signals
839
-
840
- // block signals while initializing threads.
841
- // this causes the threads to block signals.
842
-
841
+ // ----------------------------------------------------------------------------------------------------------------
842
delta_startup_time("initialize signals");
844
- nd_initialize_signals(); // setup the signals we want to use
843
846
- // --------------------------------------------------------------------
847
- // check which threads are enabled and initialize them
844
+ nd_initialize_signals();
845
846
+ // ----------------------------------------------------------------------------------------------------------------
847
delta_startup_time("initialize static threads");
848
849
for (i = 0; static_threads[i].name != NULL ; i++) {
@@ -867,9 +865,7 @@ int netdata_main(int argc, char **argv) {
865
*st->global_variable = (st->enabled) ? true : false;
866
}
867
870
- // --------------------------------------------------------------------
871
- // create the listening sockets
872
-
868
+ // ----------------------------------------------------------------------------------------------------------------
869
delta_startup_time("initialize web server");
870
871
// get the certificate and start security
@@ -884,15 +880,19 @@ int netdata_main(int argc, char **argv) {
880
exit(1);
881
}
882
}
883
+
884
+ // ----------------------------------------------------------------------------------------------------------------
885
+ delta_startup_time("initialize sqlite");
886
+
887
if (sqlite_library_init())
888
fatal("Failed to initialize sqlite library");
889
890
- // --------------------------------------------------------------------
891
- // Initialize ML configuration
892
-
890
+ // ----------------------------------------------------------------------------------------------------------------
891
delta_startup_time("initialize ML");
892
+
893
ml_init();
894
895
+ // ----------------------------------------------------------------------------------------------------------------
896
delta_startup_time("set resource limits");
897
898
#ifdef NETDATA_INTERNAL_CHECKS
@@ -908,10 +908,14 @@ int netdata_main(int argc, char **argv) {
908
909
set_nofile_limit(&rlimit_nofile);
910
911
+ // ----------------------------------------------------------------------------------------------------------------
912
delta_startup_time("become daemon");
913
914
+ // stop the old server and later start a new one under the new permissions
915
+ netdata_main_spawn_server_cleanup();
916
+
917
#if defined(OS_LINUX) || defined(OS_MACOS) || defined(OS_FREEBSD)
914
- // fork, switch user, create pid file, set process priority
918
+ // fork, switch user, create the pid file, set process priority
919
if(become_daemon(dont_fork, user) == -1)
920
fatal("Cannot daemonize myself.");
921
#else
@@ -920,52 +924,59 @@ int netdata_main(int argc, char **argv) {
924
925
netdata_main_spawn_server_init("plugins", argc, (const char **)argv);
926
923
- // init sentry
927
#ifdef ENABLE_SENTRY
925
- nd_sentry_init();
928
+ // ----------------------------------------------------------------------------------------------------------------
929
+ delta_startup_time("initialize sentry");
930
+
931
+ nd_sentry_init();
932
#endif
933
934
+ // ----------------------------------------------------------------------------------------------------------------
935
+ delta_startup_time("initialize home");
936
+
937
// The "HOME" env var points to the root's home dir because Netdata starts as root. Can't use "HOME".
938
struct passwd *pw = getpwuid(getuid());
939
if (inicfg_exists(&netdata_config, CONFIG_SECTION_DIRECTORIES, "home") || !pw || !pw->pw_dir) {
940
netdata_configured_home_dir = inicfg_get(&netdata_config, CONFIG_SECTION_DIRECTORIES, "home", netdata_configured_home_dir);
932
- } else {
933
- netdata_configured_home_dir = inicfg_get(&netdata_config, CONFIG_SECTION_DIRECTORIES, "home", pw->pw_dir);
941
}
942
+ else
943
+ netdata_configured_home_dir = inicfg_get(&netdata_config, CONFIG_SECTION_DIRECTORIES, "home", pw->pw_dir);
944
945
nd_setenv("HOME", netdata_configured_home_dir, 1);
946
938
- dyncfg_init(true);
947
+ // ----------------------------------------------------------------------------------------------------------------
948
+ delta_startup_time("initialize dyncfg");
949
940
- netdata_log_info("netdata started on pid %d.", getpid());
950
+ dyncfg_init(true);
951
952
+ // ----------------------------------------------------------------------------------------------------------------
953
delta_startup_time("initialize threads after fork");
954
955
netdata_threads_init_after_fork((size_t)inicfg_get_size_bytes(&netdata_config, CONFIG_SECTION_GLOBAL, "pthread stack size", default_stacksize));
956
946
- // initialize internal registry
957
+ // ----------------------------------------------------------------------------------------------------------------
958
delta_startup_time("initialize registry");
959
+
960
registry_load();
961
cloud_conf_init_after_registry();
962
netdata_random_session_id_generate();
963
952
- // ------------------------------------------------------------------------
953
- // initialize rrd, registry, health, streaming, etc.
954
-
955
- delta_startup_time("collecting system info");
956
-
957
- struct rrdhost_system_info *system_info = rrdhost_system_info_create();
958
- rrdhost_system_info_detect(system_info);
959
-
960
- const char *guid = registry_get_this_machine_guid();
964
+ const char *guid = registry_get_this_machine_guid(true);
965
#ifdef ENABLE_SENTRY
966
nd_sentry_set_user(guid);
967
#else
968
UNUSED(guid);
969
#endif
970
971
+ // ----------------------------------------------------------------------------------------------------------------
972
+ delta_startup_time("collecting system info");
973
+
974
+ struct rrdhost_system_info *system_info = rrdhost_system_info_create();
975
+ rrdhost_system_info_detect(system_info);
976
+
977
get_install_type(system_info);
978
979
+ // ----------------------------------------------------------------------------------------------------------------
980
delta_startup_time("initialize RRD structures");
981
982
abort_on_fatal_disable();
@@ -974,29 +985,19 @@ int netdata_main(int argc, char **argv) {
985
fatal("Cannot initialize localhost instance with name '%s'.", netdata_configured_hostname);
986
}
987
abort_on_fatal_enable();
988
+ reload_host_labels();
989
978
- // ------------------------------------------------------------------------
979
- // Claim netdata agent to a cloud endpoint
980
-
990
+ // ----------------------------------------------------------------------------------------------------------------
991
delta_startup_time("collect claiming info");
992
+
993
+ bearer_tokens_init();
994
load_claiming_state();
995
984
- // ------------------------------------------------------------------------
985
- // enable log flood protection
996
+ // ----------------------------------------------------------------------------------------------------------------
997
+ delta_startup_time("start the static threads");
998
999
nd_log_limits_reset();
988
-
989
- // Load host labels
990
- delta_startup_time("collect host labels");
991
- reload_host_labels();
992
-
993
- // ------------------------------------------------------------------------
994
- // spawn the threads
995
-
1000
get_agent_event_time_median_init();
997
- bearer_tokens_init();
998
-
999
- delta_startup_time("start the static threads");
1001
1002
netdata_conf_section_web();
1003
@@ -1013,13 +1014,12 @@ int netdata_main(int argc, char **argv) {
1014
}
1015
ml_start_threads();
1016
1016
- // ------------------------------------------------------------------------
1017
- // Initialize netdata agent command serving from cli and signals
1018
-
1017
+ // ----------------------------------------------------------------------------------------------------------------
1018
delta_startup_time("initialize commands API");
1019
1020
commands_init();
1021
1022
+ // ----------------------------------------------------------------------------------------------------------------
1023
delta_startup_time("ready");
1024
1025
usec_t ready_ut = now_monotonic_usec();
@@ -1057,6 +1057,7 @@ int netdata_main(int argc, char **argv) {
1057
1058
webrtc_initialize();
1059
1060
+ daemon_status_file_startup_step(NULL);
1061
daemon_status_file_save(DAEMON_STATUS_RUNNING);
1062
return 10;
1063
}
src/database/rrd.c
+1
-1
@@ -121,7 +121,7 @@ int rrd_init(const char *hostname, struct rrdhost_system_info *system_info, bool
121
localhost = rrdhost_create(
122
hostname
123
, registry_get_this_machine_hostname()
124
- , registry_get_this_machine_guid()
124
+ , registry_get_this_machine_guid(true)
125
, os_type
126
, netdata_configured_timezone
127
, netdata_configured_abbrev_timezone
src/database/rrdhost-system-info.c
-5
@@ -562,12 +562,7 @@ void rrdhost_system_info_to_streaming_function_array(BUFFER *wb, struct rrdhost_
562
void get_daemon_status_fields_from_system_info(DAEMON_STATUS_FILE *ds) {
563
if(ds->read_system_info) return;
564
565
- struct rrdhost_system_info tmp = { 0 };
565
struct rrdhost_system_info *ri = (localhost && localhost->system_info) ? localhost->system_info : NULL;
567
-
568
- if(!ri && rrdhost_system_info_detect(&tmp) == 0)
569
- ri = &tmp;
570
-
566
if(!ri) {
567
// nothing we can do, let it be
568
return;
src/libnetdata/spawn_server/spawn_server_nofork.c
+2
-2
@@ -1063,11 +1063,11 @@ SPAWN_SERVER* spawn_server_create(SPAWN_SERVER_OPTIONS options, const char *name
1063
char path[1024];
1064
if(name && *name) {
1065
server->name = strdupz(name);
1066
- snprintf(path, sizeof(path), "%s/.netdata-spawn-%s.sock", runtime_directory, name);
1066
+ snprintf(path, sizeof(path), "%s/netdata-spawn-%s.sock", runtime_directory, name);
1067
}
1068
else {
1069
server->name = strdupz("unnamed");
1070
- snprintf(path, sizeof(path), "%s/.netdata-spawn-%d-%zu.sock", runtime_directory, getpid(), server->id);
1070
+ snprintf(path, sizeof(path), "%s/netdata-spawn-%d-%zu.sock", runtime_directory, getpid(), server->id);
1071
}
1072
1073
server->path = strdupz(path);
src/registry/registry.h
+1
-1
@@ -75,7 +75,7 @@ void registry_update_cloud_base_url();
75
// update the registry monitoring charts
76
void registry_statistics(void);
77
78
-const char *registry_get_this_machine_guid(void);
78
+const char *registry_get_this_machine_guid(bool create_it);
79
char *registry_get_mgmt_api_key(void);
80
const char *registry_get_this_machine_hostname(void);
81
src/registry/registry_internals.c
+4
-3
@@ -270,7 +270,7 @@ const char *registry_get_this_machine_hostname(void) {
270
return registry.hostname;
271
}
272
273
-const char *registry_get_this_machine_guid(void) {
273
+const char *registry_get_this_machine_guid(bool create_it) {
274
static char guid[GUID_LEN + 1] = "";
275
276
if(likely(guid[0]))
@@ -297,7 +297,7 @@ const char *registry_get_this_machine_guid(void) {
297
}
298
299
// generate a new one?
300
- if(!guid[0]) {
300
+ if(!guid[0] && create_it) {
301
nd_uuid_t uuid;
302
303
uuid_generate_time(uuid);
@@ -315,7 +315,8 @@ const char *registry_get_this_machine_guid(void) {
315
close(fd);
316
}
317
318
- nd_setenv("NETDATA_REGISTRY_UNIQUE_ID", guid, 1);
318
+ if(guid[0])
319
+ nd_setenv("NETDATA_REGISTRY_UNIQUE_ID", guid, 1);
320
321
return guid;
322
}