diff --git a/libs/infinity_emb/infinity_emb/cli.py b/libs/infinity_emb/infinity_emb/cli.py index 58b41810..618aadd7 100644 --- a/libs/infinity_emb/infinity_emb/cli.py +++ b/libs/infinity_emb/infinity_emb/cli.py @@ -5,7 +5,6 @@ import re import sys - import infinity_emb from infinity_emb._optional_imports import CHECK_TYPER, CHECK_UVICORN from infinity_emb.args import EngineArgs @@ -107,6 +106,7 @@ def _construct(name: str): tp = typer.Typer() + @tp.command("v1") def v1( # v1 is deprecated. Please do no longer modify it. @@ -177,6 +177,7 @@ def v1( proxy_root_path="", # set as empty string ) + @tp.command("v2") def v2( # t @@ -380,6 +381,8 @@ def v2( api_key=api_key, proxy_root_path=proxy_root_path, ) + # Update logging configs + set_uvicorn_logging_configs() uvicorn.run( app, @@ -391,6 +394,47 @@ def v2( ) +def set_uvicorn_logging_configs(): + """Configure Uvicorn logging with environment variable overrides. + + Allows customization of log formats through environment variables: + - INFINITY_UVICORN_DEFAULT_FORMAT: Format for default logs + - INFINITY_UVICORN_ACCESS_FORMAT: Format for access logs + - INFINITY_UVICORN_DATE_FORMAT: Date format for all logs + """ + from uvicorn.config import LOGGING_CONFIG + import os + + # Define constants for environment variable names to improve maintainability + default_format_env = MANAGER.uvicorn_default_format + access_format_env = MANAGER.uvicorn_access_format + date_format_env = MANAGER.uvicorn_date_format + + # Default log format (can be overridden by env var) + default_fmt = os.getenv( + default_format_env, + "%(asctime)s %(levelprefix)s %(message)s" + ) + + # Access log format (can be overridden by env var) + access_fmt = os.getenv( + access_format_env, + '%(asctime)s %(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s' + ) + + # Date format for all logs (can be overridden by env var) + date_fmt = os.getenv( + date_format_env, + "%Y-%m-%d %H:%M:%S" + ) + + # Apply the configurations + LOGGING_CONFIG["formatters"]["default"]["fmt"] = default_fmt + LOGGING_CONFIG["formatters"]["default"]["datefmt"] = date_fmt + LOGGING_CONFIG["formatters"]["access"]["fmt"] = access_fmt + LOGGING_CONFIG["formatters"]["access"]["datefmt"] = date_fmt + + def cli(): CHECK_TYPER.mark_required() if len(sys.argv) == 1 or sys.argv[1] not in [ diff --git a/libs/infinity_emb/infinity_emb/env.py b/libs/infinity_emb/infinity_emb/env.py index 48833e47..676bb4b5 100644 --- a/libs/infinity_emb/infinity_emb/env.py +++ b/libs/infinity_emb/infinity_emb/env.py @@ -271,4 +271,23 @@ def onnx_do_not_prefer_quantized(self): return self._to_bool_multiple( self._optional_infinity_var_multiple("onnx_do_not_prefer_quantized", default=["false"]) ) + @cached_property + def disable_rich_handler(self): + return self._to_bool(self._optional_infinity_var("disable_rich_handler", default="false")) + + @cached_property + def log_format(self): + return self._optional_infinity_var("log_format", default="%(asctime)s %(name)s %(levelname)s: %(message)s") + @cached_property + def uvicorn_default_format(self): + return self._optional_infinity_var("uvicorn_default_format", default="[%(asctime)s] %(levelprefix)s %(message)s") + + @cached_property + def uvicorn_access_format(self): + return self._optional_infinity_var("uvicorn_access_format", default='[%(asctime)s] %(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s') + + @cached_property + def uvicorn_date_format(self): + return self._optional_infinity_var("uvicorn_date_format", default="%Y-%m-%d %H:%M:%S") MANAGER = __Infinity_EnvManager() + diff --git a/libs/infinity_emb/infinity_emb/log_handler.py b/libs/infinity_emb/infinity_emb/log_handler.py index 2eca5d34..d2ebbb4d 100644 --- a/libs/infinity_emb/infinity_emb/log_handler.py +++ b/libs/infinity_emb/infinity_emb/log_handler.py @@ -2,20 +2,39 @@ # Copyright (c) 2023-now michaelfeil import logging +import os import sys from enum import Enum from typing import Any +from infinity_emb.env import MANAGER + logging.getLogger().handlers.clear() -handlers: list[Any] = [] -try: - from rich.console import Console - from rich.logging import RichHandler +def configure_log_handlers() -> list[Any]: + """Configure and return logging handlers based on environment settings.""" + handlers = [] + + # Determine the appropriate handler + if not MANAGER.disable_rich_handler: + try: + from rich.console import Console + from rich.logging import RichHandler + handlers.append(RichHandler( + console=Console(stderr=True), + show_time=False, + markup=True + )) + return handlers + except ImportError: + pass # Fall through to default handler - handlers.append(RichHandler(console=Console(stderr=True), show_time=False)) -except ImportError: + # Default handler (used when Rich is disabled or not available) handlers.append(logging.StreamHandler(sys.stderr)) + return handlers + + +handlers = configure_log_handlers() LOG_LEVELS: dict[str, int] = { "critical": logging.CRITICAL, @@ -26,7 +45,7 @@ "trace": 5, } -FORMAT = "%(asctime)s %(name)s %(levelname)s: %(message)s" +FORMAT = MANAGER.log_format logging.basicConfig( level="INFO", format=FORMAT,