pythonLogs 4.0.1__tar.gz → 4.0.2__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.2}/PKG-INFO +18 -6
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/README.md +15 -4
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pyproject.toml +15 -2
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/.env.example +4 -1
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/factory.py +32 -1
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/settings.py +7 -4
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/LICENSE +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/__init__.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/basic_log.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/constants.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/log_utils.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/memory_utils.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/pythonLogs/size_rotating.py +0 -0
- {pythonlogs-4.0.1 → pythonlogs-4.0.2}/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.2
|
|
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
|
|
@@ -413,18 +414,28 @@ error_logger.error("Database connection failed")
|
|
|
413
414
|
audit_logger.info("User admin logged in")
|
|
414
415
|
```
|
|
415
416
|
|
|
416
|
-
## Env Variables (Optional)
|
|
417
|
+
## Env Variables (Optional | Production)
|
|
418
|
+
.env variables can be used by leaving all options blank when calling the function
|
|
419
|
+
If not specified inside the .env file, it will use the dafault value
|
|
420
|
+
This is a good approach for production environments, since options can be changed easily
|
|
421
|
+
```python
|
|
422
|
+
from pythonLogs import timed_rotating_logger
|
|
423
|
+
log = timed_rotating_logger()
|
|
424
|
+
```
|
|
425
|
+
|
|
417
426
|
```
|
|
418
427
|
LOG_LEVEL=DEBUG
|
|
419
|
-
LOG_TIMEZONE=
|
|
428
|
+
LOG_TIMEZONE=UTC
|
|
420
429
|
LOG_ENCODING=UTF-8
|
|
421
430
|
LOG_APPNAME=app
|
|
422
431
|
LOG_FILENAME=app.log
|
|
423
432
|
LOG_DIRECTORY=/app/logs
|
|
424
433
|
LOG_DAYS_TO_KEEP=30
|
|
434
|
+
LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
|
|
425
435
|
LOG_STREAM_HANDLER=True
|
|
426
436
|
LOG_SHOW_LOCATION=False
|
|
427
|
-
|
|
437
|
+
LOG_MAX_LOGGERS=50
|
|
438
|
+
LOG_LOGGER_TTL_SECONDS=1800
|
|
428
439
|
|
|
429
440
|
# SizeRotatingLog
|
|
430
441
|
LOG_MAX_FILE_SIZE_MB=10
|
|
@@ -432,6 +443,7 @@ LOG_MAX_FILE_SIZE_MB=10
|
|
|
432
443
|
# TimedRotatingLog
|
|
433
444
|
LOG_ROTATE_WHEN=midnight
|
|
434
445
|
LOG_ROTATE_AT_UTC=True
|
|
446
|
+
LOG_ROTATE_FILE_SUFIX="%Y%m%d"
|
|
435
447
|
```
|
|
436
448
|
|
|
437
449
|
|
|
@@ -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
|
|
@@ -384,18 +384,28 @@ error_logger.error("Database connection failed")
|
|
|
384
384
|
audit_logger.info("User admin logged in")
|
|
385
385
|
```
|
|
386
386
|
|
|
387
|
-
## Env Variables (Optional)
|
|
387
|
+
## Env Variables (Optional | Production)
|
|
388
|
+
.env variables can be used by leaving all options blank when calling the function
|
|
389
|
+
If not specified inside the .env file, it will use the dafault value
|
|
390
|
+
This is a good approach for production environments, since options can be changed easily
|
|
391
|
+
```python
|
|
392
|
+
from pythonLogs import timed_rotating_logger
|
|
393
|
+
log = timed_rotating_logger()
|
|
394
|
+
```
|
|
395
|
+
|
|
388
396
|
```
|
|
389
397
|
LOG_LEVEL=DEBUG
|
|
390
|
-
LOG_TIMEZONE=
|
|
398
|
+
LOG_TIMEZONE=UTC
|
|
391
399
|
LOG_ENCODING=UTF-8
|
|
392
400
|
LOG_APPNAME=app
|
|
393
401
|
LOG_FILENAME=app.log
|
|
394
402
|
LOG_DIRECTORY=/app/logs
|
|
395
403
|
LOG_DAYS_TO_KEEP=30
|
|
404
|
+
LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
|
|
396
405
|
LOG_STREAM_HANDLER=True
|
|
397
406
|
LOG_SHOW_LOCATION=False
|
|
398
|
-
|
|
407
|
+
LOG_MAX_LOGGERS=50
|
|
408
|
+
LOG_LOGGER_TTL_SECONDS=1800
|
|
399
409
|
|
|
400
410
|
# SizeRotatingLog
|
|
401
411
|
LOG_MAX_FILE_SIZE_MB=10
|
|
@@ -403,6 +413,7 @@ LOG_MAX_FILE_SIZE_MB=10
|
|
|
403
413
|
# TimedRotatingLog
|
|
404
414
|
LOG_ROTATE_WHEN=midnight
|
|
405
415
|
LOG_ROTATE_AT_UTC=True
|
|
416
|
+
LOG_ROTATE_FILE_SUFIX="%Y%m%d"
|
|
406
417
|
```
|
|
407
418
|
|
|
408
419
|
|
|
@@ -5,8 +5,8 @@ build-backend = "poetry.core.masonry.api"
|
|
|
5
5
|
|
|
6
6
|
[tool.poetry]
|
|
7
7
|
name = "pythonLogs"
|
|
8
|
-
version = "4.0.
|
|
9
|
-
description = "
|
|
8
|
+
version = "4.0.2"
|
|
9
|
+
description = "High-performance Python logging library with file rotation and optimized caching for better performance"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = ["Daniel Costa <danieldcsta@gmail.com>"]
|
|
@@ -34,6 +34,7 @@ classifiers = [
|
|
|
34
34
|
|
|
35
35
|
[tool.poetry.dependencies]
|
|
36
36
|
python = "^3.10"
|
|
37
|
+
pydantic = "^2.11.7"
|
|
37
38
|
pydantic-settings = "^2.10.1"
|
|
38
39
|
python-dotenv = "^1.1.1"
|
|
39
40
|
|
|
@@ -48,6 +49,12 @@ pytest = "^8.4.1"
|
|
|
48
49
|
[tool.poetry.group.test]
|
|
49
50
|
optional = true
|
|
50
51
|
|
|
52
|
+
|
|
53
|
+
[tool.black]
|
|
54
|
+
line-length = 120
|
|
55
|
+
skip-string-normalization = true
|
|
56
|
+
|
|
57
|
+
|
|
51
58
|
[tool.pytest.ini_options]
|
|
52
59
|
markers = [
|
|
53
60
|
"slow: marks tests as slow (deselect with '-m \"not slow\"')"
|
|
@@ -60,6 +67,12 @@ omit = [
|
|
|
60
67
|
]
|
|
61
68
|
|
|
62
69
|
|
|
70
|
+
[tool.coverage.report]
|
|
71
|
+
exclude_lines = [
|
|
72
|
+
"pragma: no cover",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
|
|
63
76
|
[tool.poe.tasks]
|
|
64
77
|
_test = "coverage run -m pytest -v"
|
|
65
78
|
_coverage_report = "coverage report"
|
|
@@ -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
|