mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 02:09:06 +00:00
Generated
+11
@@ -2207,6 +2207,7 @@ dependencies = [
|
|||||||
"humansize",
|
"humansize",
|
||||||
"humantime-serde",
|
"humantime-serde",
|
||||||
"idna 1.0.3",
|
"idna 1.0.3",
|
||||||
|
"indoc",
|
||||||
"kcp-sys",
|
"kcp-sys",
|
||||||
"machine-uid",
|
"machine-uid",
|
||||||
"maplit",
|
"maplit",
|
||||||
@@ -2222,6 +2223,7 @@ dependencies = [
|
|||||||
"openssl",
|
"openssl",
|
||||||
"ordered_hash_map",
|
"ordered_hash_map",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"paste",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"petgraph 0.8.1",
|
"petgraph 0.8.1",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@@ -4163,6 +4165,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indoc"
|
||||||
|
version = "2.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
||||||
|
dependencies = [
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "infer"
|
name = "infer"
|
||||||
version = "0.19.0"
|
version = "0.19.0"
|
||||||
|
|||||||
+11
@@ -1130,6 +1130,7 @@ dependencies = [
|
|||||||
"humansize",
|
"humansize",
|
||||||
"humantime-serde",
|
"humantime-serde",
|
||||||
"idna",
|
"idna",
|
||||||
|
"indoc",
|
||||||
"kcp-sys",
|
"kcp-sys",
|
||||||
"machine-uid",
|
"machine-uid",
|
||||||
"multimap",
|
"multimap",
|
||||||
@@ -1142,6 +1143,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"ordered_hash_map",
|
"ordered_hash_map",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"paste",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"petgraph 0.8.2",
|
"petgraph 0.8.2",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@@ -2197,6 +2199,15 @@ dependencies = [
|
|||||||
"hashbrown 0.16.0",
|
"hashbrown 0.16.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indoc"
|
||||||
|
version = "2.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
||||||
|
dependencies = [
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inout"
|
name = "inout"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use api::routes::create_routes;
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use config::AppConfig;
|
use config::AppConfig;
|
||||||
use db::{operations::NodeOperations, Db};
|
use db::{operations::NodeOperations, Db};
|
||||||
use easytier::utils::init_logger;
|
use easytier::common::log;
|
||||||
use health_checker::HealthChecker;
|
use health_checker::HealthChecker;
|
||||||
use health_checker_manager::HealthCheckerManager;
|
use health_checker_manager::HealthCheckerManager;
|
||||||
use std::env;
|
use std::env;
|
||||||
@@ -42,7 +42,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let config = AppConfig::default();
|
let config = AppConfig::default();
|
||||||
|
|
||||||
// 初始化日志
|
// 初始化日志
|
||||||
let _ = init_logger(&config.logging, false);
|
let _ = log::init(&config.logging, false);
|
||||||
|
|
||||||
// 解析命令行参数
|
// 解析命令行参数
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ use easytier::rpc_service::remote_client::{
|
|||||||
};
|
};
|
||||||
use easytier::web_client::{self, WebClient};
|
use easytier::web_client::{self, WebClient};
|
||||||
use easytier::{
|
use easytier::{
|
||||||
common::config::{ConfigLoader, FileLoggerConfig, LoggingConfigBuilder, TomlConfigLoader},
|
common::{
|
||||||
|
config::{ConfigLoader, FileLoggerConfig, LoggingConfigBuilder, TomlConfigLoader},
|
||||||
|
log,
|
||||||
|
},
|
||||||
instance_manager::NetworkInstanceManager,
|
instance_manager::NetworkInstanceManager,
|
||||||
launcher::NetworkConfig,
|
launcher::NetworkConfig,
|
||||||
rpc_service::ApiRpcServer,
|
rpc_service::ApiRpcServer,
|
||||||
@@ -1119,7 +1122,7 @@ pub fn run_gui() -> std::process::ExitCode {
|
|||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
let Ok(_) = utils::init_logger(&config, true) else {
|
let Ok(_) = log::init(&config, true) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ use easytier::{
|
|||||||
config::{ConsoleLoggerConfig, FileLoggerConfig, LoggingConfigLoader},
|
config::{ConsoleLoggerConfig, FileLoggerConfig, LoggingConfigLoader},
|
||||||
constants::EASYTIER_VERSION,
|
constants::EASYTIER_VERSION,
|
||||||
error::Error,
|
error::Error,
|
||||||
|
log,
|
||||||
network::{local_ipv4, local_ipv6},
|
network::{local_ipv4, local_ipv6},
|
||||||
},
|
},
|
||||||
tunnel::{tcp::TcpTunnelListener, udp::UdpTunnelListener, TunnelListener},
|
tunnel::{tcp::TcpTunnelListener, udp::UdpTunnelListener, TunnelListener},
|
||||||
utils::{init_logger, setup_panic_handler},
|
utils::setup_panic_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mimalloc::MiMalloc;
|
use mimalloc::MiMalloc;
|
||||||
@@ -205,7 +206,7 @@ async fn main() {
|
|||||||
setup_panic_handler();
|
setup_panic_handler();
|
||||||
|
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
init_logger(&cli, false).unwrap();
|
log::init(&cli, false).unwrap();
|
||||||
|
|
||||||
// Validate OIDC configuration: check split-deploy specific requirements
|
// Validate OIDC configuration: check split-deploy specific requirements
|
||||||
// Basic OIDC parameter validation is handled in OidcConfig::from_params
|
// Basic OIDC parameter validation is handled in OidcConfig::from_params
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ tracing-subscriber = { version = "0.3", features = [
|
|||||||
derivative = "2.2.0"
|
derivative = "2.2.0"
|
||||||
derive_more = {version = "2.1.1", features = ["full"]}
|
derive_more = {version = "2.1.1", features = ["full"]}
|
||||||
console-subscriber = { version = "0.4.1", optional = true }
|
console-subscriber = { version = "0.4.1", optional = true }
|
||||||
|
indoc = "2.0.7"
|
||||||
|
regex = "1.8"
|
||||||
|
paste = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
auto_impl = "1.1.0"
|
auto_impl = "1.1.0"
|
||||||
crossbeam = "0.8.4"
|
crossbeam = "0.8.4"
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
use crate::common::config::LoggingConfigLoader;
|
||||||
|
use crate::common::get_logger_timer_rfc3339;
|
||||||
|
use crate::common::tracing_rolling_appender::{FileAppenderWrapper, RollingFileAppenderBase};
|
||||||
|
use crate::rpc_service::logger::{CURRENT_LOG_LEVEL, LOGGER_LEVEL_SENDER};
|
||||||
|
use anyhow::Context;
|
||||||
|
use paste::paste;
|
||||||
|
use regex::Regex;
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
|
use tracing::{Level, Metadata};
|
||||||
|
use tracing_subscriber::filter::{filter_fn, FilterExt};
|
||||||
|
use tracing_subscriber::fmt::layer;
|
||||||
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
|
use tracing_subscriber::Registry;
|
||||||
|
use tracing_subscriber::{EnvFilter, Layer};
|
||||||
|
|
||||||
|
macro_rules! __log__ {
|
||||||
|
(const $var:ident = $target:expr) => {
|
||||||
|
const $var: &'static str = $target;
|
||||||
|
__log__!(@impl $target, $);
|
||||||
|
};
|
||||||
|
|
||||||
|
(@impl $target:expr, $_:tt) => {
|
||||||
|
__log__!(@impl $_, $target, error, warn, info, debug, trace);
|
||||||
|
};
|
||||||
|
|
||||||
|
(@impl $_:tt, $target:expr, $($lvl:ident),+) => {
|
||||||
|
paste! {
|
||||||
|
$(
|
||||||
|
macro_rules! [< __ $lvl __ >] {
|
||||||
|
(category: $cat:expr, $_ ($arg:tt)+) => {
|
||||||
|
tracing::$lvl!(target: concat!($target, "::", $cat), $_ ($arg)+)
|
||||||
|
};
|
||||||
|
($_ ($arg:tt)+) => {
|
||||||
|
tracing::$lvl!(target: $target, $_ ($arg)+)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub(crate) use [< __ $lvl __ >] as $lvl;
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
__log__!(const LOG_TARGET = "CORE");
|
||||||
|
|
||||||
|
fn parse_env_filter(default_level: LevelFilter) -> Result<EnvFilter, anyhow::Error> {
|
||||||
|
let mut filter = EnvFilter::builder()
|
||||||
|
.with_default_directive(default_level.into())
|
||||||
|
.from_env()
|
||||||
|
.with_context(|| "failed to create env filter")?;
|
||||||
|
|
||||||
|
let pattern = Regex::new(&format!(r"(^|,){}\s*=", regex::escape(LOG_TARGET)))?;
|
||||||
|
if !pattern.is_match(&filter.to_string()) {
|
||||||
|
filter = filter.add_directive(format!("{LOG_TARGET}=info").parse()?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_log(meta: &Metadata) -> bool {
|
||||||
|
meta.target() == LOG_TARGET || meta.target().starts_with(&format!("{LOG_TARGET}::"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type NewFilterSender = std::sync::mpsc::Sender<String>;
|
||||||
|
|
||||||
|
macro_rules! tracing_layer {
|
||||||
|
($layer:expr) => {
|
||||||
|
$layer.with_filter(filter_fn(is_log).not()).boxed()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! log_layer {
|
||||||
|
($layer:expr) => {
|
||||||
|
$layer
|
||||||
|
.with_file(false)
|
||||||
|
.with_line_number(false)
|
||||||
|
.with_ansi(true)
|
||||||
|
.with_filter(filter_fn(is_log))
|
||||||
|
.boxed()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(
|
||||||
|
config: impl LoggingConfigLoader,
|
||||||
|
need_reload: bool,
|
||||||
|
) -> Result<Option<NewFilterSender>, anyhow::Error> {
|
||||||
|
let mut layers = Vec::new();
|
||||||
|
|
||||||
|
let file_config = config.get_file_logger_config();
|
||||||
|
let file_level = file_config
|
||||||
|
.level
|
||||||
|
.map(|s| s.parse().unwrap())
|
||||||
|
.unwrap_or(LevelFilter::OFF);
|
||||||
|
|
||||||
|
let mut ret_sender: Option<NewFilterSender> = None;
|
||||||
|
|
||||||
|
// logger to a rolling file
|
||||||
|
if file_level != LevelFilter::OFF || need_reload {
|
||||||
|
let dir = file_config.dir.as_deref().unwrap_or(".");
|
||||||
|
let file = file_config.file.as_deref().unwrap_or("easytier.log");
|
||||||
|
let path = std::path::Path::new(dir).join(file);
|
||||||
|
let path_str = path.to_string_lossy().into_owned();
|
||||||
|
|
||||||
|
let builder = RollingFileAppenderBase::builder();
|
||||||
|
let file_appender = builder
|
||||||
|
.filename(path_str)
|
||||||
|
.condition_daily()
|
||||||
|
.max_filecount(file_config.count.unwrap_or(10))
|
||||||
|
.condition_max_file_size(file_config.size_mb.unwrap_or(100) * 1024 * 1024)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Create a simple wrapper that implements MakeWriter
|
||||||
|
let wrapper = FileAppenderWrapper::new(file_appender);
|
||||||
|
|
||||||
|
let (file_filter, file_filter_reloader) =
|
||||||
|
tracing_subscriber::reload::Layer::<_, Registry>::new(parse_env_filter(file_level)?);
|
||||||
|
|
||||||
|
let layer = |wrapper| {
|
||||||
|
layer()
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_writer(wrapper)
|
||||||
|
.with_timer(get_logger_timer_rfc3339())
|
||||||
|
};
|
||||||
|
|
||||||
|
layers.push(
|
||||||
|
vec![
|
||||||
|
tracing_layer!(layer(wrapper.clone())),
|
||||||
|
log_layer!(layer(wrapper.clone())),
|
||||||
|
]
|
||||||
|
.with_filter(file_filter)
|
||||||
|
.boxed(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if need_reload {
|
||||||
|
let (sender, recver) = std::sync::mpsc::channel();
|
||||||
|
ret_sender = Some(sender.clone());
|
||||||
|
|
||||||
|
// 初始化全局状态
|
||||||
|
let _ = LOGGER_LEVEL_SENDER.set(std::sync::Mutex::new(sender));
|
||||||
|
let _ = CURRENT_LOG_LEVEL.set(std::sync::Mutex::new(file_level.to_string()));
|
||||||
|
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
while let Ok(lf) = recver.recv() {
|
||||||
|
let e = file_filter_reloader.modify(|f| {
|
||||||
|
if let Ok(nf) = EnvFilter::builder()
|
||||||
|
.with_default_directive(lf.parse::<LevelFilter>().unwrap().into())
|
||||||
|
.from_env()
|
||||||
|
.with_context(|| "failed to create file filter")
|
||||||
|
{
|
||||||
|
info!("Reload log filter succeed, new filter level: {:?}", lf);
|
||||||
|
*f = nf;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if e.is_err() {
|
||||||
|
error!("Failed to reload log filter: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("Stop log filter reloader");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// logger to console
|
||||||
|
let console_config = config.get_console_logger_config();
|
||||||
|
let console_level = console_config
|
||||||
|
.level
|
||||||
|
.map(|s| s.parse().unwrap())
|
||||||
|
.unwrap_or(LevelFilter::OFF);
|
||||||
|
|
||||||
|
let (console_filter, _) =
|
||||||
|
tracing_subscriber::reload::Layer::new(parse_env_filter(console_level)?);
|
||||||
|
|
||||||
|
let layer = || {
|
||||||
|
layer()
|
||||||
|
.pretty()
|
||||||
|
.with_timer(get_logger_timer_rfc3339())
|
||||||
|
.with_writer(std::io::stderr)
|
||||||
|
};
|
||||||
|
|
||||||
|
layers.push(
|
||||||
|
vec![
|
||||||
|
tracing_layer!(layer()),
|
||||||
|
log_layer!(layer()).with_filter(LevelFilter::WARN).boxed(),
|
||||||
|
log_layer!(layer().with_writer(std::io::stdout))
|
||||||
|
.with_filter(filter_fn(|metadata| *metadata.level() > Level::WARN))
|
||||||
|
.boxed(),
|
||||||
|
]
|
||||||
|
.with_filter(console_filter)
|
||||||
|
.boxed(),
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
{
|
||||||
|
layers.push(console_subscriber::ConsoleLayer::builder().spawn().boxed());
|
||||||
|
}
|
||||||
|
|
||||||
|
Registry::default().with(layers).init();
|
||||||
|
|
||||||
|
Ok(ret_sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::common::config::{self};
|
||||||
|
|
||||||
|
async fn test_logger_reload() {
|
||||||
|
println!("current working dir: {:?}", std::env::current_dir());
|
||||||
|
let config = config::LoggingConfigBuilder::default().build().unwrap();
|
||||||
|
let s = init(&config, true).unwrap();
|
||||||
|
tracing::debug!("test not display debug");
|
||||||
|
s.unwrap().send(LevelFilter::DEBUG.to_string()).unwrap();
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||||
|
tracing::debug!("test display debug");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ pub mod error;
|
|||||||
pub mod global_ctx;
|
pub mod global_ctx;
|
||||||
pub mod idn;
|
pub mod idn;
|
||||||
pub mod ifcfg;
|
pub mod ifcfg;
|
||||||
|
pub mod log;
|
||||||
pub mod netns;
|
pub mod netns;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
pub mod scoped_task;
|
pub mod scoped_task;
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct FileAppenderWrapper {
|
pub struct FileAppenderWrapper {
|
||||||
appender: std::sync::Arc<parking_lot::Mutex<RollingFileAppenderBase>>,
|
appender: std::sync::Arc<parking_lot::Mutex<RollingFileAppenderBase>>,
|
||||||
}
|
}
|
||||||
@@ -206,6 +207,7 @@ impl FileAppenderWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct FileAppenderWriter {
|
pub struct FileAppenderWriter {
|
||||||
appender: std::sync::Arc<parking_lot::Mutex<RollingFileAppenderBase>>,
|
appender: std::sync::Arc<parking_lot::Mutex<RollingFileAppenderBase>>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::{
|
|||||||
dns::{resolve_txt_record, RESOLVER},
|
dns::{resolve_txt_record, RESOLVER},
|
||||||
error::Error,
|
error::Error,
|
||||||
global_ctx::ArcGlobalCtx,
|
global_ctx::ArcGlobalCtx,
|
||||||
|
log,
|
||||||
},
|
},
|
||||||
tunnel::{IpVersion, Tunnel, TunnelConnector, TunnelError, PROTO_PORT_OFFSET},
|
tunnel::{IpVersion, Tunnel, TunnelConnector, TunnelError, PROTO_PORT_OFFSET},
|
||||||
};
|
};
|
||||||
@@ -131,7 +132,7 @@ impl DNSTunnelConnector {
|
|||||||
let parsed_record = Self::handle_one_srv_record(record, protocol);
|
let parsed_record = Self::handle_one_srv_record(record, protocol);
|
||||||
tracing::info!(?parsed_record, ?srv_domain, "parsed_record");
|
tracing::info!(?parsed_record, ?srv_domain, "parsed_record");
|
||||||
if let Err(e) = &parsed_record {
|
if let Err(e) = &parsed_record {
|
||||||
eprintln!("got invalid srv record {:?}", e);
|
log::warn!("got invalid srv record {:?}", e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
responses.insert(parsed_record.unwrap());
|
responses.insert(parsed_record.unwrap());
|
||||||
|
|||||||
+36
-31
@@ -15,6 +15,7 @@ use crate::{
|
|||||||
PeerConfig, PortForwardConfig, TomlConfigLoader, VpnPortalConfig,
|
PeerConfig, PortForwardConfig, TomlConfigLoader, VpnPortalConfig,
|
||||||
},
|
},
|
||||||
constants::EASYTIER_VERSION,
|
constants::EASYTIER_VERSION,
|
||||||
|
log,
|
||||||
},
|
},
|
||||||
defer,
|
defer,
|
||||||
instance_manager::NetworkInstanceManager,
|
instance_manager::NetworkInstanceManager,
|
||||||
@@ -22,7 +23,7 @@ use crate::{
|
|||||||
proto::common::{CompressionAlgoPb, SecureModeConfig},
|
proto::common::{CompressionAlgoPb, SecureModeConfig},
|
||||||
rpc_service::ApiRpcServer,
|
rpc_service::ApiRpcServer,
|
||||||
tunnel::PROTO_PORT_OFFSET,
|
tunnel::PROTO_PORT_OFFSET,
|
||||||
utils::{init_logger, setup_panic_handler},
|
utils::setup_panic_handler,
|
||||||
web_client, ShellType,
|
web_client, ShellType,
|
||||||
};
|
};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
@@ -1163,7 +1164,7 @@ fn win_service_event_loop(
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
status_handle.set_service_status(error_status).unwrap();
|
status_handle.set_service_status(error_status).unwrap();
|
||||||
eprintln!("error: {}", e);
|
log::error!("{}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1231,7 +1232,7 @@ fn win_service_main(arg: Vec<std::ffi::OsString>) {
|
|||||||
|
|
||||||
async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
||||||
defer!(dump_profile(0););
|
defer!(dump_profile(0););
|
||||||
init_logger(&cli.logging_options, true)?;
|
log::init(&cli.logging_options, true)?;
|
||||||
|
|
||||||
let manager = Arc::new(NetworkInstanceManager::new().with_config_path(cli.config_dir.clone()));
|
let manager = Arc::new(NetworkInstanceManager::new().with_config_path(cli.config_dir.clone()));
|
||||||
|
|
||||||
@@ -1253,12 +1254,12 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.inspect(|_| {
|
.inspect(|_| {
|
||||||
println!(
|
log::info!(
|
||||||
"Web client started successfully...\nserver: {}",
|
server = config_server_url_s,
|
||||||
config_server_url_s,
|
"Web client started successfully...",
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("Official config website: https://easytier.cn/web");
|
log::info!("Official config website: https://easytier.cn/web");
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Some(wc)
|
Some(wc)
|
||||||
@@ -1324,13 +1325,17 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
|||||||
control.set_no_delete(true);
|
control.set_no_delete(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
log::info!(
|
||||||
"Starting easytier from config file {:?}({:?}) with config:",
|
"\
|
||||||
config_file, control.permission
|
Starting easytier from config file {:?}({:?}) with config:\n\
|
||||||
|
############### TOML ###############\n\
|
||||||
|
{}\n\
|
||||||
|
-----------------------------------\n\
|
||||||
|
",
|
||||||
|
config_file,
|
||||||
|
control.permission,
|
||||||
|
cfg.dump()
|
||||||
);
|
);
|
||||||
println!("############### TOML ###############\n");
|
|
||||||
println!("{}", cfg.dump());
|
|
||||||
println!("-----------------------------------");
|
|
||||||
manager.run_network_instance(cfg, true, control)?;
|
manager.run_network_instance(cfg, true, control)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1339,10 +1344,15 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
|||||||
cli.network_options
|
cli.network_options
|
||||||
.merge_into(&cfg)
|
.merge_into(&cfg)
|
||||||
.with_context(|| "failed to create config from cli".to_string())?;
|
.with_context(|| "failed to create config from cli".to_string())?;
|
||||||
println!("Starting easytier from cli with config:");
|
log::info!(
|
||||||
println!("############### TOML ###############\n");
|
"\
|
||||||
println!("{}", cfg.dump());
|
Starting easytier from cli with config:\n\
|
||||||
println!("-----------------------------------");
|
############### TOML ###############\n\
|
||||||
|
{}\n\
|
||||||
|
-----------------------------------\n\
|
||||||
|
",
|
||||||
|
cfg.dump()
|
||||||
|
);
|
||||||
manager.run_network_instance(cfg, true, ConfigFileControl::STATIC_CONFIG)?;
|
manager.run_network_instance(cfg, true, ConfigFileControl::STATIC_CONFIG)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1363,11 +1373,11 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = tokio::signal::ctrl_c() => {
|
_ = tokio::signal::ctrl_c() => {
|
||||||
println!("ctrl-c received, exiting...");
|
log::info!("ctrl-c received, exiting...");
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = sigterm, if cfg!(unix) => {
|
_ = sigterm, if cfg!(unix) => {
|
||||||
println!("terminate signal received, exiting...");
|
log::warn!("terminate signal received, exiting...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1384,11 +1394,7 @@ fn memory_monitor(_force_dump: Arc<AtomicBool>) {
|
|||||||
e.advance().unwrap();
|
e.advance().unwrap();
|
||||||
let new_heap_size = allocated_stats.read().unwrap();
|
let new_heap_size = allocated_stats.read().unwrap();
|
||||||
|
|
||||||
println!(
|
log::debug!("heap size: {} bytes", new_heap_size);
|
||||||
"heap size: {} bytes, time: {}",
|
|
||||||
new_heap_size,
|
|
||||||
chrono::Local::now().format("%Y-%m-%d %H:%M:%S")
|
|
||||||
);
|
|
||||||
|
|
||||||
// dump every 75MB
|
// dump every 75MB
|
||||||
if (last_peak_size > 0
|
if (last_peak_size > 0
|
||||||
@@ -1396,10 +1402,9 @@ fn memory_monitor(_force_dump: Arc<AtomicBool>) {
|
|||||||
&& new_heap_size - last_peak_size > 10 * 1024 * 1024)
|
&& new_heap_size - last_peak_size > 10 * 1024 * 1024)
|
||||||
|| _force_dump.load(std::sync::atomic::Ordering::Relaxed)
|
|| _force_dump.load(std::sync::atomic::Ordering::Relaxed)
|
||||||
{
|
{
|
||||||
println!(
|
log::debug!(
|
||||||
"heap size increased: {} bytes, time: {}",
|
"heap size increased: {} bytes",
|
||||||
new_heap_size - last_peak_size,
|
new_heap_size - last_peak_size,
|
||||||
chrono::Local::now().format("%Y-%m-%d %H:%M:%S")
|
|
||||||
);
|
);
|
||||||
dump_profile(new_heap_size);
|
dump_profile(new_heap_size);
|
||||||
last_peak_size = new_heap_size;
|
last_peak_size = new_heap_size;
|
||||||
@@ -1475,7 +1480,7 @@ pub async fn main() -> ExitCode {
|
|||||||
// Verify configurations
|
// Verify configurations
|
||||||
if cli.check_config {
|
if cli.check_config {
|
||||||
if let Err(e) = validate_config(&cli).await {
|
if let Err(e) = validate_config(&cli).await {
|
||||||
eprintln!("Config validation failed: {:?}", e);
|
log::error!("Config validation failed: {:?}", e);
|
||||||
return ExitCode::FAILURE;
|
return ExitCode::FAILURE;
|
||||||
} else {
|
} else {
|
||||||
return ExitCode::SUCCESS;
|
return ExitCode::SUCCESS;
|
||||||
@@ -1484,12 +1489,12 @@ pub async fn main() -> ExitCode {
|
|||||||
|
|
||||||
let mut ret_code = 0;
|
let mut ret_code = 0;
|
||||||
|
|
||||||
if let Err(e) = run_main(cli).await {
|
if let Err(error) = run_main(cli).await {
|
||||||
eprintln!("error: {:?}", e);
|
log::error!(%error);
|
||||||
ret_code = 1;
|
ret_code = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Stopping easytier...");
|
log::info!("Stopping easytier...");
|
||||||
set_prof_active(false);
|
set_prof_active(false);
|
||||||
|
|
||||||
ExitCode::from(ret_code)
|
ExitCode::from(ret_code)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use tracing::Instrument;
|
|||||||
use crate::common::error::Result;
|
use crate::common::error::Result;
|
||||||
use crate::common::global_ctx::{ArcGlobalCtx, GlobalCtx};
|
use crate::common::global_ctx::{ArcGlobalCtx, GlobalCtx};
|
||||||
use crate::common::join_joinset_background;
|
use crate::common::join_joinset_background;
|
||||||
|
use crate::common::log;
|
||||||
use crate::common::stats_manager::{LabelSet, LabelType, MetricName};
|
use crate::common::stats_manager::{LabelSet, LabelType, MetricName};
|
||||||
use crate::peers::peer_manager::PeerManager;
|
use crate::peers::peer_manager::PeerManager;
|
||||||
use crate::peers::{NicPacketFilter, PeerPacketFilter};
|
use crate::peers::{NicPacketFilter, PeerPacketFilter};
|
||||||
@@ -66,9 +66,9 @@ impl NatDstConnector for NatDstTcpConnector {
|
|||||||
async fn connect(&self, _src: SocketAddr, nat_dst: SocketAddr) -> Result<Self::DstStream> {
|
async fn connect(&self, _src: SocketAddr, nat_dst: SocketAddr) -> Result<Self::DstStream> {
|
||||||
let socket = match TcpSocket::new_v4() {
|
let socket = match TcpSocket::new_v4() {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(error) => {
|
||||||
eprintln!("create v4 socket failed: {:?}", e);
|
log::error!(%error, "create v4 socket failed");
|
||||||
return Err(e.into());
|
return Err(error.into());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use crate::{
|
|||||||
error::Error,
|
error::Error,
|
||||||
global_ctx::{ArcGlobalCtx, GlobalCtxEvent},
|
global_ctx::{ArcGlobalCtx, GlobalCtxEvent},
|
||||||
ifcfg::{IfConfiger, IfConfiguerTrait},
|
ifcfg::{IfConfiger, IfConfiguerTrait},
|
||||||
|
log,
|
||||||
},
|
},
|
||||||
instance::proxy_cidrs_monitor::ProxyCidrsMonitor,
|
instance::proxy_cidrs_monitor::ProxyCidrsMonitor,
|
||||||
peers::{peer_manager::PeerManager, recv_packet_from_chan, PacketRecvChanReceiver},
|
peers::{peer_manager::PeerManager, recv_packet_from_chan, PacketRecvChanReceiver},
|
||||||
@@ -95,7 +96,7 @@ impl Stream for TunStream {
|
|||||||
match ret {
|
match ret {
|
||||||
Ok(_) => Poll::Ready(Some(Ok(ZCPacket::new_from_buf(ret_buf, ZCPacketType::NIC)))),
|
Ok(_) => Poll::Ready(Some(Ok(ZCPacket::new_from_buf(ret_buf, ZCPacketType::NIC)))),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("tun stream error: {:?}", err);
|
log::error!("tun stream error: {:?}", err);
|
||||||
Poll::Ready(None)
|
Poll::Ready(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,10 +250,11 @@ impl Drop for VirtualNic {
|
|||||||
{
|
{
|
||||||
if let Some(ref ifname) = self.ifname {
|
if let Some(ref ifname) = self.ifname {
|
||||||
// Try to clean up firewall rules, but don't panic in destructor
|
// Try to clean up firewall rules, but don't panic in destructor
|
||||||
if let Err(e) = crate::arch::windows::remove_interface_firewall_rules(ifname) {
|
if let Err(error) = crate::arch::windows::remove_interface_firewall_rules(ifname) {
|
||||||
eprintln!(
|
log::warn!(
|
||||||
"Warning: Failed to remove firewall rules for interface {}: {}",
|
%error,
|
||||||
ifname, e
|
"failed to remove firewall rules for interface {}",
|
||||||
|
ifname
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,25 +295,20 @@ impl VirtualNic {
|
|||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if !tun_module_available {
|
if !tun_module_available {
|
||||||
tracing::warn!("TUN kernel module may not be loaded");
|
log::warn!("TUN kernel module may not be available.");
|
||||||
println!("⚠ Warning: TUN kernel module may not be available.");
|
log::warn!("\tYou may need to load it with: sudo modprobe tun.");
|
||||||
println!(" You may need to load it with: sudo modprobe tun");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to create /dev/net directory if it doesn't exist
|
// Try to create /dev/net directory if it doesn't exist
|
||||||
if tokio::fs::metadata(TUN_DIR_PATH).await.is_err() {
|
if tokio::fs::metadata(TUN_DIR_PATH).await.is_err() {
|
||||||
if let Err(e) = tokio::fs::create_dir_all(TUN_DIR_PATH).await {
|
if let Err(error) = tokio::fs::create_dir_all(TUN_DIR_PATH).await {
|
||||||
tracing::warn!(
|
log::warn!(
|
||||||
"Failed to create directory {}: {}. Continuing anyway.",
|
?error,
|
||||||
TUN_DIR_PATH,
|
"Failed to create directory {}. TUN device creation may fail. Continuing anyway.",
|
||||||
e
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"⚠ Warning: Failed to create directory {}. TUN device creation may fail.",
|
|
||||||
TUN_DIR_PATH
|
TUN_DIR_PATH
|
||||||
);
|
);
|
||||||
println!(
|
log::warn!(
|
||||||
" You may need to run with root privileges or manually create the TUN device."
|
"\tYou may need to run with root privileges or manually create the TUN device."
|
||||||
);
|
);
|
||||||
Self::print_troubleshooting_info();
|
Self::print_troubleshooting_info();
|
||||||
return;
|
return;
|
||||||
@@ -330,20 +327,14 @@ impl VirtualNic {
|
|||||||
dev_node,
|
dev_node,
|
||||||
) {
|
) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
tracing::info!("Successfully created TUN device node {}", TUN_DEV_PATH);
|
log::info!("Successfully created TUN device node {}", TUN_DEV_PATH);
|
||||||
println!("✓ Created TUN device node {}", TUN_DEV_PATH);
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(error) => {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"Failed to create TUN device node {}: {}. Continuing anyway.",
|
%error,
|
||||||
|
"Failed to create TUN device node {}. Continuing anyway.",
|
||||||
TUN_DEV_PATH,
|
TUN_DEV_PATH,
|
||||||
e
|
|
||||||
);
|
);
|
||||||
println!(
|
|
||||||
"⚠ Warning: Failed to create TUN device node {}.",
|
|
||||||
TUN_DEV_PATH
|
|
||||||
);
|
|
||||||
println!(" Error: {}", e);
|
|
||||||
Self::print_troubleshooting_info();
|
Self::print_troubleshooting_info();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,13 +343,15 @@ impl VirtualNic {
|
|||||||
/// Print troubleshooting information for TUN device issues
|
/// Print troubleshooting information for TUN device issues
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn print_troubleshooting_info() {
|
fn print_troubleshooting_info() {
|
||||||
println!(" Possible solutions:");
|
log::info!(
|
||||||
println!(" 1. Run with root privileges: sudo ./easytier-core [options]");
|
"Possible solutions:\
|
||||||
println!(" 2. Manually create TUN device: sudo mkdir -p /dev/net && sudo mknod /dev/net/tun c 10 200");
|
\n\t1. Run with root privileges: sudo ./easytier-core [options]\
|
||||||
println!(" 3. Load TUN kernel module: sudo modprobe tun");
|
\n\t2. Manually create TUN device: sudo mkdir -p /dev/net && sudo mknod /dev/net/tun c 10 200\
|
||||||
println!(" 4. Use --no-tun flag if TUN functionality is not needed");
|
\n\t3. Load TUN kernel module: sudo modprobe tun\
|
||||||
println!(" 5. Check if your system/container supports TUN devices");
|
\n\t4. Use --no-tun flag if TUN functionality is not needed\
|
||||||
println!(" Note: TUN functionality may still work if the kernel supports dynamic device creation.");
|
\n\t5. Check if your system/container supports TUN devices\
|
||||||
|
\nNote: TUN functionality may still work if the kernel supports dynamic device creation."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For non-Linux systems, this is a no-op
|
/// For non-Linux systems, this is a no-op
|
||||||
@@ -535,10 +528,9 @@ impl VirtualNic {
|
|||||||
|
|
||||||
match crate::arch::windows::add_self_to_firewall_allowlist() {
|
match crate::arch::windows::add_self_to_firewall_allowlist() {
|
||||||
Ok(_) => tracing::info!("add_self_to_firewall_allowlist successful!"),
|
Ok(_) => tracing::info!("add_self_to_firewall_allowlist successful!"),
|
||||||
Err(e) => {
|
Err(error) => {
|
||||||
println!("Failed to add Easytier to firewall allowlist, Subnet proxy and KCP proxy may not work properly. error: {}", e);
|
log::warn!(%error, "Failed to add Easytier to firewall allowlist, Subnet proxy and KCP proxy may not work properly.");
|
||||||
println!("You can add firewall rules manually, or use --use-smoltcp to run with user-space TCP/IP stack.");
|
log::warn!("You can add firewall rules manually, or use --use-smoltcp to run with user-space TCP/IP stack.");
|
||||||
println!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,7 +584,7 @@ impl VirtualNic {
|
|||||||
&mut self,
|
&mut self,
|
||||||
tun_fd: std::os::fd::RawFd,
|
tun_fd: std::os::fd::RawFd,
|
||||||
) -> Result<Box<dyn Tunnel>, Error> {
|
) -> Result<Box<dyn Tunnel>, Error> {
|
||||||
println!("tun_fd: {}", tun_fd);
|
log::debug!(%tun_fd);
|
||||||
let mut config = Configuration::default();
|
let mut config = Configuration::default();
|
||||||
config.layer(Layer::L3);
|
config.layer(Layer::L3);
|
||||||
|
|
||||||
@@ -711,19 +703,11 @@ impl VirtualNic {
|
|||||||
ifname
|
ifname
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(error) => {
|
||||||
tracing::warn!("Failed to configure Windows Firewall for {}: {}", ifname, e);
|
log::warn!(%error, "Failed to configure Windows Firewall for interface {}\
|
||||||
println!(
|
\n\tThis may cause connectivity issues with ping and other network functions.\
|
||||||
"⚠ Warning: Failed to configure Windows Firewall for interface {}.",
|
\n\tPlease run as Administrator or manually configure Windows Firewall.\
|
||||||
ifname
|
\n\tAlternatively, you can disable Windows Firewall for testing purposes.", ifname);
|
||||||
);
|
|
||||||
println!(" This may cause connectivity issues with ping and other network functions.");
|
|
||||||
println!(
|
|
||||||
" Please run as Administrator or manually configure Windows Firewall."
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
" Alternatively, you can disable Windows Firewall for testing purposes."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+100
-107
@@ -1,11 +1,12 @@
|
|||||||
use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
|
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{
|
common::{
|
||||||
config::{ConfigFileControl, ConfigLoader, TomlConfigLoader},
|
config::{ConfigFileControl, ConfigLoader, TomlConfigLoader},
|
||||||
global_ctx::{EventBusSubscriber, GlobalCtxEvent},
|
global_ctx::{EventBusSubscriber, GlobalCtxEvent},
|
||||||
|
log,
|
||||||
scoped_task::ScopedTask,
|
scoped_task::ScopedTask,
|
||||||
},
|
},
|
||||||
launcher::{NetworkInstance, NetworkInstanceRunningInfo},
|
launcher::{NetworkInstance, NetworkInstanceRunningInfo},
|
||||||
@@ -85,10 +86,9 @@ impl NetworkInstanceManager {
|
|||||||
.map(|event| ScopedTask::from(handle_event(instance_id, event)));
|
.map(|event| ScopedTask::from(handle_event(instance_id, event)));
|
||||||
instance_stop_notifier.notified().await;
|
instance_stop_notifier.notified().await;
|
||||||
if let Some(instance) = instance_map.get(&instance_id) {
|
if let Some(instance) = instance_map.get(&instance_id) {
|
||||||
if let Some(e) = instance.get_latest_error_msg() {
|
if let Some(error) = instance.get_latest_error_msg() {
|
||||||
tracing::error!(?e, ?instance_id, "instance stopped with error");
|
log::error!(%error, "instance {} stopped", instance_id);
|
||||||
eprintln!("instance {} stopped with error: {}", instance_id, e);
|
instance_error_messages.insert(instance_id, error);
|
||||||
instance_error_messages.insert(instance_id, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stop_check_notifier.notify_one();
|
stop_check_notifier.notify_one();
|
||||||
@@ -261,6 +261,23 @@ impl NetworkInstanceManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! event {
|
||||||
|
($lvl:ident, category: $cat:expr, $($args:tt)+) => {
|
||||||
|
event!(@impl $lvl, concat!("INSTANCE::", $cat), $($args)+)
|
||||||
|
};
|
||||||
|
|
||||||
|
($lvl:ident, $($args:tt)+) => {
|
||||||
|
event!(@impl $lvl, "INSTANCE", $($args)+)
|
||||||
|
};
|
||||||
|
|
||||||
|
(@impl $lvl:ident, $cat:expr, $($args:tt)+) => {
|
||||||
|
log::$lvl!(
|
||||||
|
category: $cat,
|
||||||
|
$($args)+
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
fn handle_event(
|
fn handle_event(
|
||||||
instance_id: uuid::Uuid,
|
instance_id: uuid::Uuid,
|
||||||
@@ -270,158 +287,140 @@ fn handle_event(
|
|||||||
loop {
|
loop {
|
||||||
if let Ok(e) = events.recv().await {
|
if let Ok(e) = events.recv().await {
|
||||||
match e {
|
match e {
|
||||||
GlobalCtxEvent::PeerAdded(p) => {
|
GlobalCtxEvent::PeerAdded(peer_id) => {
|
||||||
print_event(instance_id, format!("new peer added. peer_id: {}", p));
|
event!(info, peer_id, "[{}] new peer added", instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::PeerRemoved(p) => {
|
GlobalCtxEvent::PeerRemoved(peer_id) => {
|
||||||
print_event(instance_id, format!("peer removed. peer_id: {}", p));
|
event!(info, peer_id, "[{}] peer removed", instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::PeerConnAdded(p) => {
|
GlobalCtxEvent::PeerConnAdded(conn_info) => {
|
||||||
print_event(
|
event!(
|
||||||
|
info,
|
||||||
|
category: "CONNECTION",
|
||||||
|
%conn_info,
|
||||||
|
"[{}] new peer connection added",
|
||||||
instance_id,
|
instance_id,
|
||||||
format!(
|
|
||||||
"new peer connection added. conn_info: {}",
|
|
||||||
peer_conn_info_to_string(p)
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::PeerConnRemoved(p) => {
|
GlobalCtxEvent::PeerConnRemoved(conn_info) => {
|
||||||
print_event(
|
event!(
|
||||||
|
info,
|
||||||
|
category: "CONNECTION",
|
||||||
|
%conn_info,
|
||||||
|
"[{}] peer connection removed",
|
||||||
instance_id,
|
instance_id,
|
||||||
format!(
|
|
||||||
"peer connection removed. conn_info: {}",
|
|
||||||
peer_conn_info_to_string(p)
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ListenerAddFailed(p, msg) => {
|
GlobalCtxEvent::ListenerAddFailed(listener, msg) => {
|
||||||
print_event(
|
event!(warn, %listener, msg, "[{}] listener add failed", instance_id);
|
||||||
instance_id,
|
|
||||||
format!("listener add failed. listener: {}, msg: {}", p, msg),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ListenerAcceptFailed(p, msg) => {
|
GlobalCtxEvent::ListenerAcceptFailed(listener, msg) => {
|
||||||
print_event(
|
event!(warn, %listener, msg, "[{}] listener accept failed", instance_id);
|
||||||
instance_id,
|
|
||||||
format!("listener accept failed. listener: {}, msg: {}", p, msg),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ListenerAdded(p) => {
|
GlobalCtxEvent::ListenerAdded(listener) => {
|
||||||
if p.scheme() == "ring" {
|
if listener.scheme() == "ring" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
print_event(instance_id, format!("new listener added. listener: {}", p));
|
event!(
|
||||||
|
info,
|
||||||
|
%listener,
|
||||||
|
"[{}] new listener added",
|
||||||
|
instance_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ConnectionAccepted(local, remote) => {
|
GlobalCtxEvent::ConnectionAccepted(local, remote) => {
|
||||||
print_event(
|
event!(info, category: "CONNECTION", local, remote, "[{}] new connection accepted", instance_id);
|
||||||
instance_id,
|
|
||||||
format!(
|
|
||||||
"new connection accepted. local: {}, remote: {}",
|
|
||||||
local, remote
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ConnectionError(local, remote, err) => {
|
GlobalCtxEvent::ConnectionError(local, remote, err) => {
|
||||||
print_event(
|
event!(info, category: "CONNECTION", local, remote, err, "[{}] connection error", instance_id);
|
||||||
instance_id,
|
|
||||||
format!(
|
|
||||||
"connection error. local: {}, remote: {}, err: {}",
|
|
||||||
local, remote, err
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::TunDeviceReady(dev) => {
|
GlobalCtxEvent::TunDeviceReady(dev) => {
|
||||||
print_event(instance_id, format!("tun device ready. dev: {}", dev));
|
event!(info, dev, "[{}] tun device ready", instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::TunDeviceError(err) => {
|
GlobalCtxEvent::TunDeviceError(err) => {
|
||||||
print_event(instance_id, format!("tun device error. err: {}", err));
|
event!(error, %err, "[{}] tun device error", instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::Connecting(dst) => {
|
GlobalCtxEvent::Connecting(dst) => {
|
||||||
print_event(instance_id, format!("connecting to peer. dst: {}", dst));
|
event!(info, category: "CONNECTION", %dst, "[{}] connecting to peer", instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ConnectError(dst, ip_version, err) => {
|
GlobalCtxEvent::ConnectError(dst, ip_version, error) => {
|
||||||
print_event(
|
event!(
|
||||||
instance_id,
|
info,
|
||||||
format!(
|
category: "CONNECTION",
|
||||||
"connect to peer error. dst: {}, ip_version: {}, err: {}",
|
dst,
|
||||||
dst, ip_version, err
|
ip_version,
|
||||||
),
|
%error,
|
||||||
|
"[{}] connect to peer error",
|
||||||
|
instance_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::VpnPortalStarted(portal) => {
|
GlobalCtxEvent::VpnPortalStarted(portal) => {
|
||||||
print_event(
|
event!(info, portal, "[{}] vpn portal started", instance_id);
|
||||||
instance_id,
|
|
||||||
format!("vpn portal started. portal: {}", portal),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::VpnPortalClientConnected(portal, client_addr) => {
|
GlobalCtxEvent::VpnPortalClientConnected(portal, client_addr) => {
|
||||||
print_event(
|
event!(
|
||||||
instance_id,
|
info,
|
||||||
format!(
|
portal,
|
||||||
"vpn portal client connected. portal: {}, client_addr: {}",
|
client_addr,
|
||||||
portal, client_addr
|
"[{}] vpn portal client connected",
|
||||||
),
|
instance_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::VpnPortalClientDisconnected(portal, client_addr) => {
|
GlobalCtxEvent::VpnPortalClientDisconnected(portal, client_addr) => {
|
||||||
print_event(
|
event!(
|
||||||
instance_id,
|
info,
|
||||||
format!(
|
portal,
|
||||||
"vpn portal client disconnected. portal: {}, client_addr: {}",
|
client_addr,
|
||||||
portal, client_addr
|
"[{}] vpn portal client disconnected",
|
||||||
),
|
instance_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::DhcpIpv4Changed(old, new) => {
|
GlobalCtxEvent::DhcpIpv4Changed(old, new) => {
|
||||||
print_event(
|
event!(info, ?old, ?new, "[{}] dhcp ip changed", instance_id);
|
||||||
instance_id,
|
|
||||||
format!("dhcp ip changed. old: {:?}, new: {:?}", old, new),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::DhcpIpv4Conflicted(ip) => {
|
GlobalCtxEvent::DhcpIpv4Conflicted(ip) => {
|
||||||
print_event(instance_id, format!("dhcp ip conflict. ip: {:?}", ip));
|
event!(info, ?ip, "[{}] dhcp ip conflict", instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::PortForwardAdded(cfg) => {
|
GlobalCtxEvent::PortForwardAdded(cfg) => {
|
||||||
print_event(
|
event!(
|
||||||
|
info,
|
||||||
|
local = %cfg.bind_addr.unwrap(),
|
||||||
|
remote = %cfg.dst_addr.unwrap(),
|
||||||
|
proto = %cfg.socket_type().as_str_name(),
|
||||||
|
"[{}] port forward added",
|
||||||
instance_id,
|
instance_id,
|
||||||
format!(
|
|
||||||
"port forward added. local: {}, remote: {}, proto: {}",
|
|
||||||
cfg.bind_addr.unwrap(),
|
|
||||||
cfg.dst_addr.unwrap(),
|
|
||||||
cfg.socket_type().as_str_name()
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ConfigPatched(patch) => {
|
GlobalCtxEvent::ConfigPatched(patch) => {
|
||||||
print_event(instance_id, format!("config patched. patch: {:?}", patch));
|
event!(info, ?patch, "[{}] config patched", instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalCtxEvent::ProxyCidrsUpdated(added, removed) => {
|
GlobalCtxEvent::ProxyCidrsUpdated(added, removed) => {
|
||||||
print_event(
|
event!(
|
||||||
instance_id,
|
info,
|
||||||
format!(
|
?added,
|
||||||
"proxy CIDRs updated. added: {:?}, removed: {:?}",
|
?removed,
|
||||||
added, removed
|
"[{}] proxy CIDRs updated",
|
||||||
),
|
instance_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,20 +431,14 @@ fn handle_event(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_event(instance_id: uuid::Uuid, msg: String) {
|
impl Display for proto::api::instance::PeerConnInfo {
|
||||||
println!(
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
"{}: [{}] {}",
|
f.debug_struct("PeerConnInfo")
|
||||||
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
|
.field("my_peer_id", &self.my_peer_id)
|
||||||
instance_id,
|
.field("dst_peer_id", &self.peer_id)
|
||||||
msg
|
.field("tunnel_info", &self.tunnel)
|
||||||
);
|
.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_conn_info_to_string(p: proto::api::instance::PeerConnInfo) -> String {
|
|
||||||
format!(
|
|
||||||
"my_peer_id: {}, dst_peer_id: {}, tunnel_info: {:?}",
|
|
||||||
p.my_peer_id, p.peer_id, p.tunnel
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{common::config::EncryptionAlgorithm, tunnel::packet_def::ZCPacket};
|
use crate::{
|
||||||
|
common::{config::EncryptionAlgorithm, log},
|
||||||
|
tunnel::packet_def::ZCPacket,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "wireguard")]
|
#[cfg(feature = "wireguard")]
|
||||||
pub mod ring_aes_gcm;
|
pub mod ring_aes_gcm;
|
||||||
@@ -66,7 +69,7 @@ pub fn create_encryptor(
|
|||||||
let algorithm = match EncryptionAlgorithm::try_from(algorithm) {
|
let algorithm = match EncryptionAlgorithm::try_from(algorithm) {
|
||||||
Ok(algorithm) => algorithm,
|
Ok(algorithm) => algorithm,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!(
|
log::warn!(
|
||||||
"Unknown encryption algorithm: {}, falling back to default AES-GCM",
|
"Unknown encryption algorithm: {}, falling back to default AES-GCM",
|
||||||
algorithm
|
algorithm
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use service_manager::ServiceManager as _;
|
use service_manager::ServiceManager as _;
|
||||||
|
|
||||||
|
use crate::common::log;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ServiceInstallOptions {
|
pub struct ServiceInstallOptions {
|
||||||
pub program: PathBuf,
|
pub program: PathBuf,
|
||||||
@@ -72,7 +74,7 @@ impl Service {
|
|||||||
|
|
||||||
let kind = service_manager::ServiceManagerKind::native()?;
|
let kind = service_manager::ServiceManagerKind::native()?;
|
||||||
|
|
||||||
println!("service manager kind: {:?}", kind);
|
log::info!("service manager kind: {:?}", kind);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
label: name.parse()?,
|
label: name.parse()?,
|
||||||
@@ -98,7 +100,7 @@ impl Service {
|
|||||||
self.service_manager
|
self.service_manager
|
||||||
.update(ctx)
|
.update(ctx)
|
||||||
.map_err(|e| anyhow::anyhow!("failed to update service: {:?}", e))?;
|
.map_err(|e| anyhow::anyhow!("failed to update service: {:?}", e))?;
|
||||||
println!("Service updated successfully! Service Name: {}", self.label);
|
log::info!("Service updated successfully! Service Name: {}", self.label);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +108,7 @@ impl Service {
|
|||||||
.install(ctx)
|
.install(ctx)
|
||||||
.map_err(|e| anyhow::anyhow!("failed to install service: {:?}", e))?;
|
.map_err(|e| anyhow::anyhow!("failed to install service: {:?}", e))?;
|
||||||
|
|
||||||
println!(
|
log::info!(
|
||||||
"Service installed successfully! Service Name: {}",
|
"Service installed successfully! Service Name: {}",
|
||||||
self.label
|
self.label
|
||||||
);
|
);
|
||||||
|
|||||||
+35
-168
@@ -1,15 +1,7 @@
|
|||||||
|
use crate::common::log;
|
||||||
|
use indoc::formatdoc;
|
||||||
use std::{fs::OpenOptions, str::FromStr};
|
use std::{fs::OpenOptions, str::FromStr};
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use tracing::level_filters::LevelFilter;
|
|
||||||
use tracing_subscriber::{
|
|
||||||
layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, Registry,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::common::{
|
|
||||||
config::LoggingConfigLoader, get_logger_timer_rfc3339, tracing_rolling_appender::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub type PeerRoutePair = crate::proto::api::instance::PeerRoutePair;
|
pub type PeerRoutePair = crate::proto::api::instance::PeerRoutePair;
|
||||||
|
|
||||||
pub fn cost_to_str(cost: i32) -> String {
|
pub fn cost_to_str(cost: i32) -> String {
|
||||||
@@ -24,124 +16,6 @@ pub fn float_to_str(f: f64, precision: usize) -> String {
|
|||||||
format!("{:.1$}", f, precision)
|
format!("{:.1$}", f, precision)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type NewFilterSender = std::sync::mpsc::Sender<String>;
|
|
||||||
|
|
||||||
pub fn init_logger(
|
|
||||||
config: impl LoggingConfigLoader,
|
|
||||||
need_reload: bool,
|
|
||||||
) -> Result<Option<NewFilterSender>, anyhow::Error> {
|
|
||||||
use crate::rpc_service::logger::{CURRENT_LOG_LEVEL, LOGGER_LEVEL_SENDER};
|
|
||||||
|
|
||||||
let file_config = config.get_file_logger_config();
|
|
||||||
let file_level = file_config
|
|
||||||
.level
|
|
||||||
.map(|s| s.parse().unwrap())
|
|
||||||
.unwrap_or(LevelFilter::OFF);
|
|
||||||
|
|
||||||
let mut ret_sender: Option<NewFilterSender> = None;
|
|
||||||
|
|
||||||
// logger to rolling file
|
|
||||||
let mut file_layer = None;
|
|
||||||
if file_level != LevelFilter::OFF || need_reload {
|
|
||||||
let mut l = tracing_subscriber::fmt::layer();
|
|
||||||
l.set_ansi(false);
|
|
||||||
let file_filter = EnvFilter::builder()
|
|
||||||
.with_default_directive(file_level.into())
|
|
||||||
.from_env()
|
|
||||||
.with_context(|| "failed to create file filter")?;
|
|
||||||
let (file_filter, file_filter_reloader) =
|
|
||||||
tracing_subscriber::reload::Layer::new(file_filter);
|
|
||||||
|
|
||||||
if need_reload {
|
|
||||||
let (sender, recver) = std::sync::mpsc::channel();
|
|
||||||
ret_sender = Some(sender.clone());
|
|
||||||
|
|
||||||
// 初始化全局状态
|
|
||||||
let _ = LOGGER_LEVEL_SENDER.set(std::sync::Mutex::new(sender));
|
|
||||||
let _ = CURRENT_LOG_LEVEL.set(std::sync::Mutex::new(file_level.to_string()));
|
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
while let Ok(lf) = recver.recv() {
|
|
||||||
let e = file_filter_reloader.modify(|f| {
|
|
||||||
if let Ok(nf) = EnvFilter::builder()
|
|
||||||
.with_default_directive(lf.parse::<LevelFilter>().unwrap().into())
|
|
||||||
.from_env()
|
|
||||||
.with_context(|| "failed to create file filter")
|
|
||||||
{
|
|
||||||
println!("Reload log filter succeed, new filter level: {:?}", lf);
|
|
||||||
*f = nf;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if e.is_err() {
|
|
||||||
println!("Failed to reload log filter: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Stop log filter reloader");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let dir = file_config.dir.as_deref().unwrap_or(".");
|
|
||||||
let file = file_config.file.as_deref().unwrap_or("easytier.log");
|
|
||||||
let path = std::path::Path::new(dir).join(file);
|
|
||||||
let path_str = path.to_string_lossy().into_owned();
|
|
||||||
|
|
||||||
let builder = RollingFileAppenderBase::builder();
|
|
||||||
let file_appender = builder
|
|
||||||
.filename(path_str)
|
|
||||||
.condition_daily()
|
|
||||||
.max_filecount(file_config.count.unwrap_or(10))
|
|
||||||
.condition_max_file_size(file_config.size_mb.unwrap_or(100) * 1024 * 1024)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let wrapper = FileAppenderWrapper::new(file_appender);
|
|
||||||
|
|
||||||
// Create a simple wrapper that implements MakeWriter
|
|
||||||
file_layer = Some(
|
|
||||||
l.with_writer(wrapper)
|
|
||||||
.with_timer(get_logger_timer_rfc3339())
|
|
||||||
.with_filter(file_filter),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// logger to console
|
|
||||||
let console_config = config.get_console_logger_config();
|
|
||||||
let console_level = console_config
|
|
||||||
.level
|
|
||||||
.map(|s| s.parse().unwrap())
|
|
||||||
.unwrap_or(LevelFilter::OFF);
|
|
||||||
|
|
||||||
let console_filter = EnvFilter::builder()
|
|
||||||
.with_default_directive(console_level.into())
|
|
||||||
.from_env()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let console_layer = tracing_subscriber::fmt::layer()
|
|
||||||
.pretty()
|
|
||||||
.with_timer(get_logger_timer_rfc3339())
|
|
||||||
.with_writer(std::io::stderr)
|
|
||||||
.with_filter(console_filter);
|
|
||||||
|
|
||||||
let registry = Registry::default();
|
|
||||||
|
|
||||||
#[cfg(not(feature = "tracing"))]
|
|
||||||
{
|
|
||||||
registry.with(console_layer).with(file_layer).init();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
|
||||||
{
|
|
||||||
let console_subscriber_layer = console_subscriber::ConsoleLayer::builder().spawn();
|
|
||||||
registry
|
|
||||||
.with(console_layer)
|
|
||||||
.with(file_layer)
|
|
||||||
.with(console_subscriber_layer)
|
|
||||||
.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ret_sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub fn utf8_or_gbk_to_string(s: &[u8]) -> String {
|
pub fn utf8_or_gbk_to_string(s: &[u8]) -> String {
|
||||||
use encoding::{all::GBK, DecoderTrap, Encoding};
|
use encoding::{all::GBK, DecoderTrap, Encoding};
|
||||||
@@ -165,13 +39,17 @@ pub fn setup_panic_handler() {
|
|||||||
use std::backtrace;
|
use std::backtrace;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
std::panic::set_hook(Box::new(|info| {
|
std::panic::set_hook(Box::new(|info| {
|
||||||
|
let mut stderr = std::io::stderr();
|
||||||
|
let sep = format!("{}\n", "=======".repeat(10));
|
||||||
|
let _ = stderr.write_all(format!("{sep}{}\n{sep}", "!PANIC!".repeat(10)).as_bytes());
|
||||||
|
|
||||||
PANIC_COUNT.with(|c| {
|
PANIC_COUNT.with(|c| {
|
||||||
let mut count = c.borrow_mut();
|
let mut count = c.borrow_mut();
|
||||||
*count += 1;
|
*count += 1;
|
||||||
});
|
});
|
||||||
let panic_count = PANIC_COUNT.with(|c| *c.borrow());
|
let panic_count = PANIC_COUNT.with(|c| *c.borrow());
|
||||||
if panic_count > 1 {
|
if panic_count > 1 {
|
||||||
println!("panic happened more than once, exit immediately");
|
log::error!("panic happened more than once, exit immediately");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,36 +86,42 @@ pub fn setup_panic_handler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}", rust_i18n::t!("core_app.panic_backtrace_save"));
|
log::error!("{}", rust_i18n::t!("core_app.panic_backtrace_save"));
|
||||||
|
|
||||||
// write str to stderr & file
|
// write str to stderr & file
|
||||||
let write_err = |s: String| {
|
let mut write_err = |s: String| {
|
||||||
let mut stderr = std::io::stderr();
|
let _ = stderr.write_all(s.as_bytes());
|
||||||
let content = format!("{}: {}", chrono::Local::now(), s);
|
|
||||||
let _ = writeln!(stderr, "{}", content);
|
|
||||||
if let Some(mut f) = file.as_ref() {
|
if let Some(mut f) = file.as_ref() {
|
||||||
let _ = writeln!(f, "{}", content);
|
let _ = f.write_all(s.as_bytes());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
write_err("panic occurred, if this is a bug, please report this issue on github (https://github.com/easytier/easytier/issues)".to_string());
|
let msg = formatdoc! {"
|
||||||
write_err(format!("easytier version: {}", crate::VERSION));
|
panic occurred, if this is a bug, please report this issue on github (https://github.com/easytier/easytier/issues)
|
||||||
write_err(format!("os version: {}", std::env::consts::OS));
|
easytier version: {version}
|
||||||
write_err(format!("arch: {}", std::env::consts::ARCH));
|
os: {os}
|
||||||
write_err(format!(
|
arch: {arch}
|
||||||
"panic is recorded in: {}",
|
panic is recorded in: {file}
|
||||||
file_path
|
thread: {thread}
|
||||||
|
time: {time}
|
||||||
|
location: {location}
|
||||||
|
panic info: {payload}
|
||||||
|
",
|
||||||
|
version = crate::VERSION,
|
||||||
|
os = std::env::consts::OS,
|
||||||
|
arch = std::env::consts::ARCH,
|
||||||
|
file = file_path
|
||||||
.and_then(|p| p.to_str().map(|x| x.to_string()))
|
.and_then(|p| p.to_str().map(|x| x.to_string()))
|
||||||
.unwrap_or("<no file>".to_string())
|
.unwrap_or("<no file>".to_string()),
|
||||||
));
|
thread = thread,
|
||||||
write_err(format!("thread: {}", thread));
|
time = chrono::Local::now(),
|
||||||
write_err(format!("time: {}", chrono::Local::now()));
|
location = location,
|
||||||
write_err(format!("location: {}", location));
|
payload = payload_str,
|
||||||
write_err(format!("panic info: {}", payload_str));
|
};
|
||||||
|
|
||||||
// backtrace is risky, so use it last
|
write_err(msg);
|
||||||
let backtrace = backtrace::Backtrace::force_capture();
|
write_err(sep);
|
||||||
write_err(format!("backtrace: {:#?}", backtrace));
|
write_err(format!("{:#?}", backtrace::Backtrace::force_capture()));
|
||||||
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}));
|
}));
|
||||||
@@ -257,20 +141,3 @@ pub fn weak_upgrade<T>(weak: &std::sync::Weak<T>) -> anyhow::Result<std::sync::A
|
|||||||
weak.upgrade()
|
weak.upgrade()
|
||||||
.ok_or_else(|| anyhow::anyhow!("{} not available", std::any::type_name::<T>()))
|
.ok_or_else(|| anyhow::anyhow!("{} not available", std::any::type_name::<T>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::common::config::{self};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
async fn test_logger_reload() {
|
|
||||||
println!("current working dir: {:?}", std::env::current_dir());
|
|
||||||
let config = config::LoggingConfigBuilder::default().build().unwrap();
|
|
||||||
let s = init_logger(&config, true).unwrap();
|
|
||||||
tracing::debug!("test not display debug");
|
|
||||||
s.unwrap().send(LevelFilter::DEBUG.to_string()).unwrap();
|
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
|
||||||
tracing::debug!("test display debug");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{
|
common::{
|
||||||
config::TomlConfigLoader, global_ctx::GlobalCtx, scoped_task::ScopedTask,
|
config::TomlConfigLoader, global_ctx::GlobalCtx, log, scoped_task::ScopedTask,
|
||||||
set_default_machine_id, stun::MockStunInfoCollector,
|
set_default_machine_id, stun::MockStunInfoCollector,
|
||||||
},
|
},
|
||||||
connector::create_connector_by_url,
|
connector::create_connector_by_url,
|
||||||
@@ -87,18 +87,16 @@ impl WebClient {
|
|||||||
loop {
|
loop {
|
||||||
let conn = match connector.connect().await {
|
let conn = match connector.connect().await {
|
||||||
Ok(conn) => conn,
|
Ok(conn) => conn,
|
||||||
Err(e) => {
|
Err(error) => {
|
||||||
println!(
|
let wait = 1;
|
||||||
"Failed to connect to the server ({}), retrying in 5 seconds...",
|
log::warn!(%error, "Failed to connect to the server, retrying in {} seconds...", wait);
|
||||||
e
|
tokio::time::sleep(std::time::Duration::from_secs(wait)).await;
|
||||||
);
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
connected.store(true, Ordering::Release);
|
connected.store(true, Ordering::Release);
|
||||||
println!("Successfully connected to {:?}", conn.info());
|
log::info!("Successfully connected to {:?}", conn.info());
|
||||||
|
|
||||||
let mut session = session::Session::new(conn, controller.clone());
|
let mut session = session::Session::new(conn, controller.clone());
|
||||||
session.wait().await;
|
session.wait().await;
|
||||||
|
|||||||
Reference in New Issue
Block a user