beans-logging-fastapi 7.0.0__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 (29) hide show
  1. {beans_logging_fastapi-7.0.0/src/beans_logging_fastapi.egg-info → beans_logging_fastapi-8.0.0}/PKG-INFO +17 -23
  2. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/README.md +16 -22
  3. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/__init__.py +2 -1
  4. beans_logging_fastapi-8.0.0/src/beans_logging_fastapi/__version__.py +1 -0
  5. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/_core.py +3 -3
  6. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/config.py +31 -33
  7. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/formats.py +59 -7
  8. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/http_error.py +20 -20
  9. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/middlewares.py +38 -32
  10. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/mode.py +14 -2
  11. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0/src/beans_logging_fastapi.egg-info}/PKG-INFO +17 -23
  12. beans_logging_fastapi-7.0.0/src/beans_logging_fastapi/__version__.py +0 -1
  13. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/.python-version +0 -0
  14. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/LICENSE.txt +0 -0
  15. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/pyproject.toml +0 -0
  16. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/requirements/requirements.build.txt +0 -0
  17. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/requirements/requirements.dev.txt +0 -0
  18. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/requirements/requirements.docs.txt +0 -0
  19. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/requirements/requirements.test.txt +0 -0
  20. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/requirements.txt +0 -0
  21. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/setup.cfg +0 -0
  22. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/setup.py +0 -0
  23. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/_async.py +0 -0
  24. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/constants.py +0 -0
  25. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi/filters.py +0 -0
  26. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi.egg-info/SOURCES.txt +0 -0
  27. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi.egg-info/dependency_links.txt +0 -0
  28. {beans_logging_fastapi-7.0.0 → beans_logging_fastapi-8.0.0}/src/beans_logging_fastapi.egg-info/requires.txt +0 -0
  29. {beans_logging_fastapi-7.0.0 → 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: 7.0.0
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
@@ -170,15 +170,7 @@ logger:
170
170
  app_name: "fastapi-app"
171
171
  level:
172
172
  base: TRACE
173
- default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} | {extra[request_id]}]: {message}"
174
173
  http:
175
- std:
176
- msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
177
- err_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
178
- debug_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
179
- file:
180
- 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}'
181
- tz: "localtime"
182
174
  has_proxy_headers: false
183
175
  has_cf_headers: false
184
176
  intercept:
@@ -186,10 +178,8 @@ logger:
186
178
  handlers:
187
179
  std_handler:
188
180
  enabled: true
189
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w> | <w>{name}:{line}</w>]: <level>{message}</level>"
190
181
  http_access_std_handler:
191
182
  enabled: true
192
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w>]: <level>{message}</level>"
193
183
  http_access_file_handler:
194
184
  enabled: true
195
185
  sink: "http/{app_name}.http-access.log"
@@ -202,6 +192,7 @@ logger:
202
192
  http_err_json_handler:
203
193
  enabled: true
204
194
  sink: "http.json/{app_name}.http-err.json.log"
195
+
205
196
  ```
206
197
 
207
198
  [**`.env`**](./examples/.env):
@@ -255,14 +246,17 @@ __all__ = [
255
246
 
256
247
  ```python
257
248
  from pydantic import validate_call
258
- from fastapi import FastAPI, APIRouter, HTTPException
249
+ from fastapi import FastAPI, APIRouter, HTTPException, Request
259
250
  from fastapi.responses import RedirectResponse
260
251
 
261
252
  router = APIRouter()
262
253
 
263
254
 
264
255
  @router.get("/")
265
- def root():
256
+ def root(request: Request):
257
+ _logger = request.state.logger
258
+ _logger.info("Root endpoint accessed.")
259
+
266
260
  return {"Hello": "World"}
267
261
 
268
262
 
@@ -452,7 +446,7 @@ logger:
452
446
  level:
453
447
  base: INFO
454
448
  err: WARNING
455
- format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} | {extra[request_id]}]: {message}"
449
+ default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} {extra[request_id]}]: {message}"
456
450
  file:
457
451
  logs_dir: "./logs"
458
452
  rotate_size: 10000000
@@ -462,11 +456,11 @@ logger:
462
456
  custom_serialize: false
