beans-logging 4.1.1__tar.gz → 6.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {beans_logging-4.1.1 → beans_logging-6.0.0}/PKG-INFO +22 -164
- {beans_logging-4.1.1 → beans_logging-6.0.0}/README.md +17 -161
- beans_logging-6.0.0/beans_logging/__init__.py +16 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/__version__.py +1 -1
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/_base.py +35 -10
- beans_logging-6.0.0/beans_logging/_consts.py +20 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/_utils.py +36 -5
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/auto.py +11 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/schemas.py +70 -53
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging.egg-info/PKG-INFO +22 -164
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging.egg-info/SOURCES.txt +1 -6
- beans_logging-6.0.0/beans_logging.egg-info/requires.txt +6 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/setup.py +2 -1
- beans_logging-4.1.1/beans_logging/__init__.py +0 -6
- beans_logging-4.1.1/beans_logging/_const.py +0 -10
- beans_logging-4.1.1/beans_logging/fastapi/__init__.py +0 -6
- beans_logging-4.1.1/beans_logging/fastapi/_filters.py +0 -22
- beans_logging-4.1.1/beans_logging/fastapi/_formats.py +0 -49
- beans_logging-4.1.1/beans_logging/fastapi/_handlers.py +0 -74
- beans_logging-4.1.1/beans_logging/fastapi/_middlewares.py +0 -239
- beans_logging-4.1.1/beans_logging.egg-info/requires.txt +0 -3
- {beans_logging-4.1.1 → beans_logging-6.0.0}/LICENSE.txt +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/_handlers.py +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/filters.py +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/formats.py +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/rotation.py +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging/sinks.py +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging.egg-info/dependency_links.txt +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/beans_logging.egg-info/top_level.txt +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/setup.cfg +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/tests/__init__.py +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/tests/conftest.py +0 -0
- {beans_logging-4.1.1 → beans_logging-6.0.0}/tests/test_beans_logging.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: beans_logging
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.0
|
|
4
4
|
Summary: 'beans_logging' is a python package for simple logger and easily managing logging modules. It is a Loguru based custom logging package for python projects.
|
|
5
5
|
Home-page: https://github.com/bybatkhuu/module.python-logging
|
|
6
|
-
Download-URL: https://github.com/bybatkhuu/module.python-logging/archive/
|
|
6
|
+
Download-URL: https://github.com/bybatkhuu/module.python-logging/archive/v6.0.0.tar.gz
|
|
7
7
|
Author: Batkhuu Byambajav
|
|
8
8
|
Author-email: batkhuu10@gmail.com
|
|
9
9
|
License: MIT
|
|
@@ -20,8 +20,10 @@ Requires-Python: >=3.8
|
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE.txt
|
|
22
22
|
Requires-Dist: PyYAML<7.0,>=6.0
|
|
23
|
-
Requires-Dist: pydantic
|
|
23
|
+
Requires-Dist: pydantic!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.10.0
|
|
24
24
|
Requires-Dist: loguru<1.0.0,>=0.7.2
|
|
25
|
+
Provides-Extra: fastapi
|
|
26
|
+
Requires-Dist: beans-logging-fastapi<2.0.0,>=1.0.0; extra == "fastapi"
|
|
25
27
|
|
|
26
28
|
# beans_logging
|
|
27
29
|
|
|
@@ -47,8 +49,8 @@ It is a `Loguru` based custom logging package for python projects.
|
|
|
47
49
|
- Custom logging **formats**
|
|
48
50
|
- **Multiprocess** compatibility (Linux, macOS - 'fork')
|
|
49
51
|
- Add custom **handlers**
|
|
50
|
-
- **FastAPI** HTTP access logging **middleware**
|
|
51
52
|
- **Base** logging module
|
|
53
|
+
- Support **Pydantic-v1** and **Pydantic-v2**
|
|
52
54
|
|
|
53
55
|
---
|
|
54
56
|
|
|
@@ -206,16 +208,16 @@ python ./main.py
|
|
|
206
208
|
**Output**:
|
|
207
209
|
|
|
208
210
|
```txt
|
|
209
|
-
[2023-09-01
|
|
210
|
-
[2023-09-01
|
|
211
|
-
[2023-09-01
|
|
212
|
-
[2023-09-01
|
|
213
|
-
[2023-09-01
|
|
214
|
-
[2023-09-01
|
|
215
|
-
[2023-09-01
|
|
216
|
-
[2023-09-01
|
|
217
|
-
[2023-09-01
|
|
218
|
-
[2023-09-01
|
|
211
|
+
[2023-09-01 00:00:00.000 +09:00 | TRACE | beans_logging._base:478]: Intercepted modules: ['concurrent', 'concurrent.futures', 'asyncio']; Muted modules: [];
|
|
212
|
+
[2023-09-01 00:00:00.000 +09:00 | TRACE | __main__:7]: Tracing...
|
|
213
|
+
[2023-09-01 00:00:00.000 +09:00 | DEBUG | __main__:8]: Debugging...
|
|
214
|
+
[2023-09-01 00:00:00.000 +09:00 | INFO | __main__:9]: Logging info.
|
|
215
|
+
[2023-09-01 00:00:00.000 +09:00 | OK | __main__:10]: Success.
|
|
216
|
+
[2023-09-01 00:00:00.000 +09:00 | WARN | __main__:11]: Warning something.
|
|
217
|
+
[2023-09-01 00:00:00.000 +09:00 | ERROR | __main__:12]: Error occured.
|
|
218
|
+
[2023-09-01 00:00:00.000 +09:00 | CRIT | __main__:13]: CRITICAL ERROR.
|
|
219
|
+
[2023-09-01 00:00:00.000 +09:00 | ERROR | __main__:25]: division by zero
|
|
220
|
+
[2023-09-01 00:00:00.000 +09:00 | ERROR | __main__:32]: Show me, what value is wrong:
|
|
219
221
|
Traceback (most recent call last):
|
|
220
222
|
|
|
221
223
|
> File "/home/user/workspaces/projects/beans_logging/examples/simple/./main.py", line 30, in <module>
|
|
@@ -235,157 +237,12 @@ Traceback (most recent call last):
|
|
|
235
237
|
ZeroDivisionError: division by zero
|
|
236
238
|
```
|
|
237
239
|
|
|
238
|
-
### **
|
|
240
|
+
### **FastAPI**
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
Checkout `beans_logging_fastapi` package: <https://github.com/bybatkhuu/module.fastapi-logging>
|
|
241
243
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
app_name: "fastapi-app"
|
|
245
|
-
level: "TRACE"
|
|
246
|
-
use_diagnose: false
|
|
247
|
-
stream:
|
|
248
|
-
use_color: true
|
|
249
|
-
use_icon: false
|
|
250
|
-
format_str: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{level_short:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
|
|
251
|
-
std_handler:
|
|
252
|
-
enabled: true
|
|
253
|
-
file:
|
|
254
|
-
logs_dir: "./logs"
|
|
255
|
-
rotate_size: 10000000 # 10MB
|
|
256
|
-
rotate_time: "00:00:00"
|
|
257
|
-
backup_count: 90
|
|
258
|
-
log_handlers:
|
|
259
|
-
enabled: true
|
|
260
|
-
format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {level_short:<5} | {name}:{line}]: {message}"
|
|
261
|
-
log_path: "{app_name}.std.all.log"
|
|
262
|
-
err_path: "{app_name}.std.err.log"
|
|
263
|
-
json_handlers:
|
|
264
|
-
enabled: true
|
|
265
|
-
use_custom: false
|
|
266
|
-
log_path: "json/{app_name}.json.all.log"
|
|
267
|
-
err_path: "json/{app_name}.json.err.log"
|
|
268
|
-
intercept:
|
|
269
|
-
auto_load:
|
|
270
|
-
enabled: true
|
|
271
|
-
only_base: false
|
|
272
|
-
ignore_modules: []
|
|
273
|
-
include_modules: []
|
|
274
|
-
mute_modules: ["uvicorn.access", "uvicorn.error"]
|
|
275
|
-
extra:
|
|
276
|
-
http_std_debug_format: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
277
|
-
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'
|
|
278
|
-
http_file_enabled: true
|
|
279
|
-
http_log_path: "http/{app_name}.http.access.log"
|
|
280
|
-
http_err_path: "http/{app_name}.http.err.log"
|
|
281
|
-
http_json_enabled: true
|
|
282
|
-
http_json_path: "json.http/{app_name}.json.http.access.log"
|
|
283
|
-
http_json_err_path: "json.http/{app_name}.json.http.err.log"
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
[**`.env`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/.env):
|
|
287
|
-
|
|
288
|
-
```sh
|
|
289
|
-
ENV=development
|
|
290
|
-
DEBUG=true
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
[**`logger.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/logger.py):
|
|
294
|
-
|
|
295
|
-
```python
|
|
296
|
-
from beans_logging import Logger, LoggerLoader
|
|
297
|
-
from beans_logging.fastapi import add_http_file_handler, add_http_file_json_handler
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
logger_loader = LoggerLoader()
|
|
301
|
-
logger: Logger = logger_loader.load()
|
|
302
|
-
|
|
303
|
-
if logger_loader.config.extra.http_file_enabled:
|
|
304
|
-
add_http_file_handler(
|
|
305
|
-
logger_loader=logger_loader,
|
|
306
|
-
log_path=logger_loader.config.extra.http_log_path,
|
|
307
|
-
err_path=logger_loader.config.extra.http_err_path,
|
|
308
|
-
)
|
|
309
|
-
|
|
310
|
-
if logger_loader.config.extra.http_json_enabled:
|
|
311
|
-
add_http_file_json_handler(
|
|
312
|
-
logger_loader=logger_loader,
|
|
313
|
-
log_path=logger_loader.config.extra.http_json_path,
|
|
314
|
-
err_path=logger_loader.config.extra.http_json_err_path,
|
|
315
|
-
)
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
[**`app.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/app.py):
|
|
319
|
-
|
|
320
|
-
```python
|
|
321
|
-
from typing import Union
|
|
322
|
-
from contextlib import asynccontextmanager
|
|
323
|
-
|
|
324
|
-
from dotenv import load_dotenv
|
|
325
|
-
from fastapi import FastAPI, HTTPException
|
|
326
|
-
from fastapi.responses import RedirectResponse
|
|
327
|
-
|
|
328
|
-
load_dotenv()
|
|
329
|
-
|
|
330
|
-
from beans_logging.fastapi import HttpAccessLogMiddleware
|
|
331
|
-
|
|
332
|
-
from logger import logger, logger_loader
|
|
333
|
-
from __version__ import __version__
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
@asynccontextmanager
|
|
337
|
-
async def lifespan(app: FastAPI):
|
|
338
|
-
logger.info("Preparing to startup...")
|
|
339
|
-
logger.success("Finished preparation to startup.")
|
|
340
|
-
logger.info(f"API version: {__version__}")
|
|
341
|
-
|
|
342
|
-
yield
|
|
343
|
-
logger.info("Praparing to shutdown...")
|
|
344
|
-
logger.success("Finished preparation to shutdown.")
|
|
345
|
-
|
|
346
|
-
app = FastAPI(lifespan=lifespan, version=__version__)
|
|
347
|
-
app.add_middleware(
|
|
348
|
-
HttpAccessLogMiddleware,
|
|
349
|
-
has_proxy_headers=True,
|
|
350
|
-
debug_format=logger_loader.config.extra.http_std_debug_format,
|
|
351
|
-
msg_format=logger_loader.config.extra.http_std_msg_format,
|
|
352
|
-
)
|
|
353
|
-
|
|
354
|
-
@app.get("/")
|
|
355
|
-
def root():
|
|
356
|
-
return {"Hello": "World"}
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
Run the [**`examples/advanced`**](https://github.com/bybatkhuu/module.python-logging/tree/main/examples/advanced):
|
|
360
|
-
|
|
361
|
-
```sh
|
|
362
|
-
cd ./examples/advanced
|
|
363
|
-
# Install python dependencies for examples:
|
|
364
|
-
pip install -r ./requirements.txt
|
|
365
|
-
|
|
366
|
-
uvicorn app:app --host=0.0.0.0 --port=8000
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
**Output**:
|
|
370
|
-
|
|
371
|
-
```txt
|
|
372
|
-
[2023-09-01 12:37:38.569 +09:00 | TRACE | beans_logging._base:499]: Intercepted modules: ['watchfiles.watcher', 'asyncio', 'watchfiles', 'concurrent', 'dotenv', 'concurrent.futures', 'fastapi', 'dotenv.main', 'uvicorn', 'watchfiles.main']; Muted modules: ['uvicorn.error', 'uvicorn.access'];
|
|
373
|
-
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.server:76]: Started server process [22599]
|
|
374
|
-
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.lifespan.on:46]: Waiting for application startup.
|
|
375
|
-
[2023-09-01 12:37:38.579 +09:00 | INFO | app:21]: Preparing to startup...
|
|
376
|
-
[2023-09-01 12:37:38.580 +09:00 | OK | app:22]: Finished preparation to startup.
|
|
377
|
-
[2023-09-01 12:37:38.580 +09:00 | INFO | app:23]: API version: 0.0.1-000000
|
|
378
|
-
[2023-09-01 12:37:38.580 +09:00 | INFO | uvicorn.lifespan.on:60]: Application startup complete.
|
|
379
|
-
[2023-09-01 12:37:38.582 +09:00 | INFO | uvicorn.server:218]: Uvicorn running on http://0.0.0.0:9000 (Press CTRL+C to quit)
|
|
380
|
-
[2023-09-01 12:37:48.487 +09:00 | DEBUG | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1"
|
|
381
|
-
[2023-09-01 12:37:48.488 +09:00 | OK | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 0.5ms
|
|
382
|
-
^C[2023-09-01 12:37:51.845 +09:00 | INFO | uvicorn.server:264]: Shutting down
|
|
383
|
-
[2023-09-01 12:37:51.949 +09:00 | INFO | uvicorn.lifespan.on:65]: Waiting for application shutdown.
|
|
384
|
-
[2023-09-01 12:37:51.951 +09:00 | INFO | app:26]: Praparing to shutdown...
|
|
385
|
-
[2023-09-01 12:37:51.952 +09:00 | OK | app:27]: Finished preparation to shutdown.
|
|
386
|
-
[2023-09-01 12:37:51.952 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
|
|
387
|
-
[2023-09-01 12:37:51.953 +09:00 | INFO | uvicorn.server:86]: Finished server process [22599]
|
|
388
|
-
```
|
|
244
|
+
- FastAPI HTTP access logging middleware
|
|
245
|
+
- Install with pip: `pip install -U beans-logging[fastapi]` or `pip install -U beans-logging-fastapi`
|
|
389
246
|
|
|
390
247
|
---
|
|
391
248
|
|
|
@@ -411,7 +268,7 @@ DEBUG=true
|
|
|
411
268
|
|
|
412
269
|
BEANS_LOGGING_DISABLE_DEFAULT=false
|
|
413
270
|
BEANS_LOGGING_CONFIG_PATH="./configs/logger.yml"
|
|
414
|
-
|
|
271
|
+
BEANS_LOGGING_LOGS_DIR="./logs"
|
|
415
272
|
```
|
|
416
273
|
|
|
417
274
|
## Configuration
|
|
@@ -466,3 +323,4 @@ logger:
|
|
|
466
323
|
- <https://github.com/Delgan/loguru>
|
|
467
324
|
- <https://loguru.readthedocs.io/en/stable/api/logger.html>
|
|
468
325
|
- <https://loguru.readthedocs.io/en/stable/resources/recipes.html>
|
|
326
|
+
- <https://github.com/bybatkhuu/module.fastapi-logging>
|
|
@@ -22,8 +22,8 @@ It is a `Loguru` based custom logging package for python projects.
|
|
|
22
22
|
- Custom logging **formats**
|
|
23
23
|
- **Multiprocess** compatibility (Linux, macOS - 'fork')
|
|
24
24
|
- Add custom **handlers**
|
|
25
|
-
- **FastAPI** HTTP access logging **middleware**
|
|
26
25
|
- **Base** logging module
|
|
26
|
+
- Support **Pydantic-v1** and **Pydantic-v2**
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
@@ -181,16 +181,16 @@ python ./main.py
|
|
|
181
181
|
**Output**:
|
|
182
182
|
|
|
183
183
|
```txt
|
|
184
|
-
[2023-09-01
|
|
185
|
-
[2023-09-01
|
|
186
|
-
[2023-09-01
|
|
187
|
-
[2023-09-01
|
|
188
|
-
[2023-09-01
|
|
189
|
-
[2023-09-01
|
|
190
|
-
[2023-09-01
|
|
191
|
-
[2023-09-01
|
|
192
|
-
[2023-09-01
|
|
193
|
-
[2023-09-01
|
|
184
|
+
[2023-09-01 00:00:00.000 +09:00 | TRACE | beans_logging._base:478]: Intercepted modules: ['concurrent', 'concurrent.futures', 'asyncio']; Muted modules: [];
|
|
185
|
+
[2023-09-01 00:00:00.000 +09:00 | TRACE | __main__:7]: Tracing...
|
|
186
|
+
[2023-09-01 00:00:00.000 +09:00 | DEBUG | __main__:8]: Debugging...
|
|
187
|
+
[2023-09-01 00:00:00.000 +09:00 | INFO | __main__:9]: Logging info.
|
|
188
|
+
[2023-09-01 00:00:00.000 +09:00 | OK | __main__:10]: Success.
|
|
189
|
+
[2023-09-01 00:00:00.000 +09:00 | WARN | __main__:11]: Warning something.
|
|
190
|
+
[2023-09-01 00:00:00.000 +09:00 | ERROR | __main__:12]: Error occured.
|
|
191
|
+
[2023-09-01 00:00:00.000 +09:00 | CRIT | __main__:13]: CRITICAL ERROR.
|
|
192
|
+
[2023-09-01 00:00:00.000 +09:00 | ERROR | __main__:25]: division by zero
|
|
193
|
+
[2023-09-01 00:00:00.000 +09:00 | ERROR | __main__:32]: Show me, what value is wrong:
|
|
194
194
|
Traceback (most recent call last):
|
|
195
195
|
|
|
196
196
|
> File "/home/user/workspaces/projects/beans_logging/examples/simple/./main.py", line 30, in <module>
|
|
@@ -210,157 +210,12 @@ Traceback (most recent call last):
|
|
|
210
210
|
ZeroDivisionError: division by zero
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
-
### **
|
|
213
|
+
### **FastAPI**
|
|
214
214
|
|
|
215
|
-
|
|
215
|
+
Checkout `beans_logging_fastapi` package: <https://github.com/bybatkhuu/module.fastapi-logging>
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
app_name: "fastapi-app"
|
|
220
|
-
level: "TRACE"
|
|
221
|
-
use_diagnose: false
|
|
222
|
-
stream:
|
|
223
|
-
use_color: true
|
|
224
|
-
use_icon: false
|
|
225
|
-
format_str: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{level_short:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
|
|
226
|
-
std_handler:
|
|
227
|
-
enabled: true
|
|
228
|
-
file:
|
|
229
|
-
logs_dir: "./logs"
|
|
230
|
-
rotate_size: 10000000 # 10MB
|
|
231
|
-
rotate_time: "00:00:00"
|
|
232
|
-
backup_count: 90
|
|
233
|
-
log_handlers:
|
|
234
|
-
enabled: true
|
|
235
|
-
format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {level_short:<5} | {name}:{line}]: {message}"
|
|
236
|
-
log_path: "{app_name}.std.all.log"
|
|
237
|
-
err_path: "{app_name}.std.err.log"
|
|
238
|
-
json_handlers:
|
|
239
|
-
enabled: true
|
|
240
|
-
use_custom: false
|
|
241
|
-
log_path: "json/{app_name}.json.all.log"
|
|
242
|
-
err_path: "json/{app_name}.json.err.log"
|
|
243
|
-
intercept:
|
|
244
|
-
auto_load:
|
|
245
|
-
enabled: true
|
|
246
|
-
only_base: false
|
|
247
|
-
ignore_modules: []
|
|
248
|
-
include_modules: []
|
|
249
|
-
mute_modules: ["uvicorn.access", "uvicorn.error"]
|
|
250
|
-
extra:
|
|
251
|
-
http_std_debug_format: '<n>[{request_id}]</n> {client_host} {user_id} "<u>{method} {url_path}</u> HTTP/{http_version}"'
|
|
252
|
-
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'
|
|
253
|
-
http_file_enabled: true
|
|
254
|
-
http_log_path: "http/{app_name}.http.access.log"
|
|
255
|
-
http_err_path: "http/{app_name}.http.err.log"
|
|
256
|
-
http_json_enabled: true
|
|
257
|
-
http_json_path: "json.http/{app_name}.json.http.access.log"
|
|
258
|
-
http_json_err_path: "json.http/{app_name}.json.http.err.log"
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
[**`.env`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/.env):
|
|
262
|
-
|
|
263
|
-
```sh
|
|
264
|
-
ENV=development
|
|
265
|
-
DEBUG=true
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
[**`logger.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/logger.py):
|
|
269
|
-
|
|
270
|
-
```python
|
|
271
|
-
from beans_logging import Logger, LoggerLoader
|
|
272
|
-
from beans_logging.fastapi import add_http_file_handler, add_http_file_json_handler
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
logger_loader = LoggerLoader()
|
|
276
|
-
logger: Logger = logger_loader.load()
|
|
277
|
-
|
|
278
|
-
if logger_loader.config.extra.http_file_enabled:
|
|
279
|
-
add_http_file_handler(
|
|
280
|
-
logger_loader=logger_loader,
|
|
281
|
-
log_path=logger_loader.config.extra.http_log_path,
|
|
282
|
-
err_path=logger_loader.config.extra.http_err_path,
|
|
283
|
-
)
|
|
284
|
-
|
|
285
|
-
if logger_loader.config.extra.http_json_enabled:
|
|
286
|
-
add_http_file_json_handler(
|
|
287
|
-
logger_loader=logger_loader,
|
|
288
|
-
log_path=logger_loader.config.extra.http_json_path,
|
|
289
|
-
err_path=logger_loader.config.extra.http_json_err_path,
|
|
290
|
-
)
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
[**`app.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/app.py):
|
|
294
|
-
|
|
295
|
-
```python
|
|
296
|
-
from typing import Union
|
|
297
|
-
from contextlib import asynccontextmanager
|
|
298
|
-
|
|
299
|
-
from dotenv import load_dotenv
|
|
300
|
-
from fastapi import FastAPI, HTTPException
|
|
301
|
-
from fastapi.responses import RedirectResponse
|
|
302
|
-
|
|
303
|
-
load_dotenv()
|
|
304
|
-
|
|
305
|
-
from beans_logging.fastapi import HttpAccessLogMiddleware
|
|
306
|
-
|
|
307
|
-
from logger import logger, logger_loader
|
|
308
|
-
from __version__ import __version__
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
@asynccontextmanager
|
|
312
|
-
async def lifespan(app: FastAPI):
|
|
313
|
-
logger.info("Preparing to startup...")
|
|
314
|
-
logger.success("Finished preparation to startup.")
|
|
315
|
-
logger.info(f"API version: {__version__}")
|
|
316
|
-
|
|
317
|
-
yield
|
|
318
|
-
logger.info("Praparing to shutdown...")
|
|
319
|
-
logger.success("Finished preparation to shutdown.")
|
|
320
|
-
|
|
321
|
-
app = FastAPI(lifespan=lifespan, version=__version__)
|
|
322
|
-
app.add_middleware(
|
|
323
|
-
HttpAccessLogMiddleware,
|
|
324
|
-
has_proxy_headers=True,
|
|
325
|
-
debug_format=logger_loader.config.extra.http_std_debug_format,
|
|
326
|
-
msg_format=logger_loader.config.extra.http_std_msg_format,
|
|
327
|
-
)
|
|
328
|
-
|
|
329
|
-
@app.get("/")
|
|
330
|
-
def root():
|
|
331
|
-
return {"Hello": "World"}
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
Run the [**`examples/advanced`**](https://github.com/bybatkhuu/module.python-logging/tree/main/examples/advanced):
|
|
335
|
-
|
|
336
|
-
```sh
|
|
337
|
-
cd ./examples/advanced
|
|
338
|
-
# Install python dependencies for examples:
|
|
339
|
-
pip install -r ./requirements.txt
|
|
340
|
-
|
|
341
|
-
uvicorn app:app --host=0.0.0.0 --port=8000
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
**Output**:
|
|
345
|
-
|
|
346
|
-
```txt
|
|
347
|
-
[2023-09-01 12:37:38.569 +09:00 | TRACE | beans_logging._base:499]: Intercepted modules: ['watchfiles.watcher', 'asyncio', 'watchfiles', 'concurrent', 'dotenv', 'concurrent.futures', 'fastapi', 'dotenv.main', 'uvicorn', 'watchfiles.main']; Muted modules: ['uvicorn.error', 'uvicorn.access'];
|
|
348
|
-
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.server:76]: Started server process [22599]
|
|
349
|
-
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.lifespan.on:46]: Waiting for application startup.
|
|
350
|
-
[2023-09-01 12:37:38.579 +09:00 | INFO | app:21]: Preparing to startup...
|
|
351
|
-
[2023-09-01 12:37:38.580 +09:00 | OK | app:22]: Finished preparation to startup.
|
|
352
|
-
[2023-09-01 12:37:38.580 +09:00 | INFO | app:23]: API version: 0.0.1-000000
|
|
353
|
-
[2023-09-01 12:37:38.580 +09:00 | INFO | uvicorn.lifespan.on:60]: Application startup complete.
|
|
354
|
-
[2023-09-01 12:37:38.582 +09:00 | INFO | uvicorn.server:218]: Uvicorn running on http://0.0.0.0:9000 (Press CTRL+C to quit)
|
|
355
|
-
[2023-09-01 12:37:48.487 +09:00 | DEBUG | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1"
|
|
356
|
-
[2023-09-01 12:37:48.488 +09:00 | OK | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 0.5ms
|
|
357
|
-
^C[2023-09-01 12:37:51.845 +09:00 | INFO | uvicorn.server:264]: Shutting down
|
|
358
|
-
[2023-09-01 12:37:51.949 +09:00 | INFO | uvicorn.lifespan.on:65]: Waiting for application shutdown.
|
|
359
|
-
[2023-09-01 12:37:51.951 +09:00 | INFO | app:26]: Praparing to shutdown...
|
|
360
|
-
[2023-09-01 12:37:51.952 +09:00 | OK | app:27]: Finished preparation to shutdown.
|
|
361
|
-
[2023-09-01 12:37:51.952 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
|
|
362
|
-
[2023-09-01 12:37:51.953 +09:00 | INFO | uvicorn.server:86]: Finished server process [22599]
|
|
363
|
-
```
|
|
217
|
+
- FastAPI HTTP access logging middleware
|
|
218
|
+
- Install with pip: `pip install -U beans-logging[fastapi]` or `pip install -U beans-logging-fastapi`
|
|
364
219
|
|
|
365
220
|
---
|
|
366
221
|
|
|
@@ -386,7 +241,7 @@ DEBUG=true
|
|
|
386
241
|
|
|
387
242
|
BEANS_LOGGING_DISABLE_DEFAULT=false
|
|
388
243
|
BEANS_LOGGING_CONFIG_PATH="./configs/logger.yml"
|
|
389
|
-
|
|
244
|
+
BEANS_LOGGING_LOGS_DIR="./logs"
|
|
390
245
|
```
|
|
391
246
|
|
|
392
247
|
## Configuration
|
|
@@ -441,3 +296,4 @@ logger:
|
|
|
441
296
|
- <https://github.com/Delgan/loguru>
|
|
442
297
|
- <https://loguru.readthedocs.io/en/stable/api/logger.html>
|
|
443
298
|
- <https://loguru.readthedocs.io/en/stable/resources/recipes.html>
|
|
299
|
+
- <https://github.com/bybatkhuu/module.fastapi-logging>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from ._base import Logger, logger, LoggerLoader
|
|
4
|
+
from .schemas import LoggerConfigPM
|
|
5
|
+
from ._consts import WarnEnum
|
|
6
|
+
from .__version__ import __version__
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"Logger",
|
|
11
|
+
"logger",
|
|
12
|
+
"LoggerLoader",
|
|
13
|
+
"LoggerConfigPM",
|
|
14
|
+
"WarnEnum",
|
|
15
|
+
"__version__",
|
|
16
|
+
]
|
|
@@ -11,7 +11,12 @@ from typing import Union, Dict, Any
|
|
|
11
11
|
import yaml
|
|
12
12
|
from loguru import logger
|
|
13
13
|
from loguru._logger import Logger
|
|
14
|
-
|
|
14
|
+
import pydantic
|
|
15
|
+
|
|
16
|
+
if "2.0.0" <= pydantic.__version__:
|
|
17
|
+
from pydantic import validate_call
|
|
18
|
+
else:
|
|
19
|
+
from pydantic import validate_arguments as validate_call
|
|
15
20
|
|
|
16
21
|
## Internal modules
|
|
17
22
|
from ._utils import create_dir, deep_merge
|
|
@@ -168,7 +173,11 @@ class LoggerLoader:
|
|
|
168
173
|
"""
|
|
169
174
|
|
|
170
175
|
if isinstance(config, dict):
|
|
171
|
-
|
|
176
|
+
if "2.0.0" <= pydantic.__version__:
|
|
177
|
+
_config_dict = self.config.model_dump()
|
|
178
|
+
else:
|
|
179
|
+
_config_dict = self.config.dict()
|
|
180
|
+
|
|
172
181
|
_merged_dict = deep_merge(_config_dict, config)
|
|
173
182
|
try:
|
|
174
183
|
self.config = LoggerConfigPM(**_merged_dict)
|
|
@@ -219,7 +228,11 @@ class LoggerLoader:
|
|
|
219
228
|
return
|
|
220
229
|
|
|
221
230
|
_new_config_dict = _new_config_dict["logger"]
|
|
222
|
-
|
|
231
|
+
if "2.0.0" <= pydantic.__version__:
|
|
232
|
+
_config_dict = self.config.model_dump()
|
|
233
|
+
else:
|
|
234
|
+
_config_dict = self.config.dict()
|
|
235
|
+
|
|
223
236
|
_merged_dict = deep_merge(_config_dict, _new_config_dict)
|
|
224
237
|
self.config = LoggerConfigPM(**_merged_dict)
|
|
225
238
|
except Exception:
|
|
@@ -240,7 +253,11 @@ class LoggerLoader:
|
|
|
240
253
|
return
|
|
241
254
|
|
|
242
255
|
_new_config_dict = _new_config_dict["logger"]
|
|
243
|
-
|
|
256
|
+
if "2.0.0" <= pydantic.__version__:
|
|
257
|
+
_config_dict = self.config.model_dump()
|
|
258
|
+
else:
|
|
259
|
+
_config_dict = self.config.dict()
|
|
260
|
+
|
|
244
261
|
_merged_dict = deep_merge(_config_dict, _new_config_dict)
|
|
245
262
|
self.config = LoggerConfigPM(**_merged_dict)
|
|
246
263
|
except Exception:
|
|
@@ -252,7 +269,9 @@ class LoggerLoader:
|
|
|
252
269
|
# try:
|
|
253
270
|
# import toml
|
|
254
271
|
|
|
255
|
-
# with open(
|
|
272
|
+
# with open(
|
|
273
|
+
# self.config_file_path, "r", encoding="utf-8"
|
|
274
|
+
# ) as _config_file:
|
|
256
275
|
# _new_config_dict = toml.load(_config_file) or {}
|
|
257
276
|
# if "logger" not in _new_config_dict:
|
|
258
277
|
# logger.warning(
|
|
@@ -261,7 +280,11 @@ class LoggerLoader:
|
|
|
261
280
|
# return
|
|
262
281
|
|
|
263
282
|
# _new_config_dict = _new_config_dict["logger"]
|
|
264
|
-
#
|
|
283
|
+
# if "2.0.0" <= pydantic.__version__:
|
|
284
|
+
# _config_dict = self.config.model_dump()
|
|
285
|
+
# else:
|
|
286
|
+
# _config_dict = self.config.dict()
|
|
287
|
+
|
|
265
288
|
# _merged_dict = deep_merge(_config_dict, _new_config_dict)
|
|
266
289
|
# self.config = LoggerConfigPM(**_merged_dict)
|
|
267
290
|
# except Exception:
|
|
@@ -287,8 +310,8 @@ class LoggerLoader:
|
|
|
287
310
|
if _is_debug and (self.config.level != "TRACE"):
|
|
288
311
|
self.config.level = "DEBUG"
|
|
289
312
|
|
|
290
|
-
if "
|
|
291
|
-
self.config.file.logs_dir = os.getenv("
|
|
313
|
+
if "BEANS_LOGGING_LOGS_DIR" in os.environ:
|
|
314
|
+
self.config.file.logs_dir = os.getenv("BEANS_LOGGING_LOGS_DIR")
|
|
292
315
|
|
|
293
316
|
# if self.config.stream.use_color:
|
|
294
317
|
# ## Checking terminal could support xterm colors:
|
|
@@ -529,11 +552,13 @@ class LoggerLoader:
|
|
|
529
552
|
):
|
|
530
553
|
_logger = logging.getLogger(_module_name)
|
|
531
554
|
_logger.handlers = [_intercept_handler]
|
|
555
|
+
_logger.propagate = False
|
|
532
556
|
_intercepted_modules.add(_module_name)
|
|
533
557
|
|
|
534
558
|
for _include_module_name in self.config.intercept.include_modules:
|
|
535
559
|
_logger = logging.getLogger(_include_module_name)
|
|
536
560
|
_logger.handlers = [_intercept_handler]
|
|
561
|
+
logger.propagate = False
|
|
537
562
|
|
|
538
563
|
if _include_module_name not in _intercepted_modules:
|
|
539
564
|
_intercepted_modules.add(_include_module_name)
|
|
@@ -541,8 +566,8 @@ class LoggerLoader:
|
|
|
541
566
|
for _mute_module_name in self.config.intercept.mute_modules:
|
|
542
567
|
_logger = logging.getLogger(_mute_module_name)
|
|
543
568
|
_logger.handlers = []
|
|
544
|
-
|
|
545
|
-
|
|
569
|
+
_logger.propagate = False
|
|
570
|
+
_logger.disabled = True
|
|
546
571
|
|
|
547
572
|
if _mute_module_name in _intercepted_modules:
|
|
548
573
|
_intercepted_modules.remove(_mute_module_name)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WarnEnum(str, Enum):
|
|
7
|
+
ERROR = "ERROR"
|
|
8
|
+
ALWAYS = "ALWAYS"
|
|
9
|
+
DEBUG = "DEBUG"
|
|
10
|
+
IGNORE = "IGNORE"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LogLevelEnum(str, Enum):
|
|
14
|
+
TRACE = "TRACE"
|
|
15
|
+
DEBUG = "DEBUG"
|
|
16
|
+
INFO = "INFO"
|
|
17
|
+
SUCCESS = "SUCCESS"
|
|
18
|
+
WARNING = "WARNING"
|
|
19
|
+
ERROR = "ERROR"
|
|
20
|
+
CRITICAL = "CRITICAL"
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
import sys
|
|
4
5
|
import copy
|
|
5
6
|
import errno
|
|
6
7
|
|
|
7
8
|
from loguru import logger
|
|
8
|
-
|
|
9
|
+
import pydantic
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
if "2.0.0" <= pydantic.__version__:
|
|
12
|
+
from pydantic import validate_call
|
|
13
|
+
else:
|
|
14
|
+
from pydantic import validate_arguments as validate_call
|
|
15
|
+
|
|
16
|
+
from ._consts import WarnEnum
|
|
11
17
|
|
|
12
18
|
|
|
13
19
|
@validate_call
|
|
@@ -16,13 +22,13 @@ def create_dir(create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG):
|
|
|
16
22
|
|
|
17
23
|
Args:
|
|
18
24
|
create_dir (str, required): Create directory path.
|
|
19
|
-
warn_mode (str, optional): Warning message mode, for example: '
|
|
25
|
+
warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'. Defaults to "DEBUG".
|
|
20
26
|
"""
|
|
21
27
|
|
|
22
28
|
if not os.path.isdir(create_dir):
|
|
23
29
|
try:
|
|
24
30
|
_message = f"Creaing '{create_dir}' directory..."
|
|
25
|
-
if warn_mode == WarnEnum.
|
|
31
|
+
if warn_mode == WarnEnum.ALWAYS:
|
|
26
32
|
logger.info(_message)
|
|
27
33
|
elif warn_mode == WarnEnum.DEBUG:
|
|
28
34
|
logger.debug(_message)
|
|
@@ -36,7 +42,7 @@ def create_dir(create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG):
|
|
|
36
42
|
raise
|
|
37
43
|
|
|
38
44
|
_message = f"Successfully created '{create_dir}' directory."
|
|
39
|
-
if warn_mode == WarnEnum.
|
|
45
|
+
if warn_mode == WarnEnum.ALWAYS:
|
|
40
46
|
logger.success(_message)
|
|
41
47
|
elif warn_mode == WarnEnum.DEBUG:
|
|
42
48
|
logger.debug(_message)
|
|
@@ -67,3 +73,28 @@ def deep_merge(dict1: dict, dict2: dict) -> dict:
|
|
|
67
73
|
_merged[_key] = copy.deepcopy(_val)
|
|
68
74
|
|
|
69
75
|
return _merged
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_default_logs_dir() -> str:
|
|
79
|
+
"""Return default logs directory path (current working directory + 'logs').
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
str: Default logs directory path.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
return os.path.join(os.getcwd(), "logs")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_app_name() -> str:
|
|
89
|
+
"""Return application name (sys.argv[0]).
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
str: Application name.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
os.path.splitext(os.path.basename(sys.argv[0]))[0]
|
|
97
|
+
.strip()
|
|
98
|
+
.replace(" ", "-")
|
|
99
|
+
.lower()
|
|
100
|
+
)
|