beans-logging-fastapi 6.0.4__tar.gz → 8.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.
Files changed (30) hide show
  1. {beans_logging_fastapi-6.0.4/src/beans_logging_fastapi.egg-info → beans_logging_fastapi-8.0.0}/PKG-INFO +59 -53
  2. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/README.md +57 -51
  3. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/pyproject.toml +1 -1
  4. beans_logging_fastapi-8.0.0/requirements.txt +2 -0
  5. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/__init__.py +2 -1
  6. beans_logging_fastapi-8.0.0/src/beans_logging_fastapi/__version__.py +1 -0
  7. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/_core.py +3 -3
  8. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/config.py +46 -30
  9. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/formats.py +59 -7
  10. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/http_error.py +20 -20
  11. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/middlewares.py +46 -34
  12. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/mode.py +14 -2
  13. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0/src/beans_logging_fastapi.egg-info}/PKG-INFO +59 -53
  14. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi.egg-info/requires.txt +1 -1
  15. beans_logging_fastapi-6.0.4/requirements.txt +0 -2
  16. beans_logging_fastapi-6.0.4/src/beans_logging_fastapi/__version__.py +0 -1
  17. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/.python-version +0 -0
  18. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/LICENSE.txt +0 -0
  19. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/requirements/requirements.build.txt +0 -0
  20. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/requirements/requirements.dev.txt +0 -0
  21. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/requirements/requirements.docs.txt +0 -0
  22. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/requirements/requirements.test.txt +0 -0
  23. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/setup.cfg +0 -0
  24. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/setup.py +0 -0
  25. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/_async.py +0 -0
  26. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/constants.py +0 -0
  27. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/filters.py +0 -0
  28. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi.egg-info/SOURCES.txt +0 -0
  29. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi.egg-info/dependency_links.txt +0 -0
  30. {beans_logging_fastapi-6.0.4 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beans_logging_fastapi
3
- Version: 6.0.4
3
+ Version: 8.0.0
4
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
@@ -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<12.0.0,>=11.0.2
25
+ Requires-Dist: beans-logging<13.0.0,>=12.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"
@@ -171,30 +171,28 @@ logger:
171
171
  level:
172
172
  base: TRACE
173
173
  http:
174
- std:
175
- 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'
176
- err_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
177
- debug_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
178
- file:
179
- 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}'
180
- tz: "localtime"
181
- has_proxy_headers: true
182
- has_cf_headers: true
174
+ has_proxy_headers: false
175
+ has_cf_headers: false
183
176
  intercept:
184
177
  mute_modules: ["uvicorn.access"]
185
178
  handlers:
186
- http.access.file_handler:
179
+ std_handler:
180
+ enabled: true
181
+ http_access_std_handler:
182
+ enabled: true
183
+ http_access_file_handler:
187
184
  enabled: true
188
185
  sink: "http/{app_name}.http-access.log"
189
- http.err.file_handler:
186
+ http_err_file_handler:
190
187
  enabled: true
191
188
  sink: "http/{app_name}.http-err.log"
192
- http.access.json_handler:
189
+ http_access_json_handler:
193
190
  enabled: true
194
191
  sink: "http.json/{app_name}.http-access.json.log"
195
- http.err.json_handler:
192
+ http_err_json_handler:
196
193
  enabled: true
197
194
  sink: "http.json/{app_name}.http-err.json.log"
195
+
198
196
  ```
199
197
 
200
198
  [**`.env`**](./examples/.env):
@@ -248,14 +246,17 @@ __all__ = [
248
246
 
249
247
  ```python
250
248
  from pydantic import validate_call
251
- from fastapi import FastAPI, APIRouter, HTTPException
249
+ from fastapi import FastAPI, APIRouter, HTTPException, Request
252
250
  from fastapi.responses import RedirectResponse
253
251
 
254
252
  router = APIRouter()
255
253
 
256
254
 
257
255
  @router.get("/")
258
- def root():
256
+ def root(request: Request):
257
+ _logger = request.state.logger
258
+ _logger.info("Root endpoint accessed.")
259
+
259
260
  return {"Hello": "World"}
260
261
 
261
262
 
@@ -410,24 +411,25 @@ uvicorn main:app --host=0.0.0.0 --port=8000
410
411
  **Output**:
411
412
 