463
457
  http:
464
458
  std:
465
- msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
466
- err_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
467
- debug_msg_format_str: '{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}"'
468
462
  file:
469
- 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}'
470
464
  tz: localtime
471
465
  has_proxy_headers: true
472
466
  has_cf_headers: true
@@ -477,14 +471,14 @@ logger:
477
471
  include_modules: []
478
472
  mute_modules: [uvicorn.access]
479
473
  global_extra:
480
- trace_id: "-"
481
- request_id: "-"
482
- user_id: "-"
474
+ trace_id: ""
475
+ request_id: ""
476
+ user_id: ""
483
477
  handlers:
484
478
  std_handler:
485
479
  enabled: true
486
480
  type_: STD
487
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w> | <w>{name}:{line}</w>]: <level>{message}</level>"
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>"
488
482
  colorize: true
489
483
  file_handler:
490
484
  enabled: true
@@ -509,7 +503,7 @@ logger:
509
503
  http_access_std_handler:
510
504
  enabled: true
511
505
  type_: STD
512
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w>]: <level>{message}</level>"
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>"
513
507
  colorize: true
514
508
  http_access_file_handler:
515
509
  enabled: true
@@ -108,15 +108,7 @@ logger:
108
108
  app_name: "fastapi-app"
109
109
  level:
110
110
  base: TRACE
111
- default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} | {extra[request_id]}]: {message}"
112
111
  http:
113
- std:
114
- msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
115
- err_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
116
- debug_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
117
- file:
118
- 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}'
119
- tz: "localtime"
120
112
  has_proxy_headers: false
121
113
  has_cf_headers: false
122
114
  intercept:
@@ -124,10 +116,8 @@ logger:
124
116
  handlers:
125
117
  std_handler:
126
118
  enabled: true
127
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w> | <w>{name}:{line}</w>]: <level>{message}</level>"
128
119
  http_access_std_handler:
129
120
  enabled: true
130
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w>]: <level>{message}</level>"
131
121
  http_access_file_handler:
132
122
  enabled: true
133
123
  sink: "http/{app_name}.http-access.log"
@@ -140,6 +130,7 @@ logger:
140
130
  http_err_json_handler:
141
131
  enabled: true
142
132
  sink: "http.json/{app_name}.http-err.json.log"
133
+
143
134
  ```
144
135
 
145
136
  [**`.env`**](./examples/.env):
@@ -193,14 +184,17 @@ __all__ = [
193
184
 
194
185
  ```python
195
186
  from pydantic import validate_call
196
- from fastapi import FastAPI, APIRouter, HTTPException
187
+ from fastapi import FastAPI, APIRouter, HTTPException, Request
197
188
  from fastapi.responses import RedirectResponse
198
189
 
199
190
  router = APIRouter()
200
191
 
201
192
 
202
193
  @router.get("/")
203
- def root():
194
+ def root(request: Request):
195
+ _logger = request.state.logger
196
+ _logger.info("Root endpoint accessed.")
197
+
204
198
  return {"Hello": "World"}
205
199
 
206
200
 
@@ -390,7 +384,7 @@ logger:
390
384
  level:
391
385
  base: INFO
392
386
  err: WARNING
393
- format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} | {extra[request_id]}]: {message}"
387
+ default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} {extra[request_id]}]: {message}"
394
388
  file:
395
389
  logs_dir: "./logs"
396
390
  rotate_size: 10000000
@@ -400,11 +394,11 @@ logger:
400
394
  custom_serialize: false
401
395
  http:
402
396
  std:
403
- msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
404
- err_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
405
- debug_msg_format_str: '{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}"'
406
400
  file:
407
- 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}'
408
402
  tz: localtime
409
403
  has_proxy_headers: true
410
404
  has_cf_headers: true
@@ -415,14 +409,14 @@ logger:
415
409
  include_modules: []
416
410
  mute_modules: [uvicorn.access]
417
411
  global_extra:
418
- trace_id: "-"
419
- request_id: "-"
420
- user_id: "-"
412
+ trace_id: ""
413
+ request_id: ""
414
+ user_id: ""
421
415
  handlers:
422
416
  std_handler:
