beans-logging-fastapi 1.1.0__tar.gz → 2.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 (37) hide show
  1. beans_logging_fastapi-2.0.0/.python-version +1 -0
  2. beans_logging_fastapi-1.1.0/LICENCE.txt → beans_logging_fastapi-2.0.0/LICENSE.txt +1 -1
  3. beans_logging_fastapi-2.0.0/PKG-INFO +497 -0
  4. beans_logging_fastapi-2.0.0/README.md +438 -0
  5. beans_logging_fastapi-2.0.0/pyproject.toml +63 -0
  6. beans_logging_fastapi-2.0.0/requirements/requirements.build.txt +4 -0
  7. beans_logging_fastapi-2.0.0/requirements/requirements.dev.txt +6 -0
  8. beans_logging_fastapi-2.0.0/requirements/requirements.docs.txt +5 -0
  9. beans_logging_fastapi-2.0.0/requirements/requirements.test.txt +5 -0
  10. beans_logging_fastapi-2.0.0/requirements.txt +2 -0
  11. beans_logging_fastapi-2.0.0/setup.py +3 -0
  12. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0/src}/beans_logging_fastapi/__init__.py +1 -1
  13. beans_logging_fastapi-2.0.0/src/beans_logging_fastapi/__version__.py +1 -0
  14. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0/src}/beans_logging_fastapi/_async_log.py +38 -26
  15. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0/src}/beans_logging_fastapi/_base.py +25 -18
  16. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0/src}/beans_logging_fastapi/_filters.py +9 -4
  17. beans_logging_fastapi-2.0.0/src/beans_logging_fastapi/_formats.py +95 -0
  18. beans_logging_fastapi-2.0.0/src/beans_logging_fastapi/_handlers.py +96 -0
  19. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0/src}/beans_logging_fastapi/_middlewares.py +41 -29
  20. beans_logging_fastapi-2.0.0/src/beans_logging_fastapi.egg-info/PKG-INFO +497 -0
  21. beans_logging_fastapi-2.0.0/src/beans_logging_fastapi.egg-info/SOURCES.txt +29 -0
  22. beans_logging_fastapi-2.0.0/src/beans_logging_fastapi.egg-info/requires.txt +38 -0
  23. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0/src}/beans_logging_fastapi.egg-info/top_level.txt +1 -1
  24. beans_logging_fastapi-1.1.0/PKG-INFO +0 -385
  25. beans_logging_fastapi-1.1.0/README.md +0 -361
  26. beans_logging_fastapi-1.1.0/beans_logging_fastapi/__version__.py +0 -3
  27. beans_logging_fastapi-1.1.0/beans_logging_fastapi/_formats.py +0 -77
  28. beans_logging_fastapi-1.1.0/beans_logging_fastapi/_handlers.py +0 -82
  29. beans_logging_fastapi-1.1.0/beans_logging_fastapi.egg-info/PKG-INFO +0 -385
  30. beans_logging_fastapi-1.1.0/beans_logging_fastapi.egg-info/SOURCES.txt +0 -20
  31. beans_logging_fastapi-1.1.0/beans_logging_fastapi.egg-info/requires.txt +0 -2
  32. beans_logging_fastapi-1.1.0/setup.py +0 -55
  33. beans_logging_fastapi-1.1.0/tests/__init__.py +0 -1
  34. beans_logging_fastapi-1.1.0/tests/conftest.py +0 -16
  35. beans_logging_fastapi-1.1.0/tests/test_beans_logging_fastapi.py +0 -24
  36. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0}/setup.cfg +0 -0
  37. {beans_logging_fastapi-1.1.0 → beans_logging_fastapi-2.0.0/src}/beans_logging_fastapi.egg-info/dependency_links.txt +0 -0