412
413
  ```txt
413
- [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'];
414
- [2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.server:84]: Started server process [88375]
415
- [2026-01-01 12:00:00.003 +09:00 | INFO | uvicorn.lifespan.on:48]: Waiting for application startup.
416
- [2026-01-01 12:00:00.004 +09:00 | TRACE | lifespan:19]: TRACE diagnosis is ON!
417
- [2026-01-01 12:00:00.004 +09:00 | DEBUG | lifespan:20]: DEBUG mode is ON!
418
- [2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:21]: Preparing to startup...
419
- [2026-01-01 12:00:00.004 +09:00 | OK | lifespan:24]: Finished preparation to startup.
420
- [2026-01-01 12:00:00.004 +09:00 | INFO | lifespan:25]: Version: 0.0.0
421
- [2026-01-01 12:00:00.005 +09:00 | INFO | uvicorn.lifespan.on:62]: Application startup complete.
422
- [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)
423
- [2026-01-01 12:00:01.775 +09:00 | DEBUG ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1"
424
- [2026-01-01 12:00:01.783 +09:00 | OK ]: [80138308bc00406387fb804cf6cc0e11] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 5.7ms
425
- ^C[2026-01-01 12:00:02.368 +09:00 | INFO | uvicorn.server:264]: Shutting down
426
- [2026-01-01 12:00:02.470 +09:00 | INFO | uvicorn.lifespan.on:67]: Waiting for application shutdown.
427
- [2026-01-01 12:00:02.472 +09:00 | INFO | lifespan:29]: Preparing to shutdown...
428
- [2026-01-01 12:00:02.472 +09:00 | OK | lifespan:31]: Finished preparation to shutdown.
429
- [2026-01-01 12:00:02.473 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
430
- [2026-01-01 12:00:02.474 +09:00 | INFO | uvicorn.server:94]: Finished server process [88375]
414
+ [2026-06-05 00:55:29.335 +09:00 | TRACE | - | beans_logging.intercepters:96]: Intercepted modules: ['potato_util', 'dotenv.main', 'concurrent', 'potato_util.io', 'asyncio', 'fastapi', 'concurrent.futures', 'dotenv', 'uvicorn', 'watchfiles.watcher', 'potato_util.io._sync', 'watchfiles.main', 'potato_util._base', 'uvicorn.error', 'watchfiles']; Muted modules: ['uvicorn.access'];
415
+ [2026-06-05 00:55:29.336 +09:00 | INFO | - | uvicorn.server:84]: Started server process [95017]
416
+ [2026-06-05 00:55:29.336 +09:00 | INFO | - | uvicorn.lifespan.on:48]: Waiting for application startup.
417
+ [2026-06-05 00:55:29.337 +09:00 | TRACE | - | lifespan:19]: TRACE diagnosis is ON!
418
+ [2026-06-05 00:55:29.337 +09:00 | DEBUG | - | lifespan:20]: DEBUG mode is ON!
419
+ [2026-06-05 00:55:29.337 +09:00 | INFO | - | lifespan:21]: Preparing to startup...
420
+ [2026-06-05 00:55:29.337 +09:00 | OK | - | lifespan:24]: Finished preparation to startup.
421
+ [2026-06-05 00:55:29.337 +09:00 | INFO | - | lifespan:25]: Version: 0.0.0
422
+ [2026-06-05 00:55:29.337 +09:00 | INFO | - | uvicorn.lifespan.on:62]: Application startup complete.
423
+ [2026-06-05 00:55:29.339 +09:00 | INFO | - | uvicorn.server:216]: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
424
+ [2026-06-05 00:55:33.367 +09:00 | DEBUG | 58c916d045844314bb6c10b390ad5593]: 127.0.0.1 - "GET / HTTP/1.1"
425
+ [2026-06-05 00:55:33.370 +09:00 | INFO | 58c916d045844314bb6c10b390ad5593 | router:11]: Root endpoint accessed.
426
+ [2026-06-05 00:55:33.371 +09:00 | OK | 58c916d045844314bb6c10b390ad5593]: 127.0.0.1 - "GET / HTTP/1.1" 200 17B 3.0ms
427
+ ^C[2026-06-05 00:55:35.702 +09:00 | INFO | - | uvicorn.server:264]: Shutting down
428
+ [2026-06-05 00:55:35.805 +09:00 | INFO | - | uvicorn.lifespan.on:67]: Waiting for application shutdown.
429
+ [2026-06-05 00:55:35.805 +09:00 | INFO | - | lifespan:29]: Preparing to shutdown...
430
+ [2026-06-05 00:55:35.805 +09:00 | OK | - | lifespan:31]: Finished preparation to shutdown.
431
+ [2026-06-05 00:55:35.805 +09:00 | INFO | - | uvicorn.lifespan.on:76]: Application shutdown complete.
432
+ [2026-06-05 00:55:35.806 +09:00 | INFO | - | uvicorn.server:94]: Finished server process [95017]
431
433
  ```