423
417
  enabled: true
424
418
  type_: STD
425
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w> | <w>{name}:{line}</w>]: <level>{message}</level>"
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>"
426
420
  colorize: true
427
421
  file_handler:
428
422
  enabled: true
@@ -447,7 +441,7 @@ logger:
447
441
  http_access_std_handler:
448
442
  enabled: true
449
443
  type_: STD
450
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w>]: <level>{message}</level>"
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>"
451
445
  colorize: true
452
446
  http_access_file_handler:
453
447
  enabled: true
@@ -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 (
@@ -8,7 +8,7 @@ from beans_logging.constants import (
8
8
  DEFAULT_HANDLER_NAMES,
9
9
  DEFAULT_STD_HANDLER_NAME,
10
10
  )
11
- from beans_logging.schemas import LogHandlerPM
11
+ from beans_logging.schemas import LogHandlerPM, FormatType
12
12
  from beans_logging.config import (
13
13
  get_default_handlers as get_base_handlers,
14
14
  ExtraBaseModel,
@@ -23,6 +23,7 @@ from .constants import (
23
23
  HTTP_ACCESS_JSON_HANDLER_NAME,
24
24
  HTTP_ERR_JSON_HANDLER_NAME,
25
25
  )
26
+ from .formats import id_std_format, id_file_format
26
27
 
27
28
 
28
29
  def get_default_handlers() -> dict[str, LogHandlerPM]:
@@ -38,17 +39,18 @@ def get_default_handlers() -> dict[str, LogHandlerPM]:
38
39
  _handler.enabled = True
39
40
 
40
41
  if _name == DEFAULT_STD_HANDLER_NAME:
41
- _handler.format_ = (
42
- "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | "
43
- "<w>{extra[request_id]}</w> | <w>{name}:{line}</w>]: <level>{message}</level>"
44
- )
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
+ # )
45
47
 
46
48
  _http_handlers: dict[str, LogHandlerPM] = {
47
49
  HTTP_ACCESS_STD_HANDLER_NAME: LogHandlerPM(
48
50
  type_=LogHandlerTypeEnum.STD,
49
51
  format_=(
50
52
  "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | "
51
- "<w>{extra[request_id]}</w>]: <level>{message}</level>"
53
+ "<d><w>{extra[request_id]}</w></d>]: <level>{message}</level>"
52
54
  ),
53
55
  colorize=True,
54
56
  ),
@@ -81,57 +83,54 @@ def get_default_intercept() -> InterceptConfigPM:
81
83
  return _default_intercept
82
84
 
83
85
 
84
- class StdConfigPM(ExtraBaseModel):
85
- msg_format_str: str = Field(
86
+ class HttpStdConfigPM(ExtraBaseModel):
87
+ sub_format: str = Field(
86
88
  default=(
87
- '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
88
- " {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"
89
91
  ),
90
92
  min_length=8,
91
93
  max_length=512,
92
94
  )
93
- err_msg_format_str: str = Field(
95
+ err_sub_format: str = Field(
94
96
  default=(
95
- '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
96
- " <n>{status_code}</n>"
97
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" '
98
+ "<n>{status_code}</n>"
97
99
  ),
98
100
  min_length=8,
99
101
  max_length=512,
100
102
  )
101
- debug_msg_format_str: str = Field(
103
+ debug_sub_format: str = Field(
102
104
  default='{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"',
103
105
  min_length=8,
104
106
  max_length=512,
105
107
  )
106
108
 
107
109
 
108
- class FileConfigPM(ExtraBaseModel):
109
- format_str: str = Field(
110
+ class HttpFileConfigPM(ExtraBaseModel):
111
+ format_: str = Field(
110
112
  default=(
111
- '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}"'
112
- ' {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
113
- ),
114
- min_length=8,
115
- 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
+ )
116
116
  )
117
117
  tz: str = Field(default="localtime", min_length=2, max_length=64)
118
118
 
119
119
 
120
120
  class HttpConfigPM(ExtraBaseModel):
121
- std: StdConfigPM = Field(default_factory=StdConfigPM)
122
- file: FileConfigPM = Field(default_factory=FileConfigPM)
121
+ std: HttpStdConfigPM = Field(default_factory=HttpStdConfigPM)
122
+ file: HttpFileConfigPM = Field(default_factory=HttpFileConfigPM)
123
123
  has_proxy_headers: bool = Field(default=True)
124
124
  has_cf_headers: bool = Field(default=True)
125
125
 
126
126
 
127
127
  class LoggerConfigPM(BaseLoggerConfigPM):
128
- default_format: str = Field(
129
- default=(
130
- "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} | {extra[request_id]}]: "
131
- "{message}"
132
- ),
133
- min_length=8,
134
- max_length=512,
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
+ # ),
135
134
  )
136
135
  http: HttpConfigPM = Field(default_factory=HttpConfigPM)
137
136
  intercept: InterceptConfigPM = Field(default_factory=get_default_intercept)
@@ -183,9 +182,8 @@ class LoggerConfigPM(BaseLoggerConfigPM):
183
182
  __all__ = [
184
183
  "LoggerConfigPM",
185
184
  "HttpConfigPM",
186
- "StdConfigPM",
187
- "FileConfigPM",
188
- # "HeadersConfigPM",
185
+ "HttpStdConfigPM",
186
+ "HttpFileConfigPM",
189
187
  "get_default_intercept",
190
188
  "get_default_handlers",
191
189
  ]
@@ -9,18 +9,18 @@ if TYPE_CHECKING:
9
9
 
10
10
  def http_file_format(
11
11
  record: "Record",
12
- format_str: str = (
13
- '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}"'
14
- ' {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
12
+ format_: str = (
13
+ '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" '
14
+ '{status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
15
15
  ),
16
16
  tz: str = "localtime",
17
17
  ) -> str:
18
18
  """Http access log file format.
19
19
 
20
20
  Args:
21
- record (Record, required): Log record as dictionary.
22
- format_str (str , optional): Log message format.
23
- tz (str , optional): Timezone for datetime field. Defaults to 'localtime'.
21
+ record (Record, required): Log record as dictionary.
22
+ format_ (str , optional): Log message format.
23
+ tz (str , optional): Timezone for datetime field. Defaults to 'localtime'.
24
24
 
25
25
  Returns:
26
26
  str: Format for http access log record.
@@ -56,7 +56,7 @@ def http_file_format(
56
56
  _http_info["response_time"] = 0
57
57
 
58
58
  record["extra"]["http_info"] = _http_info
59
- _msg = format_str.format(**_http_info)
59
+ _msg = format_.format(**_http_info)
60
60
 
61
61
  record["extra"]["http_message"] = _msg
62
62
  return "{extra[http_message]}\n"
@@ -89,7 +89,59 @@ def http_json_format(record: "Record") -> str:
89
89
  return "{extra[http_serialized]}\n"
90
90
 
91
91
 
92
+ def id_std_format(record: "Record") -> str:
93
+ """Std output log format with user_id, trace_id, and request_id.
94
+
95
+ Args:
96
+ record (Record): Log record as dictionary.
97
+
98
+ Returns:
99
+ str: Format for std output log with user_id, trace_id, and request_id.
100
+ """
101
+
102
+ _user_id = record["extra"].get("user_id")
103
+ _trace_id = record["extra"].get("trace_id")
104
+ _request_id = record["extra"].get("request_id")
105
+ _request_id_part = f" | <d><w>{_request_id}</w></d>" if _request_id else ""
106
+ _trace_id_part = f" | <lc>{_trace_id}</lc>" if _trace_id else ""
107
+ _user_id_part = f" | <m>{_user_id}</m>" if _user_id else ""
108
+
109
+ _format = (
110
+ "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>"
111
+ f"{_request_id_part}{_trace_id_part}{_user_id_part}"
112
+ "]: <level>{message}</level>\n"
113
+ )
114
+ return _format
115
+
116
+
117
+ def id_file_format(record: "Record") -> str:
118
+ """File log format with user_id, trace_id, and request_id.
119
+
120
+ Args:
121
+ record (Record): Log record as dictionary.
122
+
123
+ Returns:
124
+ str: Format for file log with user_id, trace_id, and request_id.
125
+ """
126
+
127
+ _user_id = record["extra"].get("user_id")
128
+ _trace_id = record["extra"].get("trace_id")
129
+ _request_id = record["extra"].get("request_id")
130
+ _request_id_part = f" | {_request_id}" if _request_id else ""
131
+ _trace_id_part = f" | {_trace_id}" if _trace_id else ""
132
+ _user_id_part = f" | {_user_id}" if _user_id else ""
133
+
134
+ _format = (
135
+ "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line}"
136
+ f"{_request_id_part}{_trace_id_part}{_user_id_part}"
137
+ "]: {message}\n"
138
+ )
139
+ return _format
140
+
141
+
92
142
  __all__ = [
93
143
  "http_file_format",
94
144
  "http_json_format",
145
+ "id_std_format",
146
+ "id_file_format",
95
147
  ]
@@ -11,19 +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
- 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>'
14
+ sub_format: str = (
15
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
17
16
  ),
18
17
  ) -> None:
19
18
  """Async Log HTTP error for unhandled Exception.
20
19
 
21
20
  Args:
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
- '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"
26
- <n>{status_code}</n>'.
21
+ request (Request, required): Request instance.
22
+ status_code (int , required): HTTP status code.
23
+ sub_format (str , optional): Message format. Defaults to
24
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'.
27
25
  """
28
26
 
29
27
  _http_info: dict[str, Any] = {"request_id": request.state.request_id}
@@ -33,9 +31,11 @@ async def async_log_http_error(
33
31
  _http_info: dict[str, Any] = request.state.http_info
34
32
  _http_info["status_code"] = status_code
35
33
 
36
- _msg = msg_format_str.format(**_http_info)
34
+ _msg = sub_format.format(**_http_info)
37
35
  _logger: Logger = logger.opt(colors=True, record=True).bind(
38
- http_info=_http_info, disable_std_handler=True
36
+ http_info=_http_info,
37
+ request_id=_http_info.get("request_id", ""),
38
+ disable_std_handler=True,
39
39
  )
40
40
  await run_in_threadpool(_logger.error, _msg)
41
41
  return
@@ -45,19 +45,17 @@ async def async_log_http_error(
45
45
  def log_http_error(
46
46
  request: Request,
47
47
  status_code: int,
48
- msg_format_str: str = (
49
- '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u>'
50
- ' HTTP/{http_version}" <n>{status_code}</n>'
48
+ sub_format: str = (
49
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
51
50
  ),
52
51
  ) -> None:
53
52
  """Log HTTP error for unhandled Exception.
54
53
 
55
54
  Args:
56
- request (Request, required): Request instance.
57
- status_code (int , required): HTTP status code.
58
- msg_format_str (str , optional): Message format. Defaults to
59
- '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"
60
- <n>{status_code}</n>'.
55
+ request (Request, required): Request instance.
56
+ status_code (int , required): HTTP status code.
57
+ sub_format (str , optional): Message format. Defaults to
58
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'.
61
59
  """
62
60
 
63
61
  _http_info: dict[str, Any] = {"request_id": request.state.request_id}
@@ -67,9 +65,11 @@ def log_http_error(
67
65
  _http_info: dict[str, Any] = request.state.http_info
68
66
  _http_info["status_code"] = status_code
69
67
 
70
- _msg = msg_format_str.format(**_http_info)
68
+ _msg = sub_format.format(**_http_info)
71
69
  _logger: Logger = logger.opt(colors=True, record=True, depth=3).bind(
72
- http_info=_http_info, disable_std_handler=True
70
+ http_info=_http_info,
71
+ request_id=_http_info.get("request_id", ""),
72
+ disable_std_handler=True,
73
73
  )
74
74
  _logger.error(_msg)
75
75
  return
@@ -239,37 +239,37 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware):
239
239
  BaseHTTPMiddleware: Base HTTP middleware class from starlette.
240
240
 
241
241
  Attributes:
242
- _DEBUG_MSG_FORMAT_STR (str ): Default http access log debug message format. Defaults to
243
- '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'.
244
- _MSG_FORMAT_STR (str ): Default http access log message format. Defaults to
245
- '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"
242
+ _DEBUG_SUB_FORMAT (str ): Default http access log debug message format. Defaults to
243
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'.
244
+ _SUB_FORMAT (str ): Default http access log message format. Defaults to
245
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"
246
246
  {status_code} {content_length}B {response_time}ms'.
247
247
 
248
- debug_msg_format_str (str ): Http access log debug message format.
249
- Defaults to `HttpAccessLogMiddleware._DEBUG_MSG_FORMAT_STR`.
250
- msg_format_str (str ): Http access log message format.
251
- Defaults to `HttpAccessLogMiddleware._MSG_FORMAT_STR`.
252
- use_debug_log (bool): If True, use debug log to log http access log. Defaults to True.
248
+ debug_sub_format (str ): Http access log debug message format.
249
+ Defaults to `HttpAccessLogMiddleware._DEBUG_SUB_FORMAT`.
250
+ sub_format (str ): Http access log message format.
251
+ Defaults to `HttpAccessLogMiddleware._SUB_FORMAT`.
252
+ use_debug_log (bool): If True, use debug log to log http access log. Defaults to True.
253
253
  """
254
254
 
255
- _DEBUG_MSG_FORMAT_STR = (
255
+ _DEBUG_SUB_FORMAT = (
256
256
  '{client_host} {user_id} "<u>{method} {url_path}</u>' ' HTTP/{http_version}"'
257
257
  )
258
- _MSG_FORMAT_STR = (
259
- '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
260
- " {status_code} {content_length}B {response_time}ms"
258
+ _SUB_FORMAT = (
259
+ '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" '
260
+ "{status_code} {content_length}B {response_time}ms"
261
261
  )
262
262
 
263
263
  def __init__(
264
264
  self,
265
265
  app,
266
- debug_msg_format_str: str = _DEBUG_MSG_FORMAT_STR,
267
- msg_format_str: str = _MSG_FORMAT_STR,
266
+ debug_sub_format: str = _DEBUG_SUB_FORMAT,
267
+ sub_format: str = _SUB_FORMAT,
268
268
  use_debug_log: bool = True,
269
269
  ):
270
270
  super().__init__(app)
271
- self.debug_msg_format_str = debug_msg_format_str
272
- self.msg_format_str = msg_format_str
271
+ self.debug_sub_format = debug_sub_format
272
+ self.sub_format = sub_format
273
273
  self.use_debug_log = use_debug_log
274
274
 
275
275
  async def dispatch(self, request: Request, call_next) -> Response:
@@ -283,16 +283,18 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware):
283
283
 
284
284
  # Debug log:
285
285
  if self.use_debug_log:
286
- _debug_msg = self.debug_msg_format_str.format(**_http_info)
286
+ _debug_msg = self.debug_sub_format.format(**_http_info)
287
287
 
288
288
  _logger.bind(
289
289
  http_info=_http_info,
290
- request_id=_http_info.get("request_id", "-"),
290
+ request_id=_http_info.get("request_id", ""),
291
291
  disable_http_all_file_handlers=True,
292
292
  ).debug(_debug_msg)
293
293
  # await run_in_threadpool(
294
294
  # _logger.bind(
295
- # http_info=_http_info, disable_http_all_file_handlers=True
295
+ # http_info=_http_info,
296
+ # request_id=_http_info.get("request_id", ""),
297
+ # disable_http_all_file_handlers=True,
296
298
  # ).debug,
297
299
  # _debug_msg,
298
300
  # )
@@ -309,32 +311,36 @@ class HttpAccessLogMiddleware(BaseHTTPMiddleware):
309
311
 
310
312
  # Http access log:
311
313
  _LEVEL = "INFO"
312
- _msg_format_str = self.msg_format_str
314
+ _sub_format = self.sub_format
313
315
  if _http_info["status_code"] < 200:
314
316
  _LEVEL = "DEBUG"
315
- _msg_format_str = f'<d>{_msg_format_str.replace("{status_code}", "<n><b><k>{status_code}</k></b></n>")}</d>'
317
+ _sub_format = f'<d>{_sub_format.replace("{status_code}", "<n><b><k>{status_code}</k></b></n>")}</d>'
316
318
  elif (200 <= _http_info["status_code"]) and (_http_info["status_code"] < 300):
317
319
  _LEVEL = "SUCCESS"
318
- _msg_format_str = f'<w>{_msg_format_str.replace("{status_code}", "<lvl>{status_code}</lvl>")}</w>'
320
+ _sub_format = f'<w>{_sub_format.replace("{status_code}", "<lvl>{status_code}</lvl>")}</w>'
319
321
  elif (300 <= _http_info["status_code"]) and (_http_info["status_code"] < 400):
320
322
  _LEVEL = "INFO"
321
- _msg_format_str = f'<d>{_msg_format_str.replace("{status_code}", "<n><b><c>{status_code}</c></b></n>")}</d>'
323
+ _sub_format = f'<d>{_sub_format.replace("{status_code}", "<n><b><c>{status_code}</c></b></n>")}</d>'
322
324
  elif (400 <= _http_info["status_code"]) and (_http_info["status_code"] < 500):
323
325
  _LEVEL = "WARNING"
324
- _msg_format_str = _msg_format_str.replace(
325
- "{status_code}", "<r>{status_code}</r>"
326
- )
326
+ _sub_format = _sub_format.replace("{status_code}", "<r>{status_code}</r>")
327
327
  elif 500 <= _http_info["status_code"]:
328
328
  _LEVEL = "ERROR"
329
- _msg_format_str = (
330
- f'{_msg_format_str.replace("{status_code}", "<n>{status_code}</n>")}'
329
+ _sub_format = (
330
+ f'{_sub_format.replace("{status_code}", "<n>{status_code}</n>")}'
331
331
  )
332
332
 
333
- _msg = _msg_format_str.format(**_http_info)
333
+ _msg = _sub_format.format(**_http_info)
334
334
  _logger.bind(
335
- http_info=_http_info, request_id=_http_info.get("request_id", "-")
335
+ http_info=_http_info, request_id=_http_info.get("request_id", "")
336
336
  ).log(_LEVEL, _msg)
337
- # await run_in_threadpool(_logger.bind(http_info=_http_info).log, _LEVEL, _msg)
337
+ # await run_in_threadpool(
338
+ # _logger.bind(
339
+ # http_info=_http_info, request_id=_http_info.get("request_id", "")
340
+ # ).log,
341
+ # _LEVEL,
342
+ # _msg,
343
+ # )
338
344
  # Http access log.
339
345
 
340
346
  return response
@@ -1,16 +1,24 @@
1
+ from typing import TYPE_CHECKING
2
+
1
3
  from pydantic import validate_call
2
4
  from fastapi.concurrency import run_in_threadpool
3
5
 
6
+ if TYPE_CHECKING:
7
+ from loguru import Logger
8
+ else:
9
+ from loguru._logger import Logger
10
+
4
11
  from potato_util.constants import WarnEnum
5
12
  from beans_logging.constants import LogLevelEnum
6
13
  from beans_logging import logger
7
14
 
8
15
 
9
- @validate_call
16
+ @validate_call(config={"arbitrary_types_allowed": True})
10
17
  async def async_log_at(
11
18
  message: str,
12
19
  level: LogLevelEnum | str = LogLevelEnum.INFO,
13
20
  warn_mode: WarnEnum | str = WarnEnum.ALWAYS,
21
+ logger: Logger = logger,
14
22
  ) -> None:
15
23
  """Log message with level and warn mode in async context.
16
24
 
@@ -19,6 +27,7 @@ async def async_log_at(
19
27
  level (LogLevelEnum | str, optional): Log level when warn mode is `WarnEnum.ALWAYS`.
20
28
  Defaults to `LogLevelEnum.INFO`.
21
29
  warn_mode (WarnEnum | str , optional): Warn mode to use. Defaults to `WarnEnum.ALWAYS`.
30
+ logger (Logger , optional): Logger instance to use. Defaults to `logger`.
22
31
 
23
32
  Raises:
24
33
  ValueError: If `level` is not a valid log level.
@@ -32,7 +41,10 @@ async def async_log_at(
32
41
  warn_mode = WarnEnum(warn_mode.strip().upper())
33
42
 
34
43
  if warn_mode == WarnEnum.ALWAYS:
35
- await run_in_threadpool(logger.log, level.name, message)
44
+ if level == LogLevelEnum.EXCEPTION:
45
+ await run_in_threadpool(logger.exception, message)
46
+ else:
47
+ await run_in_threadpool(logger.log, level.name, message)
36
48
  elif warn_mode == WarnEnum.DEBUG:
37
49
  await run_in_threadpool(logger.debug, message)
38
50
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beans_logging_fastapi
3
- Version: 7.0.0
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
@@ -170,15 +170,7 @@ logger:
170
170
  app_name: "fastapi-app"
171
171
  level:
172
172
  base: TRACE
173
- default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} | {extra[request_id]}]: {message}"
174
173
  http:
175
- std:
176
- msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
177
- err_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
178
- debug_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
179
- file:
180
- 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}'
181
- tz: "localtime"
182
174
  has_proxy_headers: false
183
175
  has_cf_headers: false
184
176
  intercept:
@@ -186,10 +178,8 @@ logger:
186
178
  handlers:
187
179
  std_handler:
188
180
  enabled: true
189
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w> | <w>{name}:{line}</w>]: <level>{message}</level>"
190
181
  http_access_std_handler:
191
182
  enabled: true
192
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w>]: <level>{message}</level>"
193
183
  http_access_file_handler:
194
184
  enabled: true
195
185
  sink: "http/{app_name}.http-access.log"
@@ -202,6 +192,7 @@ logger:
202
192
  http_err_json_handler:
203
193
  enabled: true
204
194
  sink: "http.json/{app_name}.http-err.json.log"
195
+
205
196
  ```
206
197
 
207
198
  [**`.env`**](./examples/.env):
@@ -255,14 +246,17 @@ __all__ = [
255
246
 
256
247
  ```python
257
248
  from pydantic import validate_call
258
- from fastapi import FastAPI, APIRouter, HTTPException
249
+ from fastapi import FastAPI, APIRouter, HTTPException, Request
259
250
  from fastapi.responses import RedirectResponse
260
251
 
261
252
  router = APIRouter()
262
253
 
263
254
 
264
255
  @router.get("/")
265
- def root():
256
+ def root(request: Request):
257
+ _logger = request.state.logger
258
+ _logger.info("Root endpoint accessed.")
259
+
266
260
  return {"Hello": "World"}
267
261
 
268
262
 
@@ -452,7 +446,7 @@ logger:
452
446
  level:
453
447
  base: INFO
454
448
  err: WARNING
455
- format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} | {extra[request_id]}]: {message}"
449
+ default_format: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line} {extra[request_id]}]: {message}"
456
450
  file:
457
451
  logs_dir: "./logs"
458
452
  rotate_size: 10000000
@@ -462,11 +456,11 @@ logger:
462
456
  custom_serialize: false
463
457
  http:
464
458
  std:
465
- msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
466
- err_msg_format_str: '{client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
467
- debug_msg_format_str: '{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}"'
468
462
  file:
469
- 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}'
470
464
  tz: localtime
471
465
  has_proxy_headers: true
472
466
  has_cf_headers: true
@@ -477,14 +471,14 @@ logger:
477
471
  include_modules: []
478
472
  mute_modules: [uvicorn.access]
479
473
  global_extra:
480
- trace_id: "-"
481
- request_id: "-"
482
- user_id: "-"
474
+ trace_id: ""
475
+ request_id: ""
476
+ user_id: ""
483
477
  handlers:
484
478
  std_handler:
485
479
  enabled: true
486
480
  type_: STD
487
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w> | <w>{name}:{line}</w>]: <level>{message}</level>"
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>"
488
482
  colorize: true
489
483
  file_handler:
490
484
  enabled: true
@@ -509,7 +503,7 @@ logger:
509
503
  http_access_std_handler:
510
504
  enabled: true
511
505
  type_: STD
512
- format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{extra[request_id]}</w>]: <level>{message}</level>"
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>"
513
507
  colorize: true
514
508
  http_access_file_handler:
515
509
  enabled: true
@@ -1 +0,0 @@
1
- __version__ = "7.0.0"