mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-25 05:26:50 +00:00
trace log use local time and get custom user agent
This commit is contained in:
@@ -1,19 +1,19 @@
|
|||||||
use crate::OtelConfig;
|
use crate::OtelConfig;
|
||||||
use flexi_logger::{Age, Cleanup, Criterion, DeferredNow, FileSpec, LogSpecification, Naming, Record, WriteMode, style};
|
use flexi_logger::{style, Age, Cleanup, Criterion, DeferredNow, FileSpec, LogSpecification, Naming, Record, WriteMode};
|
||||||
use nu_ansi_term::Color;
|
use nu_ansi_term::Color;
|
||||||
use opentelemetry::trace::TracerProvider;
|
use opentelemetry::trace::TracerProvider;
|
||||||
use opentelemetry::{KeyValue, global};
|
use opentelemetry::{global, KeyValue};
|
||||||
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
|
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
|
||||||
use opentelemetry_otlp::WithExportConfig;
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
use opentelemetry_sdk::logs::SdkLoggerProvider;
|
use opentelemetry_sdk::logs::SdkLoggerProvider;
|
||||||
use opentelemetry_sdk::{
|
use opentelemetry_sdk::{
|
||||||
Resource,
|
|
||||||
metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider},
|
metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider},
|
||||||
trace::{RandomIdGenerator, Sampler, SdkTracerProvider},
|
trace::{RandomIdGenerator, Sampler, SdkTracerProvider},
|
||||||
|
Resource,
|
||||||
};
|
};
|
||||||
use opentelemetry_semantic_conventions::{
|
use opentelemetry_semantic_conventions::{
|
||||||
SCHEMA_URL,
|
|
||||||
attribute::{DEPLOYMENT_ENVIRONMENT_NAME, NETWORK_LOCAL_ADDRESS, SERVICE_VERSION as OTEL_SERVICE_VERSION},
|
attribute::{DEPLOYMENT_ENVIRONMENT_NAME, NETWORK_LOCAL_ADDRESS, SERVICE_VERSION as OTEL_SERVICE_VERSION},
|
||||||
|
SCHEMA_URL,
|
||||||
};
|
};
|
||||||
use rustfs_config::{
|
use rustfs_config::{
|
||||||
APP_NAME, DEFAULT_LOG_DIR, DEFAULT_LOG_KEEP_FILES, DEFAULT_LOG_LEVEL, ENVIRONMENT, METER_INTERVAL, SAMPLE_RATIO,
|
APP_NAME, DEFAULT_LOG_DIR, DEFAULT_LOG_KEEP_FILES, DEFAULT_LOG_LEVEL, ENVIRONMENT, METER_INTERVAL, SAMPLE_RATIO,
|
||||||
@@ -27,7 +27,8 @@ use tracing::info;
|
|||||||
use tracing_error::ErrorLayer;
|
use tracing_error::ErrorLayer;
|
||||||
use tracing_opentelemetry::{MetricsLayer, OpenTelemetryLayer};
|
use tracing_opentelemetry::{MetricsLayer, OpenTelemetryLayer};
|
||||||
use tracing_subscriber::fmt::format::FmtSpan;
|
use tracing_subscriber::fmt::format::FmtSpan;
|
||||||
use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::fmt::time::LocalTime;
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
|
||||||
|
|
||||||
/// A guard object that manages the lifecycle of OpenTelemetry components.
|
/// A guard object that manages the lifecycle of OpenTelemetry components.
|
||||||
///
|
///
|
||||||
@@ -224,6 +225,7 @@ pub(crate) fn init_telemetry(config: &OtelConfig) -> OtelGuard {
|
|||||||
let fmt_layer = {
|
let fmt_layer = {
|
||||||
let enable_color = std::io::stdout().is_terminal();
|
let enable_color = std::io::stdout().is_terminal();
|
||||||
let mut layer = tracing_subscriber::fmt::layer()
|
let mut layer = tracing_subscriber::fmt::layer()
|
||||||
|
.with_timer(LocalTime::rfc_3339())
|
||||||
.with_target(true)
|
.with_target(true)
|
||||||
.with_ansi(enable_color)
|
.with_ansi(enable_color)
|
||||||
.with_thread_names(true)
|
.with_thread_names(true)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ rand = { workspace = true, optional = true }
|
|||||||
futures = { workspace = true, optional = true }
|
futures = { workspace = true, optional = true }
|
||||||
transform-stream = { workspace = true, optional = true }
|
transform-stream = { workspace = true, optional = true }
|
||||||
bytes = { workspace = true, optional = true }
|
bytes = { workspace = true, optional = true }
|
||||||
|
sysinfo = { workspace = true, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
@@ -62,4 +63,5 @@ crypto = ["dep:base64-simd", "dep:hex-simd"]
|
|||||||
hash = ["dep:highway", "dep:md-5", "dep:sha2", "dep:blake3", "dep:serde", "dep:siphasher"]
|
hash = ["dep:highway", "dep:md-5", "dep:sha2", "dep:blake3", "dep:serde", "dep:siphasher"]
|
||||||
os = ["dep:nix", "dep:tempfile", "winapi"] # operating system utilities
|
os = ["dep:nix", "dep:tempfile", "winapi"] # operating system utilities
|
||||||
integration = [] # integration test features
|
integration = [] # integration test features
|
||||||
full = ["ip", "tls", "net", "io", "hash", "os", "integration", "path", "crypto", "string", "compress"] # all features
|
sys = ["dep:sysinfo"] # system information features
|
||||||
|
full = ["ip", "tls", "net", "io", "hash", "os", "integration", "path", "crypto", "string", "compress", "sys"] # all features
|
||||||
|
|||||||
@@ -33,10 +33,13 @@ pub mod dirs;
|
|||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
pub use certs::*;
|
pub use certs::*;
|
||||||
|
|
||||||
#[cfg(feature = "hash")]
|
#[cfg(feature = "hash")]
|
||||||
pub use hash::*;
|
pub use hash::*;
|
||||||
|
|
||||||
#[cfg(feature = "io")]
|
#[cfg(feature = "io")]
|
||||||
pub use io::*;
|
pub use io::*;
|
||||||
|
|
||||||
#[cfg(feature = "ip")]
|
#[cfg(feature = "ip")]
|
||||||
pub use ip::*;
|
pub use ip::*;
|
||||||
|
|
||||||
@@ -45,3 +48,6 @@ pub use crypto::*;
|
|||||||
|
|
||||||
#[cfg(feature = "compress")]
|
#[cfg(feature = "compress")]
|
||||||
pub use compress::*;
|
pub use compress::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "sys")]
|
||||||
|
pub mod sys;
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
mod user_agent;
|
||||||
|
|
||||||
|
pub use user_agent::get_user_agent;
|
||||||
|
pub use user_agent::ServiceType;
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
|
use rustfs_config::VERSION;
|
||||||
|
use std::env;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
#[cfg(unix)]
|
use sysinfo::System;
|
||||||
use std::os::unix::process::ExitStatusExt;
|
|
||||||
#[cfg(windows)]
|
|
||||||
use std::os::windows::process::ExitStatusExt;
|
|
||||||
use std::{env, process};
|
|
||||||
|
|
||||||
// Define Rustfs version
|
/// Business Type Enumeration
|
||||||
const RUSTFS_VERSION: &str = "1.0.0";
|
|
||||||
|
|
||||||
// Business Type Enumeration
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum ServiceType {
|
pub enum ServiceType {
|
||||||
Basis,
|
Basis,
|
||||||
@@ -39,11 +34,16 @@ struct UserAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UserAgent {
|
impl UserAgent {
|
||||||
// Create a new UserAgent instance and accept business type parameters
|
/// Create a new UserAgent instance and accept business type parameters
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `service` - The type of service for which the User-Agent is being created.
|
||||||
|
/// # Returns
|
||||||
|
/// A new instance of `UserAgent` with the current OS platform, architecture, version, and service type.
|
||||||
fn new(service: ServiceType) -> Self {
|
fn new(service: ServiceType) -> Self {
|
||||||
let os_platform = Self::get_os_platform();
|
let os_platform = Self::get_os_platform();
|
||||||
let arch = env::consts::ARCH.to_string();
|
let arch = env::consts::ARCH.to_string();
|
||||||
let version = RUSTFS_VERSION.to_string();
|
let version = VERSION.to_string();
|
||||||
|
|
||||||
UserAgent {
|
UserAgent {
|
||||||
os_platform,
|
os_platform,
|
||||||
@@ -53,64 +53,57 @@ impl UserAgent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain operating system platform information
|
/// Obtain operating system platform information
|
||||||
fn get_os_platform() -> String {
|
fn get_os_platform() -> String {
|
||||||
|
let sys = System::new_all();
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
Self::get_windows_platform()
|
Self::get_windows_platform(&sys)
|
||||||
} else if cfg!(target_os = "macos") {
|
} else if cfg!(target_os = "macos") {
|
||||||
Self::get_macos_platform()
|
Self::get_macos_platform(&sys)
|
||||||
} else if cfg!(target_os = "linux") {
|
} else if cfg!(target_os = "linux") {
|
||||||
Self::get_linux_platform()
|
Self::get_linux_platform(&sys)
|
||||||
} else {
|
} else {
|
||||||
"Unknown".to_string()
|
"Unknown".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Windows platform information
|
/// Get Windows platform information
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn get_windows_platform() -> String {
|
fn get_windows_platform(sys: &System) -> String {
|
||||||
// Use cmd /c ver to get the version
|
// Priority to using sysinfo to get versions
|
||||||
let output = process::Command::new("cmd")
|
if let Some(version) = sys.os_version() {
|
||||||
.args(&["/C", "ver"])
|
format!("Windows NT {}", version)
|
||||||
.output()
|
} else {
|
||||||
.unwrap_or_else(|_| process::Output {
|
// Fallback to cmd /c ver
|
||||||
status: process::ExitStatus::from_raw(0),
|
let output = std::process::Command::new("cmd")
|
||||||
stdout: Vec::new(),
|
.args(&["/C", "ver"])
|
||||||
stderr: Vec::new(),
|
.output()
|
||||||
});
|
.unwrap_or_default();
|
||||||
let version = String::from_utf8_lossy(&output.stdout);
|
let version = String::from_utf8_lossy(&output.stdout);
|
||||||
let version = version
|
let version = version
|
||||||
.lines()
|
.lines()
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or("Windows NT 10.0")
|
.unwrap_or("Windows NT 10.0")
|
||||||
.replace("Microsoft Windows [Version ", "")
|
.replace("Microsoft Windows [Version ", "")
|
||||||
.replace("]", "");
|
.replace("]", "");
|
||||||
format!("Windows NT {}", version.trim())
|
format!("Windows NT {}", version.trim())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
fn get_windows_platform() -> String {
|
fn get_windows_platform(_sys: &System) -> String {
|
||||||
"N/A".to_string()
|
"N/A".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get macOS platform information
|
/// Get macOS platform information
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
fn get_macos_platform() -> String {
|
fn get_macos_platform(_sys: &System) -> String {
|
||||||
let output = process::Command::new("sw_vers")
|
let binding = System::os_version().unwrap_or("14.5.0".to_string());
|
||||||
.args(&["-productVersion"])
|
let version = binding.split('.').collect::<Vec<&str>>();
|
||||||
.output()
|
let major = version.get(0).unwrap_or(&"14").to_string();
|
||||||
.unwrap_or_else(|_| process::Output {
|
let minor = version.get(1).unwrap_or(&"5").to_string();
|
||||||
status: process::ExitStatus::from_raw(0),
|
let patch = version.get(2).unwrap_or(&"0").to_string();
|
||||||
stdout: Vec::new(),
|
|
||||||
stderr: Vec::new(),
|
|
||||||
});
|
|
||||||
let version = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
||||||
let parts: Vec<&str> = version.split('.').collect();
|
|
||||||
let major = parts.get(0).unwrap_or(&"10").parse::<i32>().unwrap_or(10);
|
|
||||||
let minor = parts.get(1).map_or("15", |&m| m);
|
|
||||||
let patch = parts.get(2).map_or("0", |&p| p);
|
|
||||||
|
|
||||||
// Detect whether it is an Apple Silicon chip
|
|
||||||
let arch = env::consts::ARCH;
|
let arch = env::consts::ARCH;
|
||||||
let cpu_info = if arch == "aarch64" { "Apple" } else { "Intel" };
|
let cpu_info = if arch == "aarch64" { "Apple" } else { "Intel" };
|
||||||
|
|
||||||
@@ -119,36 +112,25 @@ impl UserAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
fn get_macos_platform() -> String {
|
fn get_macos_platform(_sys: &System) -> String {
|
||||||
"N/A".to_string()
|
"N/A".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Linux platform information
|
/// Get Linux platform information
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn get_linux_platform() -> String {
|
fn get_linux_platform(sys: &System) -> String {
|
||||||
let output = process::Command::new("uname")
|
let name = sys.name().unwrap_or("Linux".to_string());
|
||||||
.arg("-r")
|
let version = sys.os_version().unwrap_or("Unknown".to_string());
|
||||||
.output()
|
format!("X11; {} {}", name, version)
|
||||||
.unwrap_or_else(|_| process::Output {
|
|
||||||
status: process::ExitStatus::from_raw(0),
|
|
||||||
stdout: Vec::new(),
|
|
||||||
stderr: Vec::new(),
|
|
||||||
});
|
|
||||||
if output.status.success() {
|
|
||||||
let release = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
||||||
format!("X11; Linux {}", release)
|
|
||||||
} else {
|
|
||||||
"X11; Linux Unknown".to_string()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
fn get_linux_platform() -> String {
|
fn get_linux_platform(_sys: &System) -> String {
|
||||||
"N/A".to_string()
|
"N/A".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement Display trait to format User-Agent
|
/// Implement Display trait to format User-Agent
|
||||||
impl fmt::Display for UserAgent {
|
impl fmt::Display for UserAgent {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.service == ServiceType::Basis {
|
if self.service == ServiceType::Basis {
|
||||||
@@ -195,7 +177,6 @@ mod tests {
|
|||||||
let ua = get_user_agent(ServiceType::Event);
|
let ua = get_user_agent(ServiceType::Event);
|
||||||
assert!(ua.starts_with("Mozilla/5.0"));
|
assert!(ua.starts_with("Mozilla/5.0"));
|
||||||
assert!(ua.contains("Rustfs/1.0.0 (event)"));
|
assert!(ua.contains("Rustfs/1.0.0 (event)"));
|
||||||
|
|
||||||
println!("User-Agent: {}", ua);
|
println!("User-Agent: {}", ua);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,4 +195,18 @@ mod tests {
|
|||||||
assert!(ua.contains("Rustfs/1.0.0 (monitor)"));
|
assert!(ua.contains("Rustfs/1.0.0 (monitor)"));
|
||||||
println!("User-Agent: {}", ua);
|
println!("User-Agent: {}", ua);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_all_service_type() {
|
||||||
|
// Example: Generate User-Agents of Different Business Types
|
||||||
|
let ua_core = get_user_agent(ServiceType::Core);
|
||||||
|
let ua_event = get_user_agent(ServiceType::Event);
|
||||||
|
let ua_logger = get_user_agent(ServiceType::Logger);
|
||||||
|
let ua_custom = get_user_agent(ServiceType::Custom("monitor".to_string()));
|
||||||
|
|
||||||
|
println!("Core User-Agent: {}", ua_core);
|
||||||
|
println!("Event User-Agent: {}", ua_event);
|
||||||
|
println!("Logger User-Agent: {}", ua_logger);
|
||||||
|
println!("Custom User-Agent: {}", ua_custom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user