mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-25 21:46:50 +00:00
@@ -2092,6 +2092,7 @@ impl DiskAPI for LocalDisk {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
data_usage_info.info.last_update = Some(SystemTime::now());
|
data_usage_info.info.last_update = Some(SystemTime::now());
|
||||||
|
info!("ns_scanner completed: {data_usage_info:?}");
|
||||||
Ok(data_usage_info)
|
Ok(data_usage_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -351,6 +351,7 @@ impl DiskAPI for Disk {
|
|||||||
updates: Sender<DataUsageEntry>,
|
updates: Sender<DataUsageEntry>,
|
||||||
scan_mode: HealScanMode,
|
scan_mode: HealScanMode,
|
||||||
) -> Result<DataUsageCache> {
|
) -> Result<DataUsageCache> {
|
||||||
|
info!("ns_scanner");
|
||||||
match self {
|
match self {
|
||||||
Disk::Local(local_disk) => local_disk.ns_scanner(cache, updates, scan_mode).await,
|
Disk::Local(local_disk) => local_disk.ns_scanner(cache, updates, scan_mode).await,
|
||||||
Disk::Remote(remote_disk) => remote_disk.ns_scanner(cache, updates, scan_mode).await,
|
Disk::Remote(remote_disk) => remote_disk.ns_scanner(cache, updates, scan_mode).await,
|
||||||
|
|||||||
@@ -86,23 +86,28 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn init_data_scanner() {
|
pub async fn init_data_scanner() {
|
||||||
let mut r = rand::thread_rng();
|
|
||||||
let random = r.gen_range(0.0..1.0);
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
run_data_scanner().await;
|
run_data_scanner().await;
|
||||||
|
let random = {
|
||||||
|
let mut r = rand::thread_rng();
|
||||||
|
r.gen_range(0.0..1.0)
|
||||||
|
};
|
||||||
let duration = Duration::from_secs_f64(random * (SCANNER_CYCLE.load(std::sync::atomic::Ordering::SeqCst) as f64));
|
let duration = Duration::from_secs_f64(random * (SCANNER_CYCLE.load(std::sync::atomic::Ordering::SeqCst) as f64));
|
||||||
let sleep_duration = if duration < Duration::new(1, 0) {
|
let sleep_duration = if duration < Duration::new(1, 0) {
|
||||||
Duration::new(1, 0)
|
Duration::new(1, 0)
|
||||||
} else {
|
} else {
|
||||||
duration
|
duration
|
||||||
};
|
};
|
||||||
|
|
||||||
|
info!("data scanner will sleeping {sleep_duration:?}");
|
||||||
sleep(sleep_duration).await;
|
sleep(sleep_duration).await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_data_scanner() {
|
async fn run_data_scanner() {
|
||||||
|
info!("run_data_scanner");
|
||||||
let Some(store) = new_object_layer_fn() else {
|
let Some(store) = new_object_layer_fn() else {
|
||||||
error!("errServerNotInitialized");
|
error!("errServerNotInitialized");
|
||||||
return;
|
return;
|
||||||
@@ -163,8 +168,10 @@ async fn run_data_scanner() {
|
|||||||
});
|
});
|
||||||
let mut res = HashMap::new();
|
let mut res = HashMap::new();
|
||||||
res.insert("cycle".to_string(), cycle_info.current.to_string());
|
res.insert("cycle".to_string(), cycle_info.current.to_string());
|
||||||
|
info!("start ns_scanner");
|
||||||
match store.clone().ns_scanner(tx, cycle_info.current as usize, scan_mode).await {
|
match store.clone().ns_scanner(tx, cycle_info.current as usize, scan_mode).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
info!("ns_scanner completed");
|
||||||
cycle_info.next += 1;
|
cycle_info.next += 1;
|
||||||
cycle_info.current = 0;
|
cycle_info.current = 0;
|
||||||
cycle_info.cycle_completed.push(Utc::now());
|
cycle_info.cycle_completed.push(Utc::now());
|
||||||
@@ -176,9 +183,14 @@ async fn run_data_scanner() {
|
|||||||
globalScannerMetrics.write().await.set_cycle(Some(cycle_info.clone())).await;
|
globalScannerMetrics.write().await.set_cycle(Some(cycle_info.clone())).await;
|
||||||
let mut tmp = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
tmp.write_u64::<LittleEndian>(cycle_info.next).unwrap();
|
tmp.write_u64::<LittleEndian>(cycle_info.next).unwrap();
|
||||||
let _ = save_config(store.clone(), &DATA_USAGE_BLOOM_NAME_PATH, &tmp).await;
|
if let Ok(data) = cycle_info.marshal_msg(&tmp) {
|
||||||
|
let _ = save_config(store.clone(), &DATA_USAGE_BLOOM_NAME_PATH, &data).await;
|
||||||
|
} else {
|
||||||
|
let _ = save_config(store.clone(), &DATA_USAGE_BLOOM_NAME_PATH, &tmp).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
info!("ns_scanner failed: {:?}", err);
|
||||||
res.insert("error".to_string(), err.to_string());
|
res.insert("error".to_string(), err.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use std::{
|
|||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
use super::data_scanner::{CurrentScannerCycle, UpdateCurrentPathFn};
|
use super::data_scanner::{CurrentScannerCycle, UpdateCurrentPathFn};
|
||||||
|
|
||||||
@@ -148,6 +149,7 @@ impl ScannerMetrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_cycle(&mut self, c: Option<CurrentScannerCycle>) {
|
pub async fn set_cycle(&mut self, c: Option<CurrentScannerCycle>) {
|
||||||
|
info!("ScannerMetrics set_cycle {c:?}");
|
||||||
*self.cycle_info.write().await = c;
|
*self.cycle_info.write().await = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ const OBJECTS_VERSION_COUNT_INTERVALS: [ObjectHistogramInterval; DATA_USAGE_VERS
|
|||||||
];
|
];
|
||||||
|
|
||||||
// sizeHistogram is a size histogram.
|
// sizeHistogram is a size histogram.
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct SizeHistogram(Vec<u64>);
|
pub struct SizeHistogram(Vec<u64>);
|
||||||
|
|
||||||
impl Default for SizeHistogram {
|
impl Default for SizeHistogram {
|
||||||
@@ -168,7 +168,7 @@ impl SizeHistogram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// versionsHistogram is a histogram of number of versions in an object.
|
// versionsHistogram is a histogram of number of versions in an object.
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct VersionsHistogram(Vec<u64>);
|
pub struct VersionsHistogram(Vec<u64>);
|
||||||
|
|
||||||
impl Default for VersionsHistogram {
|
impl Default for VersionsHistogram {
|
||||||
@@ -238,7 +238,7 @@ impl ReplicationAllStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct DataUsageEntry {
|
pub struct DataUsageEntry {
|
||||||
pub children: DataUsageHashMap,
|
pub children: DataUsageHashMap,
|
||||||
// These fields do no include any children.
|
// These fields do no include any children.
|
||||||
@@ -340,7 +340,7 @@ pub struct DataUsageEntryInfo {
|
|||||||
pub entry: DataUsageEntry,
|
pub entry: DataUsageEntry,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct DataUsageCacheInfo {
|
pub struct DataUsageCacheInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub next_cycle: u32,
|
pub next_cycle: u32,
|
||||||
@@ -367,7 +367,7 @@ pub struct DataUsageCacheInfo {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct DataUsageCache {
|
pub struct DataUsageCache {
|
||||||
pub info: DataUsageCacheInfo,
|
pub info: DataUsageCacheInfo,
|
||||||
pub cache: HashMap<String, DataUsageEntry>,
|
pub cache: HashMap<String, DataUsageEntry>,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use chrono::Utc;
|
|||||||
use common::globals::{GLOBAL_Local_Node_Name, GLOBAL_Rustfs_Addr};
|
use common::globals::{GLOBAL_Local_Node_Name, GLOBAL_Rustfs_Addr};
|
||||||
use madmin::metrics::{DiskIOStats, DiskMetric, RealtimeMetrics};
|
use madmin::metrics::{DiskIOStats, DiskMetric, RealtimeMetrics};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
admin_server_info::get_local_server_property,
|
admin_server_info::get_local_server_property,
|
||||||
@@ -55,8 +56,10 @@ impl MetricType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn collect_local_metrics(types: MetricType, opts: &CollectMetricsOpts) -> RealtimeMetrics {
|
pub async fn collect_local_metrics(types: MetricType, opts: &CollectMetricsOpts) -> RealtimeMetrics {
|
||||||
|
info!("collect_local_metrics");
|
||||||
let mut real_time_metrics = RealtimeMetrics::default();
|
let mut real_time_metrics = RealtimeMetrics::default();
|
||||||
if types.0 == MetricType::NONE.0 {
|
if types.0 == MetricType::NONE.0 {
|
||||||
|
info!("types is None, return");
|
||||||
return real_time_metrics;
|
return real_time_metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +78,13 @@ pub async fn collect_local_metrics(types: MetricType, opts: &CollectMetricsOpts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if types.contains(&MetricType::DISK) {
|
if types.contains(&MetricType::DISK) {
|
||||||
|
info!("start get disk metrics");
|
||||||
let mut aggr = DiskMetric {
|
let mut aggr = DiskMetric {
|
||||||
collected_at: Utc::now(),
|
collected_at: Utc::now(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
for (name, disk) in collect_local_disks_metrics(&opts.disks).await.into_iter() {
|
for (name, disk) in collect_local_disks_metrics(&opts.disks).await.into_iter() {
|
||||||
|
info!("got disk metric, name: {name}, metric: {disk:?}");
|
||||||
real_time_metrics.by_disk.insert(name, disk.clone());
|
real_time_metrics.by_disk.insert(name, disk.clone());
|
||||||
aggr.merge(&disk);
|
aggr.merge(&disk);
|
||||||
}
|
}
|
||||||
@@ -87,10 +92,31 @@ pub async fn collect_local_metrics(types: MetricType, opts: &CollectMetricsOpts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if types.contains(&MetricType::SCANNER) {
|
if types.contains(&MetricType::SCANNER) {
|
||||||
|
info!("start get scanner metrics");
|
||||||
let metrics = globalScannerMetrics.read().await.report().await;
|
let metrics = globalScannerMetrics.read().await.report().await;
|
||||||
real_time_metrics.aggregated.scanner = Some(metrics);
|
real_time_metrics.aggregated.scanner = Some(metrics);
|
||||||
}
|
}
|
||||||
RealtimeMetrics::default()
|
|
||||||
|
if types.contains(&MetricType::OS) {}
|
||||||
|
|
||||||
|
if types.contains(&MetricType::BATCH_JOBS) {}
|
||||||
|
|
||||||
|
if types.contains(&MetricType::SITE_RESYNC) {}
|
||||||
|
|
||||||
|
if types.contains(&MetricType::NET) {}
|
||||||
|
|
||||||
|
if types.contains(&MetricType::MEM) {}
|
||||||
|
|
||||||
|
if types.contains(&MetricType::CPU) {}
|
||||||
|
|
||||||
|
if types.contains(&MetricType::RPC) {}
|
||||||
|
|
||||||
|
real_time_metrics
|
||||||
|
.by_host
|
||||||
|
.insert(by_host_name.clone(), real_time_metrics.aggregated.clone());
|
||||||
|
real_time_metrics.hosts.push(by_host_name);
|
||||||
|
|
||||||
|
real_time_metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn collect_local_disks_metrics(disks: &HashSet<String>) -> HashMap<String, DiskMetric> {
|
async fn collect_local_disks_metrics(disks: &HashSet<String>) -> HashMap<String, DiskMetric> {
|
||||||
@@ -167,3 +193,25 @@ async fn collect_local_disks_metrics(disks: &HashSet<String>) -> HashMap<String,
|
|||||||
|
|
||||||
metrics
|
metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::MetricType;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tes_types() {
|
||||||
|
let t = MetricType::ALL;
|
||||||
|
assert!(t.contains(&MetricType::NONE));
|
||||||
|
assert!(t.contains(&MetricType::DISK));
|
||||||
|
assert!(t.contains(&MetricType::OS));
|
||||||
|
assert!(t.contains(&MetricType::BATCH_JOBS));
|
||||||
|
assert!(t.contains(&MetricType::SITE_RESYNC));
|
||||||
|
assert!(t.contains(&MetricType::NET));
|
||||||
|
assert!(t.contains(&MetricType::MEM));
|
||||||
|
assert!(t.contains(&MetricType::CPU));
|
||||||
|
assert!(t.contains(&MetricType::RPC));
|
||||||
|
|
||||||
|
let disk = MetricType::new(1 << 1);
|
||||||
|
assert!(disk.contains(&MetricType::DISK));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2668,6 +2668,7 @@ impl SetDisks {
|
|||||||
updates: Sender<DataUsageCache>,
|
updates: Sender<DataUsageCache>,
|
||||||
heal_scan_mode: HealScanMode,
|
heal_scan_mode: HealScanMode,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
info!("ns_scanner");
|
||||||
if buckets.is_empty() {
|
if buckets.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -2846,6 +2847,7 @@ impl SetDisks {
|
|||||||
}
|
}
|
||||||
let _ = join_all(futures).await;
|
let _ = join_all(futures).await;
|
||||||
let _ = task.await;
|
let _ = task.await;
|
||||||
|
info!("ns_scanner completed");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ impl Operation for MetricsHandler {
|
|||||||
// todo write resp
|
// todo write resp
|
||||||
match serde_json::to_vec(&m) {
|
match serde_json::to_vec(&m) {
|
||||||
Ok(re) => {
|
Ok(re) => {
|
||||||
info!("got metrics, send it to client, m: {m:?}, re: {re:?}");
|
info!("got metrics, send it to client, m: {m:?}");
|
||||||
let _ = tx.send(Ok(Bytes::from(re))).await;
|
let _ = tx.send(Ok(Bytes::from(re))).await;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user