allow enable log with cli, limit log size (#1384)

* impl logger rpc
* use size based appender
* add log args
This commit is contained in:
Sijie.Sun
2025-09-18 16:35:12 +08:00
committed by GitHub
parent 56fd6e4ab6
commit e06e8a9e8a
17 changed files with 1296 additions and 38 deletions
+107 -6
View File
@@ -30,16 +30,18 @@ use easytier::{
cli::{
list_peer_route_pair, AclManageRpc, AclManageRpcClientFactory, AddPortForwardRequest,
ConnectorManageRpc, ConnectorManageRpcClientFactory, DumpRouteRequest,
GetAclStatsRequest, GetPrometheusStatsRequest, GetStatsRequest,
GetAclStatsRequest, GetLoggerConfigRequest, GetPrometheusStatsRequest, GetStatsRequest,
GetVpnPortalInfoRequest, GetWhitelistRequest, ListConnectorRequest,
ListForeignNetworkRequest, ListGlobalForeignNetworkRequest, ListMappedListenerRequest,
ListPeerRequest, ListPeerResponse, ListPortForwardRequest, ListRouteRequest,
ListRouteResponse, ManageMappedListenerRequest, MappedListenerManageAction,
MappedListenerManageRpc, MappedListenerManageRpcClientFactory, NodeInfo, PeerManageRpc,
ListRouteResponse, LogLevel, LoggerRpc, LoggerRpcClientFactory,
ManageMappedListenerRequest, MappedListenerManageAction, MappedListenerManageRpc,
MappedListenerManageRpcClientFactory, NodeInfo, PeerManageRpc,
PeerManageRpcClientFactory, PortForwardManageRpc, PortForwardManageRpcClientFactory,
RemovePortForwardRequest, SetWhitelistRequest, ShowNodeInfoRequest, StatsRpc,
StatsRpcClientFactory, TcpProxyEntryState, TcpProxyEntryTransportType, TcpProxyRpc,
TcpProxyRpcClientFactory, VpnPortalRpc, VpnPortalRpcClientFactory,
RemovePortForwardRequest, SetLoggerConfigRequest, SetWhitelistRequest,
ShowNodeInfoRequest, StatsRpc, StatsRpcClientFactory, TcpProxyEntryState,
TcpProxyEntryTransportType, TcpProxyRpc, TcpProxyRpcClientFactory, VpnPortalRpc,
VpnPortalRpcClientFactory,
},
common::{NatType, SocketType},
peer_rpc::{GetGlobalPeerMapRequest, PeerCenterRpc, PeerCenterRpcClientFactory},
@@ -105,6 +107,8 @@ enum SubCommand {
Whitelist(WhitelistArgs),
#[command(about = "show statistics information")]
Stats(StatsArgs),
#[command(about = "manage logger configuration")]
Logger(LoggerArgs),
#[command(about = t!("core_clap.generate_completions").to_string())]
GenAutocomplete { shell: Shell },
}
@@ -272,6 +276,23 @@ enum StatsSubCommand {
Prometheus,
}
#[derive(Args, Debug)]
struct LoggerArgs {
#[command(subcommand)]
sub_command: Option<LoggerSubCommand>,
}
#[derive(Subcommand, Debug)]
enum LoggerSubCommand {
/// Get current logger configuration
Get,
/// Set logger level
Set {
#[arg(help = "Log level (disabled, error, warning, info, debug, trace)")]
level: String,
},
}
#[derive(Args, Debug)]
struct ServiceArgs {
#[arg(short, long, default_value = env!("CARGO_PKG_NAME"), help = "service name")]
@@ -443,6 +464,18 @@ impl CommandHandler<'_> {
.with_context(|| "failed to get stats client")?)
}
async fn get_logger_client(
&self,
) -> Result<Box<dyn LoggerRpc<Controller = BaseController>>, Error> {
Ok(self
.client
.lock()
.await
.scoped_client::<LoggerRpcClientFactory<BaseController>>("".to_string())
.await
.with_context(|| "failed to get logger client")?)
}
async fn list_peers(&self) -> Result<ListPeerResponse, Error> {
let client = self.get_peer_manager_client().await?;
let request = ListPeerRequest::default();
@@ -1163,6 +1196,66 @@ impl CommandHandler<'_> {
Ok(())
}
async fn handle_logger_get(&self) -> Result<(), Error> {
let client = self.get_logger_client().await?;
let request = GetLoggerConfigRequest {};
let response = client
.get_logger_config(BaseController::default(), request)
.await?;
match self.output_format {
OutputFormat::Table => {
let level_str = match response.level() {
LogLevel::Disabled => "disabled",
LogLevel::Error => "error",
LogLevel::Warning => "warning",
LogLevel::Info => "info",
LogLevel::Debug => "debug",
LogLevel::Trace => "trace",
};
println!("Current Log Level: {}", level_str);
}
OutputFormat::Json => {
let json = serde_json::to_string_pretty(&response)?;
println!("{}", json);
}
}
Ok(())
}
async fn handle_logger_set(&self, level: &str) -> Result<(), Error> {
let log_level = match level.to_lowercase().as_str() {
"disabled" => LogLevel::Disabled,
"error" => LogLevel::Error,
"warning" => LogLevel::Warning,
"info" => LogLevel::Info,
"debug" => LogLevel::Debug,
"trace" => LogLevel::Trace,
_ => return Err(anyhow::anyhow!("Invalid log level: {}. Valid levels are: disabled, error, warning, info, debug, trace", level)),
};
let client = self.get_logger_client().await?;
let request = SetLoggerConfigRequest {
level: log_level.into(),
};
let response = client
.set_logger_config(BaseController::default(), request)
.await?;
match self.output_format {
OutputFormat::Table => {
println!("Log level successfully set to: {}", level);
}
OutputFormat::Json => {
let json = serde_json::to_string_pretty(&response)?;
println!("{}", json);
}
}
Ok(())
}
fn parse_port_list(ports_str: &str) -> Result<Vec<String>, Error> {
let mut ports = Vec::new();
for port_spec in ports_str.split(',') {
@@ -1996,6 +2089,14 @@ async fn main() -> Result<(), Error> {
println!("{}", response.prometheus_text);
}
},
SubCommand::Logger(logger_args) => match &logger_args.sub_command {
Some(LoggerSubCommand::Get) | None => {
handler.handle_logger_get().await?;
}
Some(LoggerSubCommand::Set { level }) => {
handler.handle_logger_set(level).await?;
}
},
SubCommand::GenAutocomplete { shell } => {
let mut cmd = Cli::command();
easytier::print_completions(shell, &mut cmd, "easytier-cli");