beans-logging-fastapi 1.1.1__py3-none-any.whl → 3.0.0__py3-none-any.whl

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.
@@ -0,0 +1,586 @@
1
+ Metadata-Version: 2.4
2
+ Name: beans_logging_fastapi
3
+ Version: 3.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<9.0.0,>=8.0.2
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
+ Requires-Dist: uvicorn[standard]<1.0.0,>=0.23.0; extra == "dev"
59
+ Dynamic: license-file
60
+
61
+ # FastAPI Logging (beans-logging-fastapi)
62
+
63
+ [![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit)
64
+ [![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)
65
+ [![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)
66
+
67
+ This is a HTTP access logging module for **FastAPI** based on **'beans-logging'** package.
68
+
69
+ ## ✨ Features
70
+
71
+ - **Logger** based on **'beans-logging'** package
72
+ - **FastAPI** HTTP access logging **middleware**
73
+ - HTTP access log as structured JSON format
74
+ - Predefined **configuration** for HTTP access logs
75
+ - Easy to **install** and **use**
76
+
77
+ ---
78
+
79
+ ## 🛠 Installation
80
+
81
+ ### 1. 🚧 Prerequisites
82
+
83
+ - Install **Python (>= v3.10)** and **pip (>= 23)**:
84
+ - **[RECOMMENDED] [Miniconda (v3)](https://www.anaconda.com/docs/getting-started/miniconda/install)**
85
+ - *[arm64/aarch64] [Miniforge (v3)](https://github.com/conda-forge/miniforge)*
86
+ - *[Python virutal environment] [venv](https://docs.python.org/3/library/venv.html)*
87
+
88
+ [OPTIONAL] For **DEVELOPMENT** environment:
89
+
90
+ - Install [**git**](https://git-scm.com/downloads)
91
+ - Setup an [**SSH key**](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh)
92
+
93
+ ### 2. 📦 Install the package
94
+
95
+ [NOTE] Choose one of the following methods to install the package **[A ~ F]**:
96
+
97
+ **OPTION A.** [**RECOMMENDED**] Install from **PyPi**:
98
+
99
+ ```sh
100
+ pip install -U beans-logging-fastapi
101
+ ```
102
+
103
+ **OPTION B.** Install latest version directly from **GitHub** repository:
104
+
105
+ ```sh
106
+ pip install git+https://github.com/bybatkhuu/module-fastapi-logging.git
107
+ ```
108
+
109
+ **OPTION C.** Install from the downloaded **source code**:
110
+
111
+ ```sh
112
+ git clone https://github.com/bybatkhuu/module-fastapi-logging.git && \
113
+ cd ./module-fastapi-logging
114
+
115
+ # Install directly from the source code:
116
+ pip install .
117
+
118
+ # Or install with editable mode:
119
+ pip install -e .
120
+ ```
121
+
122
+ **OPTION D.** Install for **DEVELOPMENT** environment:
123
+
124
+ ```sh
125
+ pip install -e .[dev]
126
+
127
+ # Install pre-commit hooks:
128
+ pre-commit install
129
+ ```
130
+
131
+ **OPTION E.** Install from **pre-built release** files:
132
+
133
+ 1. Download **`.whl`** or **`.tar.gz`** file from [**releases**](https://github.com/bybatkhuu/module-fastapi-logging/releases)
134
+ 2. Install with pip:
135
+
136
+ ```sh
137
+ # Install from .whl file:
138
+ pip install ./beans_logging_fastapi-[VERSION]-py3-none-any.whl
139
+
140
+ # Or install from .tar.gz file:
141
+ pip install ./beans_logging_fastapi-[VERSION].tar.gz
142
+ ```
143
+
144
+ **OPTION F.** Copy the **module** into the project directory (for **testing**):
145
+
146
+ ```sh
147
+ # Install python dependencies:
148
+ pip install -r ./requirements.txt
149
+
150
+ # Copy the module source code into the project:
151
+ cp -r ./src/beans_logging_fastapi [PROJECT_DIR]
152
+ # For example:
153
+ cp -r ./src/beans_logging_fastapi /some/path/project/
154
+ ```
155
+
156
+ ## 🚸 Usage/Examples
157
+
158
+ To use `beans_logging_fastapi`:
159
+
160
+ ### **FastAPI**
161
+
162
+ [**`configs/logger.yml`**](./examples/configs/logger.yml):
163
+
164
+ ```yaml
165
+ logger:
166
+ app_name: "fastapi-app"
167
+ default:
168
+ level:
169
+ base: TRACE
170
+ http:
171
+ std:
172
+ 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'
173
+ 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>'
174
+ debug_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
175
+ file:
176
+ 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}'
177
+ tz: "localtime"
178
+ headers:
179
+ has_proxy: false
180
+ has_cf: false
181
+ intercept:
182
+ mute_modules: ["uvicorn.access"]
183
+ handlers:
184
+ http.access.file_handler:
185
+ enabled: true
186
+ sink: "http/{app_name}.http-access.log"
187
+ http.err.file_handler:
188
+ enabled: true
189
+ sink: "http/{app_name}.http-err.log"
190
+ http.access.json_handler:
191
+ enabled: true
192
+ sink: "http.json/{app_name}.http-access.json.log"
193
+ http.err.json_handler:
194
+ enabled: true
195
+ sink: "http.json/{app_name}.http-err.json.log"
196
+ ```
197
+
198
+ [**`.env`**](./examples/.env):
199
+
200
+ ```sh
201
+ ENV=development
202
+ DEBUG=true
203
+ ```
204
+
205
+ [**`config.py`**](./examples/config.py):
206
+
207
+ ```python
208
+ import os
209
+
210
+ from pydantic_settings import BaseSettings
211
+
212
+ from potato_util import io as io_utils
213
+ from beans_logging_fastapi import LoggerConfigPM
214
+
215
+
216
+ _config_path = os.path.join(os.getcwd(), "configs", "logger.yml")
217
+ _config_data = {}
218
+ if os.path.isfile(_config_path):
219
+ _config_data = io_utils.read_config_file(config_path=_config_path)
220
+
221
+
222
+ class MainConfig(BaseSettings):
223
+ logger: LoggerConfigPM = LoggerConfigPM()
224
+
225
+
226
+ config = MainConfig(**_config_data)
227
+
228
+
229
+ __all__ = [
230
+ "MainConfig",
231
+ "config",
232
+ ]
233
+ ```
234
+
235
+ [**`logger.py`**](./examples/logger.py):
236
+
237
+ ```python
238
+ from beans_logging_fastapi import logger
239
+
240
+ __all__ = [
241
+ "logger",
242
+ ]
243
+ ```
244
+
245
+ [**`router.py`**](./examples/router.py):
246
+
247
+ ```python
248
+ from pydantic import validate_call
249
+ from fastapi import FastAPI, APIRouter, HTTPException
250
+ from fastapi.responses import RedirectResponse
251
+
252
+ router = APIRouter()
253
+
254
+
255
+ @router.get("/")
256
+ def root():
257
+ return {"Hello": "World"}
258
+
259
+
260
+ @router.get("/items/{item_id}")
261
+ def read_item(item_id: int, q: str | None = None):
262
+ return {"item_id": item_id, "q": q}
263
+
264
+
265
+ @router.get("/continue", status_code=100)
266
+ def get_continue():
267
+ return {}
268
+
269
+
270
+ @router.get("/redirect")
271
+ def redirect():
272
+ return RedirectResponse("/")
273
+
274
+
275
+ @router.get("/error")
276
+ def error():
277
+ raise HTTPException(status_code=500)
278
+
279
+
280
+ @validate_call(config={"arbitrary_types_allowed": True})
281
+ def add_routers(app: FastAPI) -> None:
282
+ """Add routers to FastAPI app.
283
+
284
+ Args:
285
+ app (FastAPI): FastAPI app instance.
286
+ """
287
+
288
+ app.include_router(router)
289
+
290
+ return
291
+
292
+
293
+ __all__ = ["add_routers"]
294
+ ```
295
+
296
+ [**`bootstrap.py`**](./examples/bootstrap.py):
297
+
298
+ ```python
299
+ # Standard libraries
300
+ from typing import Any
301
+ from collections.abc import Callable
302
+
303
+ # Third-party libraries
304
+ import uvicorn
305
+ from uvicorn._types import ASGIApplication
306
+ from pydantic import validate_call
307
+ from fastapi import FastAPI
308
+
309
+ from beans_logging_fastapi import add_logger
310
+
311
+ # Internal modules
312
+ from __version__ import __version__
313
+ from config import config
314
+ from lifespan import lifespan
315
+ from router import add_routers
316
+
317
+
318
+ def create_app() -> FastAPI:
319
+ """Create FastAPI application instance.
320
+
321
+ Returns:
322
+ FastAPI: FastAPI application instance.
323
+ """
324
+
325
+ app = FastAPI(lifespan=lifespan, version=__version__)
326
+
327
+ # Add logger before any other components:
328
+ add_logger(app=app, config=config.logger)
329
+
330
+ # Add any other components after logger:
331
+ add_routers(app=app)
332
+
333
+ return app
334
+
335
+
336
+ @validate_call(config={"arbitrary_types_allowed": True})
337
+ def run_server(
338
+ app: FastAPI | ASGIApplication | Callable[..., Any] | str = "main:app",
339
+ ) -> None:
340
+ """Run uvicorn server.
341
+
342
+ Args:
343
+ app (Union[ASGIApplication, str], optional): ASGI application instance or module path.
344
+ """
345
+
346
+ uvicorn.run(
347
+ app=app,
348
+ host="0.0.0.0", # nosec B104
349
+ port=8000,
350
+ access_log=False, # Disable default uvicorn access log
351
+ server_header=False,
352
+ proxy_headers=False,
353
+ forwarded_allow_ips="*",
354
+ )
355
+
356
+ return
357
+
358
+
359
+ __all__ = [
360
+ "create_app",
361
+ "run_server",
362
+ ]
363
+ ```
364
+
365
+ [**`main.py`**](./examples/main.py):
366
+
367
+ ```python
368
+ #!/usr/bin/env python
369
+
370
+ # Third-party libraries
371
+ from dotenv import load_dotenv
372
+
373
+ load_dotenv(override=True)
374
+
375
+ # Internal modules
376
+ from bootstrap import create_app, run_server # noqa: E402
377
+ from logger import logger # noqa: E402
378
+
379
+
380
+ app = create_app()
381
+
382
+
383
+ def main() -> None:
384
+ """Main function."""
385
+
386
+ run_server(app=app)
387
+ return
388
+
389
+
390
+ if __name__ == "__main__":
391
+ logger.info("Starting server from 'main.py'...")
392
+ main()
393
+
394
+
395
+ __all__ = ["app"]
396
+ ```
397
+
398
+ Run the [**`examples`**](./examples):
399
+
400
+ ```sh
401
+ cd ./examples
402
+ # Install python dependencies for examples:
403
+ pip install -r ./requirements.txt
404
+
405
+ uvicorn main:app --host=0.0.0.0 --port=8000
406
+ ```
407
+
408
+ **Output**:
409
+
410
+ ```txt
411
+ [2026-01-01 12:00:00.907 +09:00 | TRACE | beans_logging.intercepters:96]: Intercepted modules: ['concurrent.futures', 'potato_util', 'watchfiles.watcher', 'potato_util.io._sync', 'concurrent', 'uvicorn', 'fastapi', 'uvicorn.error', 'dotenv.main', 'watchfiles.main', 'asyncio', 'dotenv', 'potato_util._base', 'potato_util.io', 'watchfiles']; Muted modules: ['uvicorn.access'];
412
+ [2026-01-01 12:00:00.908 +09:00 | INFO | uvicorn.server:84]: Started server process [64590]
413
+ [2026-01-01 12:00:00.909 +09:00 | INFO | uvicorn.lifespan.on:48]: Waiting for application startup.
414
+ [2026-01-01 12:00:00.909 +09:00 | TRACE | lifespan:19]: TRACE diagnosis is ON!
415
+ [2026-01-01 12:00:00.909 +09:00 | DEBUG | lifespan:20]: DEBUG mode is ON!
416
+ [2026-01-01 12:00:00.909 +09:00 | INFO | lifespan:21]: Preparing to startup...
417
+ [2026-01-01 12:00:00.909 +09:00 | OK | lifespan:24]: Finished preparation to startup.
418
+ [2026-01-01 12:00:00.909 +09:00 | INFO | lifespan:25]: Version: 0.0.0
419
+ [2026-01-01 12:00:00.909 +09:00 | INFO | uvicorn.lifespan.on:62]: Application startup complete.
420
+ [2026-01-01 12:00:00.911 +09:00 | INFO | uvicorn.server:216]: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
421
+ [2026-01-01 12:00:01.582 +09:00 | DEBUG | anyio._backends._asyncio:986]: [c433596f728744aaa1cde63399dd3995] 127.0.0.1 - "GET / HTTP/1.1"
422
+ [2026-01-01 12:00:01.586 +09:00 | OK | anyio._backends._asyncio:986]: [c433596f728744aaa1cde63399dd3995] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 3.1ms
423
+ ^C[2026-01-01 12:00:02.074 +09:00 | INFO | uvicorn.server:264]: Shutting down
424
+ [2026-01-01 12:00:02.177 +09:00 | INFO | uvicorn.lifespan.on:67]: Waiting for application shutdown.
425
+ [2026-01-01 12:00:02.178 +09:00 | INFO | lifespan:29]: Preparing to shutdown...
426
+ [2026-01-01 12:00:02.179 +09:00 | OK | lifespan:31]: Finished preparation to shutdown.
427
+ [2026-01-01 12:00:02.179 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
428
+ [2026-01-01 12:00:02.180 +09:00 | INFO | uvicorn.server:94]: Finished server process [64590]
429
+ ```
430
+
431
+ 👍
432
+
433
+ ---
434
+
435
+ ## ⚙️ Configuration
436
+
437
+ [**`templates/configs/config.yml`**](./templates/configs/config.yml):
438
+
439
+ ```yaml
440
+ logger:
441
+ # app_name: fastapi-app
442
+ default:
443
+ level:
444
+ base: INFO
445
+ err: WARNING
446
+ format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line}]: {message}"
447
+ file:
448
+ logs_dir: "./logs"
449
+ rotate_size: 10000000
450
+ rotate_time: "00:00:00"
451
+ retention: 90
452
+ encoding: utf8
453
+ custom_serialize: false
454
+ http:
455
+ std:
456
+ format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" {status_code} {content_length}B {response_time}ms'
457
+ err_format_str: '<n><w>[{request_id}]</w></n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}" <n>{status_code}</n>'
458
+ debug_format_str: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
459
+ file:
460
+ format_str: '{client_host} {request_id} {user_id} [{datetime}] "{method} {url_path} HTTP/{http_version}" {status_code} {content_length} "{h_referer}" "{h_user_agent}" {response_time}'
461
+ tz: localtime
462
+ headers:
463
+ has_proxy: false
464
+ has_cf: false
465
+ intercept:
466
+ enabled: true
467
+ only_base: false
468
+ ignore_modules: []
469
+ include_modules: []
470
+ mute_modules: [uvicorn.access]
471
+ handlers:
472
+ default.all.std_handler:
473
+ 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>"
476
+ colorize: true
477
+ default.all.file_handler:
478
+ enabled: true
479
+ h_type: FILE
480
+ sink: "{app_name}.all.log"
481
+ default.err.file_handler:
482
+ enabled: true
483
+ h_type: FILE
484
+ sink: "{app_name}.err.log"
485
+ error: true
486
+ default.all.json_handler:
487
+ enabled: true
488
+ h_type: FILE
489
+ sink: "json/{app_name}.all.json.log"
490
+ serialize: true
491
+ default.err.json_handler:
492
+ enabled: true
493
+ h_type: FILE
494
+ sink: "json/{app_name}.err.json.log"
495
+ serialize: true
496
+ error: true
497
+ http.access.file_handler:
498
+ enabled: true
499
+ h_type: FILE
500
+ sink: "http/{app_name}.http-access.log"
501
+ http.err.file_handler:
502
+ enabled: true
503
+ h_type: FILE
504
+ sink: "http/{app_name}.http-err.log"
505
+ error: true
506
+ http.access.json_handler:
507
+ enabled: true
508
+ h_type: FILE
509
+ sink: "http.json/{app_name}.http-access.json.log"
510
+ http.err.json_handler:
511
+ enabled: true
512
+ h_type: FILE
513
+ sink: "http.json/{app_name}.http-err.json.log"
514
+ error: true
515
+ extra:
516
+ ```
517
+
518
+ ### 🌎 Environment Variables
519
+
520
+ [**`.env.example`**](./.env.example):
521
+
522
+ ```sh
523
+ # ENV=LOCAL
524
+ # DEBUG=false
525
+ # TZ=UTC
526
+ ```
527
+
528
+ ---
529
+
530
+ ## 🧪 Running Tests
531
+
532
+ To run tests, run the following command:
533
+
534
+ ```sh
535
+ # Install python test dependencies:
536
+ pip install .[test]
537
+
538
+ # Run tests:
539
+ python -m pytest -sv -o log_cli=true
540
+ # Or use the test script:
541
+ ./scripts/test.sh -l -v -c
542
+ ```
543
+
544
+ ## 🏗️ Build Package
545
+
546
+ To build the python package, run the following command:
547
+
548
+ ```sh
549
+ # Install python build dependencies:
550
+ pip install -r ./requirements/requirements.build.txt
551
+
552
+ # Build python package:
553
+ python -m build
554
+ # Or use the build script:
555
+ ./scripts/build.sh
556
+ ```
557
+
558
+ ## 📝 Generate Docs
559
+
560
+ To build the documentation, run the following command:
561
+
562
+ ```sh
563
+ # Install python documentation dependencies:
564
+ pip install -r ./requirements/requirements.docs.txt
565
+
566
+ # Serve documentation locally (for development):
567
+ mkdocs serve -a 0.0.0.0:8000 --livereload
568
+ # Or use the docs script:
569
+ ./scripts/docs.sh
570
+
571
+ # Or build documentation:
572
+ mkdocs build
573
+ # Or use the docs script:
574
+ ./scripts/docs.sh -b
575
+ ```
576
+
577
+ ## 📚 Documentation
578
+
579
+ - [Docs](./docs)
580
+
581
+ ---
582
+
583
+ ## 📑 References
584
+
585
+ - <https://packaging.python.org/en/latest/tutorials/packaging-projects>
586
+ - <https://python-packaging.readthedocs.io/en/latest>
@@ -0,0 +1,14 @@
1
+ beans_logging_fastapi/__init__.py,sha256=5nnhUvYdtaMSZ1t549nhYfxOzcKsC4YPx8nEqJWfZYw,225
2
+ beans_logging_fastapi/__version__.py,sha256=EPmgXOdWKks5S__ZMH7Nu6xpAeVrZpfxaFy4pykuyeI,22
3
+ beans_logging_fastapi/_async.py,sha256=IcoQPeBfZwPLt-WBJBpc7g5pELh6plf7VYUel2KyM_c,3478
4
+ beans_logging_fastapi/_core.py,sha256=NUpQGvuLw5YlRNTvssBo4aqrE0lia4nhL1aDahZXncU,2744
5
+ beans_logging_fastapi/config.py,sha256=gt9Kh0-MOZdf0LMGV5gbyYucoTkF8He5QceUP-9vS8U,5298
6
+ beans_logging_fastapi/constants.py,sha256=pRsgi1pqkEDMKmSWDQeK72TSXiuVkJaEMTOUeB82E5A,382
7
+ beans_logging_fastapi/filters.py,sha256=hBhHqCWJr7c2CA7uDAje8R8x9RtpCcBHZSC6xuXLYDs,622
8
+ beans_logging_fastapi/formats.py,sha256=ENfCB54ftUZZFj5J9kKCsdCkeqzStG3l0_9vLBLi8Oc,2600
9
+ beans_logging_fastapi/middlewares.py,sha256=ToUS4jPUPcZHTr_d7DWLjfBI-E9FrspasRqkc4Gyg2M,13676
10
+ beans_logging_fastapi-3.0.0.dist-info/licenses/LICENSE.txt,sha256=CUTK-r0BWIg1r0bBiemAcMhakgV0N7HuRhw6rQ-A9A4,1074
11
+ beans_logging_fastapi-3.0.0.dist-info/METADATA,sha256=iL3NjWvF6KMVxaO7RytgEMuGxMoWAQBlyXqF0lsaBdM,17344
12
+ beans_logging_fastapi-3.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
+ beans_logging_fastapi-3.0.0.dist-info/top_level.txt,sha256=PXoqVo9HGfyd81gDi3D2mXMYPM9JKITL0ycFftJxlhw,22
14
+ beans_logging_fastapi-3.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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