master
c 125 lines 5.06 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #define RRDHOST_INTERNALS
4 #include "rrd.h"
5 #include "rrd-retention.h"
6 #include "libnetdata/parsers/duration.h"
7
8 // Round retention time to more human-readable values (days/hours/minutes)
9 static time_t round_retention(time_t retention_seconds) {
10 if(retention_seconds > 60 * 86400)
11 retention_seconds = HOWMANY(retention_seconds, 86400) * 86400;
12 else if(retention_seconds > 86400)
13 retention_seconds = HOWMANY(retention_seconds, 3600) * 3600;
14 else
15 retention_seconds = HOWMANY(retention_seconds, 60) * 60;
16
17 return retention_seconds;
18 }
19
20 // Collect retention statistics from all tiers
21 RRDSTATS_RETENTION rrdstats_retention_collect(void) {
22 time_t now_s = now_realtime_sec();
23
24 // Initialize the retention structure
25 RRDSTATS_RETENTION retention = {
26 .storage_tiers = 0
27 };
28
29 rrd_rdlock();
30
31 if(!localhost) {
32 rrd_rdunlock();
33 return retention;
34 }
35
36 // Count the available storage tiers
37 retention.storage_tiers = nd_profile.storage_tiers;
38
39 // Iterate through all available storage tiers
40 for(size_t tier = 0; tier < retention.storage_tiers; tier++) {
41 STORAGE_ENGINE *eng = localhost->db[tier].eng;
42 if(!eng)
43 continue;
44
45 RRD_STORAGE_TIER *tier_info = &retention.tiers[tier];
46 tier_info->tier = tier;
47 tier_info->backend = eng->seb;
48 tier_info->group_seconds = get_tier_grouping(tier) * localhost->rrd_update_every;
49
50 // Format human-readable granularity
51 duration_snprintf_time_t(tier_info->granularity_human, sizeof(tier_info->granularity_human), (time_t)tier_info->group_seconds);
52
53 // Get metrics and samples counts
54 tier_info->metrics = storage_engine_metrics(eng->seb, localhost->db[tier].si);
55 tier_info->samples = storage_engine_samples(eng->seb, localhost->db[tier].si);
56
57 // Get disk usage information
58 tier_info->disk_max = storage_engine_disk_space_max(eng->seb, localhost->db[tier].si);
59 tier_info->disk_used = storage_engine_disk_space_used(eng->seb, localhost->db[tier].si);
60
61 #ifdef ENABLE_DBENGINE
62 if(!tier_info->disk_max && eng->seb == STORAGE_ENGINE_BACKEND_DBENGINE) {
63 tier_info->disk_max = rrdeng_get_directory_free_bytes_space(multidb_ctx[tier]);
64 tier_info->disk_max += tier_info->disk_used;
65 }
66 #endif
67
68 // Calculate disk usage percentage
69 if(tier_info->disk_used && tier_info->disk_max)
70 tier_info->disk_percent = (double)tier_info->disk_used * 100.0 / (double)tier_info->disk_max;
71 else
72 tier_info->disk_percent = 0.0;
73
74 // Get retention information
75 tier_info->first_time_s = storage_engine_global_first_time_s(eng->seb, localhost->db[tier].si);
76 tier_info->last_time_s = now_s;
77
78 if(tier_info->first_time_s < tier_info->last_time_s) {
79 tier_info->retention = tier_info->last_time_s - tier_info->first_time_s;
80
81 // Format human-readable retention
82 duration_snprintf(tier_info->retention_human, sizeof(tier_info->retention_human),
83 round_retention(tier_info->retention), "s", false);
84
85 if(tier_info->disk_used || tier_info->disk_max) {
86 // Get requested retention time
87 tier_info->requested_retention = 0;
88 #ifdef ENABLE_DBENGINE
89 if(eng->seb == STORAGE_ENGINE_BACKEND_DBENGINE)
90 tier_info->requested_retention = multidb_ctx[tier]->config.max_retention_s;
91 #endif
92
93 // Format human-readable requested retention
94 duration_snprintf(tier_info->requested_retention_human, sizeof(tier_info->requested_retention_human),
95 (int)tier_info->requested_retention, "s", false);
96
97 // Calculate expected retention based on current usage
98 time_t space_retention = 0;
99 if(tier_info->disk_percent > 0)
100 space_retention = (time_t)((double)(now_s - tier_info->first_time_s) * 100.0 / tier_info->disk_percent);
101
102 tier_info->expected_retention = (tier_info->requested_retention && tier_info->requested_retention < space_retention)
103 ? tier_info->requested_retention
104 : space_retention;
105
106 // Format human-readable expected retention
107 duration_snprintf(tier_info->expected_retention_human, sizeof(tier_info->expected_retention_human),
108 (int)round_retention(tier_info->expected_retention), "s", false);
109 }
110 }
111 else {
112 // No data yet in this tier
113 tier_info->retention = 0;
114 tier_info->retention_human[0] = '\0';
115 tier_info->requested_retention = 0;
116 tier_info->requested_retention_human[0] = '\0';
117 tier_info->expected_retention = 0;
118 tier_info->expected_retention_human[0] = '\0';
119 }
120 }
121
122 rrd_rdunlock();
123
124 return retention;
125 }