]> git.proxmox.com Git - proxmox-backup.git/blame - src/rrd_cache.rs
update to proxmox-sys 0.2 crate
[proxmox-backup.git] / src / rrd_cache.rs
CommitLineData
2e3f94e1
DM
1use std::path::Path;
2
fae4f6c5
DM
3use anyhow::{format_err, Error};
4use once_cell::sync::OnceCell;
5
25877d05 6use proxmox_sys::fs::CreateOptions;
fae4f6c5 7use proxmox_rrd::RRDCache;
2e3f94e1 8use proxmox_rrd::rrd::{RRD, DST, CF};
fae4f6c5 9
b9352095 10use pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M;
fae4f6c5
DM
11use pbs_api_types::{RRDMode, RRDTimeFrame};
12
b9352095
DM
13const RRD_CACHE_BASEDIR: &str = concat!(PROXMOX_BACKUP_STATE_DIR_M!(), "/rrdb");
14
fae4f6c5
DM
15pub static RRD_CACHE: OnceCell<RRDCache> = OnceCell::new();
16
17/// Get the RRD cache instance
18pub 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)
25pub 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 53fn 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
72pub 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
101pub 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
109pub 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
119pub 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}