diff --git a/.github/labeler.yml b/.github/labeler.yml index 1e41db0..c1208d3 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -21,3 +21,9 @@ internal: - '!README.md' - '!src/**' - '!pyproject.toml' + +feature: + - any: + - changed-files: + - any-glob-to-any-file: + - src/** diff --git a/src/fastapi_cli/cli.py b/src/fastapi_cli/cli.py index c983b5c..f5af037 100644 --- a/src/fastapi_cli/cli.py +++ b/src/fastapi_cli/cli.py @@ -86,6 +86,7 @@ def _run( command: str, app: Union[str, None] = None, proxy_headers: bool = False, + log_config: Union[Path, None] = None, ) -> None: with get_rich_toolkit() as toolkit: server_type = "development" if command == "dev" else "production" @@ -167,7 +168,7 @@ def _run( workers=workers, root_path=root_path, proxy_headers=proxy_headers, - log_config=get_uvicorn_log_config(), + log_config=get_uvicorn_log_config() if not log_config else str(log_config), ) @@ -216,6 +217,12 @@ def dev( help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info." ), ] = True, + log_config: Annotated[ + Union[Path, None], + typer.Option( + help="Logging configuration file. Supported formats: .ini, .json, .yaml. be tried." + ), + ] = None, ) -> Any: """ Run a [bold]FastAPI[/bold] app in [yellow]development[/yellow] mode. ๐Ÿงช @@ -251,6 +258,7 @@ def dev( app=app, command="dev", proxy_headers=proxy_headers, + log_config=log_config, ) @@ -305,6 +313,12 @@ def run( help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info." ), ] = True, + log_config: Annotated[ + Union[Path, None], + typer.Option( + help="Logging configuration file. Supported formats: .ini, .json, .yaml." + ), + ] = None, ) -> Any: """ Run a [bold]FastAPI[/bold] app in [green]production[/green] mode. ๐Ÿš€ @@ -341,6 +355,7 @@ def run( app=app, command="run", proxy_headers=proxy_headers, + log_config=log_config, ) diff --git a/tests/assets/log_config.yaml b/tests/assets/log_config.yaml new file mode 100644 index 0000000..1678d76 --- /dev/null +++ b/tests/assets/log_config.yaml @@ -0,0 +1,34 @@ +version: 1 +disable_existing_loggers: False +formatters: + default: + # "()": uvicorn.logging.DefaultFormatter + format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + access: + # "()": uvicorn.logging.AccessFormatter + format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' +handlers: + default: + formatter: default + class: logging.StreamHandler + stream: ext://sys.stderr + access: + formatter: access + class: logging.StreamHandler + stream: ext://sys.stdout +loggers: + uvicorn.error: + level: DEBUG + handlers: + - default + propagate: no + uvicorn.access: + level: DEBUG + handlers: + - access + propagate: no +root: + level: INFO + handlers: + - default + propagate: no diff --git a/tests/test_cli.py b/tests/test_cli.py index 8bdba1c..1d93c6a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -94,6 +94,8 @@ def test_dev_args() -> None: "--app", "api", "--no-proxy-headers", + "--log-config", + "log_config.yaml", ], ) assert result.exit_code == 0, result.output @@ -107,7 +109,7 @@ def test_dev_args() -> None: "workers": None, "root_path": "/api", "proxy_headers": False, - "log_config": get_uvicorn_log_config(), + "log_config": "log_config.yaml", } assert "Using import string: single_file_app:api" in result.output assert "Starting development server ๐Ÿš€" in result.output @@ -166,6 +168,8 @@ def test_run_args() -> None: "--app", "api", "--no-proxy-headers", + "--log-config", + "log_config.yaml", ], ) assert result.exit_code == 0, result.output @@ -179,7 +183,7 @@ def test_run_args() -> None: "workers": 2, "root_path": "/api", "proxy_headers": False, - "log_config": get_uvicorn_log_config(), + "log_config": "log_config.yaml", } assert "Using import string: single_file_app:api" in result.output @@ -218,6 +222,10 @@ def test_dev_help() -> None: assert "The root path is used to tell your app" in result.output assert "The name of the variable that contains the FastAPI app" in result.output assert "Use multiple worker processes." not in result.output + assert ( + "Logging configuration file. Supported formats: .ini, .json, .yaml." + in result.output + ) def test_run_help() -> None: @@ -239,6 +247,10 @@ def test_run_help() -> None: assert "The root path is used to tell your app" in result.output assert "The name of the variable that contains the FastAPI app" in result.output assert "Use multiple worker processes." in result.output + assert ( + "Logging configuration file. Supported formats: .ini, .json, .yaml." + in result.output + ) def test_callback_help() -> None: