diff --git a/Cargo.toml b/Cargo.toml index 3e615830..a2f82f85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -118,7 +118,7 @@ slog-stdlog = "4.1.0" num-bigint = "0.4.6" bigdecimal = "0.4.8" bitvec = "1.0.1" -config = "0.13.4" +config = "0.15.9" tempfile = "3.21.0" md-5 = "0.10.6" bitflags = "2.10.0" diff --git a/curvine-cli/src/main.rs b/curvine-cli/src/main.rs index 88b9218c..3a6d264d 100644 --- a/curvine-cli/src/main.rs +++ b/curvine-cli/src/main.rs @@ -23,12 +23,13 @@ use curvine_client::unified::UnifiedFileSystem; use curvine_common::conf::ClusterConf; use curvine_common::version; use orpc::common::{Logger, Utils}; -use orpc::io::net::InetAddr; use orpc::runtime::RpcRuntime; -use orpc::{err_box, CommonResult}; +use orpc::CommonResult; +use serde::Serialize; +use serde_json::json; use std::sync::Arc; -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Serialize)] #[command(author, version = version::VERSION, about, long_about = None)] pub struct CurvineArgs { /// Configuration file path (optional) @@ -48,58 +49,60 @@ pub struct CurvineArgs { )] pub master_addrs: Option, + #[serde(skip_serializing)] #[command(subcommand)] command: Commands, } impl CurvineArgs { - /// Get cluster configuration with priority: CLI args > config file > env vars > defaults pub fn get_conf(&self) -> CommonResult { - // Priority 1: Try to load from config file (CLI arg or env var) let conf_path = self .conf .clone() .or_else(|| std::env::var(ClusterConf::ENV_CONF_FILE).ok()); - let mut conf = if let Some(path) = conf_path { - match ClusterConf::from(&path) { - Ok(c) => c, - Err(e) => { - eprintln!("Warning: Failed to load config file '{}': {}", path, e); - eprintln!("Using default configuration"); - Self::create_default_conf() - } - } + let args_value = serde_json::to_value(self).unwrap(); + + // Change the format of master_addrs from "m1:8995,..." to [{"hostname": "m1", "port": 8995}, ...] + let master_addrs = if let Some(master_addrs_str) = + args_value.get("master_addrs").and_then(|v| v.as_str()) + { + master_addrs_str + .split(',') + .filter(|s| !s.trim().is_empty()) + .map(|addr| { + let addr = addr.trim(); + let parts: Vec<&str> = addr.split(':').collect(); + + if parts.len() == 2 { + let hostname = parts[0]; + let port = parts[1] + .parse::() + .map_err(|_| format!("Invalid port: {}", parts[1]))?; + + Ok(json!({ + "hostname": hostname, + "port": port + })) + } else { + Err(format!("Invalid address format: {}", addr)) + } + }) + .collect::, _>>() + .unwrap() } else { - println!("No config file specified, using default configuration"); - Self::create_default_conf() + Vec::new() }; - // Priority 2: Override with CLI master_addrs if provided - if let Some(master_addrs) = &self.master_addrs { - let mut vec = vec![]; - for node in master_addrs.split(',') { - let tmp: Vec<&str> = node.split(':').collect(); - if tmp.len() != 2 { - return err_box!("Invalid master_addrs format: '{}'. Expected format: 'host1:port1,host2:port2'", master_addrs); - } - let hostname = tmp[0].to_string(); - let port: u16 = tmp[1] - .parse() - .map_err(|_| format!("Invalid port number in master_addrs: '{}'", tmp[1]))?; - vec.push(InetAddr::new(hostname, port)); + let args_json = json!({ + "cli": args_value, + "client": { + "master_addrs": master_addrs } - conf.client.master_addrs = vec; - } - - // Initialize configuration (parse string values to actual types) - conf.client.init()?; - - Ok(conf) - } + }) + .to_string(); - fn create_default_conf() -> ClusterConf { - ClusterConf::default() + ClusterConf::from(conf_path.unwrap(), Some(&args_json)) } } diff --git a/curvine-common/Cargo.toml b/curvine-common/Cargo.toml index eb9e8e0b..fa7a4a00 100644 --- a/curvine-common/Cargo.toml +++ b/curvine-common/Cargo.toml @@ -40,6 +40,7 @@ slog = { workspace = true } slog-stdlog = { workspace = true } chrono = { workspace = true } trait-variant = { workspace = true } +config = { workspace = true } anyhow = { workspace = true } tracing = { workspace = true } diff --git a/curvine-common/src/conf/cli_conf.rs b/curvine-common/src/conf/cli_conf.rs index d3383cfc..6c1a5266 100644 --- a/curvine-common/src/conf/cli_conf.rs +++ b/curvine-common/src/conf/cli_conf.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use orpc::common::LogConf; +use orpc::{common::LogConf, CommonResult}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -21,6 +21,12 @@ pub struct CliConf { pub log: LogConf, } +impl CliConf { + pub fn init(&mut self) -> CommonResult<()> { + Ok(()) + } +} + impl Default for CliConf { fn default() -> Self { CliConf { diff --git a/curvine-common/src/conf/cluster_conf.rs b/curvine-common/src/conf/cluster_conf.rs index a45357ef..8a774db2 100644 --- a/curvine-common/src/conf/cluster_conf.rs +++ b/curvine-common/src/conf/cluster_conf.rs @@ -16,17 +16,16 @@ use crate::conf::CliConf; use crate::conf::{ClientConf, FuseConf, JobConf, JournalConf, MasterConf, WorkerConf}; use crate::rocksdb::DBConf; use crate::version; +use config::{Config, Environment, File, FileFormat}; use log::info; use orpc::client::{ClientConf as RpcConf, ClientFactory, SyncClient}; use orpc::common::{LogConf, Utils}; use orpc::io::net::{InetAddr, NodeAddr}; use orpc::io::retry::TimeBondedRetryBuilder; use orpc::server::ServerConf; -use orpc::{err_box, try_err, CommonResult}; +use orpc::{err_box, CommonResult}; use serde::{Deserialize, Serialize}; -use std::env; use std::fmt::{Display, Formatter}; -use std::fs::read_to_string; use std::time::Duration; // Cluster configuration files. @@ -75,38 +74,71 @@ impl ClusterConf { pub const ENV_CLIENT_HOSTNAME: &'static str = "CURVINE_CLIENT_HOSTNAME"; pub const ENV_CONF_FILE: &'static str = "CURVINE_CONF_FILE"; - pub fn from>(path: T) -> CommonResult { - let str = try_err!(read_to_string(path.as_ref())); - let mut conf = try_err!(toml::from_str::(&str)); - - if let Ok(v) = env::var(Self::ENV_MASTER_HOSTNAME) { - conf.master.hostname = v.to_owned(); - conf.journal.hostname = v; + pub fn from>(path: T, args: Option<&str>) -> CommonResult { + let cli_source = args.unwrap_or("{}").to_string(); + + // Get cluster configuration with priority: CLI args > env vars > config file > defaults + let config = Config::builder() + .add_source(File::new(path.as_ref(), FileFormat::Toml)) + .add_source(Environment::with_prefix("CURVINE").separator("_")) + .add_source(File::from_str(&cli_source, FileFormat::Json)); + + let mut conf; + match config.build() { + Ok(config) => { + conf = Self { + format_master: true, + format_worker: true, + testing: false, + cluster_id: "curvine".to_string(), + master: config.get::("master").unwrap_or_default(), + journal: config.get::("journal").unwrap_or_default(), + worker: config.get::("worker").unwrap_or_default(), + log: config.get::("log").unwrap_or_default(), + client: config.get::("client").unwrap_or_default(), + fuse: config.get::("fuse").unwrap_or_default(), + s3_gateway: config + .get::("s3_gateway") + .unwrap_or_default(), + job: config.get::("job").unwrap_or_default(), + cli: config.get::("cli").unwrap_or_default(), + }; + } + Err(e) => { + eprintln!( + "Warning: Failed to load config file '{}': {}", + path.as_ref(), + e + ); + eprintln!("Using default configuration"); + conf = ClusterConf::default(); + } } - // Apply worker hostname from environment variable (used by worker process) - if let Ok(v) = env::var(Self::ENV_WORKER_HOSTNAME) { - conf.worker.hostname = v; - } + conf.init()?; - // Apply client hostname from environment variable - if let Ok(v) = env::var(Self::ENV_CLIENT_HOSTNAME) { - conf.client.hostname = v; - } + Ok(conf) + } - conf.master.init()?; - conf.client.init()?; - conf.fuse.init()?; - conf.job.init()?; + pub fn init(&mut self) -> CommonResult<()> { + self.master.init()?; + self.journal.init()?; + self.worker.init()?; + self.log.init()?; + self.client.init()?; + self.fuse.init()?; + self.s3_gateway.init()?; + self.job.init()?; + self.cli.init()?; - if conf.client.master_addrs.is_empty() { - for peer in &mut conf.journal.journal_addrs { - let node = InetAddr::new(&peer.hostname, conf.master.rpc_port); - conf.client.master_addrs.push(node); + if self.client.master_addrs.is_empty() { + for peer in &mut self.journal.journal_addrs { + let node = InetAddr::new(&peer.hostname, self.master.rpc_port); + self.client.master_addrs.push(node); } } - Ok(conf) + Ok(()) } pub fn check_master_hostname(&mut self) -> CommonResult<()> { @@ -268,7 +300,7 @@ impl ClusterConf { impl Default for ClusterConf { fn default() -> Self { - Self { + let mut conf = Self { format_master: true, format_worker: true, testing: false, @@ -282,7 +314,11 @@ impl Default for ClusterConf { s3_gateway: Default::default(), job: Default::default(), cli: Default::default(), - } + }; + + conf.init().unwrap(); + + conf } } @@ -310,6 +346,12 @@ pub struct S3GatewayConf { pub web_port: u16, } +impl S3GatewayConf { + pub fn init(&mut self) -> CommonResult<()> { + Ok(()) + } +} + impl Default for S3GatewayConf { fn default() -> Self { Self { diff --git a/curvine-common/src/conf/journal_conf.rs b/curvine-common/src/conf/journal_conf.rs index f0934a74..9951d158 100644 --- a/curvine-common/src/conf/journal_conf.rs +++ b/curvine-common/src/conf/journal_conf.rs @@ -18,6 +18,7 @@ use orpc::client::ClientConf; use orpc::common::Utils; use orpc::io::net::{InetAddr, NetUtils}; use orpc::runtime::Runtime; +use orpc::CommonResult; use serde::{Deserialize, Serialize}; use std::sync::Arc; use std::vec; @@ -108,6 +109,10 @@ pub struct JournalConf { impl JournalConf { pub const DEFAULT_NODE_ID: u64 = 0; + pub fn init(&mut self) -> CommonResult<()> { + Ok(()) + } + // Create a test configuration, which will also randomly select a server port. pub fn with_test() -> Self { let mut conf = Self::default(); diff --git a/curvine-common/src/conf/mod.rs b/curvine-common/src/conf/mod.rs index 7ad040d2..8412d80c 100644 --- a/curvine-common/src/conf/mod.rs +++ b/curvine-common/src/conf/mod.rs @@ -55,7 +55,7 @@ mod tests { #[test] fn cluster() { let path = "../etc/curvine-cluster.toml"; - let conf = ClusterConf::from(path).unwrap(); + let conf = ClusterConf::from(path, None).unwrap(); println!("conf = {:#?}", conf) } diff --git a/curvine-common/src/conf/worker_conf.rs b/curvine-common/src/conf/worker_conf.rs index 2e6e3ef6..e41e8540 100644 --- a/curvine-common/src/conf/worker_conf.rs +++ b/curvine-common/src/conf/worker_conf.rs @@ -162,6 +162,10 @@ pub struct WorkerConf { } impl WorkerConf { + pub fn init(&mut self) -> CommonResult<()> { + Ok(()) + } + pub fn io_slow_us(&self) -> u64 { let dur = DurationUnit::from_str(&self.io_slow_threshold).unwrap(); dur.as_millis() * 1000 diff --git a/curvine-fuse/Cargo.toml b/curvine-fuse/Cargo.toml index 0f12187c..325edc79 100644 --- a/curvine-fuse/Cargo.toml +++ b/curvine-fuse/Cargo.toml @@ -27,6 +27,9 @@ mini-moka = { workspace = true } fxhash = { workspace = true } dashmap = { workspace = true } bitflags = { workspace = true } +serde = { workspace = true } +serde_with = { workspace = true } +serde_json = { workspace = true } axum = { workspace = true } tracing = { workspace = true } tracing-appender = { workspace = true } diff --git a/curvine-fuse/src/bin/curvine-fuse.rs b/curvine-fuse/src/bin/curvine-fuse.rs index 42d1a4ef..8dc13bab 100644 --- a/curvine-fuse/src/bin/curvine-fuse.rs +++ b/curvine-fuse/src/bin/curvine-fuse.rs @@ -19,9 +19,11 @@ use curvine_fuse::fs::CurvineFileSystem; use curvine_fuse::session::FuseSession; use curvine_fuse::web_server::WebServer; use orpc::common::Logger; -use orpc::io::net::InetAddr; use orpc::runtime::{AsyncRuntime, RpcRuntime}; -use orpc::{err_box, CommonResult}; +use orpc::CommonResult; +use serde::Serialize; +use serde_json::json; +use serde_with::skip_serializing_none; use std::sync::Arc; // fuse mount. @@ -48,8 +50,9 @@ fn main() -> CommonResult<()> { let fuse_rt = rt.clone(); + let web_port = cluster_conf.fuse.web_port; rt.spawn(async move { - if let Err(e) = WebServer::start(cluster_conf.fuse.web_port).await { + if let Err(e) = WebServer::start(web_port).await { tracing::error!("Failed to start metrics server: {}", e); } }); @@ -65,7 +68,8 @@ fn main() -> CommonResult<()> { } // Mount command function parameters -#[derive(Debug, Parser, Clone)] +#[skip_serializing_none] +#[derive(Debug, Parser, Clone, Serialize)] #[command(version = version::VERSION)] pub struct FuseArgs { // Mount the mount point, mount the file system to a directory of the machine. @@ -162,123 +166,50 @@ pub struct FuseArgs { impl FuseArgs { // parse the cluster configuration file. pub fn get_conf(&self) -> CommonResult { - let mut conf = match ClusterConf::from(&self.conf) { - Ok(c) => { - println!("Loaded configuration from {}", self.conf); - c - } - Err(e) => { - eprintln!("Warning: Failed to load config file '{}': {}", self.conf, e); - eprintln!("Using default configuration"); - Self::create_default_conf() - } + let args_value = serde_json::to_value(self).unwrap(); + + // Change the format of master_addrs from "m1:8995,..." to [{"hostname": "m1", "port": 8995}, ...] + let master_addrs = if let Some(master_addrs_str) = + args_value.get("master_addrs").and_then(|v| v.as_str()) + { + master_addrs_str + .split(',') + .filter(|s| !s.trim().is_empty()) + .map(|addr| { + let addr = addr.trim(); + let parts: Vec<&str> = addr.split(':').collect(); + + if parts.len() == 2 { + let hostname = parts[0]; + let port = parts[1] + .parse::() + .map_err(|_| format!("Invalid port: {}", parts[1]))?; + + Ok(json!({ + "hostname": hostname, + "port": port + })) + } else { + Err(format!("Invalid address format: {}", addr)) + } + }) + .collect::, _>>() + .unwrap() + } else { + Vec::new() }; - // FUSE configuration - only override if command line values are specified - if let Some(mnt_path) = &self.mnt_path { - conf.fuse.mnt_path = mnt_path.clone(); - } - if let Some(fs_path) = &self.fs_path { - conf.fuse.fs_path = fs_path.clone(); - } - if let Some(mnt_number) = self.mnt_number { - conf.fuse.mnt_number = mnt_number; - } - if self.debug { - conf.fuse.debug = true; - } - - // Optional FUSE parameters - only override if specified - if let Some(io_threads) = self.io_threads { - conf.fuse.io_threads = io_threads; - } - - if let Some(worker_threads) = self.worker_threads { - conf.fuse.worker_threads = worker_threads; - } - - if let Some(mnt_per_task) = self.mnt_per_task { - conf.fuse.mnt_per_task = mnt_per_task; - } - - if let Some(clone_fd) = self.clone_fd { - conf.fuse.clone_fd = clone_fd; - } - - if let Some(fuse_channel_size) = self.fuse_channel_size { - conf.fuse.fuse_channel_size = fuse_channel_size; - } - - if let Some(stream_channel_size) = self.stream_channel_size { - conf.fuse.stream_channel_size = stream_channel_size; - } - - if let Some(direct_io) = self.direct_io { - conf.fuse.direct_io = direct_io; - } - - if let Some(cache_readdir) = self.cache_readdir { - conf.fuse.cache_readdir = cache_readdir; - } - - if let Some(entry_timeout) = self.entry_timeout { - conf.fuse.entry_timeout = entry_timeout; - } - - if let Some(attr_timeout) = self.attr_timeout { - conf.fuse.attr_timeout = attr_timeout; - } - - if let Some(negative_timeout) = self.negative_timeout { - conf.fuse.negative_timeout = negative_timeout; - } - - if let Some(max_background) = self.max_background { - conf.fuse.max_background = max_background; - } - - if let Some(congestion_threshold) = self.congestion_threshold { - conf.fuse.congestion_threshold = congestion_threshold; - } - - if let Some(node_cache_size) = self.node_cache_size { - conf.fuse.node_cache_size = node_cache_size; - } - - if let Some(node_cache_timeout) = &self.node_cache_timeout { - conf.fuse.node_cache_timeout = node_cache_timeout.clone(); - } - - if let Some(web_port) = self.web_port { - conf.fuse.web_port = web_port; - } - - if let Some(master_addrs) = &self.master_addrs { - let mut vec = vec![]; - for node in master_addrs.split(",") { - let tmp: Vec<&str> = node.split(":").collect(); - if tmp.len() != 2 { - return err_box!("wrong format master_addrs {}", master_addrs); - } - let hostname = tmp[0].to_string(); - let port: u16 = tmp[1].parse()?; - vec.push(InetAddr::new(hostname, port)); + let args_json = json!({ + "fuse": args_value, + "client": { + "master_addrs": master_addrs } - conf.client.master_addrs = vec; - } - - // FUSE options - override if provided - if !self.options.is_empty() { - conf.fuse.fuse_opts = self.options.clone() - } else { - conf.fuse.fuse_opts = Self::default_mnt_opts(); - } - - Ok(conf) - } + }) + .to_string(); - fn create_default_conf() -> ClusterConf { - ClusterConf::default() + let conf = ClusterConf::from(&self.conf, Some(&args_json)); + println!("Loaded configuration from {}", &self.conf); + conf } pub fn default_mnt_opts() -> Vec { diff --git a/curvine-s3-gateway/Cargo.toml b/curvine-s3-gateway/Cargo.toml index 9a3e4074..feef65c3 100644 --- a/curvine-s3-gateway/Cargo.toml +++ b/curvine-s3-gateway/Cargo.toml @@ -15,6 +15,7 @@ tokio = { workspace = true } bytes = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +serde_with = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["fmt", "env-filter"] } async-trait = { workspace = true } diff --git a/curvine-s3-gateway/src/bin/curvine-s3-gateway.rs b/curvine-s3-gateway/src/bin/curvine-s3-gateway.rs index 31208c16..ef358c1e 100644 --- a/curvine-s3-gateway/src/bin/curvine-s3-gateway.rs +++ b/curvine-s3-gateway/src/bin/curvine-s3-gateway.rs @@ -22,9 +22,13 @@ use curvine_s3_gateway::auth::{ use orpc::runtime::{AsyncRuntime, RpcRuntime}; use orpc::CommonResult; use rand::Rng; +use serde::Serialize; +use serde_json::json; +use serde_with::skip_serializing_none; use std::sync::Arc; -#[derive(Debug, Parser, Clone)] +#[skip_serializing_none] +#[derive(Debug, Parser, Clone, Serialize)] #[command(version = version::VERSION)] pub struct ObjectArgs { #[arg( @@ -44,6 +48,7 @@ pub struct ObjectArgs { #[arg(long)] pub credentials_path: Option, + #[serde(skip_serializing)] #[command(subcommand)] pub command: Option, } @@ -81,19 +86,13 @@ pub enum CredentialAction { fn main() -> CommonResult<()> { let args = ObjectArgs::parse(); - let conf = match ClusterConf::from(&args.conf) { - Ok(c) => { - tracing::info!("Loaded configuration from {}", args.conf); - c - } - Err(e) => { - println!( - "Warning: Failed to load config file '{}': {}. Using default configuration", - args.conf, e - ); - ClusterConf::default() - } - }; + let args_value = serde_json::to_value(&args).unwrap(); + let args_json = json!({ + "s3_gateway": args_value, + }) + .to_string(); + let conf = ClusterConf::from(&args.conf, Some(&args_json))?; + println!("Loaded configuration from {}", &args.conf); orpc::common::Logger::init(conf.master.log.clone()); @@ -101,21 +100,12 @@ fn main() -> CommonResult<()> { return handle_credential_command(&args, &conf, action.clone()); } - serve_gateway(args, conf) + serve_gateway(conf) } -fn serve_gateway(args: ObjectArgs, conf: ClusterConf) -> CommonResult<()> { - let listen = if args.listen != "0.0.0.0:9900" { - args.listen.clone() - } else { - conf.s3_gateway.listen.clone() - }; - - let region = if args.region != "us-east-1" { - args.region.clone() - } else { - conf.s3_gateway.region.clone() - }; +fn serve_gateway(conf: ClusterConf) -> CommonResult<()> { + let listen = conf.s3_gateway.listen.clone(); + let region = conf.s3_gateway.region.clone(); tracing::info!( "S3 Gateway configuration - Listen: {}, Region: {}", diff --git a/curvine-server/src/bin/curvine-server.rs b/curvine-server/src/bin/curvine-server.rs index 4d8fd647..0af3bad9 100644 --- a/curvine-server/src/bin/curvine-server.rs +++ b/curvine-server/src/bin/curvine-server.rs @@ -73,7 +73,9 @@ impl ServerArgs { } pub fn get_conf(&self) -> CommonResult { - ClusterConf::from(&self.conf) + let conf = ClusterConf::from(&self.conf, None); + println!("Loaded configuration from {}", &self.conf); + conf } } diff --git a/curvine-tests/src/bench_action.rs b/curvine-tests/src/bench_action.rs index 0519663b..8d9d5ee0 100644 --- a/curvine-tests/src/bench_action.rs +++ b/curvine-tests/src/bench_action.rs @@ -111,7 +111,7 @@ impl BenchAction { } pub fn get_fs(&self, rt: Arc) -> CurvineFileSystem { - let conf = ClusterConf::from(&self.args.conf).unwrap(); + let conf = ClusterConf::from(&self.args.conf, None).unwrap(); CurvineFileSystem::with_rt(conf, rt).unwrap() } } diff --git a/curvine-tests/src/testing.rs b/curvine-tests/src/testing.rs index 6ef1b9c3..6b971460 100644 --- a/curvine-tests/src/testing.rs +++ b/curvine-tests/src/testing.rs @@ -93,7 +93,7 @@ impl Testing { /// Read the active cluster configuration from the persisted path. pub fn get_active_cluster_conf(&self) -> CommonResult { - ClusterConf::from(self.active_cluster_conf_path.clone()) + ClusterConf::from(self.active_cluster_conf_path.clone(), None) } /// Expose the active config file path. @@ -225,7 +225,7 @@ impl TestingBuilder { let mut conf = if let Some(c) = self.base_conf { c } else if let Some(p) = self.base_conf_path { - ClusterConf::from(p)? + ClusterConf::from(p, None)? } else { ClusterConf::default() }; diff --git a/etc/curvine-env.sh b/etc/curvine-env.sh index 2ec260fa..854b8024 100644 --- a/etc/curvine-env.sh +++ b/etc/curvine-env.sh @@ -33,6 +33,7 @@ fi # master bound host name export CURVINE_MASTER_HOSTNAME=${CURVINE_MASTER_HOSTNAME:-$LOCAL_HOSTNAME} +export CURVINE_JOURNAL_HOSTNAME=${CURVINE_MASTER_HOSTNAME:-$LOCAL_HOSTNAME} # worker bound host name export CURVINE_WORKER_HOSTNAME=${CURVINE_WORKER_HOSTNAME:-$LOCAL_IP} diff --git a/orpc/src/common/logger.rs b/orpc/src/common/logger.rs index 92ec4b3a..175f8588 100644 --- a/orpc/src/common/logger.rs +++ b/orpc/src/common/logger.rs @@ -13,6 +13,7 @@ // limitations under the License. use crate::common::LogFormatter; +use crate::CommonResult; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -44,6 +45,12 @@ pub struct LogConf { pub targets: Vec, } +impl LogConf { + pub fn init(&mut self) -> CommonResult<()> { + Ok(()) + } +} + impl Default for LogConf { fn default() -> Self { Self {