Fixing URL output format in IPv6 environments #1343 and Incorrect time in UI #1350 (#1363)

This commit is contained in:
houseme
2026-01-04 14:56:54 +08:00
committed by GitHub
parent d06397cf4a
commit 75b144b7d4
5 changed files with 56 additions and 12 deletions

View File

@@ -14,6 +14,7 @@
#![allow(non_upper_case_globals)] // FIXME
use chrono::{DateTime, Utc};
use std::collections::HashMap;
use std::sync::LazyLock;
use tokio::sync::RwLock;
@@ -26,6 +27,30 @@ pub static GLOBAL_RUSTFS_ADDR: LazyLock<RwLock<String>> = LazyLock::new(|| RwLoc
pub static GLOBAL_CONN_MAP: LazyLock<RwLock<HashMap<String, Channel>>> = LazyLock::new(|| RwLock::new(HashMap::new()));
pub static GLOBAL_ROOT_CERT: LazyLock<RwLock<Option<Vec<u8>>>> = LazyLock::new(|| RwLock::new(None));
pub static GLOBAL_MTLS_IDENTITY: LazyLock<RwLock<Option<MtlsIdentityPem>>> = LazyLock::new(|| RwLock::new(None));
/// Global initialization time of the RustFS node.
pub static GLOBAL_INIT_TIME: LazyLock<RwLock<Option<DateTime<Utc>>>> = LazyLock::new(|| RwLock::new(None));
/// Set the global local node name.
///
/// # Arguments
/// * `name` - A string slice representing the local node name.
pub async fn set_global_local_node_name(name: &str) {
*GLOBAL_LOCAL_NODE_NAME.write().await = name.to_string();
}
/// Set the global RustFS initialization time to the current UTC time.
pub async fn set_global_init_time_now() {
let now = Utc::now();
*GLOBAL_INIT_TIME.write().await = Some(now);
}
/// Get the global RustFS initialization time.
///
/// # Returns
/// * `Option<DateTime<Utc>>` - The initialization time if set.
pub async fn get_global_init_time() -> Option<DateTime<Utc>> {
*GLOBAL_INIT_TIME.read().await
}
/// Set the global RustFS address used for gRPC connections.
///

View File

@@ -18,6 +18,7 @@ use rustfs_madmin::metrics::ScannerMetrics as M_ScannerMetrics;
use std::{
collections::HashMap,
fmt::Display,
future::Future,
pin::Pin,
sync::{
Arc, OnceLock,
@@ -115,7 +116,7 @@ pub enum Metric {
impl Metric {
/// Convert to string representation for metrics
pub fn as_str(self) -> &'static str {
pub fn as_str(&self) -> &'static str {
match self {
Self::ReadMetadata => "read_metadata",
Self::CheckMissing => "check_missing",
@@ -460,6 +461,11 @@ impl Metrics {
metrics.current_started = cycle.started;
}
// Replace default start time with global init time if it's the placeholder
if let Some(init_time) = crate::get_global_init_time().await {
metrics.current_started = init_time;
}
metrics.collected_at = Utc::now();
metrics.active_paths = self.get_current_paths().await;
@@ -489,8 +495,8 @@ impl Metrics {
}
// Type aliases for compatibility with existing code
pub type UpdateCurrentPathFn = Arc<dyn Fn(&str) -> Pin<Box<dyn std::future::Future<Output = ()> + Send>> + Send + Sync>;
pub type CloseDiskFn = Arc<dyn Fn() -> Pin<Box<dyn std::future::Future<Output = ()> + Send>> + Send + Sync>;
pub type UpdateCurrentPathFn = Arc<dyn Fn(&str) -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync>;
pub type CloseDiskFn = Arc<dyn Fn() -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync>;
/// Create a current path updater for tracking scan progress
pub fn current_path_updater(disk: &str, initial: &str) -> (UpdateCurrentPathFn, CloseDiskFn) {
@@ -506,7 +512,7 @@ pub fn current_path_updater(disk: &str, initial: &str) -> (UpdateCurrentPathFn,
let update_fn = {
let tracker = Arc::clone(&tracker);
Arc::new(move |path: &str| -> Pin<Box<dyn std::future::Future<Output = ()> + Send>> {
Arc::new(move |path: &str| -> Pin<Box<dyn Future<Output = ()> + Send>> {
let tracker = Arc::clone(&tracker);
let path = path.to_string();
Box::pin(async move {
@@ -517,7 +523,7 @@ pub fn current_path_updater(disk: &str, initial: &str) -> (UpdateCurrentPathFn,
let done_fn = {
let disk_name = disk_name.clone();
Arc::new(move || -> Pin<Box<dyn std::future::Future<Output = ()> + Send>> {
Arc::new(move || -> Pin<Box<dyn Future<Output = ()> + Send>> {
let disk_name = disk_name.clone();
Box::pin(async move {
global_metrics().current_paths.write().await.remove(&disk_name);

View File

@@ -112,7 +112,10 @@ pub async fn collect_local_metrics(types: MetricType, opts: &CollectMetricsOpts)
if types.contains(&MetricType::SCANNER) {
debug!("start get scanner metrics");
let metrics = global_metrics().report().await;
let mut metrics = global_metrics().report().await;
if let Some(init_time) = rustfs_common::get_global_init_time().await {
metrics.current_started = init_time;
}
real_time_metrics.aggregated.scanner = Some(metrics);
}

View File

@@ -369,6 +369,9 @@ async fn run(opt: config::Opt) -> Result<()> {
// 4. Mark as Full Ready now that critical components are warm
readiness.mark_stage(SystemStage::FullReady);
// Set the global RustFS initialization time to now
rustfs_common::set_global_init_time_now().await;
// Perform hibernation for 1 second
tokio::time::sleep(SHUTDOWN_TIMEOUT).await;
// listen to the shutdown signal

View File

@@ -177,6 +177,9 @@ pub async fn start_http_server(
TcpListener::from_std(socket.into())?
};
let tls_acceptor = setup_tls_acceptor(opt.tls_path.as_deref().unwrap_or_default()).await?;
let tls_enabled = tls_acceptor.is_some();
let protocol = if tls_enabled { "https" } else { "http" };
// Obtain the listener address
let local_addr: SocketAddr = listener.local_addr()?;
let local_ip = match rustfs_utils::get_local_ip() {
@@ -186,11 +189,15 @@ pub async fn start_http_server(
local_addr.ip()
}
};
let tls_acceptor = setup_tls_acceptor(opt.tls_path.as_deref().unwrap_or_default()).await?;
let tls_enabled = tls_acceptor.is_some();
let protocol = if tls_enabled { "https" } else { "http" };
let local_ip_str = if local_ip.is_ipv6() {
format!("[{local_ip}]")
} else {
local_ip.to_string()
};
// Detailed endpoint information (showing all API endpoints)
let api_endpoints = format!("{protocol}://{local_ip}:{server_port}");
let api_endpoints = format!("{protocol}://{local_ip_str}:{server_port}");
let localhost_endpoint = format!("{protocol}://127.0.0.1:{server_port}");
let now_time = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
if opt.console_enable {
@@ -198,7 +205,7 @@ pub async fn start_http_server(
info!(
target: "rustfs::console::startup",
"Console WebUI available at: {protocol}://{local_ip}:{server_port}/rustfs/console/index.html"
"Console WebUI available at: {protocol}://{local_ip_str}:{server_port}/rustfs/console/index.html"
);
info!(
target: "rustfs::console::startup",
@@ -207,7 +214,7 @@ pub async fn start_http_server(
);
println!("Console WebUI Start Time: {now_time}");
println!("Console WebUI available at: {protocol}://{local_ip}:{server_port}/rustfs/console/index.html");
println!("Console WebUI available at: {protocol}://{local_ip_str}:{server_port}/rustfs/console/index.html");
println!("Console WebUI (localhost): {protocol}://127.0.0.1:{server_port}/rustfs/console/index.html",);
} else {
info!(target: "rustfs::main::startup","RustFS API: {api_endpoints} {localhost_endpoint}");