Skip to content

Commit 14cb9ad

Browse files
07pepa07pepa
07pepa
authored andcommitted
add logging overriding
1 parent 2173760 commit 14cb9ad

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

src/fastapi_cli/cli.py

+19
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from rich.padding import Padding
88
from rich.panel import Panel
99
from typing_extensions import Annotated
10+
from uvicorn.config import LOGGING_CONFIG
1011

1112
from fastapi_cli.discover import get_import_string
1213
from fastapi_cli.exceptions import FastAPICLIException
@@ -60,6 +61,7 @@ def _run(
6061
command: str,
6162
app: Union[str, None] = None,
6263
proxy_headers: bool = False,
64+
log_config: Union[Path, None] = None,
6365
) -> None:
6466
try:
6567
use_uvicorn_app = get_import_string(path=path, app_name=app)
@@ -89,6 +91,7 @@ def _run(
8991
raise FastAPICLIException(
9092
"Could not import Uvicorn, try running 'pip install uvicorn'"
9193
) from None
94+
9295
uvicorn.run(
9396
app=use_uvicorn_app,
9497
host=host,
@@ -97,6 +100,8 @@ def _run(
97100
workers=workers,
98101
root_path=root_path,
99102
proxy_headers=proxy_headers,
103+
# fallback to default uvicorn log config if nothing is provided
104+
log_config=LOGGING_CONFIG if not log_config else str(log_config),
100105
)
101106

102107

@@ -145,6 +150,12 @@ def dev(
145150
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info."
146151
),
147152
] = True,
153+
log_config: Annotated[
154+
Union[Path, None],
155+
typer.Option(
156+
help="Logging configuration file. Supported formats: .ini, .json, .yaml. be tried."
157+
),
158+
] = None,
148159
) -> Any:
149160
"""
150161
Run a [bold]FastAPI[/bold] app in [yellow]development[/yellow] mode. 🧪
@@ -180,6 +191,7 @@ def dev(
180191
app=app,
181192
command="dev",
182193
proxy_headers=proxy_headers,
194+
log_config=log_config,
183195
)
184196

185197

@@ -234,6 +246,12 @@ def run(
234246
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info."
235247
),
236248
] = True,
249+
log_config: Annotated[
250+
Union[Path, None],
251+
typer.Option(
252+
help="Logging configuration file. Supported formats: .ini, .json, .yaml."
253+
),
254+
] = None,
237255
) -> Any:
238256
"""
239257
Run a [bold]FastAPI[/bold] app in [green]production[/green] mode. 🚀
@@ -270,6 +288,7 @@ def run(
270288
app=app,
271289
command="run",
272290
proxy_headers=proxy_headers,
291+
log_config=log_config,
273292
)
274293

275294

tests/assets/log_config.yaml

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
version: 1
2+
disable_existing_loggers: False
3+
formatters:
4+
default:
5+
# "()": uvicorn.logging.DefaultFormatter
6+
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
7+
access:
8+
# "()": uvicorn.logging.AccessFormatter
9+
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
10+
handlers:
11+
default:
12+
formatter: default
13+
class: logging.StreamHandler
14+
stream: ext://sys.stderr
15+
access:
16+
formatter: access
17+
class: logging.StreamHandler
18+
stream: ext://sys.stdout
19+
loggers:
20+
uvicorn.error:
21+
level: DEBUG
22+
handlers:
23+
- default
24+
propagate: no
25+
uvicorn.access:
26+
level: DEBUG
27+
handlers:
28+
- access
29+
propagate: no
30+
root:
31+
level: INFO
32+
handlers:
33+
- default
34+
propagate: no

tests/test_cli.py

+17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import uvicorn
77
from fastapi_cli.cli import app
88
from typer.testing import CliRunner
9+
from uvicorn.config import LOGGING_CONFIG
910

1011
from tests.utils import changing_dir
1112

@@ -29,6 +30,7 @@ def test_dev() -> None:
2930
"workers": None,
3031
"root_path": "",
3132
"proxy_headers": True,
33+
"log_config": LOGGING_CONFIG,
3234
}
3335
assert "Using import string single_file_app:app" in result.output
3436
assert (
@@ -58,6 +60,8 @@ def test_dev_args() -> None:
5860
"--app",
5961
"api",
6062
"--no-proxy-headers",
63+
"--log-config",
64+
"log_config.yaml",
6165
],
6266
)
6367
assert result.exit_code == 0, result.output
@@ -71,6 +75,7 @@ def test_dev_args() -> None:
7175
"workers": None,
7276
"root_path": "/api",
7377
"proxy_headers": False,
78+
"log_config": "log_config.yaml",
7479
}
7580
assert "Using import string single_file_app:api" in result.output
7681
assert (
@@ -97,6 +102,7 @@ def test_run() -> None:
97102
"workers": None,
98103
"root_path": "",
99104
"proxy_headers": True,
105+
"log_config": LOGGING_CONFIG,
100106
}
101107
assert "Using import string single_file_app:app" in result.output
102108
assert (
@@ -128,6 +134,8 @@ def test_run_args() -> None:
128134
"--app",
129135
"api",
130136
"--no-proxy-headers",
137+
"--log-config",
138+
"log_config.yaml",
131139
],
132140
)
133141
assert result.exit_code == 0, result.output
@@ -141,6 +149,7 @@ def test_run_args() -> None:
141149
"workers": 2,
142150
"root_path": "/api",
143151
"proxy_headers": False,
152+
"log_config": "log_config.yaml",
144153
}
145154
assert "Using import string single_file_app:api" in result.output
146155
assert (
@@ -178,6 +187,10 @@ def test_dev_help() -> None:
178187
assert "The root path is used to tell your app" in result.output
179188
assert "The name of the variable that contains the FastAPI app" in result.output
180189
assert "Use multiple worker processes." not in result.output
190+
assert (
191+
"Logging configuration file. Supported formats: .ini, .json, .yaml."
192+
in result.output
193+
)
181194

182195

183196
def test_run_help() -> None:
@@ -199,6 +212,10 @@ def test_run_help() -> None:
199212
assert "The root path is used to tell your app" in result.output
200213
assert "The name of the variable that contains the FastAPI app" in result.output
201214
assert "Use multiple worker processes." in result.output
215+
assert (
216+
"Logging configuration file. Supported formats: .ini, .json, .yaml."
217+
in result.output
218+
)
202219

203220

204221
def test_callback_help() -> None:

0 commit comments

Comments
 (0)