]>
Commit | Line | Data |
---|---|---|
2e3f94e1 DM |
1 | use std::path::Path; |
2 | ||
fae4f6c5 DM |
3 | use anyhow::{format_err, Error}; |
4 | use once_cell::sync::OnceCell; | |
5 | ||
25877d05 | 6 | use proxmox_sys::fs::CreateOptions; |
fae4f6c5 | 7 | use proxmox_rrd::RRDCache; |
2e3f94e1 | 8 | use proxmox_rrd::rrd::{RRD, DST, CF}; |
fae4f6c5 | 9 | |
b9352095 | 10 | use pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M; |
fae4f6c5 DM |
11 | use pbs_api_types::{RRDMode, RRDTimeFrame}; |
12 | ||
b9352095 DM |
13 | const RRD_CACHE_BASEDIR: &str = concat!(PROXMOX_BACKUP_STATE_DIR_M!(), "/rrdb"); |
14 | ||
fae4f6c5 DM |
15 | pub static RRD_CACHE: OnceCell<RRDCache> = OnceCell::new(); |
16 | ||
17 | /// Get the RRD cache instance | |
18 | pub fn get_rrd_cache() -> Result<&'static RRDCache, Error> { | |
19 | RRD_CACHE.get().ok_or_else(|| format_err!("RRD cache not initialized!")) | |
20 | } | |
21 | ||
22 | /// Initialize the RRD cache instance | |
23 | /// | |
24 | /// Note: Only a single process must do this (proxmox-backup-proxy) | |
25 | pub fn initialize_rrd_cache() -> Result<&'static RRDCache, Error> { | |
26 | ||
27 | let backup_user = pbs_config::backup_user()?; | |
28 | ||
29 | let file_options = CreateOptions::new() | |
30 | .owner(backup_user.uid) | |
31 | .group(backup_user.gid); | |
32 | ||
33 | let dir_options = CreateOptions::new() | |
34 | .owner(backup_user.uid) | |
35 | .group(backup_user.gid); | |
36 | ||
37 | let apply_interval = 30.0*60.0; // 30 minutes | |
38 | ||
39 | let cache = RRDCache::new( | |
b9352095 | 40 | RRD_CACHE_BASEDIR, |
fae4f6c5 DM |
41 | Some(file_options), |
42 | Some(dir_options), | |
43 | apply_interval, | |
2e3f94e1 | 44 | load_callback, |
fae4f6c5 DM |
45 | )?; |
46 | ||
47 | RRD_CACHE.set(cache) | |
48 | .map_err(|_| format_err!("RRD cache already initialized!"))?; | |
49 | ||
50 | Ok(RRD_CACHE.get().unwrap()) | |
51 | } | |
52 | ||
2e3f94e1 | 53 | fn load_callback( |
2e3f94e1 DM |
54 | path: &Path, |
55 | _rel_path: &str, | |
56 | dst: DST, | |
57 | ) -> RRD { | |
58 | ||
934c8724 | 59 | match RRD::load(path, true) { |
2e3f94e1 DM |
60 | Ok(rrd) => rrd, |
61 | Err(err) => { | |
62 | if err.kind() != std::io::ErrorKind::NotFound { | |
63 | log::warn!("overwriting RRD file {:?}, because of load error: {}", path, err); | |
64 | } | |
65 | RRDCache::create_proxmox_backup_default_rrd(dst) | |
66 | }, | |
67 | } | |
68 | } | |
69 | ||
70 | ||
fae4f6c5 DM |
71 | /// Extracts data for the specified time frame from from RRD cache |
72 | pub fn extract_rrd_data( | |
73 | basedir: &str, | |
74 | name: &str, | |
75 | timeframe: RRDTimeFrame, | |
76 | mode: RRDMode, | |
77 | ) -> Result<Option<(u64, u64, Vec<Option<f64>>)>, Error> { | |
78 | ||
79 | let end = proxmox_time::epoch_f64() as u64; | |
80 | ||
81 | let (start, resolution) = match timeframe { | |
82 | RRDTimeFrame::Hour => (end - 3600, 60), | |
83 | RRDTimeFrame::Day => (end - 3600*24, 60), | |
84 | RRDTimeFrame::Week => (end - 3600*24*7, 30*60), | |
85 | RRDTimeFrame::Month => (end - 3600*24*30, 30*60), | |
86 | RRDTimeFrame::Year => (end - 3600*24*365, 6*60*60), | |
87 | RRDTimeFrame::Decade => (end - 10*3600*24*366, 7*86400), | |
88 | }; | |
89 | ||
90 | let cf = match mode { | |
91 | RRDMode::Max => CF::Maximum, | |
92 | RRDMode::Average => CF::Average, | |
93 | }; | |
94 | ||
95 | let rrd_cache = get_rrd_cache()?; | |
96 | ||
97 | rrd_cache.extract_cached_data(basedir, name, cf, resolution, Some(start), Some(end)) | |
98 | } | |
99 | ||
98eb435d DM |
100 | /// Sync/Flush the RRD journal |
101 | pub fn rrd_sync_journal() { | |
102 | if let Ok(rrd_cache) = get_rrd_cache() { | |
103 | if let Err(err) = rrd_cache.sync_journal() { | |
104 | log::error!("rrd_sync_journal failed - {}", err); | |
105 | } | |
106 | } | |
107 | } | |
fae4f6c5 DM |
108 | /// Update RRD Gauge values |
109 | pub fn rrd_update_gauge(name: &str, value: f64) { | |
110 | if let Ok(rrd_cache) = get_rrd_cache() { | |
58f70bcc DM |
111 | let now = proxmox_time::epoch_f64(); |
112 | if let Err(err) = rrd_cache.update_value(name, now, value, DST::Gauge) { | |
fae4f6c5 DM |
113 | log::error!("rrd::update_value '{}' failed - {}", name, err); |
114 | } | |
115 | } | |
116 | } | |
117 | ||
118 | /// Update RRD Derive values | |
119 | pub fn rrd_update_derive(name: &str, value: f64) { | |
120 | if let Ok(rrd_cache) = get_rrd_cache() { | |
58f70bcc DM |
121 | let now = proxmox_time::epoch_f64(); |
122 | if let Err(err) = rrd_cache.update_value(name, now, value, DST::Derive) { | |
fae4f6c5 DM |
123 | log::error!("rrd::update_value '{}' failed - {}", name, err); |
124 | } | |
125 | } | |
126 | } |