432
434
 
433
435
  👍
@@ -444,21 +446,21 @@ logger:
444
446
  level:
445
447
  base: INFO
446
448
  err: WARNING
447
- format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line}]: {message}"
449
+ default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} {extra[request_id]}]: {message}"
448
450
  file:
449
451
  logs_dir: "./logs"
450
452
  rotate_size: 10000000
451
453
  rotate_time: "00:00:00"
452
454
  retention: 90
453
455
  encoding: utf8
454
- use_custom_serialize: false
456
+ custom_serialize: false
455
457
  http:
456
458
  std:
457
- 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'
458
- 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>'
459
- debug_msg_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
459
+ sub_format: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
460
+ err_sub_format: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
461
+ debug_sub_format: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
460
462
  file:
461
- 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}'
463
+ format_: '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
462
464
  tz: localtime
463
465
  has_proxy_headers: true
464
466
  has_cf_headers: true
@@ -468,53 +470,57 @@ logger:
468
470
  ignore_modules: []
469
471
  include_modules: []
470
472
  mute_modules: [uvicorn.access]
473
+ global_extra:
474
+ trace_id: ""
475
+ request_id: ""
476
+ user_id: ""
471
477
  handlers:
472
478
  std_handler:
473
479
  enabled: true
474
- h_type: STD
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>"
480
+ type_: STD
481
+ format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w> <d><w>{extra[request_id]}</w></d>]: <level>{message}</level>"
476
482
  colorize: true
477
483
  file_handler:
478
484
  enabled: true
479
- h_type: FILE
485
+ type_: FILE
480
486
  sink: "{app_name}.all.log"
481
487
  err_file_handler:
482
488
  enabled: true
483
- h_type: FILE
489
+ type_: FILE
484
490
  sink: "{app_name}.err.log"
485
491
  error: true
486
492
  json_handler:
487
493
  enabled: true
488
- h_type: FILE
494
+ type_: FILE
489
495
  sink: "json/{app_name}.all.json.log"
490
496
  serialize: true
491
497
  err_json_handler:
492
498
  enabled: true
493
- h_type: FILE
499
+ type_: FILE
494
500
  sink: "json/{app_name}.err.json.log"
495
501
  serialize: true
496
502
  error: true
497
503
  http_access_std_handler:
498
504
  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>"
505
+ type_: STD
506
+ format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <d><w>{extra[request_id]}</w></d>]: <level>{message}</level>"
501
507
  colorize: true
502
508
  http_access_file_handler:
503
509
  enabled: true
504
- h_type: FILE
510
+ type_: FILE
505
511
  sink: "http/{app_name}.http-access.log"
506
512
  http_err_file_handler:
507
513
  enabled: true
508
- h_type: FILE
514
+ type_: FILE
509
515
  sink: "http/{app_name}.http-err.log"
510
516
  error: true
511
517
  http_access_json_handler:
512
518
  enabled: true
513
- h_type: FILE
519
+ type_: FILE
514
520
  sink: "http.json/{app_name}.http-access.json.log"
515
521
  http_err_json_handler:
516
522
  enabled: true
517
- h_type: FILE
523
+ type_: FILE
518
524
  sink: "http.json/{app_name}.http-err.json.log"
519
525
  error: true
520
526
  extra:
@@ -109,30 +109,28 @@ logger:
109
109
  level:
110
110
  base: TRACE
111
111
  http:
112
- std:
113
- 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'
114
- err_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
115
- debug_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
116
- file:
117
- 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}'
118
- tz: "localtime"
119
- has_proxy_headers: true
120
- has_cf_headers: true
112
+ has_proxy_headers: false
113
+ has_cf_headers: false
121
114
  intercept:
