pythonLogs 3.0.13__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.2/PKG-INFO +627 -0
- pythonlogs-4.0.2/README.md +596 -0
- {pythonlogs-3.0.13 → pythonlogs-4.0.2}/pyproject.toml +31 -12
- {pythonlogs-3.0.13 → pythonlogs-4.0.2}/pythonLogs/.env.example +4 -1
- pythonlogs-4.0.2/pythonLogs/__init__.py +96 -0
- pythonlogs-4.0.2/pythonLogs/basic_log.py +63 -0
- pythonlogs-4.0.2/pythonLogs/constants.py +42 -0
- pythonlogs-4.0.2/pythonLogs/factory.py +415 -0
- pythonlogs-4.0.2/pythonLogs/log_utils.py +276 -0
- pythonlogs-4.0.2/pythonLogs/memory_utils.py +208 -0
- pythonlogs-4.0.2/pythonLogs/settings.py +57 -0
- {pythonlogs-3.0.13 → pythonlogs-4.0.2}/pythonLogs/size_rotating.py +51 -18
- {pythonlogs-3.0.13 → pythonlogs-4.0.2}/pythonLogs/timed_rotating.py +44 -11
- pythonlogs-3.0.13/PKG-INFO +0 -192
- pythonlogs-3.0.13/README.md +0 -161
- pythonlogs-3.0.13/pythonLogs/__init__.py +0 -55
- pythonlogs-3.0.13/pythonLogs/basic_log.py +0 -32
- pythonlogs-3.0.13/pythonLogs/log_utils.py +0 -264
- pythonlogs-3.0.13/pythonLogs/settings.py +0 -45
- {pythonlogs-3.0.13 → pythonlogs-4.0.2}/LICENSE +0 -0
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: pythonLogs
|
|
3
|
+
Version: 4.0.2
|
|
4
|
+
Summary: High-performance Python logging library with file rotation and optimized caching for better performance
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: python3,python-3,python,log,logging,logger,logutils,log-utils,pythonLogs
|
|
7
|
+
Author: Daniel Costa
|
|
8
|
+
Author-email: danieldcsta@gmail.com
|
|
9
|
+
Maintainer: Daniel Costa
|
|
10
|
+
Requires-Python: >=3.10,<4.0
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Other Environment
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Dist: pydantic (>=2.11.7,<3.0.0)
|
|
25
|
+
Requires-Dist: pydantic-settings (>=2.10.1,<3.0.0)
|
|
26
|
+
Requires-Dist: python-dotenv (>=1.1.1,<2.0.0)
|
|
27
|
+
Project-URL: Homepage, https://pypi.org/project/pythonLogs
|
|
28
|
+
Project-URL: Repository, https://github.com/ddc/pythonLogs
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# High-performance Python logging library
|
|
32
|
+
|
|
33
|
+
[](https://www.paypal.com/ncp/payment/6G9Z78QHUD4RJ)
|
|
34
|
+
[](https://opensource.org/licenses/MIT)
|
|
35
|
+
[](https://pypi.python.org/pypi/pythonLogs)
|
|
36
|
+
[](https://pepy.tech/projects/pythonLogs)
|
|
37
|
+
[](https://codecov.io/gh/ddc/pythonLogs)
|
|
38
|
+
[](https://github.com/psf/black)
|
|
39
|
+
[](https://actions-badge.atrox.dev/ddc/pythonLogs/goto?ref=main)
|
|
40
|
+
[](https://www.python.org/downloads)
|
|
41
|
+
|
|
42
|
+
[](https://github.com/sponsors/ddc)
|
|
43
|
+
|
|
44
|
+
High-performance Python logging library with file rotation and optimized caching for better performance
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## Table of Contents
|
|
48
|
+
|
|
49
|
+
- [Features](#features)
|
|
50
|
+
- [Installation](#installation)
|
|
51
|
+
- [Logger Types](#logger-types)
|
|
52
|
+
- [Basic Logger](#basic-logger)
|
|
53
|
+
- [Size Rotating Logger](#size-rotating-logger)
|
|
54
|
+
- [Timed Rotating Logger](#timed-rotating-logger)
|
|
55
|
+
- [Context Manager Support](#context-manager-support)
|
|
56
|
+
- [Advanced Factory Features](#advanced-factory-features)
|
|
57
|
+
- [Memory Management](#memory-management)
|
|
58
|
+
- [Migration Guide](#migration-guide)
|
|
59
|
+
- [Performance Improvements](#performance-improvements)
|
|
60
|
+
- [Environment Variables](#env-variables-optional)
|
|
61
|
+
- [Development](#source-code)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# Features
|
|
66
|
+
|
|
67
|
+
✨ **Factory Pattern** - Easy logger creation with centralized configuration
|
|
68
|
+
🚀 **High Performance** - Optimized caching for 90%+ performance improvements
|
|
69
|
+
🔄 **File Rotation** - Automatic rotation by size or time with compression
|
|
70
|
+
🎯 **Type Safety** - Enum-based configuration with IDE support
|
|
71
|
+
⚙️ **Flexible Configuration** - Environment variables, direct parameters, or defaults
|
|
72
|
+
📍 **Location Tracking** - Optional filename and line number in logs
|
|
73
|
+
🌍 **Timezone Support** - Full timezone handling including `localtime` and `UTC`
|
|
74
|
+
💾 **Memory Efficient** - Logger registry and settings caching
|
|
75
|
+
🔒 **Context Manager Support** - Automatic resource cleanup and exception safety
|
|
76
|
+
🧵 **Thread Safe** - Concurrent access protection for all operations
|
|
77
|
+
🔧 **Resource Management** - Automatic handler cleanup and memory leak prevention
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Installation
|
|
81
|
+
```shell
|
|
82
|
+
pip install pythonLogs
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# Logger Types
|
|
87
|
+
|
|
88
|
+
## Basic Logger
|
|
89
|
+
Console-only logging without file output. Perfect for development and simple applications.
|
|
90
|
+
|
|
91
|
+
### Using Factory Pattern (Recommended)
|
|
92
|
+
```python
|
|
93
|
+
from pythonLogs import basic_logger, LogLevel
|
|
94
|
+
|
|
95
|
+
# Option 1: Using string (simple) (case-insensitive)
|
|
96
|
+
logger = basic_logger(
|
|
97
|
+
name="my_app",
|
|
98
|
+
level="debug", # "debug", "info", "warning", "error", "critical"
|
|
99
|
+
timezone="America/Sao_Paulo",
|
|
100
|
+
showlocation=False
|
|
101
|
+
)
|
|
102
|
+
logger.warning("This is a warning example")
|
|
103
|
+
|
|
104
|
+
# Option 2: Using enum (type-safe)
|
|
105
|
+
logger = basic_logger(
|
|
106
|
+
name="my_app",
|
|
107
|
+
level=LogLevel.DEBUG,
|
|
108
|
+
timezone="America/Sao_Paulo",
|
|
109
|
+
showlocation=False
|
|
110
|
+
)
|
|
111
|
+
logger.warning("This is a warning example")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Legacy Method (Still Supported)
|
|
115
|
+
```python
|
|
116
|
+
from pythonLogs import BasicLog
|
|
117
|
+
|
|
118
|
+
logger = BasicLog(
|
|
119
|
+
level="debug",
|
|
120
|
+
name="app",
|
|
121
|
+
timezone="America/Sao_Paulo",
|
|
122
|
+
showlocation=False,
|
|
123
|
+
).init()
|
|
124
|
+
logger.warning("This is a warning example")
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### Example Output
|
|
128
|
+
`[2024-10-08T19:08:56.918-0300]:[WARNING]:[my_app]:This is a warning example`
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
## Size Rotating Logger
|
|
135
|
+
File-based logging with automatic rotation when files reach a specified size. Rotated files are compressed as `.gz`.
|
|
136
|
+
|
|
137
|
+
+ **Rotation**: Based on file size (`maxmbytes` parameter)
|
|
138
|
+
+ **Naming**: Rotated logs have sequence numbers: `app.log_1.gz`, `app.log_2.gz`
|
|
139
|
+
+ **Cleanup**: Old logs deleted based on `daystokeep` (default: 30 days)
|
|
140
|
+
|
|
141
|
+
### Using Factory Pattern (Recommended)
|
|
142
|
+
```python
|
|
143
|
+
from pythonLogs import size_rotating_logger, LogLevel
|
|
144
|
+
|
|
145
|
+
# Option 1: Using string (simple) (case-insensitive)
|
|
146
|
+
logger = size_rotating_logger(
|
|
147
|
+
name="my_app",
|
|
148
|
+
level="debug", # "debug", "info", "warning", "error", "critical"
|
|
149
|
+
directory="/app/logs",
|
|
150
|
+
filenames=["main.log", "app1.log"],
|
|
151
|
+
maxmbytes=5,
|
|
152
|
+
daystokeep=7,
|
|
153
|
+
timezone="America/Chicago",
|
|
154
|
+
streamhandler=True,
|
|
155
|
+
showlocation=False
|
|
156
|
+
)
|
|
157
|
+
logger.warning("This is a warning example")
|
|
158
|
+
|
|
159
|
+
# Option 2: Using enum (type-safe)
|
|
160
|
+
logger = size_rotating_logger(
|
|
161
|
+
name="my_app",
|
|
162
|
+
level=LogLevel.DEBUG,
|
|
163
|
+
directory="/app/logs",
|
|
164
|
+
filenames=["main.log", "app1.log"],
|
|
165
|
+
maxmbytes=5,
|
|
166
|
+
daystokeep=7,
|
|
167
|
+
timezone="America/Chicago",
|
|
168
|
+
streamhandler=True,
|
|
169
|
+
showlocation=False
|
|
170
|
+
)
|
|
171
|
+
logger.warning("This is a warning example")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Legacy Method (Still Supported)
|
|
175
|
+
```python
|
|
176
|
+
from pythonLogs import SizeRotatingLog
|
|
177
|
+
|
|
178
|
+
logger = SizeRotatingLog(
|
|
179
|
+
level="debug",
|
|
180
|
+
name="app",
|
|
181
|
+
directory="/app/logs",
|
|
182
|
+
filenames=["main.log", "app1.log"],
|
|
183
|
+
maxmbytes=5,
|
|
184
|
+
daystokeep=7,
|
|
185
|
+
timezone="America/Chicago",
|
|
186
|
+
streamhandler=True,
|
|
187
|
+
showlocation=False
|
|
188
|
+
).init()
|
|
189
|
+
logger.warning("This is a warning example")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Example Output
|
|
193
|
+
`[2024-10-08T19:08:56.918-0500]:[WARNING]:[my_app]:This is a warning example`
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
## Timed Rotating Logger
|
|
200
|
+
File-based logging with automatic rotation based on time intervals. Rotated files are compressed as `.gz`.
|
|
201
|
+
|
|
202
|
+
+ **Rotation**: Based on time (`when` parameter, defaults to `midnight`)
|
|
203
|
+
+ **Naming**: Rotated logs have date suffix: `app_20240816.log.gz`
|
|
204
|
+
+ **Cleanup**: Old logs deleted based on `daystokeep` (default: 30 days)
|
|
205
|
+
+ **Supported Intervals**: `midnight`, `hourly`, `daily`, `W0-W6` (weekdays, 0=Monday)
|
|
206
|
+
|
|
207
|
+
### Using Factory Pattern (Recommended)
|
|
208
|
+
```python
|
|
209
|
+
from pythonLogs import timed_rotating_logger, LogLevel, RotateWhen
|
|
210
|
+
|
|
211
|
+
# Option 1: Using string (simple) (case-insensitive)
|
|
212
|
+
logger = timed_rotating_logger(
|
|
213
|
+
name="my_app",
|
|
214
|
+
level="debug", # "debug", "info", "warning", "error", "critical"
|
|
215
|
+
directory="/app/logs",
|
|
216
|
+
filenames=["main.log", "app2.log"],
|
|
217
|
+
when="midnight", # String when value
|
|
218
|
+
daystokeep=7,
|
|
219
|
+
timezone="UTC",
|
|
220
|
+
streamhandler=True,
|
|
221
|
+
showlocation=False
|
|
222
|
+
)
|
|
223
|
+
logger.warning("This is a warning example")
|
|
224
|
+
|
|
225
|
+
# Option 2: Using enum (type-safe)
|
|
226
|
+
logger = timed_rotating_logger(
|
|
227
|
+
name="my_app",
|
|
228
|
+
level=LogLevel.DEBUG, # Type-safe enum
|
|
229
|
+
directory="/app/logs",
|
|
230
|
+
filenames=["main.log", "app2.log"],
|
|
231
|
+
when=RotateWhen.MIDNIGHT, # Type-safe enum
|
|
232
|
+
daystokeep=7,
|
|
233
|
+
timezone="UTC",
|
|
234
|
+
streamhandler=True,
|
|
235
|
+
showlocation=False
|
|
236
|
+
)
|
|
237
|
+
logger.warning("This is a warning example")
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Legacy Method (Still Supported)
|
|
241
|
+
```python
|
|
242
|
+
from pythonLogs import TimedRotatingLog
|
|
243
|
+
|
|
244
|
+
logger = TimedRotatingLog(
|
|
245
|
+
level="debug",
|
|
246
|
+
name="app",
|
|
247
|
+
directory="/app/logs",
|
|
248
|
+
filenames=["main.log", "app2.log"],
|
|
249
|
+
when="midnight",
|
|
250
|
+
daystokeep=7,
|
|
251
|
+
timezone="UTC",
|
|
252
|
+
streamhandler=True,
|
|
253
|
+
showlocation=False
|
|
254
|
+
).init()
|
|
255
|
+
logger.warning("This is a warning example")
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Example Output
|
|
259
|
+
`[2024-10-08T19:08:56.918-0000]:[WARNING]:[my_app]:This is a warning example`
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
# Context Manager Support
|
|
266
|
+
|
|
267
|
+
All logger types support context managers for automatic resource cleanup and exception safety:
|
|
268
|
+
|
|
269
|
+
## Basic Usage
|
|
270
|
+
```python
|
|
271
|
+
from pythonLogs import BasicLog, SizeRotatingLog, TimedRotatingLog, LogLevel
|
|
272
|
+
|
|
273
|
+
# Automatic cleanup with context managers
|
|
274
|
+
with BasicLog(name="app", level=LogLevel.INFO) as logger:
|
|
275
|
+
logger.info("This is automatically cleaned up")
|
|
276
|
+
# Handlers are automatically closed on exit
|
|
277
|
+
|
|
278
|
+
with SizeRotatingLog(name="app", directory="/logs", filenames=["app.log"]) as logger:
|
|
279
|
+
logger.info("File handlers cleaned up automatically")
|
|
280
|
+
# File handlers closed and resources freed
|
|
281
|
+
|
|
282
|
+
# Exception safety - cleanup happens even if exceptions occur
|
|
283
|
+
try:
|
|
284
|
+
with TimedRotatingLog(name="app", directory="/logs") as logger:
|
|
285
|
+
logger.error("Error occurred")
|
|
286
|
+
raise ValueError("Something went wrong")
|
|
287
|
+
except ValueError:
|
|
288
|
+
pass # Logger was still cleaned up properly
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Benefits of Context Manager Usage
|
|
292
|
+
- 🔒 **Automatic Cleanup** - Handlers are closed and removed automatically
|
|
293
|
+
- ⚡ **Exception Safety** - Resources cleaned up even when exceptions occur
|
|
294
|
+
- 💾 **Memory Management** - Prevents memory leaks from unclosed handlers
|
|
295
|
+
- 🧵 **Thread Safety** - Cleanup operations are thread-safe
|
|
296
|
+
- 🔧 **No Manual Management** - No need to manually call cleanup methods
|
|
297
|
+
|
|
298
|
+
## Factory Pattern + Context Managers
|
|
299
|
+
```python
|
|
300
|
+
from pythonLogs import LoggerFactory, LoggerType
|
|
301
|
+
|
|
302
|
+
# Create logger through factory and use with context manager
|
|
303
|
+
logger_instance = LoggerFactory.get_or_create_logger(
|
|
304
|
+
LoggerType.SIZE_ROTATING,
|
|
305
|
+
name="production_app",
|
|
306
|
+
directory="/var/log"
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
# Use the logger instance directly
|
|
310
|
+
with logger_instance as logger:
|
|
311
|
+
logger.info("Factory created logger with automatic cleanup")
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
# Advanced Factory Features
|
|
316
|
+
|
|
317
|
+
## Logger Registry (Performance Optimization)
|
|
318
|
+
The factory pattern includes a built-in registry that caches loggers for improved performance:
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
from pythonLogs import get_or_create_logger, LoggerType, clear_logger_registry
|
|
322
|
+
|
|
323
|
+
# First call creates the logger
|
|
324
|
+
logger1 = get_or_create_logger(LoggerType.BASIC, name="cached_app")
|
|
325
|
+
|
|
326
|
+
# The Second call returns the same logger instance (90% faster)
|
|
327
|
+
logger2 = get_or_create_logger(LoggerType.BASIC, name="cached_app")
|
|
328
|
+
|
|
329
|
+
# Both variables point to the same logger instance
|
|
330
|
+
assert logger1 is logger2
|
|
331
|
+
|
|
332
|
+
# Clear registry when needed (useful for testing)
|
|
333
|
+
clear_logger_registry()
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Flexible Configuration Options
|
|
337
|
+
You can use either enums (for type safety) or strings (for simplicity):
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
from pythonLogs import LogLevel, RotateWhen, LoggerType
|
|
341
|
+
|
|
342
|
+
# Option 1: Type-safe enums (recommended)
|
|
343
|
+
LogLevel.DEBUG # "DEBUG"
|
|
344
|
+
LogLevel.INFO # "INFO"
|
|
345
|
+
LogLevel.WARNING # "WARNING"
|
|
346
|
+
LogLevel.ERROR # "ERROR"
|
|
347
|
+
LogLevel.CRITICAL # "CRITICAL"
|
|
348
|
+
|
|
349
|
+
# Option 2: String values (case-insensitive)
|
|
350
|
+
"debug" # Same as LogLevel.DEBUG
|
|
351
|
+
"info" # Same as LogLevel.INFO
|
|
352
|
+
"warning" # Same as LogLevel.WARNING
|
|
353
|
+
"warn" # Same as LogLevel.WARN (alias)
|
|
354
|
+
"error" # Same as LogLevel.ERROR
|
|
355
|
+
"critical" # Same as LogLevel.CRITICAL
|
|
356
|
+
"crit" # Same as LogLevel.CRIT (alias)
|
|
357
|
+
# Also supports: "DEBUG", "Info", "Warning", etc.
|
|
358
|
+
|
|
359
|
+
# RotateWhen values
|
|
360
|
+
RotateWhen.MIDNIGHT # "midnight"
|
|
361
|
+
RotateWhen.HOURLY # "H"
|
|
362
|
+
RotateWhen.DAILY # "D"
|
|
363
|
+
RotateWhen.MONDAY # "W0"
|
|
364
|
+
# ... through SUNDAY # "W6"
|
|
365
|
+
# String equivalents: "midnight", "H", "D", "W0"-"W6"
|
|
366
|
+
|
|
367
|
+
# LoggerType values
|
|
368
|
+
LoggerType.BASIC # "basic"
|
|
369
|
+
LoggerType.SIZE_ROTATING # "size_rotating"
|
|
370
|
+
LoggerType.TIMED_ROTATING # "timed_rotating"
|
|
371
|
+
# String equivalents: "basic", "size_rotating", "timed_rotating"
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Production Setup Example
|
|
375
|
+
```python
|
|
376
|
+
from pythonLogs import size_rotating_logger, timed_rotating_logger, LogLevel, RotateWhen
|
|
377
|
+
|
|
378
|
+
# Application logger
|
|
379
|
+
app_logger = size_rotating_logger(
|
|
380
|
+
name="production_app",
|
|
381
|
+
directory="/var/log/myapp",
|
|
382
|
+
filenames=["app.log"],
|
|
383
|
+
maxmbytes=50, # 50MB files
|
|
384
|
+
daystokeep=30, # Keep 30 days
|
|
385
|
+
level=LogLevel.INFO,
|
|
386
|
+
streamhandler=True, # Also log to console
|
|
387
|
+
showlocation=True, # Show file:function:line
|
|
388
|
+
timezone="UTC"
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
# Error logger with longer retention
|
|
392
|
+
error_logger = size_rotating_logger(
|
|
393
|
+
name="production_errors",
|
|
394
|
+
directory="/var/log/myapp",
|
|
395
|
+
filenames=["errors.log"],
|
|
396
|
+
maxmbytes=10,
|
|
397
|
+
daystokeep=90, # Keep errors longer
|
|
398
|
+
level=LogLevel.ERROR,
|
|
399
|
+
streamhandler=False
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
# Audit logger with daily rotation
|
|
403
|
+
audit_logger = timed_rotating_logger(
|
|
404
|
+
name="audit_log",
|
|
405
|
+
directory="/var/log/myapp",
|
|
406
|
+
filenames=["audit.log"],
|
|
407
|
+
when=RotateWhen.MIDNIGHT,
|
|
408
|
+
level=LogLevel.INFO
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
# Use the loggers
|
|
412
|
+
app_logger.info("Application started")
|
|
413
|
+
error_logger.error("Database connection failed")
|
|
414
|
+
audit_logger.info("User admin logged in")
|
|
415
|
+
```
|
|
416
|
+
|
|
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
|
+
|
|
426
|
+
```
|
|
427
|
+
LOG_LEVEL=DEBUG
|
|
428
|
+
LOG_TIMEZONE=UTC
|
|
429
|
+
LOG_ENCODING=UTF-8
|
|
430
|
+
LOG_APPNAME=app
|
|
431
|
+
LOG_FILENAME=app.log
|
|
432
|
+
LOG_DIRECTORY=/app/logs
|
|
433
|
+
LOG_DAYS_TO_KEEP=30
|
|
434
|
+
LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
|
|
435
|
+
LOG_STREAM_HANDLER=True
|
|
436
|
+
LOG_SHOW_LOCATION=False
|
|
437
|
+
LOG_MAX_LOGGERS=50
|
|
438
|
+
LOG_LOGGER_TTL_SECONDS=1800
|
|
439
|
+
|
|
440
|
+
# SizeRotatingLog
|
|
441
|
+
LOG_MAX_FILE_SIZE_MB=10
|
|
442
|
+
|
|
443
|
+
# TimedRotatingLog
|
|
444
|
+
LOG_ROTATE_WHEN=midnight
|
|
445
|
+
LOG_ROTATE_AT_UTC=True
|
|
446
|
+
LOG_ROTATE_FILE_SUFIX="%Y%m%d"
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
# Memory Management
|
|
453
|
+
|
|
454
|
+
The library includes comprehensive memory management features to prevent memory leaks and optimize resource usage:
|
|
455
|
+
|
|
456
|
+
## Automatic Resource Cleanup
|
|
457
|
+
```python
|
|
458
|
+
from pythonLogs import clear_logger_registry, shutdown_logger, LoggerFactory
|
|
459
|
+
|
|
460
|
+
# Clear the entire logger registry with proper cleanup
|
|
461
|
+
clear_logger_registry()
|
|
462
|
+
|
|
463
|
+
# Shutdown specific logger and remove from registry
|
|
464
|
+
shutdown_logger("my_app_logger")
|
|
465
|
+
|
|
466
|
+
# Manual registry management
|
|
467
|
+
LoggerFactory.shutdown_logger("specific_logger")
|
|
468
|
+
LoggerFactory.clear_registry()
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## Memory Optimization Features
|
|
472
|
+
```python
|
|
473
|
+
from pythonLogs import (
|
|
474
|
+
get_memory_stats,
|
|
475
|
+
clear_formatter_cache,
|
|
476
|
+
clear_directory_cache,
|
|
477
|
+
optimize_lru_cache_sizes,
|
|
478
|
+
force_garbage_collection
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
# Get current memory usage statistics
|
|
482
|
+
stats = get_memory_stats()
|
|
483
|
+
print(f"Registry size: {stats['registry_size']}")
|
|
484
|
+
print(f"Formatter cache: {stats['formatter_cache_size']}")
|
|
485
|
+
print(f"Active loggers: {stats['active_logger_count']}")
|
|
486
|
+
|
|
487
|
+
# Clear various caches to free memory
|
|
488
|
+
clear_formatter_cache() # Clear cached formatters
|
|
489
|
+
clear_directory_cache() # Clear directory permission cache
|
|
490
|
+
|
|
491
|
+
# Optimize LRU cache sizes for memory-constrained environments
|
|
492
|
+
optimize_lru_cache_sizes()
|
|
493
|
+
|
|
494
|
+
# Force garbage collection and get collection statistics
|
|
495
|
+
gc_stats = force_garbage_collection()
|
|
496
|
+
print(f"Objects collected: {gc_stats['objects_collected']}")
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
## Registry Configuration
|
|
500
|
+
```python
|
|
501
|
+
from pythonLogs import LoggerFactory
|
|
502
|
+
|
|
503
|
+
# Configure registry limits for memory management
|
|
504
|
+
LoggerFactory.set_memory_limits(
|
|
505
|
+
max_loggers=50, # Maximum cached loggers
|
|
506
|
+
ttl_seconds=1800 # Logger time-to-live (30 minutes)
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
# Monitor registered loggers
|
|
510
|
+
registered = LoggerFactory.get_registered_loggers()
|
|
511
|
+
print(f"Currently registered: {list(registered.keys())}")
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Thread-Safe Operations
|
|
515
|
+
All memory management operations are thread-safe and can be used safely in multi-threaded applications:
|
|
516
|
+
|
|
517
|
+
```python
|
|
518
|
+
import threading
|
|
519
|
+
from pythonLogs import size_rotating_logger, clear_logger_registry
|
|
520
|
+
|
|
521
|
+
def worker_function(worker_id):
|
|
522
|
+
# Each thread can safely create and use loggers
|
|
523
|
+
logger = size_rotating_logger(
|
|
524
|
+
name=f"worker_{worker_id}",
|
|
525
|
+
directory="/app/logs"
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
with logger as log:
|
|
529
|
+
log.info(f"Worker {worker_id} started")
|
|
530
|
+
# Automatic cleanup per thread
|
|
531
|
+
|
|
532
|
+
# Create multiple threads - all operations are thread-safe
|
|
533
|
+
threads = []
|
|
534
|
+
for i in range(10):
|
|
535
|
+
thread = threading.Thread(target=worker_function, args=(i,))
|
|
536
|
+
threads.append(thread)
|
|
537
|
+
thread.start()
|
|
538
|
+
|
|
539
|
+
# Wait for completion and clean up
|
|
540
|
+
for thread in threads:
|
|
541
|
+
thread.join()
|
|
542
|
+
|
|
543
|
+
# Safe to clear registry from main thread
|
|
544
|
+
clear_logger_registry()
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
# Migration Guide
|
|
549
|
+
|
|
550
|
+
## Upgrading from Legacy to Factory Pattern
|
|
551
|
+
|
|
552
|
+
The factory pattern is **100% backward compatible**. Your existing code will continue to work unchanged.
|
|
553
|
+
|
|
554
|
+
### Before (Legacy - Still Works)
|
|
555
|
+
```python
|
|
556
|
+
from pythonLogs import BasicLog, SizeRotatingLog, TimedRotatingLog
|
|
557
|
+
|
|
558
|
+
# Old way
|
|
559
|
+
basic_logger = BasicLog(level="info", name="app").init()
|
|
560
|
+
size_logger = SizeRotatingLog(level="debug", name="app", directory="/logs").init()
|
|
561
|
+
timed_logger = TimedRotatingLog(level="warning", name="app", directory="/logs").init()
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### After (Factory Pattern - Recommended)
|
|
565
|
+
```python
|
|
566
|
+
from pythonLogs import basic_logger, size_rotating_logger, timed_rotating_logger, LogLevel
|
|
567
|
+
|
|
568
|
+
# New way - cleaner and faster
|
|
569
|
+
basic_logger = basic_logger(level=LogLevel.INFO, name="app")
|
|
570
|
+
size_logger = size_rotating_logger(level=LogLevel.DEBUG, name="app", directory="/logs")
|
|
571
|
+
timed_logger = timed_rotating_logger(level=LogLevel.WARNING, name="app", directory="/logs")
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Benefits of Migration
|
|
575
|
+
- 🚀 **90% faster logger creation** with registry caching
|
|
576
|
+
- 🎯 **Type safety** with enum-based parameters
|
|
577
|
+
- 💡 **Better IDE support** with autocomplete and validation
|
|
578
|
+
- 🔧 **Cleaner API** without manual `.init()` calls
|
|
579
|
+
- 📚 **Centralized configuration** through factory pattern
|
|
580
|
+
|
|
581
|
+
# Performance Improvements
|
|
582
|
+
|
|
583
|
+
## Benchmarks
|
|
584
|
+
The factory pattern with optimizations provides significant performance improvements:
|
|
585
|
+
|
|
586
|
+
| Feature | Improvement | Benefit |
|
|
587
|
+
|---------|-------------|---------|
|
|
588
|
+
| Logger Registry | 90%+ faster | Cached logger instances |
|
|
589
|
+
| Settings Caching | ~85% faster | Reused configuration objects |
|
|
590
|
+
| Directory Validation | ~75% faster | Cached permission checks |
|
|
591
|
+
| Timezone Operations | ~60% faster | Cached timezone functions |
|
|
592
|
+
|
|
593
|
+
## Performance Test Results
|
|
594
|
+
```python
|
|
595
|
+
# Create 100 loggers - Performance comparison
|
|
596
|
+
# Legacy method: ~0.045 seconds
|
|
597
|
+
# Factory pattern: ~0.004 seconds
|
|
598
|
+
# Improvement: 91% faster ⚡
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
# Source Code
|
|
602
|
+
### Build
|
|
603
|
+
```shell
|
|
604
|
+
poetry build -f wheel
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
# Run Tests and Get Coverage Report using Poe
|
|
610
|
+
```shell
|
|
611
|
+
poetry update --with test
|
|
612
|
+
poe test
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
# License
|
|
618
|
+
Released under the [MIT License](LICENSE)
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
# Buy me a cup of coffee
|
|
624
|
+
+ [GitHub Sponsor](https://github.com/sponsors/ddc)
|
|
625
|
+
+ [ko-fi](https://ko-fi.com/ddcsta)
|
|
626
|
+
+ [Paypal](https://www.paypal.com/ncp/payment/6G9Z78QHUD4RJ)
|
|
627
|
+
|