store status file in /var/lib/netdata, not in /var/cache/netdata (#19831)
* store status file in /var/lib/netdata, not in /var/cache/netdata * add db mode and db tiers to the status file * fix compilation * remove old status files * clear errno after deletions * save kubernetes status * do not cleanup old status files on every save
Costa Tsaousis committed
Mar 12, 2025 at 12:47 UTC
90f94eba470905c9db527b035640467004208aad
3 files changed
+63
-4
src/daemon/daemon-status-file.c
+52
-4
@@ -9,7 +9,7 @@
9
#include <openssl/pem.h>
10
#include <openssl/err.h>
11
12
-#define STATUS_FILE_VERSION 13
12
+#define STATUS_FILE_VERSION 14
13
14
#define STATUS_FILENAME "status-netdata.json"
15
@@ -118,6 +118,12 @@ static void daemon_status_file_to_json(BUFFER *wb, DAEMON_STATUS_FILE *ds) {
118
119
buffer_json_member_add_string_or_empty(wb, "ND_install_type", ds->install_type); // custom
120
121
+ if(ds->v >= 14) {
122
+ buffer_json_member_add_string(wb, "ND_db_mode", rrd_memory_mode_name(ds->db_mode)); // custom
123
+ buffer_json_member_add_uint64(wb, "ND_db_tiers", ds->db_tiers); // custom
124
+ buffer_json_member_add_boolean(wb, "ND_kubernetes", ds->kubernetes); // custom
125
+ }
126
+
127
buffer_json_member_add_object(wb, "ND_timings"); // custom
128
{
129
buffer_json_member_add_time_t(wb, "init", ds->timings.init);
@@ -226,6 +232,7 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
232
bool required_v4 = version >= 4 ? strict : false;
233
bool required_v5 = version >= 5 ? strict : false;
234
bool required_v10 = version >= 10 ? strict : false;
235
+ bool required_v14 = version >= 14 ? strict : false;
236
237
// Parse timestamp
238
JSONC_PARSE_TXT2CHAR_OR_ERROR_AND_RETURN(jobj, path, "@timestamp", datetime, error, required_v1);
@@ -252,6 +259,17 @@ static bool daemon_status_file_from_json(json_object *jobj, void *data, BUFFER *
259
260
if(version >= 4)
261
JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "ND_restarts", ds->restarts, error, required_v4);
262
+
263
+ if(version >= 14) {
264
+ JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, "ND_db_mode", rrd_memory_mode_id, ds->db_mode, error, required_v14);
265
+ JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, "ND_db_tiers", ds->db_tiers, error, required_v14);
266
+ JSONC_PARSE_BOOL_OR_ERROR_AND_RETURN(jobj, path, "ND_kubernetes", ds->kubernetes, error, required_v14);
267
+ }
268
+ else {
269
+ ds->db_mode = default_rrd_memory_mode;
270
+ ds->db_tiers = nd_profile.storage_tiers;
271
+ ds->kubernetes = false;
272
+ }
273
});
274
275
// Parse host object
@@ -383,6 +401,8 @@ static void daemon_status_file_refresh(DAEMON_STATUS status) {
401
session_status.uptime = now_realtime_sec() - netdata_start_time;
402
session_status.timestamp_ut = now_ut;
403
session_status.invocation = nd_log_get_invocation_id();
404
+ session_status.db_mode = default_rrd_memory_mode;
405
+ session_status.db_tiers = nd_profile.storage_tiers;
406
407
session_status.claim_id = claim_id_get_uuid();
408
@@ -470,11 +490,17 @@ static void daemon_status_file_refresh(DAEMON_STATUS status) {
490
491
// List of fallback directories to try
492
static const char *status_file_fallbacks[] = {
493
+ CACHE_DIR,
494
"/tmp",
495
"/run",
496
"/var/run",
497
+ ".",
498
};
499
500
+static void set_dynamic_fallbacks(void) {
501
+ status_file_fallbacks[0] = netdata_configured_cache_dir;
502
+}
503
+
504
static bool check_status_file(const char *directory, char *filename, size_t filename_size, time_t *mtime) {
505
if(!directory || !*directory)
506
return false;
@@ -529,12 +555,13 @@ void daemon_status_file_load(DAEMON_STATUS_FILE *ds) {
555
time_t newest_mtime = 0, current_mtime;
556
557
// Check the primary directory first
532
- if(check_status_file(netdata_configured_cache_dir, current_filename, sizeof(current_filename), ¤t_mtime)) {
558
+ if(check_status_file(netdata_configured_varlib_dir, current_filename, sizeof(current_filename), ¤t_mtime)) {
559
strncpyz(newest_filename, current_filename, sizeof(newest_filename) - 1);
560
newest_mtime = current_mtime;
561
}
562
563
// Check each fallback location
564
+ set_dynamic_fallbacks();
565
for(size_t i = 0; i < _countof(status_file_fallbacks); i++) {
566
if(check_status_file(status_file_fallbacks[i], current_filename, sizeof(current_filename), ¤t_mtime) &&
567
(!*newest_filename || current_mtime > newest_mtime)) {
@@ -655,6 +682,23 @@ static void static_save_buffer_init(void) {
682
buffer_flush(static_save_buffer);
683
}
684
685
+static void remove_old_status_files(const char *protected_dir) {
686
+ FUNCTION_RUN_ONCE();
687
+
688
+ char filename[FILENAME_MAX];
689
+
690
+ set_dynamic_fallbacks();
691
+ for(size_t i = 0; i < _countof(status_file_fallbacks); i++) {
692
+ if(strcmp(status_file_fallbacks[i], protected_dir) == 0)
693
+ continue;
694
+
695
+ snprintfz(filename, sizeof(filename), "%s/%s", status_file_fallbacks[i], STATUS_FILENAME);
696
+ unlink(filename);
697
+ }
698
+
699
+ errno_clear();
700
+}
701
+
702
static void daemon_status_file_save(BUFFER *wb, DAEMON_STATUS_FILE *ds, bool log) {
703
buffer_flush(wb);
704
buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_DEFAULT);
@@ -666,18 +710,22 @@ static void daemon_status_file_save(BUFFER *wb, DAEMON_STATUS_FILE *ds, bool log
710
711
// Try primary directory first
712
bool saved = false;
669
- if (save_status_file(netdata_configured_cache_dir, content, content_size))
713
+ if (save_status_file(netdata_configured_varlib_dir, content, content_size)) {
714
+ remove_old_status_files(netdata_configured_varlib_dir);
715
saved = true;
716
+ }
717
else {
718
if(log)
719
nd_log(NDLS_DAEMON, NDLP_DEBUG, "Failed to save status file in primary directory %s",
674
- netdata_configured_cache_dir);
720
+ netdata_configured_varlib_dir);
721
722
// Try each fallback directory until successful
723
+ set_dynamic_fallbacks();
724
for(size_t i = 0; i < _countof(status_file_fallbacks); i++) {
725
if (save_status_file(status_file_fallbacks[i], content, content_size)) {
726
if(log)
727
nd_log(NDLS_DAEMON, NDLP_DEBUG, "Saved status file in fallback %s", status_file_fallbacks[i]);
728
+
729
saved = true;
730
break;
731
}
src/daemon/daemon-status-file.h
+4
@@ -5,6 +5,7 @@
5
6
#include "libnetdata/libnetdata.h"
7
#include "daemon/config/netdata-conf-profile.h"
8
+#include "database/rrd-database-mode.h"
9
10
typedef enum {
11
DAEMON_STATUS_NONE,
@@ -33,6 +34,9 @@ typedef struct daemon_status_file {
34
EXIT_REASON exit_reason; // the exit reason (maybe empty)
35
ND_PROFILE profile; // the profile of the agent
36
DAEMON_OS_TYPE os_type;
37
+ RRD_DB_MODE db_mode;
38
+ uint8_t db_tiers;
39
+ bool kubernetes;
40
41
time_t boottime; // system boottime
42
time_t uptime; // netdata uptime
src/database/rrdhost-system-info.c
+7
@@ -652,5 +652,12 @@ void get_daemon_status_fields_from_system_info(DAEMON_STATUS_FILE *ds) {
652
if(ri->host_os_id_like)
653
strncpyz(ds->os_id_like, ri->host_os_id_like, sizeof(ds->os_id_like) - 1);
654
655
+ if(ri->is_k8s_node) {
656
+ if (strcmp(ri->is_k8s_node, "true") == 0)
657
+ ds->kubernetes = true;
658
+ else
659
+ ds->kubernetes = false;
660
+ }
661
+
662
ds->read_system_info = true;
663
}