122
115
  mute_modules: ["uvicorn.access"]
123
116
  handlers:
124
- http.access.file_handler:
117
+ std_handler:
118
+ enabled: true
119
+ http_access_std_handler:
120
+ enabled: true
121
+ http_access_file_handler:
125
122
  enabled: true
126
123
  sink: "http/{app_name}.http-access.log"
127
- http.err.file_handler:
124
+ http_err_file_handler:
128
125
  enabled: true
129
126
  sink: "http/{app_name}.http-err.log"
130
- http.access.json_handler:
127
+ http_access_json_handler:
131
128
  enabled: true
132
129
  sink: "http.json/{app_name}.http-access.json.log"
133
- http.err.json_handler:
130
+ http_err_json_handler:
134
131
  enabled: true
135
132
  sink: "http.json/{app_name}.http-err.json.log"
133
+
136
134
  ```
137
135
 
138
136
  [**`.env`**](./examples/.env):
@@ -186,14 +184,17 @@ __all__ = [
186
184
 
187
185
  ```python
188
186
  from pydantic import validate_call
189
- from fastapi import FastAPI, APIRouter, HTTPException
187
+ from fastapi import FastAPI, APIRouter, HTTPException, Request
190
188
  from fastapi.responses import RedirectResponse
191
189
 
192
190
  router = APIRouter()
193
191
 
194
192
 
195
193
  @router.get("/")
196
- def root():
194
+ def root(request: Request):
195
+ _logger = request.state.logger
196
+ _logger.info("Root endpoint accessed.")
197
+
197
198
  return {"Hello": "World"}
198
199
 
199
200
 
@@ -348,24 +349,25 @@ uvicorn main:app --host=0.0.0.0 --port=8000
348
349
  **Output**:
349
350
 
350
351
  ```txt
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]
352
+ [2026-06-05 00:55:29.335 +09:00 | TRACE | - | beans_logging.intercepters:96]: Intercepted modules: ['potato_util', 'dotenv.main', 'concurrent', 'potato_util.io', 'asyncio', 'fastapi', 'concurrent.futures', 'dotenv', 'uvicorn', 'watchfiles.watcher', 'potato_util.io._sync', 'watchfiles.main', 'potato_util._base', 'uvicorn.error', 'watchfiles']; Muted modules: ['uvicorn.access'];
353
+ [2026-06-05 00:55:29.336 +09:00 | INFO | - | uvicorn.server:84]: Started server process [95017]
354
+ [2026-06-05 00:55:29.336 +09:00 | INFO | - | uvicorn.lifespan.on:48]: Waiting for application startup.
355
+ [2026-06-05 00:55:29.337 +09:00 | TRACE | - | lifespan:19]: TRACE diagnosis is ON!
356
+ [2026-06-05 00:55:29.337 +09:00 | DEBUG | - | lifespan:20]: DEBUG mode is ON!
357
+ [2026-06-05 00:55:29.337 +09:00 | INFO | - | lifespan:21]: Preparing to startup...
358
+ [2026-06-05 00:55:29.337 +09:00 | OK | - | lifespan:24]: Finished preparation to startup.
359
+ [2026-06-05 00:55:29.337 +09:00 | INFO | - | lifespan:25]: Version: 0.0.0
360
+ [2026-06-05 00:55:29.337 +09:00 | INFO | - | uvicorn.lifespan.on:62]: Application startup complete.
361
+ [2026-06-05 00:55:29.339 +09:00 | INFO | - | uvicorn.server:216]: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
362
+ [2026-06-05 00:55:33.367 +09:00 | DEBUG | 58c916d045844314bb6c10b390ad5593]: 127.0.0.1 - "GET / HTTP/1.1"
363
+ [2026-06-05 00:55:33.370 +09:00 | INFO | 58c916d045844314bb6c10b390ad5593 | router:11]: Root endpoint accessed.
364
+ [2026-06-05 00:55:33.371 +09:00 | OK | 58c916d045844314bb6c10b390ad5593]: 127.0.0.1 - "GET / HTTP/1.1" 200 17B 3.0ms
365
+ ^C[2026-06-05 00:55:35.702 +09:00 | INFO | - | uvicorn.server:264]: Shutting down
366
+ [2026-06-05 00:55:35.805 +09:00 | INFO | - | uvicorn.lifespan.on:67]: Waiting for application shutdown.
367
+ [2026-06-05 00:55:35.805 +09:00 | INFO | - | lifespan:29]: Preparing to shutdown...
368
+ [2026-06-05 00:55:35.805 +09:00 | OK | - | lifespan:31]: Finished preparation to shutdown.
369
+ [2026-06-05 00:55:35.805 +09:00 | INFO | - | uvicorn.lifespan.on:76]: Application shutdown complete.
370
+ [2026-06-05 00:55:35.806 +09:00 | INFO | - | uvicorn.server:94]: Finished server process [95017]
369
371
  ```
