From 82f021e22e09e862b481bb36dcfafbb8b86f7cb1 Mon Sep 17 00:00:00 2001 From: Zilin Zhu Date: Thu, 3 Jul 2025 10:33:04 +0800 Subject: [PATCH] [router] add --log-level to sgl-router (#6512) --- sgl-router/README.md | 2 +- .../py_src/sglang_router/launch_router.py | 18 ++++++++++-------- sgl-router/py_src/sglang_router/router.py | 6 +++--- sgl-router/py_test/test_launch_router.py | 1 + sgl-router/src/config/types.rs | 6 +++--- sgl-router/src/lib.rs | 12 ++++++------ sgl-router/src/server.rs | 18 ++++++++++++------ 7 files changed, 36 insertions(+), 27 deletions(-) diff --git a/sgl-router/README.md b/sgl-router/README.md index 47349a380..5c1ef12cd 100644 --- a/sgl-router/README.md +++ b/sgl-router/README.md @@ -79,7 +79,7 @@ router = Router( ) ``` -Use the `--verbose` flag with the CLI for more detailed logs. +Use the `--log-level` flag with the CLI to set [log level](https://docs.sglang.ai/backend/server_arguments.html#logging). ### Metrics diff --git a/sgl-router/py_src/sglang_router/launch_router.py b/sgl-router/py_src/sglang_router/launch_router.py index 82a56eec9..092946a27 100644 --- a/sgl-router/py_src/sglang_router/launch_router.py +++ b/sgl-router/py_src/sglang_router/launch_router.py @@ -48,8 +48,8 @@ class RouterArgs: eviction_interval: int = 60 max_tree_size: int = 2**24 max_payload_size: int = 256 * 1024 * 1024 # 256MB default for large batches - verbose: bool = False log_dir: Optional[str] = None + log_level: Optional[str] = None # Service discovery configuration service_discovery: bool = False selector: Dict[str, str] = dataclasses.field(default_factory=dict) @@ -178,17 +178,19 @@ class RouterArgs: default=RouterArgs.max_payload_size, help="Maximum payload size in bytes", ) - parser.add_argument( - f"--{prefix}verbose", - action="store_true", - help="Enable verbose logging", - ) parser.add_argument( f"--{prefix}log-dir", type=str, default=None, help="Directory to store log files. If not specified, logs are only output to console.", ) + parser.add_argument( + f"--{prefix}log-level", + type=str, + default="info", + choices=["debug", "info", "warning", "error", "critical"], + help="Set the logging level. If not specified, defaults to INFO.", + ) parser.add_argument( f"--{prefix}service-discovery", action="store_true", @@ -275,8 +277,8 @@ class RouterArgs: eviction_interval=getattr(args, f"{prefix}eviction_interval"), max_tree_size=getattr(args, f"{prefix}max_tree_size"), max_payload_size=getattr(args, f"{prefix}max_payload_size"), - verbose=getattr(args, f"{prefix}verbose", False), log_dir=getattr(args, f"{prefix}log_dir", None), + log_level=getattr(args, f"{prefix}log_level", None), service_discovery=getattr(args, f"{prefix}service_discovery", False), selector=cls._parse_selector(getattr(args, f"{prefix}selector", None)), service_discovery_port=getattr(args, f"{prefix}service_discovery_port"), @@ -404,8 +406,8 @@ def launch_router(args: argparse.Namespace) -> Optional[Router]: eviction_interval_secs=router_args.eviction_interval, max_tree_size=router_args.max_tree_size, max_payload_size=router_args.max_payload_size, - verbose=router_args.verbose, log_dir=router_args.log_dir, + log_level=router_args.log_level, service_discovery=router_args.service_discovery, selector=router_args.selector, service_discovery_port=router_args.service_discovery_port, diff --git a/sgl-router/py_src/sglang_router/router.py b/sgl-router/py_src/sglang_router/router.py index 7708e393a..4c5eed796 100644 --- a/sgl-router/py_src/sglang_router/router.py +++ b/sgl-router/py_src/sglang_router/router.py @@ -31,8 +31,8 @@ class Router: routing. Default: 60 max_payload_size: Maximum payload size in bytes. Default: 256MB max_tree_size: Maximum size of the approximation tree for cache-aware routing. Default: 2^24 - verbose: Enable verbose logging. Default: False log_dir: Directory to store log files. If None, logs are only output to console. Default: None + log_level: Logging level. Options: 'debug', 'info', 'warning', 'error', 'critical'. service_discovery: Enable Kubernetes service discovery. When enabled, the router will automatically discover worker pods based on the selector. Default: False selector: Dictionary mapping of label keys to values for Kubernetes pod selection. @@ -66,8 +66,8 @@ class Router: eviction_interval_secs: int = 60, max_tree_size: int = 2**24, max_payload_size: int = 256 * 1024 * 1024, # 256MB - verbose: bool = False, log_dir: Optional[str] = None, + log_level: Optional[str] = None, service_discovery: bool = False, selector: Dict[str, str] = None, service_discovery_port: int = 80, @@ -100,8 +100,8 @@ class Router: eviction_interval_secs=eviction_interval_secs, max_tree_size=max_tree_size, max_payload_size=max_payload_size, - verbose=verbose, log_dir=log_dir, + log_level=log_level, service_discovery=service_discovery, selector=selector, service_discovery_port=service_discovery_port, diff --git a/sgl-router/py_test/test_launch_router.py b/sgl-router/py_test/test_launch_router.py index 884109e67..eb2018283 100644 --- a/sgl-router/py_test/test_launch_router.py +++ b/sgl-router/py_test/test_launch_router.py @@ -38,6 +38,7 @@ class TestLaunchRouter(unittest.TestCase): max_payload_size=256 * 1024 * 1024, # 256MB verbose=False, log_dir=None, + log_level=None, service_discovery=False, selector=None, service_discovery_port=80, diff --git a/sgl-router/src/config/types.rs b/sgl-router/src/config/types.rs index 732b1f874..3926db5a2 100644 --- a/sgl-router/src/config/types.rs +++ b/sgl-router/src/config/types.rs @@ -27,8 +27,8 @@ pub struct RouterConfig { pub metrics: Option, /// Log directory (None = stdout only) pub log_dir: Option, - /// Verbose logging - pub verbose: bool, + /// Log level (None = info) + pub log_level: Option, } /// Routing mode configuration @@ -177,7 +177,7 @@ impl Default for RouterConfig { discovery: None, metrics: None, log_dir: None, - verbose: false, + log_level: None, } } } diff --git a/sgl-router/src/lib.rs b/sgl-router/src/lib.rs index 1f7e3c8f7..fb90c635e 100644 --- a/sgl-router/src/lib.rs +++ b/sgl-router/src/lib.rs @@ -37,8 +37,8 @@ struct Router { eviction_interval_secs: u64, max_tree_size: usize, max_payload_size: usize, - verbose: bool, log_dir: Option, + log_level: Option, service_discovery: bool, selector: HashMap, service_discovery_port: u16, @@ -129,7 +129,7 @@ impl Router { discovery, metrics, log_dir: self.log_dir.clone(), - verbose: self.verbose, + log_level: self.log_level.clone(), }) } } @@ -150,8 +150,8 @@ impl Router { eviction_interval_secs = 60, max_tree_size = 2usize.pow(24), max_payload_size = 256 * 1024 * 1024, // 256MB default for large batches - verbose = false, log_dir = None, + log_level = None, service_discovery = false, selector = HashMap::new(), service_discovery_port = 80, @@ -179,8 +179,8 @@ impl Router { eviction_interval_secs: u64, max_tree_size: usize, max_payload_size: usize, - verbose: bool, log_dir: Option, + log_level: Option, service_discovery: bool, selector: HashMap, service_discovery_port: u16, @@ -208,8 +208,8 @@ impl Router { eviction_interval_secs, max_tree_size, max_payload_size, - verbose, log_dir, + log_level, service_discovery, selector, service_discovery_port, @@ -283,9 +283,9 @@ impl Router { port: self.port, worker_urls: self.worker_urls.clone(), policy_config, - verbose: self.verbose, max_payload_size: self.max_payload_size, log_dir: self.log_dir.clone(), + log_level: self.log_level.clone(), service_discovery_config, prometheus_config, request_timeout_secs: self.request_timeout_secs, diff --git a/sgl-router/src/server.rs b/sgl-router/src/server.rs index a1fd50acd..e87405517 100644 --- a/sgl-router/src/server.rs +++ b/sgl-router/src/server.rs @@ -278,9 +278,9 @@ pub struct ServerConfig { pub port: u16, pub worker_urls: Vec, pub policy_config: PolicyConfig, - pub verbose: bool, pub max_payload_size: usize, pub log_dir: Option, + pub log_level: Option, pub service_discovery_config: Option, pub prometheus_config: Option, pub request_timeout_secs: u64, @@ -292,11 +292,17 @@ pub async fn startup(config: ServerConfig) -> std::io::Result<()> { let _log_guard = if !LOGGING_INITIALIZED.swap(true, Ordering::SeqCst) { Some(logging::init_logging(LoggingConfig { - level: if config.verbose { - Level::DEBUG - } else { - Level::INFO - }, + level: config + .log_level + .as_deref() + .and_then(|s| match s.to_uppercase().parse::() { + Ok(l) => Some(l), + Err(_) => { + warn!("Invalid log level string: '{}'. Defaulting to INFO.", s); + None + } + }) + .unwrap_or(Level::INFO), json_format: false, log_dir: config.log_dir.clone(), colorize: true,