From 2e241e3275ca1a2cec40993e108161012ba3694e Mon Sep 17 00:00:00 2001 From: 07pepa Date: Tue, 18 Jun 2024 18:09:50 +0200 Subject: [PATCH 1/2] add logging overriding --- src/fastapi_cli/cli.py | 19 +++++++++++++++++++ tests/assets/log_config.yaml | 34 ++++++++++++++++++++++++++++++++++ tests/test_cli.py | 17 +++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 tests/assets/log_config.yaml diff --git a/src/fastapi_cli/cli.py b/src/fastapi_cli/cli.py index d5bcb8e5..357106b4 100644 --- a/src/fastapi_cli/cli.py +++ b/src/fastapi_cli/cli.py @@ -7,6 +7,7 @@ from rich.padding import Padding from rich.panel import Panel from typing_extensions import Annotated +from uvicorn.config import LOGGING_CONFIG from fastapi_cli.discover import get_import_string from fastapi_cli.exceptions import FastAPICLIException @@ -60,6 +61,7 @@ def _run( command: str, app: Union[str, None] = None, proxy_headers: bool = False, + log_config: Union[Path, None] = None, ) -> None: try: use_uvicorn_app = get_import_string(path=path, app_name=app) @@ -89,6 +91,7 @@ def _run( raise FastAPICLIException( "Could not import Uvicorn, try running 'pip install uvicorn'" ) from None + uvicorn.run( app=use_uvicorn_app, host=host, @@ -97,6 +100,8 @@ def _run( workers=workers, root_path=root_path, proxy_headers=proxy_headers, + # fallback to default uvicorn log config if nothing is provided + log_config=LOGGING_CONFIG if not log_config else str(log_config), ) @@ -145,6 +150,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. ๐Ÿงช @@ -180,6 +191,7 @@ def dev( app=app, command="dev", proxy_headers=proxy_headers, + log_config=log_config, ) @@ -234,6 +246,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. ๐Ÿš€ @@ -270,6 +288,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 00000000..1678d761 --- /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 44c14d2c..291e1c9d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,6 +6,7 @@ import uvicorn from fastapi_cli.cli import app from typer.testing import CliRunner +from uvicorn.config import LOGGING_CONFIG from tests.utils import changing_dir @@ -29,6 +30,7 @@ def test_dev() -> None: "workers": None, "root_path": "", "proxy_headers": True, + "log_config": LOGGING_CONFIG, } assert "Using import string single_file_app:app" in result.output assert ( @@ -58,6 +60,8 @@ def test_dev_args() -> None: "--app", "api", "--no-proxy-headers", + "--log-config", + "log_config.yaml", ], ) assert result.exit_code == 0, result.output @@ -71,6 +75,7 @@ def test_dev_args() -> None: "workers": None, "root_path": "/api", "proxy_headers": False, + "log_config": "log_config.yaml", } assert "Using import string single_file_app:api" in result.output assert ( @@ -97,6 +102,7 @@ def test_run() -> None: "workers": None, "root_path": "", "proxy_headers": True, + "log_config": LOGGING_CONFIG, } assert "Using import string single_file_app:app" in result.output assert ( @@ -128,6 +134,8 @@ def test_run_args() -> None: "--app", "api", "--no-proxy-headers", + "--log-config", + "log_config.yaml", ], ) assert result.exit_code == 0, result.output @@ -141,6 +149,7 @@ def test_run_args() -> None: "workers": 2, "root_path": "/api", "proxy_headers": False, + "log_config": "log_config.yaml", } assert "Using import string single_file_app:api" in result.output assert ( @@ -178,6 +187,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: @@ -199,6 +212,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: From efcf326a3f4c8ca6ad3b7383b055845261129637 Mon Sep 17 00:00:00 2001 From: 07pepa <9963200+07pepa@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:37:38 +0200 Subject: [PATCH 2/2] add logging overriding --- .github/labeler.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index 1e41db0d..1031236a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -21,3 +21,7 @@ internal: - '!README.md' - '!src/**' - '!pyproject.toml' + +#if branch starts with feature/ then apply this label +feature: + - head-branch: ['^feature', 'feature']