pythonLogs 4.0.1__tar.gz → 4.0.3__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.
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/PKG-INFO +63 -47
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/README.md +60 -45
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pyproject.toml +17 -13
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/.env.example +4 -1
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/factory.py +32 -1
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/settings.py +7 -4
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/LICENSE +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/__init__.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/basic_log.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/constants.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/log_utils.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/memory_utils.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/size_rotating.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.3}/pythonLogs/timed_rotating.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pythonLogs
|
|
3
|
-
Version: 4.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 4.0.3
|
|
4
|
+
Summary: High-performance Python logging library with file rotation and optimized caching for better performance
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: python3,python-3,python,log,logging,logger,logutils,log-utils,pythonLogs
|
|
7
7
|
Author: Daniel Costa
|
|
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
23
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Dist: pydantic (>=2.11.7,<3.0.0)
|
|
24
25
|
Requires-Dist: pydantic-settings (>=2.10.1,<3.0.0)
|
|
25
26
|
Requires-Dist: python-dotenv (>=1.1.1,<2.0.0)
|
|
26
27
|
Project-URL: Homepage, https://pypi.org/project/pythonLogs
|
|
@@ -40,7 +41,7 @@ Description-Content-Type: text/markdown
|
|
|
40
41
|
|
|
41
42
|
[](https://github.com/sponsors/ddc)
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
High-performance Python logging library with file rotation and optimized caching for better performance
|
|
44
45
|
|
|
45
46
|
|
|
46
47
|
## Table of Contents
|
|
@@ -53,11 +54,15 @@ A modern, high-performance Python logging library with automatic file rotation,
|
|
|
53
54
|
- [Timed Rotating Logger](#timed-rotating-logger)
|
|
54
55
|
- [Context Manager Support](#context-manager-support)
|
|
55
56
|
- [Advanced Factory Features](#advanced-factory-features)
|
|
57
|
+
- [Environment Variables](#env-variables-optional--production)
|
|
56
58
|
- [Memory Management](#memory-management)
|
|
59
|
+
- [Flexible Configuration Options](#flexible-configuration-options)
|
|
57
60
|
- [Migration Guide](#migration-guide)
|
|
58
61
|
- [Performance Improvements](#performance-improvements)
|
|
59
|
-
- [Environment Variables](#env-variables-optional)
|
|
60
62
|
- [Development](#source-code)
|
|
63
|
+
- [Run Tests and Get Coverage Report using Poe](#run-tests-and-get-coverage-report-using-poe)
|
|
64
|
+
- [License](#license)
|
|
65
|
+
- [Buy me a cup of coffee](#buy-me-a-cup-of-coffee)
|
|
61
66
|
|
|
62
67
|
|
|
63
68
|
|
|
@@ -263,6 +268,7 @@ logger.warning("This is a warning example")
|
|
|
263
268
|
|
|
264
269
|
# Context Manager Support
|
|
265
270
|
|
|
271
|
+
Slow, but if you want immediate, deterministic cleanup for a specific scope.\
|
|
266
272
|
All logger types support context managers for automatic resource cleanup and exception safety:
|
|
267
273
|
|
|
268
274
|
## Basic Usage
|
|
@@ -332,44 +338,6 @@ assert logger1 is logger2
|
|
|
332
338
|
clear_logger_registry()
|
|
333
339
|
```
|
|
334
340
|
|
|
335
|
-
## Flexible Configuration Options
|
|
336
|
-
You can use either enums (for type safety) or strings (for simplicity):
|
|
337
|
-
|
|
338
|
-
```python
|
|
339
|
-
from pythonLogs import LogLevel, RotateWhen, LoggerType
|
|
340
|
-
|
|
341
|
-
# Option 1: Type-safe enums (recommended)
|
|
342
|
-
LogLevel.DEBUG # "DEBUG"
|
|
343
|
-
LogLevel.INFO # "INFO"
|
|
344
|
-
LogLevel.WARNING # "WARNING"
|
|
345
|
-
LogLevel.ERROR # "ERROR"
|
|
346
|
-
LogLevel.CRITICAL # "CRITICAL"
|
|
347
|
-
|
|
348
|
-
# Option 2: String values (case-insensitive)
|
|
349
|
-
"debug" # Same as LogLevel.DEBUG
|
|
350
|
-
"info" # Same as LogLevel.INFO
|
|
351
|
-
"warning" # Same as LogLevel.WARNING
|
|
352
|
-
"warn" # Same as LogLevel.WARN (alias)
|
|
353
|
-
"error" # Same as LogLevel.ERROR
|
|
354
|
-
"critical" # Same as LogLevel.CRITICAL
|
|
355
|
-
"crit" # Same as LogLevel.CRIT (alias)
|
|
356
|
-
# Also supports: "DEBUG", "Info", "Warning", etc.
|
|
357
|
-
|
|
358
|
-
# RotateWhen values
|
|
359
|
-
RotateWhen.MIDNIGHT # "midnight"
|
|
360
|
-
RotateWhen.HOURLY # "H"
|
|
361
|
-
RotateWhen.DAILY # "D"
|
|
362
|
-
RotateWhen.MONDAY # "W0"
|
|
363
|
-
# ... through SUNDAY # "W6"
|
|
364
|
-
# String equivalents: "midnight", "H", "D", "W0"-"W6"
|
|
365
|
-
|
|
366
|
-
# LoggerType values
|
|
367
|
-
LoggerType.BASIC # "basic"
|
|
368
|
-
LoggerType.SIZE_ROTATING # "size_rotating"
|
|
369
|
-
LoggerType.TIMED_ROTATING # "timed_rotating"
|
|
370
|
-
# String equivalents: "basic", "size_rotating", "timed_rotating"
|
|
371
|
-
```
|
|
372
|
-
|
|
373
341
|
## Production Setup Example
|
|
374
342
|
```python
|
|
375
343
|
from pythonLogs import size_rotating_logger, timed_rotating_logger, LogLevel, RotateWhen
|
|
@@ -413,18 +381,28 @@ error_logger.error("Database connection failed")
|
|
|
413
381
|
audit_logger.info("User admin logged in")
|
|
414
382
|
```
|
|
415
383
|
|
|
416
|
-
## Env Variables (Optional)
|
|
384
|
+
## Env Variables (Optional | Production)
|
|
385
|
+
The .env variables file can be used by leaving all options blank when calling the function.\
|
|
386
|
+
If not specified inside the .env file, it will use the dafault value.\
|
|
387
|
+
This is a good approach for production environments, since options can be changed easily.
|
|
388
|
+
```python
|
|
389
|
+
from pythonLogs import timed_rotating_logger
|
|
390
|
+
log = timed_rotating_logger()
|
|
391
|
+
```
|
|
392
|
+
|
|
417
393
|
```
|
|
418
394
|
LOG_LEVEL=DEBUG
|
|
419
|
-
LOG_TIMEZONE=
|
|
395
|
+
LOG_TIMEZONE=UTC
|
|
420
396
|
LOG_ENCODING=UTF-8
|
|
421
397
|
LOG_APPNAME=app
|
|
422
398
|
LOG_FILENAME=app.log
|
|
423
399
|
LOG_DIRECTORY=/app/logs
|
|
424
400
|
LOG_DAYS_TO_KEEP=30
|
|
401
|
+
LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
|
|
425
402
|
LOG_STREAM_HANDLER=True
|
|
426
403
|
LOG_SHOW_LOCATION=False
|
|
427
|
-
|
|
404
|
+
LOG_MAX_LOGGERS=50
|
|
405
|
+
LOG_LOGGER_TTL_SECONDS=1800
|
|
428
406
|
|
|
429
407
|
# SizeRotatingLog
|
|
430
408
|
LOG_MAX_FILE_SIZE_MB=10
|
|
@@ -432,11 +410,10 @@ LOG_MAX_FILE_SIZE_MB=10
|
|
|
432
410
|
# TimedRotatingLog
|
|
433
411
|
LOG_ROTATE_WHEN=midnight
|
|
434
412
|
LOG_ROTATE_AT_UTC=True
|
|
413
|
+
LOG_ROTATE_FILE_SUFIX="%Y%m%d"
|
|
435
414
|
```
|
|
436
415
|
|
|
437
416
|
|
|
438
|
-
|
|
439
|
-
|
|
440
417
|
# Memory Management
|
|
441
418
|
|
|
442
419
|
The library includes comprehensive memory management features to prevent memory leaks and optimize resource usage:
|
|
@@ -533,6 +510,45 @@ clear_logger_registry()
|
|
|
533
510
|
```
|
|
534
511
|
|
|
535
512
|
|
|
513
|
+
# Flexible Configuration Options
|
|
514
|
+
You can use either enums (for type safety) or strings (for simplicity):
|
|
515
|
+
|
|
516
|
+
```python
|
|
517
|
+
from pythonLogs import LogLevel, RotateWhen, LoggerType
|
|
518
|
+
|
|
519
|
+
# Option 1: Type-safe enums (recommended)
|
|
520
|
+
LogLevel.DEBUG # "DEBUG"
|
|
521
|
+
LogLevel.INFO # "INFO"
|
|
522
|
+
LogLevel.WARNING # "WARNING"
|
|
523
|
+
LogLevel.ERROR # "ERROR"
|
|
524
|
+
LogLevel.CRITICAL # "CRITICAL"
|
|
525
|
+
|
|
526
|
+
# Option 2: String values (case-insensitive)
|
|
527
|
+
"debug" # Same as LogLevel.DEBUG
|
|
528
|
+
"info" # Same as LogLevel.INFO
|
|
529
|
+
"warning" # Same as LogLevel.WARNING
|
|
530
|
+
"warn" # Same as LogLevel.WARN (alias)
|
|
531
|
+
"error" # Same as LogLevel.ERROR
|
|
532
|
+
"critical" # Same as LogLevel.CRITICAL
|
|
533
|
+
"crit" # Same as LogLevel.CRIT (alias)
|
|
534
|
+
# Also supports: "DEBUG", "Info", "Warning", etc.
|
|
535
|
+
|
|
536
|
+
# RotateWhen values
|
|
537
|
+
RotateWhen.MIDNIGHT # "midnight"
|
|
538
|
+
RotateWhen.HOURLY # "H"
|
|
539
|
+
RotateWhen.DAILY # "D"
|
|
540
|
+
RotateWhen.MONDAY # "W0"
|
|
541
|
+
# ... through SUNDAY # "W6"
|
|
542
|
+
# String equivalents: "midnight", "H", "D", "W0"-"W6"
|
|
543
|
+
|
|
544
|
+
# LoggerType values
|
|
545
|
+
LoggerType.BASIC # "basic"
|
|
546
|
+
LoggerType.SIZE_ROTATING # "size_rotating"
|
|
547
|
+
LoggerType.TIMED_ROTATING # "timed_rotating"
|
|
548
|
+
# String equivalents: "basic", "size_rotating", "timed_rotating"
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
|
|
536
552
|
# Migration Guide
|
|
537
553
|
|
|
538
554
|
## Upgrading from Legacy to Factory Pattern
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
[](https://github.com/sponsors/ddc)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
High-performance Python logging library with file rotation and optimized caching for better performance
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
## Table of Contents
|
|
@@ -24,11 +24,15 @@ A modern, high-performance Python logging library with automatic file rotation,
|
|
|
24
24
|
- [Timed Rotating Logger](#timed-rotating-logger)
|
|
25
25
|
- [Context Manager Support](#context-manager-support)
|
|
26
26
|
- [Advanced Factory Features](#advanced-factory-features)
|
|
27
|
+
- [Environment Variables](#env-variables-optional--production)
|
|
27
28
|
- [Memory Management](#memory-management)
|
|
29
|
+
- [Flexible Configuration Options](#flexible-configuration-options)
|
|
28
30
|
- [Migration Guide](#migration-guide)
|
|
29
31
|
- [Performance Improvements](#performance-improvements)
|
|
30
|
-
- [Environment Variables](#env-variables-optional)
|
|
31
32
|
- [Development](#source-code)
|
|
33
|
+
- [Run Tests and Get Coverage Report using Poe](#run-tests-and-get-coverage-report-using-poe)
|
|
34
|
+
- [License](#license)
|
|
35
|
+
- [Buy me a cup of coffee](#buy-me-a-cup-of-coffee)
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
|
|
@@ -234,6 +238,7 @@ logger.warning("This is a warning example")
|
|
|
234
238
|
|
|
235
239
|
# Context Manager Support
|
|
236
240
|
|
|
241
|
+
Slow, but if you want immediate, deterministic cleanup for a specific scope.\
|
|
237
242
|
All logger types support context managers for automatic resource cleanup and exception safety:
|
|
238
243
|
|
|
239
244
|
## Basic Usage
|
|
@@ -303,44 +308,6 @@ assert logger1 is logger2
|
|
|
303
308
|
clear_logger_registry()
|
|
304
309
|
```
|
|
305
310
|
|
|
306
|
-
## Flexible Configuration Options
|
|
307
|
-
You can use either enums (for type safety) or strings (for simplicity):
|
|
308
|
-
|
|
309
|
-
```python
|
|
310
|
-
from pythonLogs import LogLevel, RotateWhen, LoggerType
|
|
311
|
-
|
|
312
|
-
# Option 1: Type-safe enums (recommended)
|
|
313
|
-
LogLevel.DEBUG # "DEBUG"
|
|
314
|
-
LogLevel.INFO # "INFO"
|
|
315
|
-
LogLevel.WARNING # "WARNING"
|
|
316
|
-
LogLevel.ERROR # "ERROR"
|
|
317
|
-
LogLevel.CRITICAL # "CRITICAL"
|
|
318
|
-
|
|
319
|
-
# Option 2: String values (case-insensitive)
|
|
320
|
-
"debug" # Same as LogLevel.DEBUG
|
|
321
|
-
"info" # Same as LogLevel.INFO
|
|
322
|
-
"warning" # Same as LogLevel.WARNING
|
|
323
|
-
"warn" # Same as LogLevel.WARN (alias)
|
|
324
|
-
"error" # Same as LogLevel.ERROR
|
|
325
|
-
"critical" # Same as LogLevel.CRITICAL
|
|
326
|
-
"crit" # Same as LogLevel.CRIT (alias)
|
|
327
|
-
# Also supports: "DEBUG", "Info", "Warning", etc.
|
|
328
|
-
|
|
329
|
-
# RotateWhen values
|
|
330
|
-
RotateWhen.MIDNIGHT # "midnight"
|
|
331
|
-
RotateWhen.HOURLY # "H"
|
|
332
|
-
RotateWhen.DAILY # "D"
|
|
333
|
-
RotateWhen.MONDAY # "W0"
|
|
334
|
-
# ... through SUNDAY # "W6"
|
|
335
|
-
# String equivalents: "midnight", "H", "D", "W0"-"W6"
|
|
336
|
-
|
|
337
|
-
# LoggerType values
|
|
338
|
-
LoggerType.BASIC # "basic"
|
|
339
|
-
LoggerType.SIZE_ROTATING # "size_rotating"
|
|
340
|
-
LoggerType.TIMED_ROTATING # "timed_rotating"
|
|
341
|
-
# String equivalents: "basic", "size_rotating", "timed_rotating"
|
|
342
|
-
```
|
|
343
|
-
|
|
344
311
|
## Production Setup Example
|
|
345
312
|
```python
|
|
346
313
|
from pythonLogs import size_rotating_logger, timed_rotating_logger, LogLevel, RotateWhen
|
|
@@ -384,18 +351,28 @@ error_logger.error("Database connection failed")
|
|
|
384
351
|
audit_logger.info("User admin logged in")
|
|
385
352
|
```
|
|
386
353
|
|
|
387
|
-
## Env Variables (Optional)
|
|
354
|
+
## Env Variables (Optional | Production)
|
|
355
|
+
The .env variables file can be used by leaving all options blank when calling the function.\
|
|
356
|
+
If not specified inside the .env file, it will use the dafault value.\
|
|
357
|
+
This is a good approach for production environments, since options can be changed easily.
|
|
358
|
+
```python
|
|
359
|
+
from pythonLogs import timed_rotating_logger
|
|
360
|
+
log = timed_rotating_logger()
|
|
361
|
+
```
|
|
362
|
+
|
|
388
363
|
```
|
|
389
364
|
LOG_LEVEL=DEBUG
|
|
390
|
-
LOG_TIMEZONE=
|
|
365
|
+
LOG_TIMEZONE=UTC
|
|
391
366
|
LOG_ENCODING=UTF-8
|
|
392
367
|
LOG_APPNAME=app
|
|
393
368
|
LOG_FILENAME=app.log
|
|
394
369
|
LOG_DIRECTORY=/app/logs
|
|
395
370
|
LOG_DAYS_TO_KEEP=30
|
|
371
|
+
LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
|
|
396
372
|
LOG_STREAM_HANDLER=True
|
|
397
373
|
LOG_SHOW_LOCATION=False
|
|
398
|
-
|
|
374
|
+
LOG_MAX_LOGGERS=50
|
|
375
|
+
LOG_LOGGER_TTL_SECONDS=1800
|
|
399
376
|
|
|
400
377
|
# SizeRotatingLog
|
|
401
378
|
LOG_MAX_FILE_SIZE_MB=10
|
|
@@ -403,11 +380,10 @@ LOG_MAX_FILE_SIZE_MB=10
|
|
|
403
380
|
# TimedRotatingLog
|
|
404
381
|
LOG_ROTATE_WHEN=midnight
|
|
405
382
|
LOG_ROTATE_AT_UTC=True
|
|
383
|
+
LOG_ROTATE_FILE_SUFIX="%Y%m%d"
|
|
406
384
|
```
|
|
407
385
|
|
|
408
386
|
|
|
409
|
-
|
|
410
|
-
|
|
411
387
|
# Memory Management
|
|
412
388
|
|
|
413
389
|
The library includes comprehensive memory management features to prevent memory leaks and optimize resource usage:
|
|
@@ -504,6 +480,45 @@ clear_logger_registry()
|
|
|
504
480
|
```
|
|
505
481
|
|
|
506
482
|
|
|
483
|
+
# Flexible Configuration Options
|
|
484
|
+
You can use either enums (for type safety) or strings (for simplicity):
|
|
485
|
+
|
|
486
|
+
```python
|
|
487
|
+
from pythonLogs import LogLevel, RotateWhen, LoggerType
|
|
488
|
+
|
|
489
|
+
# Option 1: Type-safe enums (recommended)
|
|
490
|
+
LogLevel.DEBUG # "DEBUG"
|
|
491
|
+
LogLevel.INFO # "INFO"
|
|
492
|
+
LogLevel.WARNING # "WARNING"
|
|
493
|
+
LogLevel.ERROR # "ERROR"
|
|
494
|
+
LogLevel.CRITICAL # "CRITICAL"
|
|
495
|
+
|
|
496
|
+
# Option 2: String values (case-insensitive)
|
|
497
|
+
"debug" # Same as LogLevel.DEBUG
|
|
498
|
+
"info" # Same as LogLevel.INFO
|
|
499
|
+
"warning" # Same as LogLevel.WARNING
|
|
500
|
+
"warn" # Same as LogLevel.WARN (alias)
|
|
501
|
+
"error" # Same as LogLevel.ERROR
|
|
502
|
+
"critical" # Same as LogLevel.CRITICAL
|
|
503
|
+
"crit" # Same as LogLevel.CRIT (alias)
|
|
504
|
+
# Also supports: "DEBUG", "Info", "Warning", etc.
|
|
505
|
+
|
|
506
|
+
# RotateWhen values
|
|
507
|
+
RotateWhen.MIDNIGHT # "midnight"
|
|
508
|
+
RotateWhen.HOURLY # "H"
|
|
509
|
+
RotateWhen.DAILY # "D"
|
|
510
|
+
RotateWhen.MONDAY # "W0"
|
|
511
|
+
# ... through SUNDAY # "W6"
|
|
512
|
+
# String equivalents: "midnight", "H", "D", "W0"-"W6"
|
|
513
|
+
|
|
514
|
+
# LoggerType values
|
|
515
|
+
LoggerType.BASIC # "basic"
|
|
516
|
+
LoggerType.SIZE_ROTATING # "size_rotating"
|
|
517
|
+
LoggerType.TIMED_ROTATING # "timed_rotating"
|
|
518
|
+
# String equivalents: "basic", "size_rotating", "timed_rotating"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
|
|
507
522
|
# Migration Guide
|
|
508
523
|
|
|
509
524
|
## Upgrading from Legacy to Factory Pattern
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
3
3
|
build-backend = "poetry.core.masonry.api"
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
[tool.poetry]
|
|
7
6
|
name = "pythonLogs"
|
|
8
|
-
version = "4.0.
|
|
9
|
-
description = "
|
|
7
|
+
version = "4.0.3"
|
|
8
|
+
description = "High-performance Python logging library with file rotation and optimized caching for better performance"
|
|
10
9
|
license = "MIT"
|
|
11
10
|
readme = "README.md"
|
|
12
11
|
authors = ["Daniel Costa <danieldcsta@gmail.com>"]
|
|
@@ -31,38 +30,43 @@ classifiers = [
|
|
|
31
30
|
"Natural Language :: English",
|
|
32
31
|
]
|
|
33
32
|
|
|
34
|
-
|
|
35
33
|
[tool.poetry.dependencies]
|
|
36
34
|
python = "^3.10"
|
|
35
|
+
pydantic = "^2.11.7"
|
|
37
36
|
pydantic-settings = "^2.10.1"
|
|
38
37
|
python-dotenv = "^1.1.1"
|
|
39
38
|
|
|
40
|
-
|
|
41
39
|
[tool.poetry.group.test.dependencies]
|
|
42
40
|
coverage = "^7.9.2"
|
|
43
41
|
poethepoet = "^0.36.0"
|
|
44
42
|
psutil = "^7.0.0"
|
|
45
43
|
pytest = "^8.4.1"
|
|
46
44
|
|
|
45
|
+
[tool.poe.tasks]
|
|
46
|
+
_test = "coverage run -m pytest -v"
|
|
47
|
+
_coverage_report = "coverage report"
|
|
48
|
+
_coverage_xml = "coverage xml"
|
|
49
|
+
tests = ["_test", "_coverage_report", "_coverage_xml"]
|
|
50
|
+
test = ["tests"]
|
|
47
51
|
|
|
48
52
|
[tool.poetry.group.test]
|
|
49
53
|
optional = true
|
|
50
54
|
|
|
55
|
+
[tool.black]
|
|
56
|
+
line-length = 120
|
|
57
|
+
skip-string-normalization = true
|
|
58
|
+
|
|
51
59
|
[tool.pytest.ini_options]
|
|
52
60
|
markers = [
|
|
53
61
|
"slow: marks tests as slow (deselect with '-m \"not slow\"')"
|
|
54
62
|
]
|
|
55
63
|
|
|
56
|
-
|
|
57
64
|
[tool.coverage.run]
|
|
58
65
|
omit = [
|
|
59
66
|
"tests/*",
|
|
60
67
|
]
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
[
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
_coverage_xml = "coverage xml"
|
|
67
|
-
tests = ["_test", "_coverage_report", "_coverage_xml"]
|
|
68
|
-
test = ["tests"]
|
|
69
|
+
[tool.coverage.report]
|
|
70
|
+
exclude_lines = [
|
|
71
|
+
"pragma: no cover",
|
|
72
|
+
]
|
|
@@ -5,9 +5,11 @@ LOG_APPNAME=app
|
|
|
5
5
|
LOG_FILENAME=app.log
|
|
6
6
|
LOG_DIRECTORY=/app/logs
|
|
7
7
|
LOG_DAYS_TO_KEEP=30
|
|
8
|
+
LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
|
|
8
9
|
LOG_STREAM_HANDLER=True
|
|
9
10
|
LOG_SHOW_LOCATION=False
|
|
10
|
-
|
|
11
|
+
LOG_MAX_LOGGERS=50
|
|
12
|
+
LOG_LOGGER_TTL_SECONDS=1800
|
|
11
13
|
|
|
12
14
|
# SizeRotatingLog
|
|
13
15
|
LOG_MAX_FILE_SIZE_MB=10
|
|
@@ -15,3 +17,4 @@ LOG_MAX_FILE_SIZE_MB=10
|
|
|
15
17
|
# TimedRotatingLog
|
|
16
18
|
LOG_ROTATE_WHEN=midnight
|
|
17
19
|
LOG_ROTATE_AT_UTC=True
|
|
20
|
+
LOG_ROTATE_FILE_SUFIX="%Y%m%d"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
import atexit
|
|
2
3
|
import logging
|
|
3
4
|
import threading
|
|
4
5
|
import time
|
|
@@ -28,6 +29,23 @@ class LoggerFactory:
|
|
|
28
29
|
# Memory optimization settings
|
|
29
30
|
_max_loggers = 100 # Maximum number of cached loggers
|
|
30
31
|
_logger_ttl = 3600 # Logger TTL in seconds (1 hour)
|
|
32
|
+
_initialized = False # Flag to track if memory limits have been initialized
|
|
33
|
+
_atexit_registered = False # Flag to track if atexit cleanup is registered
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def _ensure_initialized(cls) -> None:
|
|
37
|
+
"""Ensure memory limits are initialized from settings on first use."""
|
|
38
|
+
if not cls._initialized:
|
|
39
|
+
from pythonLogs.settings import get_log_settings
|
|
40
|
+
settings = get_log_settings()
|
|
41
|
+
cls._max_loggers = settings.max_loggers
|
|
42
|
+
cls._logger_ttl = settings.logger_ttl_seconds
|
|
43
|
+
cls._initialized = True
|
|
44
|
+
|
|
45
|
+
# Register atexit cleanup on first use
|
|
46
|
+
if not cls._atexit_registered:
|
|
47
|
+
atexit.register(cls._atexit_cleanup)
|
|
48
|
+
cls._atexit_registered = True
|
|
31
49
|
|
|
32
50
|
@classmethod
|
|
33
51
|
def get_or_create_logger(
|
|
@@ -54,6 +72,9 @@ class LoggerFactory:
|
|
|
54
72
|
|
|
55
73
|
# Thread-safe check-and-create operation
|
|
56
74
|
with cls._registry_lock:
|
|
75
|
+
# Initialize memory limits from settings on first use
|
|
76
|
+
cls._ensure_initialized()
|
|
77
|
+
|
|
57
78
|
# Clean up expired loggers first
|
|
58
79
|
cls._cleanup_expired_loggers()
|
|
59
80
|
|
|
@@ -114,7 +135,7 @@ class LoggerFactory:
|
|
|
114
135
|
|
|
115
136
|
@classmethod
|
|
116
137
|
def set_memory_limits(cls, max_loggers: int = 100, ttl_seconds: int = 3600) -> None:
|
|
117
|
-
"""Configure memory management limits for the logger registry.
|
|
138
|
+
"""Configure memory management limits for the logger registry at runtime.
|
|
118
139
|
|
|
119
140
|
Args:
|
|
120
141
|
max_loggers: Maximum number of cached loggers
|
|
@@ -123,10 +144,20 @@ class LoggerFactory:
|
|
|
123
144
|
with cls._registry_lock:
|
|
124
145
|
cls._max_loggers = max_loggers
|
|
125
146
|
cls._logger_ttl = ttl_seconds
|
|
147
|
+
cls._initialized = True # Mark as manually configured
|
|
126
148
|
# Clean up immediately with new settings
|
|
127
149
|
cls._cleanup_expired_loggers()
|
|
128
150
|
cls._enforce_size_limit()
|
|
129
151
|
|
|
152
|
+
@classmethod
|
|
153
|
+
def _atexit_cleanup(cls) -> None:
|
|
154
|
+
"""Cleanup function registered with atexit to ensure proper resource cleanup."""
|
|
155
|
+
try:
|
|
156
|
+
cls.clear_registry()
|
|
157
|
+
except Exception:
|
|
158
|
+
# Silently ignore exceptions during shutdown cleanup
|
|
159
|
+
pass
|
|
160
|
+
|
|
130
161
|
@staticmethod
|
|
131
162
|
def _cleanup_logger(logger: logging.Logger) -> None:
|
|
132
163
|
"""Clean up logger resources by closing all handlers."""
|
|
@@ -23,15 +23,18 @@ class LogSettings(BaseSettings):
|
|
|
23
23
|
"""If any ENV variable is omitted, it falls back to default values here"""
|
|
24
24
|
|
|
25
25
|
level: Optional[LogLevel] = Field(default=LogLevel.INFO)
|
|
26
|
+
timezone: Optional[str] = Field(default=DEFAULT_TIMEZONE)
|
|
27
|
+
encoding: Optional[str] = Field(default=DEFAULT_ENCODING)
|
|
26
28
|
appname: Optional[str] = Field(default="app")
|
|
27
|
-
directory: Optional[str] = Field(default="/app/logs")
|
|
28
29
|
filename: Optional[str] = Field(default="app.log")
|
|
29
|
-
|
|
30
|
-
date_format: Optional[str] = Field(default=DEFAULT_DATE_FORMAT)
|
|
30
|
+
directory: Optional[str] = Field(default="/app/logs")
|
|
31
31
|
days_to_keep: Optional[int] = Field(default=DEFAULT_BACKUP_COUNT)
|
|
32
|
-
|
|
32
|
+
date_format: Optional[str] = Field(default=DEFAULT_DATE_FORMAT)
|
|
33
33
|
stream_handler: Optional[bool] = Field(default=True)
|
|
34
34
|
show_location: Optional[bool] = Field(default=False)
|
|
35
|
+
# Memory management
|
|
36
|
+
max_loggers: Optional[int] = Field(default=100)
|
|
37
|
+
logger_ttl_seconds: Optional[int] = Field(default=3600)
|
|
35
38
|
|
|
36
39
|
# SizeRotatingLog
|
|
37
40
|
max_file_size_mb: Optional[int] = Field(default=10)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|