@@ -0,0 +1 @@
1
+ 3.10
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Batkhuu Byambajav
3
+ Copyright (c) 2025 Batkhuu Byambajav
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,497 @@
1
+ Metadata-Version: 2.4
2
+ Name: beans_logging_fastapi
3
+ Version: 2.0.0
4
+ Summary: This is a middleware for FastAPI HTTP access logs. It is based on 'beans-logging' package.
5
+ Author-email: Batkhuu Byambajav <batkhuu10@gmail.com>
6
+ Project-URL: Homepage, https://github.com/bybatkhuu/module-fastapi-logging
7
+ Project-URL: Documentation, https://fastapi-logging-docs.bybatkhuu.dev
8
+ Project-URL: Repository, https://github.com/bybatkhuu/module-fastapi-logging.git
9
+ Project-URL: Issues, https://github.com/bybatkhuu/module-fastapi-logging/issues
10
+ Project-URL: Changelog, https://github.com/bybatkhuu/module-fastapi-logging/blob/main/CHANGELOG.md
11
+ Keywords: beans_logging_fastapi,fastapi-logging,fastapi-logging-middleware,fastapi-middleware,logging-middleware,middleware,beans-logging,http-access-logging,logging,logger,loguru
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Requires-Python: <4.0,>=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE.txt
24
+ Requires-Dist: fastapi<1.0.0,>=0.99.1
25
+ Requires-Dist: beans-logging<8.0.0,>=7.1.0
26
+ Provides-Extra: test
27
+ Requires-Dist: pytest<10.0.0,>=8.0.2; extra == "test"
28
+ Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "test"
29
+ Requires-Dist: pytest-xdist<4.0.0,>=3.6.1; extra == "test"
30
+ Requires-Dist: pytest-benchmark<6.0.0,>=5.0.1; extra == "test"
31
+ Provides-Extra: build
32
+ Requires-Dist: setuptools<81.0.0,>=70.3.0; extra == "build"
33
+ Requires-Dist: wheel<1.0.0,>=0.43.0; extra == "build"
34
+ Requires-Dist: build<2.0.0,>=1.1.1; extra == "build"
35
+ Requires-Dist: twine<7.0.0,>=6.0.1; extra == "build"
36
+ Provides-Extra: docs
37
+ Requires-Dist: pylint<5.0.0,>=3.0.4; extra == "docs"
38
+ Requires-Dist: mkdocs-material<10.0.0,>=9.5.50; extra == "docs"
39
+ Requires-Dist: mkdocs-awesome-nav<4.0.0,>=3.0.0; extra == "docs"
40
+ Requires-Dist: mkdocstrings[python]<2.0.0,>=0.24.3; extra == "docs"
41
+ Requires-Dist: mike<3.0.0,>=2.1.3; extra == "docs"
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest<10.0.0,>=8.0.2; extra == "dev"
44
+ Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "dev"
45
+ Requires-Dist: pytest-xdist<4.0.0,>=3.6.1; extra == "dev"
46
+ Requires-Dist: pytest-benchmark<6.0.0,>=5.0.1; extra == "dev"
47
+ Requires-Dist: setuptools<81.0.0,>=70.3.0; extra == "dev"
48
+ Requires-Dist: wheel<1.0.0,>=0.43.0; extra == "dev"
49
+ Requires-Dist: build<2.0.0,>=1.1.1; extra == "dev"
50
+ Requires-Dist: twine<7.0.0,>=6.0.1; extra == "dev"
51
+ Requires-Dist: pylint<5.0.0,>=3.0.4; extra == "dev"
52
+ Requires-Dist: mkdocs-material<10.0.0,>=9.5.50; extra == "dev"
53
+ Requires-Dist: mkdocs-awesome-nav<4.0.0,>=3.0.0; extra == "dev"
54
+ Requires-Dist: mkdocstrings[python]<2.0.0,>=0.24.3; extra == "dev"
55
+ Requires-Dist: mike<3.0.0,>=2.1.3; extra == "dev"
56
+ Requires-Dist: pyright<2.0.0,>=1.1.392; extra == "dev"
57
+ Requires-Dist: pre-commit<5.0.0,>=4.0.1; extra == "dev"
58
+ Dynamic: license-file
59
+
60
+ # FastAPI Logging (beans-logging-fastapi)
61
+
62
+ [![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit)
63
+ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bybatkhuu/module-fastapi-logging/2.build-publish.yml?logo=GitHub)](https://github.com/bybatkhuu/module-fastapi-logging/actions/workflows/2.build-publish.yml)
64
+ [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/bybatkhuu/module-fastapi-logging?logo=GitHub&color=blue)](https://github.com/bybatkhuu/module-fastapi-logging/releases)
65
+
66
+ This is a middleware for FastAPI HTTP access logs. It is based on **'beans-logging'** package.
67
+
68
+ ## ✨ Features
69
+
70
+ - **Logger** based on **'beans-logging'** package
71
+ - **FastAPI** HTTP access logging **middleware**
72
+
73
+ ---
74
+
75
+ ## 🛠 Installation
76
+
77
+ ### 1. 🚧 Prerequisites
78
+
79
+ - Install **Python (>= v3.10)** and **pip (>= 23)**:
80
+ - **[RECOMMENDED] [Miniconda (v3)](https://www.anaconda.com/docs/getting-started/miniconda/install)**
81
+ - *[arm64/aarch64] [Miniforge (v3)](https://github.com/conda-forge/miniforge)*
82
+ - *[Python virutal environment] [venv](https://docs.python.org/3/library/venv.html)*
83
+
84
+ [OPTIONAL] For **DEVELOPMENT** environment:
85
+
86
+ - Install [**git**](https://git-scm.com/downloads)
87
+ - Setup an [**SSH key**](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh)
88
+
89
+ ### 2. 📦 Install the package
90
+
91
+ [NOTE] Choose one of the following methods to install the package **[A ~ F]**:
92
+
93
+ **OPTION A.** [**RECOMMENDED**] Install from **PyPi**:
94
+
95
+ ```sh
96
+ pip install -U beans-logging-fastapi
97
+ ```
98
+
99
+ **OPTION B.** Install latest version directly from **GitHub** repository:
100
+
101
+ ```sh
102
+ pip install git+https://github.com/bybatkhuu/module-fastapi-logging.git
103
+ ```
104
+
105
+ **OPTION C.** Install from the downloaded **source code**:
106
+
107
+ ```sh
108
+ git clone https://github.com/bybatkhuu/module-fastapi-logging.git && \
109
+ cd ./module-fastapi-logging
110
+
111
+ # Install directly from the source code:
112
+ pip install .
113
+
114
+ # Or install with editable mode:
115
+ pip install -e .
116
+ ```
117
+
118
+ **OPTION D.** Install for **DEVELOPMENT** environment:
119
+
120
+ ```sh
121
+ pip install -e .[dev]
122
+
123
+ # Install pre-commit hooks:
124
+ pre-commit install
125
+ ```
126
+
127
+ **OPTION E.** Install from **pre-built release** files:
128
+
129
+ 1. Download **`.whl`** or **`.tar.gz`** file from [**releases**](https://github.com/bybatkhuu/module-fastapi-logging/releases)
130
+ 2. Install with pip:
131
+
132
+ ```sh
133
+ # Install from .whl file:
134
+ pip install ./beans_logging_fastapi-[VERSION]-py3-none-any.whl
135
+
136
+ # Or install from .tar.gz file:
137
+ pip install ./beans_logging_fastapi-[VERSION].tar.gz
138
+ ```
139
+
140
+ **OPTION F.** Copy the **module** into the project directory (for **testing**):
141
+
142
+ ```sh
143
+ # Install python dependencies:
144
+ pip install -r ./requirements.txt
145
+
146
+ # Copy the module source code into the project:
147
+ cp -r ./src/beans_logging_fastapi [PROJECT_DIR]
148
+ # For example:
149
+ cp -r ./src/beans_logging_fastapi /some/path/project/
150
+ ```
151
+
152
+ ## 🚸 Usage/Examples
153
+
154
+ To use `beans_logging_fastapi`:
155
+
156
+ ### **FastAPI**
157
+
158
+ [**`configs/logger.yml`**](./examples/configs/logger.yml):
159
+
160
+ ```yaml
161
+ logger:
162
+ app_name: "fastapi-app"
163
+ intercept:
164
+ mute_modules: ["uvicorn.access"]
165
+ handlers:
166
+ default.all.file_handler:
167
+ enabled: true
168
+ default.err.file_handler:
169
+ enabled: true
170
+ default.all.json_handler:
171
+ enabled: true
172
+ default.err.json_handler:
173
+ enabled: true
174
+ extra:
175
+ http_std_debug_format: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
176
+ http_std_msg_format: '<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'
177
+ http_file_enabled: true
178
+ http_file_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}'
179
+ http_file_tz: "localtime"
180
+ http_log_path: "http/{app_name}.http.access.log"
181
+ http_err_path: "http/{app_name}.http.err.log"
182
+ http_json_enabled: true
183
+ http_json_path: "http.json/{app_name}.http.json.access.log"
184
+ http_json_err_path: "http.json/{app_name}.http.json.err.log"
185
+ ```
186
+
187
+ [**`.env`**](./examples/.env):
188
+
189
+ ```sh
190
+ ENV=development
191
+ DEBUG=true
192
+ ```
193
+
194
+ [**`logger.py`**](./examples/logger.py):
195
+
196
+ ```python
197
+ from typing import TYPE_CHECKING
198
+
199
+ if TYPE_CHECKING:
200
+ from loguru import Record
201
+
202
+ from beans_logging import Logger, LoggerLoader
203
+ from beans_logging_fastapi import (
204
+ add_http_file_handler,
205
+ add_http_file_json_handler,
206
+ http_file_format,
207
+ )
208
+
209
+ logger_loader = LoggerLoader()
210
+ logger: Logger = logger_loader.load()
211
+
212
+
213
+ def _http_file_format(record: "Record") -> str:
214
+ _format = http_file_format(
215
+ record=record,
216
+ msg_format=logger_loader.config.extra.http_file_format, # type: ignore
217
+ tz=logger_loader.config.extra.http_file_tz, # type: ignore
218
+ )
219
+ return _format
220
+
221
+
222
+ if logger_loader.config.extra.http_file_enabled: # type: ignore
223
+ add_http_file_handler(
224
+ logger_loader=logger_loader,
225
+ log_path=logger_loader.config.extra.http_log_path, # type: ignore
226
+ err_path=logger_loader.config.extra.http_err_path, # type: ignore
227
+ formatter=_http_file_format,
228
+ )
229
+
230
+ if logger_loader.config.extra.http_json_enabled: # type: ignore
231
+ add_http_file_json_handler(
232
+ logger_loader=logger_loader,
233
+ log_path=logger_loader.config.extra.http_json_path, # type: ignore
234
+ err_path=logger_loader.config.extra.http_json_err_path, # type: ignore
235
+ )
236
+
237
+
238
+ __all__ = [
239
+ "logger",
240
+ "logger_loader",
241
+ ]
242
+ ```
243
+
244
+ [**`main.py`**](./examples/main.py):
245
+
246
+ ```python
247
+ #!/usr/bin/env python
248
+
249
+ from typing import Union
250
+ from contextlib import asynccontextmanager
251
+
252
+ import uvicorn
253
+ from dotenv import load_dotenv
254
+ from fastapi import FastAPI, HTTPException
255
+ from fastapi.responses import RedirectResponse
256
+
257
+ load_dotenv()
258
+
259
+ from beans_logging_fastapi import (
260
+ HttpAccessLogMiddleware,
261
+ RequestHTTPInfoMiddleware,
262
+ ResponseHTTPInfoMiddleware,
263
+ )
264
+
265
+ from logger import logger, logger_loader
266
+ from __version__ import __version__
267
+
268
+
269
+ @asynccontextmanager
270
+ async def lifespan(app: FastAPI):
271
+ logger.info("Preparing to startup...")
272
+ logger.success("Finished preparation to startup.")
273
+ logger.info(f"API version: {__version__}")
274
+
275
+ yield
276
+ logger.info("Praparing to shutdown...")
277
+ logger.success("Finished preparation to shutdown.")
278
+
279
+
280
+ app = FastAPI(lifespan=lifespan, version=__version__)
281
+
282
+ app.add_middleware(ResponseHTTPInfoMiddleware)
283
+ app.add_middleware(
284
+ HttpAccessLogMiddleware,
285
+ debug_format=logger_loader.config.extra.http_std_debug_format, # type: ignore
286
+ msg_format=logger_loader.config.extra.http_std_msg_format, # type: ignore
287
+ )
288
+ app.add_middleware(
289
+ RequestHTTPInfoMiddleware, has_proxy_headers=True, has_cf_headers=True
290
+ )
291
+
292
+
293
+ @app.get("/")
294
+ def root():
295
+ return {"Hello": "World"}
296
+
297
+
298
+ @app.get("/items/{item_id}")
299
+ def read_item(item_id: int, q: Union[str, None] = None):
300
+ return {"item_id": item_id, "q": q}
301
+
302
+
303
+ @app.get("/continue", status_code=100)
304
+ def get_continue():
305
+ return {}
306
+
307
+
308
+ @app.get("/redirect")
309
+ def redirect():
310
+ return RedirectResponse("/")
311
+
312
+
313
+ @app.get("/error")
314
+ def error():
315
+ raise HTTPException(status_code=500)
316
+
317
+
318
+ if __name__ == "__main__":
319
+ uvicorn.run(
320
+ app="main:app",
321
+ host="0.0.0.0",
322
+ port=8000,
323
+ access_log=False,
324
+ server_header=False,
325
+ proxy_headers=True,
326
+ forwarded_allow_ips="*",
327
+ )
328
+ ```
329
+
330
+ Run the [**`examples`**](./examples):
331
+
332
+ ```sh
333
+ cd ./examples
334
+ # Install python dependencies for examples:
335
+ pip install -r ./requirements.txt
336
+
337
+ uvicorn main:app --host=0.0.0.0 --port=8000
338
+ ```
339
+
340
+ **Output**:
341
+
342
+ ```txt
343
+ [2025-12-01 00:00:00.735 +09:00 | TRACE | beans_logging._intercept:96]: Intercepted modules: ['potato_util.io', 'concurrent', 'potato_util', 'fastapi', 'uvicorn.error', 'dotenv.main', 'potato_util._base', 'watchfiles.watcher', 'dotenv', 'potato_util.io._sync', 'asyncio', 'uvicorn', 'concurrent.futures', 'watchfiles', 'watchfiles.main']; Muted modules: ['uvicorn.access'];
344
+ [2025-12-01 00:00:00.735 +09:00 | INFO | uvicorn.server:84]: Started server process [13580]
345
+ [2025-12-01 00:00:00.735 +09:00 | INFO | uvicorn.lifespan.on:48]: Waiting for application startup.
346
+ [2025-12-01 00:00:00.735 +09:00 | INFO | main:25]: Preparing to startup...
347
+ [2025-12-01 00:00:00.735 +09:00 | OK | main:26]: Finished preparation to startup.
348
+ [2025-12-01 00:00:00.735 +09:00 | INFO | main:27]: API version: 0.0.0
349
+ [2025-12-01 00:00:00.735 +09:00 | INFO | uvicorn.lifespan.on:62]: Application startup complete.
350
+ [2025-12-01 00:00:00.735 +09:00 | INFO | uvicorn.server:216]: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
351
+ [2025-12-01 00:00:00.736 +09:00 | DEBUG | anyio._backends._asyncio:986]: [4386400aab364895ba272f3200d2a778] 127.0.0.1 - "GET / HTTP/1.1"
352
+ [2025-12-01 00:00:00.736 +09:00 | OK | anyio._backends._asyncio:986]: [4386400aab364895ba272f3200d2a778] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 0.9ms
353
+ ^C[2025-12-01 00:00:00.750 +09:00 | INFO | uvicorn.server:264]: Shutting down
354
+ [2025-12-01 00:00:00.750 +09:00 | INFO | uvicorn.lifespan.on:67]: Waiting for application shutdown.
355
+ [2025-12-01 00:00:00.750 +09:00 | INFO | main:30]: Praparing to shutdown...
356
+ [2025-12-01 00:00:00.750 +09:00 | OK | main:31]: Finished preparation to shutdown.
357
+ [2025-12-01 00:00:00.750 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
358
+ [2025-12-01 00:00:00.750 +09:00 | INFO | uvicorn.server:94]: Finished server process [13580]
359
+ ```
360
+
361
+ 👍
362
+
363
+ ---
364
+
365
+ ## ⚙️ Configuration
366
+
367
+ [**`templates/configs/config.yml`**](./templates/configs/config.yml):
368
+
369
+ ```yaml
370
+ logger:
371
+ # app_name: "app"
372
+ default:
373
+ level:
374
+ base: INFO
375
+ err: WARNING
376
+ format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line}]: {message}"
377
+ file:
378
+ logs_dir: "./logs"
379
+ rotate_size: 10000000
380
+ rotate_time: "00:00:00"
381
+ retention: 90
382
+ encoding: utf8
383
+ custom_serialize: false
384
+ intercept:
385
+ enabled: true
386
+ only_base: false
387
+ ignore_modules: []
388
+ include_modules: []
389
+ mute_modules: ["uvicorn.access"]
390
+ handlers:
391
+ default.all.std_handler:
392
+ type: STD
393
+ 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>"
394
+ colorize: true
395
+ enabled: true
396
+ default.all.file_handler:
397
+ type: FILE
398
+ sink: "{app_name}.all.log"
399
+ enabled: true
400
+ default.err.file_handler:
401
+ type: FILE
402
+ sink: "{app_name}.err.log"
403
+ error: true
404
+ enabled: true
405
+ default.all.json_handler:
406
+ type: FILE
407
+ sink: "json/{app_name}.json.all.log"
408
+ serialize: true
409
+ enabled: true
410
+ default.err.json_handler:
411
+ type: FILE
412
+ sink: "json/{app_name}.json.err.log"
413
+ serialize: true
414
+ error: true
415
+ enabled: true
416
+ extra:
417
+ http_std_debug_format: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
418
+ http_std_msg_format: '<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'
419
+ http_file_enabled: true
420
+ http_file_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}'
421
+ http_file_tz: "localtime"
422
+ http_log_path: "http/{app_name}.http.access.log"
423
+ http_err_path: "http/{app_name}.http.err.log"
424
+ http_json_enabled: true
425
+ http_json_path: "http.json/{app_name}.http.json.access.log"
426
+ http_json_err_path: "http.json/{app_name}.http.json.err.log"
427
+ ```
428
+
429
+ ### 🌎 Environment Variables
430
+
431
+ [**`.env.example`**](./.env.example):
432
+
433
+ ```sh
434
+ # ENV=LOCAL
435
+ # DEBUG=false
436
+ # TZ=UTC
437
+ ```
438
+
439
+ ---
440
+
441
+ ## 🧪 Running Tests
442
+
443
+ To run tests, run the following command:
444
+
445
+ ```sh
446
+ # Install python test dependencies:
447
+ pip install .[test]
448
+
449
+ # Run tests:
450
+ python -m pytest -sv -o log_cli=true
451
+ # Or use the test script:
452
+ ./scripts/test.sh -l -v -c
453
+ ```
454
+
455
+ ## 🏗️ Build Package
456
+
457
+ To build the python package, run the following command:
458
+
459
+ ```sh
460
+ # Install python build dependencies:
461
+ pip install -r ./requirements/requirements.build.txt
462
+
463
+ # Build python package:
464
+ python -m build
465
+ # Or use the build script:
466
+ ./scripts/build.sh
467
+ ```
468
+
469
+ ## 📝 Generate Docs
470
+
471
+ To build the documentation, run the following command:
472
+
473
+ ```sh
474
+ # Install python documentation dependencies:
475
+ pip install -r ./requirements/requirements.docs.txt
476
+
477
+ # Serve documentation locally (for development):
478
+ mkdocs serve -a 0.0.0.0:8000
479
+ # Or use the docs script:
480
+ ./scripts/docs.sh
481
+
482
+ # Or build documentation:
483
+ mkdocs build
484
+ # Or use the docs script:
485
+ ./scripts/docs.sh -b
486
+ ```
487
+
488
+ ## 📚 Documentation
489
+
490
+ - [Docs](./docs)
491
+
492
+ ---
493
+
494
+ ## 📑 References
495
+
496
+ - <https://packaging.python.org/en/latest/tutorials/packaging-projects>
497
+ - <https://python-packaging.readthedocs.io/en/latest>