370
372
 
371
373
  👍
@@ -382,21 +384,21 @@ logger:
382
384
  level:
383
385
  base: INFO
384
386
  err: WARNING
385
- format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line}]: {message}"
387
+ default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} {extra[request_id]}]: {message}"
386
388
  file:
387
389
  logs_dir: "./logs"
388
390
  rotate_size: 10000000
389
391
  rotate_time: "00:00:00"
390
392
  retention: 90
391
393
  encoding: utf8
392
- use_custom_serialize: false
394
+ custom_serialize: false
393
395
  http:
394
396
  std:
395
- 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'
396
- 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>'
397
- debug_msg_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
397
+ sub_format: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
398
+ err_sub_format: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
399
+ debug_sub_format: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
398
400
  file:
399
- 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
+ format_: '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
400
402
  tz: localtime
401
403
  has_proxy_headers: true
402
404
  has_cf_headers: true
@@ -406,53 +408,57 @@ logger:
406
408
  ignore_modules: []
407
409
  include_modules: []
408
410
  mute_modules: [uvicorn.access]
411
+ global_extra:
412
+ trace_id: ""
413
+ request_id: ""
414
+ user_id: ""
409
415
  handlers:
410
416
  std_handler:
411
417
  enabled: true
412
- h_type: STD
413
- 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>"
418
+ type_: STD
419
+ format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w> <d><w>{extra[request_id]}</w></d>]: <level>{message}</level>"
414
420
  colorize: true
415
421
  file_handler:
416
422
  enabled: true
417
- h_type: FILE
423
+ type_: FILE
418
424
  sink: "{app_name}.all.log"
419
425
  err_file_handler:
420
426
  enabled: true
421
- h_type: FILE
427
+ type_: FILE
422
428
  sink: "{app_name}.err.log"
423
429
  error: true
424
430
  json_handler:
425
431
  enabled: true
426
- h_type: FILE
432
+ type_: FILE
427
433
  sink: "json/{app_name}.all.json.log"
428
434
  serialize: true
429
435
  err_json_handler:
430
436
  enabled: true
431
- h_type: FILE
437
+ type_: FILE
432
438
  sink: "json/{app_name}.err.json.log"
433
439
  serialize: true
434
440
  error: true
435
441
  http_access_std_handler:
436
442
  enabled: true
437
- h_type: STD
438
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> ]: <level>{message}</level>"
443
+ type_: STD
444
+ format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <d><w>{extra[request_id]}</w></d>]: <level>{message}</level>"
439
445
  colorize: true
440
446
  http_access_file_handler:
441
447
  enabled: true
442
- h_type: FILE
448
+ type_: FILE
443
449
  sink: "http/{app_name}.http-access.log"
444
450
  http_err_file_handler:
445
451
  enabled: true
446
- h_type: FILE
452
+ type_: FILE
447
453
  sink: "http/{app_name}.http-err.log"
448
454
  error: true
449
455
  http_access_json_handler:
450
456
  enabled: true
451
- h_type: FILE
457
+ type_: FILE
452
458
  sink: "http.json/{app_name}.http-access.json.log"
453
459
  http_err_json_handler:
454
460
  enabled: true
455
- h_type: FILE
461
+ type_: FILE
456
462
  sink: "http.json/{app_name}.http-err.json.log"
457
463
  error: true
