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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pythonLogs
3
- Version: 4.0.1
4
- Summary: A modern, high-performance Python logging library with automatic file rotation, factory pattern for easy logger creation, and optimized caching for better performance.
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
  [![Support me on GitHub](https://img.shields.io/badge/Support_me_on_GitHub-154c79?style=for-the-badge&logo=github)](https://github.com/sponsors/ddc)
42
43
 
43
- A modern, high-performance Python logging library with automatic file rotation, context manager support, and memory optimization.
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=America/Chicago
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
- LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
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
  [![Support me on GitHub](https://img.shields.io/badge/Support_me_on_GitHub-154c79?style=for-the-badge&logo=github)](https://github.com/sponsors/ddc)
13
13
 
14
- A modern, high-performance Python logging library with automatic file rotation, context manager support, and memory optimization.
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=America/Chicago
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
- LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
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.1"
9
- description = "A modern, high-performance Python logging library with automatic file rotation, factory pattern for easy logger creation, and optimized caching for better performance."
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
- [tool.poe.tasks]
64
- _test = "coverage run -m pytest -v"
65
- _coverage_report = "coverage report"
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
- LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
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
- encoding: Optional[str] = Field(default=DEFAULT_ENCODING)
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
- timezone: Optional[str] = Field(default=DEFAULT_TIMEZONE)
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