beans-logging-fastapi 3.0.0__tar.gz → 4.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {beans_logging_fastapi-3.0.0/src/beans_logging_fastapi.egg-info → beans_logging_fastapi-4.0.0}/PKG-INFO +41 -36
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/README.md +37 -32
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/pyproject.toml +1 -5
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/requirements/requirements.dev.txt +1 -1
- beans_logging_fastapi-4.0.0/requirements.txt +2 -0
- beans_logging_fastapi-4.0.0/src/beans_logging_fastapi/__version__.py +1 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/_async.py +7 -7
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/_core.py +11 -8
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/config.py +14 -5
- beans_logging_fastapi-4.0.0/src/beans_logging_fastapi/constants.py +23 -0
- beans_logging_fastapi-4.0.0/src/beans_logging_fastapi/filters.py +72 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/formats.py +2 -2
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/middlewares.py +36 -24
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0/src/beans_logging_fastapi.egg-info}/PKG-INFO +41 -36
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi.egg-info/requires.txt +2 -2
- beans_logging_fastapi-3.0.0/requirements.txt +0 -2
- beans_logging_fastapi-3.0.0/src/beans_logging_fastapi/__version__.py +0 -1
- beans_logging_fastapi-3.0.0/src/beans_logging_fastapi/constants.py +0 -12
- beans_logging_fastapi-3.0.0/src/beans_logging_fastapi/filters.py +0 -30
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/.python-version +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/LICENSE.txt +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/requirements/requirements.build.txt +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/requirements/requirements.docs.txt +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/requirements/requirements.test.txt +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/setup.cfg +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/setup.py +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/__init__.py +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi.egg-info/SOURCES.txt +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi.egg-info/dependency_links.txt +0 -0
- {beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: beans_logging_fastapi
|
|
3
|
-
Version:
|
|
4
|
-
Summary: This is a
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: This is a HTTP access log module for FastAPI based on 'beans-logging' package.
|
|
5
5
|
Author-email: Batkhuu Byambajav <batkhuu10@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/bybatkhuu/module-fastapi-logging
|
|
7
7
|
Project-URL: Documentation, https://fastapi-logging-docs.bybatkhuu.dev
|
|
@@ -22,7 +22,7 @@ Requires-Python: <4.0,>=3.10
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE.txt
|
|
24
24
|
Requires-Dist: fastapi<1.0.0,>=0.99.1
|
|
25
|
-
Requires-Dist: beans-logging<
|
|
25
|
+
Requires-Dist: beans-logging<10.0.0,>=9.0.0
|
|
26
26
|
Provides-Extra: test
|
|
27
27
|
Requires-Dist: pytest<10.0.0,>=8.0.2; extra == "test"
|
|
28
28
|
Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "test"
|
|
@@ -55,7 +55,7 @@ Requires-Dist: mkdocstrings[python]<2.0.0,>=0.24.3; extra == "dev"
|
|
|
55
55
|
Requires-Dist: mike<3.0.0,>=2.1.3; extra == "dev"
|
|
56
56
|
Requires-Dist: pyright<2.0.0,>=1.1.392; extra == "dev"
|
|
57
57
|
Requires-Dist: pre-commit<5.0.0,>=4.0.1; extra == "dev"
|
|
58
|
-
Requires-Dist:
|
|
58
|
+
Requires-Dist: fastapi[standard]<1.0.0,>=0.99.1; extra == "dev"
|
|
59
59
|
Dynamic: license-file
|
|
60
60
|
|
|
61
61
|
# FastAPI Logging (beans-logging-fastapi)
|
|
@@ -64,7 +64,7 @@ Dynamic: license-file
|
|
|
64
64
|
[](https://github.com/bybatkhuu/module-fastapi-logging/actions/workflows/2.build-publish.yml)
|
|
65
65
|
[](https://github.com/bybatkhuu/module-fastapi-logging/releases)
|
|
66
66
|
|
|
67
|
-
This is a HTTP access
|
|
67
|
+
This is a HTTP access log module for **FastAPI** based on **'beans-logging'** package.
|
|
68
68
|
|
|
69
69
|
## ✨ Features
|
|
70
70
|
|
|
@@ -408,24 +408,24 @@ uvicorn main:app --host=0.0.0.0 --port=8000
|
|
|
408
408
|
**Output**:
|
|
409
409
|
|
|
410
410
|
```txt
|
|
411
|
-
[2026-01-01 12:00:00.
|
|
412
|
-
[2026-01-01 12:00:00.
|
|
413
|
-
[2026-01-01 12:00:00.
|
|
414
|
-
[2026-01-01 12:00:00.
|
|
415
|
-
[2026-01-01 12:00:00.
|
|
416
|
-
[2026-01-01 12:00:00.
|
|
417
|
-
[2026-01-01 12:00:00.
|
|
418
|
-
[2026-01-01 12:00:00.
|
|
419
|
-
[2026-01-01 12:00:00.
|
|
420
|
-
[2026-01-01 12:00:00.
|
|
421
|
-
[2026-01-01 12:00:01.
|
|
422
|
-
[2026-01-01 12:00:01.
|
|
423
|
-
^C[2026-01-01 12:00:02.
|
|
424
|
-
[2026-01-01 12:00:02.
|
|
425
|
-
[2026-01-01 12:00:02.
|
|
426
|
-
[2026-01-01 12:00:02.
|
|
427
|
-
[2026-01-01 12:00:02.
|
|
428
|
-
[2026-01-01 12:00:02.
|
|
411
|
+
[2026-01-01 12:00:00.002 +09:00 | TRACE | beans_logging.intercepters:96]: Intercepted modules: ['uvicorn', 'potato_util', 'fastapi', 'uvicorn.error', 'watchfiles.watcher', 'concurrent.futures', 'watchfiles', 'asyncio', 'concurrent', 'potato_util._base', 'dotenv', 'dotenv.main', 'watchfiles.main', 'potato_util.io', 'potato_util.io._sync']; Muted modules: ['uvicorn.access'];
|
|
412
|
+
[2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.server:84]: Started server process [88375]
|
|
413
|
+
[2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.lifespan.on:48]: Waiting for application startup.
|
|
414
|
+
[2026-01-01 12:00:00.004 +09:00 | TRACE | lifespan:19]: TRACE diagnosis is ON!
|
|
415
|
+
[2026-01-01 12:00:00.004 +09:00 | DEBUG | lifespan:20]: DEBUG mode is ON!
|
|
416
|
+
[2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:21]: Preparing to startup...
|
|
417
|
+
[2026-01-01 12:00:00.004 +09:00 | OK | lifespan:24]: Finished preparation to startup.
|
|
418
|
+
[2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:25]: Version: 0.0.0
|
|
419
|
+
[2026-01-01 12:00:00.005 +09:00 | INFO | uvicorn.lifespan.on:62]: Application startup complete.
|
|
420
|
+
[2026-01-01 12:00:00.006 +09:00 | INFO | uvicorn.server:216]: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
|
|
421
|
+
[2026-01-01 12:00:01.775 +09:00 | DEBUG ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1"
|
|
422
|
+
[2026-01-01 12:00:01.783 +09:00 | OK ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 5.7ms
|
|
423
|
+
^C[2026-01-01 12:00:02.368 +09:00 | INFO | uvicorn.server:264]: Shutting down
|
|
424
|
+
[2026-01-01 12:00:02.470 +09:00 | INFO | uvicorn.lifespan.on:67]: Waiting for application shutdown.
|
|
425
|
+
[2026-01-01 12:00:02.472 +09:00 | INFO | lifespan:29]: Preparing to shutdown...
|
|
426
|
+
[2026-01-01 12:00:02.472 +09:00 | OK | lifespan:31]: Finished preparation to shutdown.
|
|
427
|
+
[2026-01-01 12:00:02.473 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
|
|
428
|
+
[2026-01-01 12:00:02.474 +09:00 | INFO | uvicorn.server:94]: Finished server process [88375]
|
|
429
429
|
```
|
|
430
430
|
|
|
431
431
|
👍
|
|
@@ -450,12 +450,12 @@ logger:
|
|
|
450
450
|
rotate_time: "00:00:00"
|
|
451
451
|
retention: 90
|
|
452
452
|
encoding: utf8
|
|
453
|
-
|
|
453
|
+
use_custom_serialize: false
|
|
454
454
|
http:
|
|
455
455
|
std:
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
456
|
+
msg_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
|
|
457
|
+
err_msg_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
|
|
458
|
+
debug_msg_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
459
459
|
file:
|
|
460
460
|
format_str: '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
|
|
461
461
|
tz: localtime
|
|
@@ -469,45 +469,50 @@ logger:
|
|
|
469
469
|
include_modules: []
|
|
470
470
|
mute_modules: [uvicorn.access]
|
|
471
471
|
handlers:
|
|
472
|
-
|
|
472
|
+
all_std_handler:
|
|
473
473
|
enabled: true
|
|
474
474
|
h_type: STD
|
|
475
475
|
format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
|
|
476
476
|
colorize: true
|
|
477
|
-
|
|
477
|
+
all_file_handler:
|
|
478
478
|
enabled: true
|
|
479
479
|
h_type: FILE
|
|
480
480
|
sink: "{app_name}.all.log"
|
|
481
|
-
|
|
481
|
+
err_file_handler:
|
|
482
482
|
enabled: true
|
|
483
483
|
h_type: FILE
|
|
484
484
|
sink: "{app_name}.err.log"
|
|
485
485
|
error: true
|
|
486
|
-
|
|
486
|
+
all_json_handler:
|
|
487
487
|
enabled: true
|
|
488
488
|
h_type: FILE
|
|
489
489
|
sink: "json/{app_name}.all.json.log"
|
|
490
490
|
serialize: true
|
|
491
|
-
|
|
491
|
+
err_json_handler:
|
|
492
492
|
enabled: true
|
|
493
493
|
h_type: FILE
|
|
494
494
|
sink: "json/{app_name}.err.json.log"
|
|
495
495
|
serialize: true
|
|
496
496
|
error: true
|
|
497
|
-
|
|
497
|
+
http_access_std_handler:
|
|
498
|
+
enabled: true
|
|
499
|
+
h_type: STD
|
|
500
|
+
format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> ]: <level>{message}</level>"
|
|
501
|
+
colorize: true
|
|
502
|
+
http_access_file_handler:
|
|
498
503
|
enabled: true
|
|
499
504
|
h_type: FILE
|
|
500
505
|
sink: "http/{app_name}.http-access.log"
|
|
501
|
-
|
|
506
|
+
http_err_file_handler:
|
|
502
507
|
enabled: true
|
|
503
508
|
h_type: FILE
|
|
504
509
|
sink: "http/{app_name}.http-err.log"
|
|
505
510
|
error: true
|
|
506
|
-
|
|
511
|
+
http_access_json_handler:
|
|
507
512
|
enabled: true
|
|
508
513
|
h_type: FILE
|
|
509
514
|
sink: "http.json/{app_name}.http-access.json.log"
|
|
510
|
-
|
|
515
|
+
http_err_json_handler:
|
|
511
516
|
enabled: true
|
|
512
517
|
h_type: FILE
|
|
513
518
|
sink: "http.json/{app_name}.http-err.json.log"
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/bybatkhuu/module-fastapi-logging/actions/workflows/2.build-publish.yml)
|
|
5
5
|
[](https://github.com/bybatkhuu/module-fastapi-logging/releases)
|
|
6
6
|
|
|
7
|
-
This is a HTTP access
|
|
7
|
+
This is a HTTP access log module for **FastAPI** based on **'beans-logging'** package.
|
|
8
8
|
|
|
9
9
|
## ✨ Features
|
|
10
10
|
|
|
@@ -348,24 +348,24 @@ uvicorn main:app --host=0.0.0.0 --port=8000
|
|
|
348
348
|
**Output**:
|
|
349
349
|
|
|
350
350
|
```txt
|
|
351
|
-
[2026-01-01 12:00:00.
|
|
352
|
-
[2026-01-01 12:00:00.
|
|
353
|
-
[2026-01-01 12:00:00.
|
|
354
|
-
[2026-01-01 12:00:00.
|
|
355
|
-
[2026-01-01 12:00:00.
|
|
356
|
-
[2026-01-01 12:00:00.
|
|
357
|
-
[2026-01-01 12:00:00.
|
|
358
|
-
[2026-01-01 12:00:00.
|
|
359
|
-
[2026-01-01 12:00:00.
|
|
360
|
-
[2026-01-01 12:00:00.
|
|
361
|
-
[2026-01-01 12:00:01.
|
|
362
|
-
[2026-01-01 12:00:01.
|
|
363
|
-
^C[2026-01-01 12:00:02.
|
|
364
|
-
[2026-01-01 12:00:02.
|
|
365
|
-
[2026-01-01 12:00:02.
|
|
366
|
-
[2026-01-01 12:00:02.
|
|
367
|
-
[2026-01-01 12:00:02.
|
|
368
|
-
[2026-01-01 12:00:02.
|
|
351
|
+
[2026-01-01 12:00:00.002 +09:00 | TRACE | beans_logging.intercepters:96]: Intercepted modules: ['uvicorn', 'potato_util', 'fastapi', 'uvicorn.error', 'watchfiles.watcher', 'concurrent.futures', 'watchfiles', 'asyncio', 'concurrent', 'potato_util._base', 'dotenv', 'dotenv.main', 'watchfiles.main', 'potato_util.io', 'potato_util.io._sync']; Muted modules: ['uvicorn.access'];
|
|
352
|
+
[2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.server:84]: Started server process [88375]
|
|
353
|
+
[2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.lifespan.on:48]: Waiting for application startup.
|
|
354
|
+
[2026-01-01 12:00:00.004 +09:00 | TRACE | lifespan:19]: TRACE diagnosis is ON!
|
|
355
|
+
[2026-01-01 12:00:00.004 +09:00 | DEBUG | lifespan:20]: DEBUG mode is ON!
|
|
356
|
+
[2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:21]: Preparing to startup...
|
|
357
|
+
[2026-01-01 12:00:00.004 +09:00 | OK | lifespan:24]: Finished preparation to startup.
|
|
358
|
+
[2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:25]: Version: 0.0.0
|
|
359
|
+
[2026-01-01 12:00:00.005 +09:00 | INFO | uvicorn.lifespan.on:62]: Application startup complete.
|
|
360
|
+
[2026-01-01 12:00:00.006 +09:00 | INFO | uvicorn.server:216]: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
|
|
361
|
+
[2026-01-01 12:00:01.775 +09:00 | DEBUG ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1"
|
|
362
|
+
[2026-01-01 12:00:01.783 +09:00 | OK ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 5.7ms
|
|
363
|
+
^C[2026-01-01 12:00:02.368 +09:00 | INFO | uvicorn.server:264]: Shutting down
|
|
364
|
+
[2026-01-01 12:00:02.470 +09:00 | INFO | uvicorn.lifespan.on:67]: Waiting for application shutdown.
|
|
365
|
+
[2026-01-01 12:00:02.472 +09:00 | INFO | lifespan:29]: Preparing to shutdown...
|
|
366
|
+
[2026-01-01 12:00:02.472 +09:00 | OK | lifespan:31]: Finished preparation to shutdown.
|
|
367
|
+
[2026-01-01 12:00:02.473 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
|
|
368
|
+
[2026-01-01 12:00:02.474 +09:00 | INFO | uvicorn.server:94]: Finished server process [88375]
|
|
369
369
|
```
|
|
370
370
|
|
|
371
371
|
👍
|
|
@@ -390,12 +390,12 @@ logger:
|
|
|
390
390
|
rotate_time: "00:00:00"
|
|
391
391
|
retention: 90
|
|
392
392
|
encoding: utf8
|
|
393
|
-
|
|
393
|
+
use_custom_serialize: false
|
|
394
394
|
http:
|
|
395
395
|
std:
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
396
|
+
msg_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
|
|
397
|
+
err_msg_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
|
|
398
|
+
debug_msg_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
399
399
|
file:
|
|
400
400
|
format_str: '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
|
|
401
401
|
tz: localtime
|
|
@@ -409,45 +409,50 @@ logger:
|
|
|
409
409
|
include_modules: []
|
|
410
410
|
mute_modules: [uvicorn.access]
|
|
411
411
|
handlers:
|
|
412
|
-
|
|
412
|
+
all_std_handler:
|
|
413
413
|
enabled: true
|
|
414
414
|
h_type: STD
|
|
415
415
|
format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
|
|
416
416
|
colorize: true
|
|
417
|
-
|
|
417
|
+
all_file_handler:
|
|
418
418
|
enabled: true
|
|
419
419
|
h_type: FILE
|
|
420
420
|
sink: "{app_name}.all.log"
|
|
421
|
-
|
|
421
|
+
err_file_handler:
|
|
422
422
|
enabled: true
|
|
423
423
|
h_type: FILE
|
|
424
424
|
sink: "{app_name}.err.log"
|
|
425
425
|
error: true
|
|
426
|
-
|
|
426
|
+
all_json_handler:
|
|
427
427
|
enabled: true
|
|
428
428
|
h_type: FILE
|
|
429
429
|
sink: "json/{app_name}.all.json.log"
|
|
430
430
|
serialize: true
|
|
431
|
-
|
|
431
|
+
err_json_handler:
|
|
432
432
|
enabled: true
|
|
433
433
|
h_type: FILE
|
|
434
434
|
sink: "json/{app_name}.err.json.log"
|
|
435
435
|
serialize: true
|
|
436
436
|
error: true
|
|
437
|
-
|
|
437
|
+
http_access_std_handler:
|
|
438
|
+
enabled: true
|
|
439
|
+
h_type: STD
|
|
440
|
+
format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> ]: <level>{message}</level>"
|
|
441
|
+
colorize: true
|
|
442
|
+
http_access_file_handler:
|
|
438
443
|
enabled: true
|
|
439
444
|
h_type: FILE
|
|
440
445
|
sink: "http/{app_name}.http-access.log"
|
|
441
|
-
|
|
446
|
+
http_err_file_handler:
|
|
442
447
|
enabled: true
|
|
443
448
|
h_type: FILE
|
|
444
449
|
sink: "http/{app_name}.http-err.log"
|
|
445
450
|
error: true
|
|
446
|
-
|
|
451
|
+
http_access_json_handler:
|
|
447
452
|
enabled: true
|
|
448
453
|
h_type: FILE
|
|
449
454
|
sink: "http.json/{app_name}.http-access.json.log"
|
|
450
|
-
|
|
455
|
+
http_err_json_handler:
|
|
451
456
|
enabled: true
|
|
452
457
|
h_type: FILE
|
|
453
458
|
sink: "http.json/{app_name}.http-err.json.log"
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "beans_logging_fastapi"
|
|
7
7
|
authors = [{ name = "Batkhuu Byambajav", email = "batkhuu10@gmail.com" }]
|
|
8
|
-
description = "This is a
|
|
8
|
+
description = "This is a HTTP access log module for FastAPI based on 'beans-logging' package."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10,<4.0"
|
|
11
11
|
keywords = [
|
|
@@ -51,10 +51,6 @@ dev = { file = [
|
|
|
51
51
|
"./requirements/requirements.dev.txt",
|
|
52
52
|
] }
|
|
53
53
|
|
|
54
|
-
# [tool.pyright]
|
|
55
|
-
# venvPath = "."
|
|
56
|
-
# venv = ".venv"
|
|
57
|
-
|
|
58
54
|
[project.urls]
|
|
59
55
|
Homepage = "https://github.com/bybatkhuu/module-fastapi-logging"
|
|
60
56
|
Documentation = "https://fastapi-logging-docs.bybatkhuu.dev"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "4.0.0"
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/_async.py
RENAMED
|
@@ -11,17 +11,17 @@ from beans_logging import logger, Logger
|
|
|
11
11
|
async def async_log_http_error(
|
|
12
12
|
request: Request,
|
|
13
13
|
status_code: int,
|
|
14
|
-
|
|
15
|
-
'<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u>
|
|
16
|
-
'HTTP/{http_version}" <n>{status_code}</n>'
|
|
14
|
+
msg_format_str: str = (
|
|
15
|
+
'<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u>'
|
|
16
|
+
' HTTP/{http_version}" <n>{status_code}</n>'
|
|
17
17
|
),
|
|
18
18
|
) -> None:
|
|
19
19
|
"""Log HTTP error for unhandled Exception.
|
|
20
20
|
|
|
21
21
|
Args:
|
|
22
|
-
request
|
|
23
|
-
status_code
|
|
24
|
-
|
|
22
|
+
request (Request, required): Request instance.
|
|
23
|
+
status_code (int , required): HTTP status code.
|
|
24
|
+
msg_format_str (str , optional): Message format. Defaults to
|
|
25
25
|
'<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"
|
|
26
26
|
<n>{status_code}</n>'.
|
|
27
27
|
"""
|
|
@@ -33,7 +33,7 @@ async def async_log_http_error(
|
|
|
33
33
|
_http_info: dict[str, Any] = request.state.http_info
|
|
34
34
|
_http_info["status_code"] = status_code
|
|
35
35
|
|
|
36
|
-
_msg =
|
|
36
|
+
_msg = msg_format_str.format(**_http_info)
|
|
37
37
|
_logger: Logger = logger.opt(colors=True, record=True).bind(http_info=_http_info)
|
|
38
38
|
await run_in_threadpool(_logger.error, _msg)
|
|
39
39
|
return
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/_core.py
RENAMED
|
@@ -11,14 +11,15 @@ else:
|
|
|
11
11
|
from beans_logging import LoggerLoader
|
|
12
12
|
|
|
13
13
|
from .constants import (
|
|
14
|
+
HTTP_ACCESS_STD_HANDLER_NAME,
|
|
14
15
|
HTTP_ACCESS_FILE_HANDLER_NAME,
|
|
15
16
|
HTTP_ERR_FILE_HANDLER_NAME,
|
|
16
17
|
HTTP_ACCESS_JSON_HANDLER_NAME,
|
|
17
18
|
HTTP_ERR_JSON_HANDLER_NAME,
|
|
18
19
|
)
|
|
19
20
|
from .config import LoggerConfigPM
|
|
20
|
-
from .filters import
|
|
21
|
-
from .formats import http_file_format,
|
|
21
|
+
from .filters import http_std_filter, http_all_file_filter
|
|
22
|
+
from .formats import http_file_format, http_json_format
|
|
22
23
|
from .middlewares import (
|
|
23
24
|
HttpAccessLogMiddleware,
|
|
24
25
|
RequestHTTPInfoMiddleware,
|
|
@@ -56,8 +57,8 @@ def add_logger(
|
|
|
56
57
|
app.add_middleware(ResponseHTTPInfoMiddleware)
|
|
57
58
|
app.add_middleware(
|
|
58
59
|
HttpAccessLogMiddleware,
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
debug_msg_format_str=config.http.std.debug_msg_format_str,
|
|
61
|
+
msg_format_str=config.http.std.msg_format_str,
|
|
61
62
|
)
|
|
62
63
|
app.add_middleware(
|
|
63
64
|
RequestHTTPInfoMiddleware,
|
|
@@ -66,10 +67,12 @@ def add_logger(
|
|
|
66
67
|
)
|
|
67
68
|
|
|
68
69
|
for _name, _handler in logger_loader.config.handlers.items():
|
|
69
|
-
if
|
|
70
|
+
if _name == HTTP_ACCESS_STD_HANDLER_NAME:
|
|
71
|
+
_handler.filter_ = http_std_filter
|
|
72
|
+
elif (_name == HTTP_ACCESS_FILE_HANDLER_NAME) or (
|
|
70
73
|
_name == HTTP_ERR_FILE_HANDLER_NAME
|
|
71
74
|
):
|
|
72
|
-
_handler.filter_ =
|
|
75
|
+
_handler.filter_ = http_all_file_filter
|
|
73
76
|
_handler.format_ = lambda record: http_file_format(
|
|
74
77
|
record=record,
|
|
75
78
|
format_str=config.http.file.format_str,
|
|
@@ -78,8 +81,8 @@ def add_logger(
|
|
|
78
81
|
elif (_name == HTTP_ACCESS_JSON_HANDLER_NAME) or (
|
|
79
82
|
_name == HTTP_ERR_JSON_HANDLER_NAME
|
|
80
83
|
):
|
|
81
|
-
_handler.filter_ =
|
|
82
|
-
_handler.format_ =
|
|
84
|
+
_handler.filter_ = http_all_file_filter
|
|
85
|
+
_handler.format_ = http_json_format
|
|
83
86
|
|
|
84
87
|
logger: Logger = logger_loader.load()
|
|
85
88
|
return logger
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/config.py
RENAMED
|
@@ -3,7 +3,7 @@ from typing import Any
|
|
|
3
3
|
import potato_util as utils
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
|
-
from beans_logging.constants import LogHandlerTypeEnum
|
|
6
|
+
from beans_logging.constants import LogHandlerTypeEnum, DEFAULT_HANDLER_NAMES
|
|
7
7
|
from beans_logging.schemas import LogHandlerPM
|
|
8
8
|
from beans_logging.config import (
|
|
9
9
|
get_default_handlers as get_base_handlers,
|
|
@@ -13,6 +13,7 @@ from beans_logging.config import (
|
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
from .constants import (
|
|
16
|
+
HTTP_ACCESS_STD_HANDLER_NAME,
|
|
16
17
|
HTTP_ACCESS_FILE_HANDLER_NAME,
|
|
17
18
|
HTTP_ERR_FILE_HANDLER_NAME,
|
|
18
19
|
HTTP_ACCESS_JSON_HANDLER_NAME,
|
|
@@ -29,10 +30,18 @@ def get_default_handlers() -> dict[str, LogHandlerPM]:
|
|
|
29
30
|
|
|
30
31
|
_base_handlers = get_base_handlers()
|
|
31
32
|
for _name, _handler in _base_handlers.items():
|
|
32
|
-
if _name
|
|
33
|
+
if _name in DEFAULT_HANDLER_NAMES:
|
|
33
34
|
_handler.enabled = True
|
|
34
35
|
|
|
35
36
|
_http_handlers: dict[str, LogHandlerPM] = {
|
|
37
|
+
HTTP_ACCESS_STD_HANDLER_NAME: LogHandlerPM(
|
|
38
|
+
h_type=LogHandlerTypeEnum.STD,
|
|
39
|
+
format_=(
|
|
40
|
+
"[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> ]:"
|
|
41
|
+
" <level>{message}</level>"
|
|
42
|
+
),
|
|
43
|
+
colorize=True,
|
|
44
|
+
),
|
|
36
45
|
HTTP_ACCESS_FILE_HANDLER_NAME: LogHandlerPM(
|
|
37
46
|
h_type=LogHandlerTypeEnum.FILE,
|
|
38
47
|
sink="http/{app_name}.http-access.log",
|
|
@@ -63,7 +72,7 @@ def get_default_intercept() -> InterceptConfigPM:
|
|
|
63
72
|
|
|
64
73
|
|
|
65
74
|
class StdConfigPM(ExtraBaseModel):
|
|
66
|
-
|
|
75
|
+
msg_format_str: str = Field(
|
|
67
76
|
default=(
|
|
68
77
|
'<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
69
78
|
" {status_code} {content_length}B {response_time}ms"
|
|
@@ -71,7 +80,7 @@ class StdConfigPM(ExtraBaseModel):
|
|
|
71
80
|
min_length=8,
|
|
72
81
|
max_length=512,
|
|
73
82
|
)
|
|
74
|
-
|
|
83
|
+
err_msg_format_str: str = Field(
|
|
75
84
|
default=(
|
|
76
85
|
'<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
77
86
|
" <n>{status_code}</n>"
|
|
@@ -79,7 +88,7 @@ class StdConfigPM(ExtraBaseModel):
|
|
|
79
88
|
min_length=8,
|
|
80
89
|
max_length=512,
|
|
81
90
|
)
|
|
82
|
-
|
|
91
|
+
debug_msg_format_str: str = Field(
|
|
83
92
|
default='<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"',
|
|
84
93
|
min_length=8,
|
|
85
94
|
max_length=512,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
HTTP_ACCESS_STD_HANDLER_NAME = "http_access_std_handler"
|
|
2
|
+
HTTP_ACCESS_FILE_HANDLER_NAME = "http_access_file_handler"
|
|
3
|
+
HTTP_ERR_FILE_HANDLER_NAME = "http_err_file_handler"
|
|
4
|
+
HTTP_ACCESS_JSON_HANDLER_NAME = "http_access_json_handler"
|
|
5
|
+
HTTP_ERR_JSON_HANDLER_NAME = "http_err_json_handler"
|
|
6
|
+
|
|
7
|
+
HTTP_HANDLER_NAMES = [
|
|
8
|
+
HTTP_ACCESS_STD_HANDLER_NAME,
|
|
9
|
+
HTTP_ACCESS_FILE_HANDLER_NAME,
|
|
10
|
+
HTTP_ERR_FILE_HANDLER_NAME,
|
|
11
|
+
HTTP_ACCESS_JSON_HANDLER_NAME,
|
|
12
|
+
HTTP_ERR_JSON_HANDLER_NAME,
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"HTTP_ACCESS_STD_HANDLER_NAME",
|
|
18
|
+
"HTTP_ACCESS_FILE_HANDLER_NAME",
|
|
19
|
+
"HTTP_ERR_FILE_HANDLER_NAME",
|
|
20
|
+
"HTTP_ACCESS_JSON_HANDLER_NAME",
|
|
21
|
+
"HTTP_ERR_JSON_HANDLER_NAME",
|
|
22
|
+
"HTTP_HANDLER_NAMES",
|
|
23
|
+
]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from loguru import Record
|
|
5
|
+
|
|
6
|
+
from beans_logging.filters import all_handlers_filter
|
|
7
|
+
|
|
8
|
+
from .constants import HTTP_ACCESS_STD_HANDLER_NAME
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def http_filter(record: "Record") -> bool:
|
|
12
|
+
"""Filter message only for http access log handler by checking 'http_info' key in extra.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
record (Record, required): Log record as dictionary.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
bool: True if record has 'http_info' key in extra, False otherwise.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
if not all_handlers_filter(record):
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
if "http_info" not in record["extra"]:
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
return True
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def http_std_filter(record: "Record") -> bool:
|
|
31
|
+
"""Filter message only for http std log handler.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
record (Record, required): Log record as dictionary.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
bool: True if record does not have 'disable_{HTTP_ACCESS_STD_HANDLER_NAME}' key in extra, False otherwise.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
if not http_filter(record):
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
if record["extra"].get(f"disable_{HTTP_ACCESS_STD_HANDLER_NAME}", False):
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def http_all_file_filter(record: "Record") -> bool:
|
|
50
|
+
"""Filter message only for http file log handler.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
record (Record, required): Log record as dictionary.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
bool: True if record does not have 'disable_http_all_file_handlers' key in extra, False otherwise.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
if not http_filter(record):
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
if record["extra"].get("disable_http_all_file_handlers", False):
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
return True
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
__all__ = [
|
|
69
|
+
"http_filter",
|
|
70
|
+
"http_std_filter",
|
|
71
|
+
"http_all_file_filter",
|
|
72
|
+
]
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/formats.py
RENAMED
|
@@ -62,7 +62,7 @@ def http_file_format(
|
|
|
62
62
|
return "{extra[http_message]}\n"
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def
|
|
65
|
+
def http_json_format(record: "Record") -> str:
|
|
66
66
|
"""Http access json log file format.
|
|
67
67
|
|
|
68
68
|
Args:
|
|
@@ -91,5 +91,5 @@ def http_file_json_format(record: "Record") -> str:
|
|
|
91
91
|
|
|
92
92
|
__all__ = [
|
|
93
93
|
"http_file_format",
|
|
94
|
-
"
|
|
94
|
+
"http_json_format",
|
|
95
95
|
]
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/middlewares.py
RENAMED
|
@@ -235,20 +235,24 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware):
|
|
|
235
235
|
BaseHTTPMiddleware: Base HTTP middleware class from starlette.
|
|
236
236
|
|
|
237
237
|
Attributes:
|
|
238
|
-
|
|
238
|
+
_DEBUG_MSG_FORMAT_STR (str ): Default http access log debug message format. Defaults to
|
|
239
239
|
'<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'.
|
|
240
|
-
|
|
240
|
+
_MSG_FORMAT_STR (str ): Default http access log message format. Defaults to
|
|
241
241
|
'<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"
|
|
242
242
|
{status_code} {content_length}B {response_time}ms'.
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
debug_msg_format_str (str ): Http access log debug message format.
|
|
245
|
+
Defaults to `HttpAccessLogMiddleware._DEBUG_MSG_FORMAT_STR`.
|
|
246
|
+
msg_format_str (str ): Http access log message format.
|
|
247
|
+
Defaults to `HttpAccessLogMiddleware._MSG_FORMAT_STR`.
|
|
248
|
+
use_debug_log (bool): If True, use debug log to log http access log. Defaults to True.
|
|
248
249
|
"""
|
|
249
250
|
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
_DEBUG_MSG_FORMAT_STR = (
|
|
252
|
+
'<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u>'
|
|
253
|
+
' HTTP/{http_version}"'
|
|
254
|
+
)
|
|
255
|
+
_MSG_FORMAT_STR = (
|
|
252
256
|
'<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
253
257
|
" {status_code} {content_length}B {response_time}ms"
|
|
254
258
|
)
|
|
@@ -256,17 +260,19 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware):
|
|
|
256
260
|
def __init__(
|
|
257
261
|
self,
|
|
258
262
|
app,
|
|
259
|
-
|
|
260
|
-
|
|
263
|
+
debug_msg_format_str: str = _DEBUG_MSG_FORMAT_STR,
|
|
264
|
+
msg_format_str: str = _MSG_FORMAT_STR,
|
|
261
265
|
use_debug_log: bool = True,
|
|
262
266
|
):
|
|
263
267
|
super().__init__(app)
|
|
264
|
-
self.
|
|
265
|
-
self.
|
|
268
|
+
self.debug_msg_format_str = debug_msg_format_str
|
|
269
|
+
self.msg_format_str = msg_format_str
|
|
266
270
|
self.use_debug_log = use_debug_log
|
|
267
271
|
|
|
268
272
|
async def dispatch(self, request: Request, call_next) -> Response:
|
|
269
|
-
_logger = logger.opt(colors=True, record=True)
|
|
273
|
+
_logger = logger.opt(colors=True, record=True).bind(
|
|
274
|
+
disable_all_std_handler=True
|
|
275
|
+
)
|
|
270
276
|
|
|
271
277
|
_http_info: dict[str, Any] = {}
|
|
272
278
|
if hasattr(request.state, "http_info") and isinstance(
|
|
@@ -276,11 +282,15 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware):
|
|
|
276
282
|
|
|
277
283
|
# Debug log:
|
|
278
284
|
if self.use_debug_log:
|
|
279
|
-
_debug_msg = self.
|
|
285
|
+
_debug_msg = self.debug_msg_format_str.format(**_http_info)
|
|
280
286
|
|
|
281
|
-
# _logger.
|
|
287
|
+
# _logger.bind(
|
|
288
|
+
# http_info=_http_info, disable_http_all_file_handlers=True
|
|
289
|
+
# ).debug(_debug_msg)
|
|
282
290
|
await run_in_threadpool(
|
|
283
|
-
_logger.
|
|
291
|
+
_logger.bind(
|
|
292
|
+
http_info=_http_info, disable_http_all_file_handlers=True
|
|
293
|
+
).debug,
|
|
284
294
|
_debug_msg,
|
|
285
295
|
)
|
|
286
296
|
# Debug log
|
|
@@ -296,26 +306,28 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware):
|
|
|
296
306
|
|
|
297
307
|
# Http access log:
|
|
298
308
|
_LEVEL = "INFO"
|
|
299
|
-
|
|
309
|
+
_msg_format_str = self.msg_format_str
|
|
300
310
|
if _http_info["status_code"] < 200:
|
|
301
311
|
_LEVEL = "DEBUG"
|
|
302
|
-
|
|
312
|
+
_msg_format_str = f'<d>{_msg_format_str.replace("{status_code}", "<n><b><k>{status_code}</k></b></n>")}</d>'
|
|
303
313
|
elif (200 <= _http_info["status_code"]) and (_http_info["status_code"] < 300):
|
|
304
314
|
_LEVEL = "SUCCESS"
|
|
305
|
-
|
|
315
|
+
_msg_format_str = f'<w>{_msg_format_str.replace("{status_code}", "<lvl>{status_code}</lvl>")}</w>'
|
|
306
316
|
elif (300 <= _http_info["status_code"]) and (_http_info["status_code"] < 400):
|
|
307
317
|
_LEVEL = "INFO"
|
|
308
|
-
|
|
318
|
+
_msg_format_str = f'<d>{_msg_format_str.replace("{status_code}", "<n><b><c>{status_code}</c></b></n>")}</d>'
|
|
309
319
|
elif (400 <= _http_info["status_code"]) and (_http_info["status_code"] < 500):
|
|
310
320
|
_LEVEL = "WARNING"
|
|
311
|
-
|
|
321
|
+
_msg_format_str = _msg_format_str.replace(
|
|
322
|
+
"{status_code}", "<r>{status_code}</r>"
|
|
323
|
+
)
|
|
312
324
|
elif 500 <= _http_info["status_code"]:
|
|
313
325
|
_LEVEL = "ERROR"
|
|
314
|
-
|
|
315
|
-
f'{
|
|
326
|
+
_msg_format_str = (
|
|
327
|
+
f'{_msg_format_str.replace("{status_code}", "<n>{status_code}</n>")}'
|
|
316
328
|
)
|
|
317
329
|
|
|
318
|
-
_msg =
|
|
330
|
+
_msg = _msg_format_str.format(**_http_info)
|
|
319
331
|
# _logger.bind(http_info=_http_info).log(_LEVEL, _msg)
|
|
320
332
|
await run_in_threadpool(_logger.bind(http_info=_http_info).log, _LEVEL, _msg)
|
|
321
333
|
# Http access log
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: beans_logging_fastapi
|
|
3
|
-
Version:
|
|
4
|
-
Summary: This is a
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: This is a HTTP access log module for FastAPI based on 'beans-logging' package.
|
|
5
5
|
Author-email: Batkhuu Byambajav <batkhuu10@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/bybatkhuu/module-fastapi-logging
|
|
7
7
|
Project-URL: Documentation, https://fastapi-logging-docs.bybatkhuu.dev
|
|
@@ -22,7 +22,7 @@ Requires-Python: <4.0,>=3.10
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE.txt
|
|
24
24
|
Requires-Dist: fastapi<1.0.0,>=0.99.1
|
|
25
|
-
Requires-Dist: beans-logging<
|
|
25
|
+
Requires-Dist: beans-logging<10.0.0,>=9.0.0
|
|
26
26
|
Provides-Extra: test
|
|
27
27
|
Requires-Dist: pytest<10.0.0,>=8.0.2; extra == "test"
|
|
28
28
|
Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "test"
|
|
@@ -55,7 +55,7 @@ Requires-Dist: mkdocstrings[python]<2.0.0,>=0.24.3; extra == "dev"
|
|
|
55
55
|
Requires-Dist: mike<3.0.0,>=2.1.3; extra == "dev"
|
|
56
56
|
Requires-Dist: pyright<2.0.0,>=1.1.392; extra == "dev"
|
|
57
57
|
Requires-Dist: pre-commit<5.0.0,>=4.0.1; extra == "dev"
|
|
58
|
-
Requires-Dist:
|
|
58
|
+
Requires-Dist: fastapi[standard]<1.0.0,>=0.99.1; extra == "dev"
|
|
59
59
|
Dynamic: license-file
|
|
60
60
|
|
|
61
61
|
# FastAPI Logging (beans-logging-fastapi)
|
|
@@ -64,7 +64,7 @@ Dynamic: license-file
|
|
|
64
64
|
[](https://github.com/bybatkhuu/module-fastapi-logging/actions/workflows/2.build-publish.yml)
|
|
65
65
|
[](https://github.com/bybatkhuu/module-fastapi-logging/releases)
|
|
66
66
|
|
|
67
|
-
This is a HTTP access
|
|
67
|
+
This is a HTTP access log module for **FastAPI** based on **'beans-logging'** package.
|
|
68
68
|
|
|
69
69
|
## ✨ Features
|
|
70
70
|
|
|
@@ -408,24 +408,24 @@ uvicorn main:app --host=0.0.0.0 --port=8000
|
|
|
408
408
|
**Output**:
|
|
409
409
|
|
|
410
410
|
```txt
|
|
411
|
-
[2026-01-01 12:00:00.
|
|
412
|
-
[2026-01-01 12:00:00.
|
|
413
|
-
[2026-01-01 12:00:00.
|
|
414
|
-
[2026-01-01 12:00:00.
|
|
415
|
-
[2026-01-01 12:00:00.
|
|
416
|
-
[2026-01-01 12:00:00.
|
|
417
|
-
[2026-01-01 12:00:00.
|
|
418
|
-
[2026-01-01 12:00:00.
|
|
419
|
-
[2026-01-01 12:00:00.
|
|
420
|
-
[2026-01-01 12:00:00.
|
|
421
|
-
[2026-01-01 12:00:01.
|
|
422
|
-
[2026-01-01 12:00:01.
|
|
423
|
-
^C[2026-01-01 12:00:02.
|
|
424
|
-
[2026-01-01 12:00:02.
|
|
425
|
-
[2026-01-01 12:00:02.
|
|
426
|
-
[2026-01-01 12:00:02.
|
|
427
|
-
[2026-01-01 12:00:02.
|
|
428
|
-
[2026-01-01 12:00:02.
|
|
411
|
+
[2026-01-01 12:00:00.002 +09:00 | TRACE | beans_logging.intercepters:96]: Intercepted modules: ['uvicorn', 'potato_util', 'fastapi', 'uvicorn.error', 'watchfiles.watcher', 'concurrent.futures', 'watchfiles', 'asyncio', 'concurrent', 'potato_util._base', 'dotenv', 'dotenv.main', 'watchfiles.main', 'potato_util.io', 'potato_util.io._sync']; Muted modules: ['uvicorn.access'];
|
|
412
|
+
[2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.server:84]: Started server process [88375]
|
|
413
|
+
[2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.lifespan.on:48]: Waiting for application startup.
|
|
414
|
+
[2026-01-01 12:00:00.004 +09:00 | TRACE | lifespan:19]: TRACE diagnosis is ON!
|
|
415
|
+
[2026-01-01 12:00:00.004 +09:00 | DEBUG | lifespan:20]: DEBUG mode is ON!
|
|
416
|
+
[2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:21]: Preparing to startup...
|
|
417
|
+
[2026-01-01 12:00:00.004 +09:00 | OK | lifespan:24]: Finished preparation to startup.
|
|
418
|
+
[2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:25]: Version: 0.0.0
|
|
419
|
+
[2026-01-01 12:00:00.005 +09:00 | INFO | uvicorn.lifespan.on:62]: Application startup complete.
|
|
420
|
+
[2026-01-01 12:00:00.006 +09:00 | INFO | uvicorn.server:216]: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
|
|
421
|
+
[2026-01-01 12:00:01.775 +09:00 | DEBUG ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1"
|
|
422
|
+
[2026-01-01 12:00:01.783 +09:00 | OK ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 5.7ms
|
|
423
|
+
^C[2026-01-01 12:00:02.368 +09:00 | INFO | uvicorn.server:264]: Shutting down
|
|
424
|
+
[2026-01-01 12:00:02.470 +09:00 | INFO | uvicorn.lifespan.on:67]: Waiting for application shutdown.
|
|
425
|
+
[2026-01-01 12:00:02.472 +09:00 | INFO | lifespan:29]: Preparing to shutdown...
|
|
426
|
+
[2026-01-01 12:00:02.472 +09:00 | OK | lifespan:31]: Finished preparation to shutdown.
|
|
427
|
+
[2026-01-01 12:00:02.473 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
|
|
428
|
+
[2026-01-01 12:00:02.474 +09:00 | INFO | uvicorn.server:94]: Finished server process [88375]
|
|
429
429
|
```
|
|
430
430
|
|
|
431
431
|
👍
|
|
@@ -450,12 +450,12 @@ logger:
|
|
|
450
450
|
rotate_time: "00:00:00"
|
|
451
451
|
retention: 90
|
|
452
452
|
encoding: utf8
|
|
453
|
-
|
|
453
|
+
use_custom_serialize: false
|
|
454
454
|
http:
|
|
455
455
|
std:
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
456
|
+
msg_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
|
|
457
|
+
err_msg_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
|
|
458
|
+
debug_msg_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
459
459
|
file:
|
|
460
460
|
format_str: '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
|
|
461
461
|
tz: localtime
|
|
@@ -469,45 +469,50 @@ logger:
|
|
|
469
469
|
include_modules: []
|
|
470
470
|
mute_modules: [uvicorn.access]
|
|
471
471
|
handlers:
|
|
472
|
-
|
|
472
|
+
all_std_handler:
|
|
473
473
|
enabled: true
|
|
474
474
|
h_type: STD
|
|
475
475
|
format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
|
|
476
476
|
colorize: true
|
|
477
|
-
|
|
477
|
+
all_file_handler:
|
|
478
478
|
enabled: true
|
|
479
479
|
h_type: FILE
|
|
480
480
|
sink: "{app_name}.all.log"
|
|
481
|
-
|
|
481
|
+
err_file_handler:
|
|
482
482
|
enabled: true
|
|
483
483
|
h_type: FILE
|
|
484
484
|
sink: "{app_name}.err.log"
|
|
485
485
|
error: true
|
|
486
|
-
|
|
486
|
+
all_json_handler:
|
|
487
487
|
enabled: true
|
|
488
488
|
h_type: FILE
|
|
489
489
|
sink: "json/{app_name}.all.json.log"
|
|
490
490
|
serialize: true
|
|
491
|
-
|
|
491
|
+
err_json_handler:
|
|
492
492
|
enabled: true
|
|
493
493
|
h_type: FILE
|
|
494
494
|
sink: "json/{app_name}.err.json.log"
|
|
495
495
|
serialize: true
|
|
496
496
|
error: true
|
|
497
|
-
|
|
497
|
+
http_access_std_handler:
|
|
498
|
+
enabled: true
|
|
499
|
+
h_type: STD
|
|
500
|
+
format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> ]: <level>{message}</level>"
|
|
501
|
+
colorize: true
|
|
502
|
+
http_access_file_handler:
|
|
498
503
|
enabled: true
|
|
499
504
|
h_type: FILE
|
|
500
505
|
sink: "http/{app_name}.http-access.log"
|
|
501
|
-
|
|
506
|
+
http_err_file_handler:
|
|
502
507
|
enabled: true
|
|
503
508
|
h_type: FILE
|
|
504
509
|
sink: "http/{app_name}.http-err.log"
|
|
505
510
|
error: true
|
|
506
|
-
|
|
511
|
+
http_access_json_handler:
|
|
507
512
|
enabled: true
|
|
508
513
|
h_type: FILE
|
|
509
514
|
sink: "http.json/{app_name}.http-access.json.log"
|
|
510
|
-
|
|
515
|
+
http_err_json_handler:
|
|
511
516
|
enabled: true
|
|
512
517
|
h_type: FILE
|
|
513
518
|
sink: "http.json/{app_name}.http-err.json.log"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
fastapi<1.0.0,>=0.99.1
|
|
2
|
-
beans-logging<
|
|
2
|
+
beans-logging<10.0.0,>=9.0.0
|
|
3
3
|
|
|
4
4
|
[build]
|
|
5
5
|
setuptools<81.0.0,>=70.3.0
|
|
@@ -23,7 +23,7 @@ mkdocstrings[python]<2.0.0,>=0.24.3
|
|
|
23
23
|
mike<3.0.0,>=2.1.3
|
|
24
24
|
pyright<2.0.0,>=1.1.392
|
|
25
25
|
pre-commit<5.0.0,>=4.0.1
|
|
26
|
-
|
|
26
|
+
fastapi[standard]<1.0.0,>=0.99.1
|
|
27
27
|
|
|
28
28
|
[docs]
|
|
29
29
|
pylint<5.0.0,>=3.0.4
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.0.0"
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
HTTP_ACCESS_FILE_HANDLER_NAME = "http.access.file_handler"
|
|
2
|
-
HTTP_ERR_FILE_HANDLER_NAME = "http.err.file_handler"
|
|
3
|
-
HTTP_ACCESS_JSON_HANDLER_NAME = "http.access.json_handler"
|
|
4
|
-
HTTP_ERR_JSON_HANDLER_NAME = "http.err.json_handler"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
__all__ = [
|
|
8
|
-
"HTTP_ACCESS_FILE_HANDLER_NAME",
|
|
9
|
-
"HTTP_ERR_FILE_HANDLER_NAME",
|
|
10
|
-
"HTTP_ACCESS_JSON_HANDLER_NAME",
|
|
11
|
-
"HTTP_ERR_JSON_HANDLER_NAME",
|
|
12
|
-
]
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING
|
|
2
|
-
|
|
3
|
-
if TYPE_CHECKING:
|
|
4
|
-
from loguru import Record
|
|
5
|
-
|
|
6
|
-
from beans_logging.filters import use_all_filter
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def use_http_filter(record: "Record") -> bool:
|
|
10
|
-
"""Filter message only for http access log handler by checking 'http_info' key in extra.
|
|
11
|
-
|
|
12
|
-
Args:
|
|
13
|
-
record (Record, required): Log record as dictionary.
|
|
14
|
-
|
|
15
|
-
Returns:
|
|
16
|
-
bool: True if record has 'http_info' key in extra, False otherwise.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
if not use_all_filter(record):
|
|
20
|
-
return False
|
|
21
|
-
|
|
22
|
-
if "http_info" not in record["extra"]:
|
|
23
|
-
return False
|
|
24
|
-
|
|
25
|
-
return True
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
__all__ = [
|
|
29
|
-
"use_http_filter",
|
|
30
|
-
]
|
|
File without changes
|
|
File without changes
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/requirements/requirements.build.txt
RENAMED
|
File without changes
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/requirements/requirements.docs.txt
RENAMED
|
File without changes
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/requirements/requirements.test.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beans_logging_fastapi-3.0.0 → beans_logging_fastapi-4.0.0}/src/beans_logging_fastapi/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|