458
464
  extra:
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["setuptools>=70.3.0,<83.0.0", "setuptools-scm>=8.0.4,<10.0.0"]
2
+ requires = ["setuptools>=70.3.0,<83.0.0", "setuptools-scm>=8.0.4,<11.0.0"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
@@ -0,0 +1,2 @@
1
+ fastapi>=0.99.1,<1.0.0
2
+ beans-logging>=12.0.0,<13.0.0
@@ -1,4 +1,4 @@
1
- from beans_logging import logger, LogLevelEnum, log_at
1
+ from beans_logging import Logger, logger, LogLevelEnum, log_at
2
2
 
3
3
  from .__version__ import __version__
4
4
  from .config import LoggerConfigPM
@@ -8,6 +8,7 @@ from .mode import async_log_at
8
8
 
9
9
  __all__ = [
10
10
  "__version__",
11
+ "Logger",
11
12
  "logger",
12
13
  "LogLevelEnum",
13
14
  "add_logger",
@@ -0,0 +1 @@
1
+ __version__ = "8.0.0"
@@ -57,8 +57,8 @@ def add_logger(
57
57
  app.add_middleware(ResponseHTTPInfoMiddleware)
58
58
  app.add_middleware(
59
59
  HttpAccessLogMiddleware,
60
- debug_msg_format_str=config.http.std.debug_msg_format_str,
61
- msg_format_str=config.http.std.msg_format_str,
60
+ debug_sub_format=config.http.std.debug_sub_format,
61
+ sub_format=config.http.std.sub_format,
62
62
  )
63
63
  app.add_middleware(
64
64
  RequestHTTPInfoMiddleware,
@@ -75,7 +75,7 @@ def add_logger(
75
75
  _handler.filter_ = http_all_file_filter
76
76
  _handler.format_ = lambda record: http_file_format(
77
77
  record=record,
78
- format_str=config.http.file.format_str,
78
+ format_=config.http.file.format_,
79
79
  tz=config.http.file.tz,
80
80
  )
81
81
  elif (_name == HTTP_ACCESS_JSON_HANDLER_NAME) or (
@@ -3,8 +3,12 @@ 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, DEFAULT_HANDLER_NAMES
7
- from beans_logging.schemas import LogHandlerPM
6
+ from beans_logging.constants import (
7
+ LogHandlerTypeEnum,
8
+ DEFAULT_HANDLER_NAMES,
9
+ DEFAULT_STD_HANDLER_NAME,
10
+ )
11
+ from beans_logging.schemas import LogHandlerPM, FormatType
8
12
  from beans_logging.config import (
9
13
  get_default_handlers as get_base_handlers,
10
14
  ExtraBaseModel,
@@ -19,6 +23,7 @@ from .constants import (
19
23
  HTTP_ACCESS_JSON_HANDLER_NAME,
20
24
  HTTP_ERR_JSON_HANDLER_NAME,
21
25
  )
26
+ from .formats import id_std_format, id_file_format
22
27
 
23
28
 
24
29
  def get_default_handlers() -> dict[str, LogHandlerPM]:
@@ -33,30 +38,37 @@ def get_default_handlers() -> dict[str, LogHandlerPM]:
33
38
  if _name in DEFAULT_HANDLER_NAMES:
34
39
  _handler.enabled = True
35
40
 
41
+ if _name == DEFAULT_STD_HANDLER_NAME:
42
+ _handler.format_ = id_std_format
43
+ # _handler.format_ = (
44
+ # "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | "
45
+ # "<w>{name}:{line}</w> <d><w>{extra[request_id]}</w></d>]: <level>{message}</level>"
46
+ # )
47
+
36
48
  _http_handlers: dict[str, LogHandlerPM] = {
37
49
  HTTP_ACCESS_STD_HANDLER_NAME: LogHandlerPM(
38
- h_type=LogHandlerTypeEnum.STD,
50
+ type_=LogHandlerTypeEnum.STD,
39
51
  format_=(
40
- "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> ]:"
41
- " <level>{message}</level>"
52
+ "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | "
53
+ "<d><w>{extra[request_id]}</w></d>]: <level>{message}</level>"
42
54
  ),
43
55
  colorize=True,
44
56
  ),
45
57
  HTTP_ACCESS_FILE_HANDLER_NAME: LogHandlerPM(
46
- h_type=LogHandlerTypeEnum.FILE,
58
+ type_=LogHandlerTypeEnum.FILE,
47
59
  sink="http/{app_name}.http-access.log",
48
60
  ),
49
61
  HTTP_ERR_FILE_HANDLER_NAME: LogHandlerPM(
50
- h_type=LogHandlerTypeEnum.FILE,
62
+ type_=LogHandlerTypeEnum.FILE,
51
63
  sink="http/{app_name}.http-err.log",
52
64
  error=True,
53
65
  ),
54
66
  HTTP_ACCESS_JSON_HANDLER_NAME: LogHandlerPM(
55
- h_type=LogHandlerTypeEnum.FILE,
67
+ type_=LogHandlerTypeEnum.FILE,
56
68
  sink="http.json/{app_name}.http-access.json.log",
57
69
  ),
58
70
  HTTP_ERR_JSON_HANDLER_NAME: LogHandlerPM(
59
- h_type=LogHandlerTypeEnum.FILE,
71
+ type_=LogHandlerTypeEnum.FILE,
60
72
  sink="http.json/{app_name}.http-err.json.log",
61
73
  error=True,
62
74
  ),
@@ -71,50 +83,55 @@ def get_default_intercept() -> InterceptConfigPM:
71
83
  return _default_intercept
72
84
 
73
85
 
74
- class StdConfigPM(ExtraBaseModel):
75
- msg_format_str: str = Field(
86
+ class HttpStdConfigPM(ExtraBaseModel):
87
+ sub_format: str = Field(
76
88
  default=(
77
- '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
78
- " {status_code} {content_length}B {response_time}ms"
89
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" '
90
+ "{status_code} {content_length}B {response_time}ms"
79
91
  ),
80
92
  min_length=8,
81
93
  max_length=512,
82
94
  )
83
- err_msg_format_str: str = Field(
95
+ err_sub_format: str = Field(
84
96
  default=(
85
- '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
86
- " <n>{status_code}</n>"
97
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" '
98
+ "<n>{status_code}</n>"
87
99
  ),
88
100
  min_length=8,
89
101
  max_length=512,
90
102
  )
91
- debug_msg_format_str: str = Field(
92
- default='<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"',
103
+ debug_sub_format: str = Field(
104
+ default='{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"',
93
105
  min_length=8,
94
106
  max_length=512,
95
107
  )
96
108
 
97
109
 
98
- class FileConfigPM(ExtraBaseModel):
99
- format_str: str = Field(
110
+ class HttpFileConfigPM(ExtraBaseModel):
111
+ format_: str = Field(
100
112
  default=(
101
- '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}"'
102
- ' {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
103
- ),
104
- min_length=8,
105
- max_length=512,
113
+ '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" '
114
+ '{status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
115
+ )
106
116
  )
107
117
  tz: str = Field(default="localtime", min_length=2, max_length=64)
108
118
 
109
119
 
110
120
  class HttpConfigPM(ExtraBaseModel):
111
- std: StdConfigPM = Field(default_factory=StdConfigPM)
112
- file: FileConfigPM = Field(default_factory=FileConfigPM)
121
+ std: HttpStdConfigPM = Field(default_factory=HttpStdConfigPM)
122
+ file: HttpFileConfigPM = Field(default_factory=HttpFileConfigPM)
113
123
  has_proxy_headers: bool = Field(default=True)
114
124
  has_cf_headers: bool = Field(default=True)
115
125
 
116
126
 
117
127
  class LoggerConfigPM(BaseLoggerConfigPM):
128
+ default_format: FormatType = Field(
129
+ default=id_file_format,
130
+ # default=(
131
+ # "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} {extra[request_id]}]: "
132
+ # "{message}"
133
+ # ),
134
+ )
118
135
  http: HttpConfigPM = Field(default_factory=HttpConfigPM)
119
136
  intercept: InterceptConfigPM = Field(default_factory=get_default_intercept)
120
137
  handlers: dict[str, LogHandlerPM] = Field(default_factory=get_default_handlers)
@@ -165,9 +182,8 @@ class LoggerConfigPM(BaseLoggerConfigPM):
165
182
  __all__ = [
166
183
  "LoggerConfigPM",
167
184
  "HttpConfigPM",
168
- "StdConfigPM",
169
- "FileConfigPM",
170
- # "HeadersConfigPM",
185
+ "HttpStdConfigPM",
186
+ "HttpFileConfigPM",
171
187
  "get_default_intercept",
172
188
  "get_default_handlers",
173
189
  ]