logging-metrics 0.1.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.
- logging_metrics-0.1.0/LICENSE +21 -0
- logging_metrics-0.1.0/PKG-INFO +565 -0
- logging_metrics-0.1.0/README.md +544 -0
- logging_metrics-0.1.0/pyproject.toml +35 -0
- logging_metrics-0.1.0/setup.cfg +4 -0
- logging_metrics-0.1.0/src/logging_metrics/__init__.py +29 -0
- logging_metrics-0.1.0/src/logging_metrics/core.py +771 -0
- logging_metrics-0.1.0/src/logging_metrics.egg-info/PKG-INFO +565 -0
- logging_metrics-0.1.0/src/logging_metrics.egg-info/SOURCES.txt +11 -0
- logging_metrics-0.1.0/src/logging_metrics.egg-info/dependency_links.txt +1 -0
- logging_metrics-0.1.0/src/logging_metrics.egg-info/requires.txt +6 -0
- logging_metrics-0.1.0/src/logging_metrics.egg-info/top_level.txt +1 -0
- logging_metrics-0.1.0/test/test_logging_toolkit.py +221 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 thaissateodoro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: logging-metrics
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Advanced logging utilities for robust, standardized logs in Python projects, APIs, data engineering, and more.
|
|
5
|
+
Author-email: Thaissa Ferreira <thaissa.teodoro@hotmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: pyspark>=3.0.0
|
|
16
|
+
Requires-Dist: pytz
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# logging-metrics - Utilities Library for Logging Configuration and Management
|
|
24
|
+
|
|
25
|
+
This module provides functions and classes to configure logging for different environments and use cases:
|
|
26
|
+
|
|
27
|
+
- Colored logs for the terminal
|
|
28
|
+
- Rotating log files (by time or size)
|
|
29
|
+
- Customizable settings for different verbosity levels
|
|
30
|
+
- Text or JSON formatters compatible with external analysis tools
|
|
31
|
+
- Utilities for timing operations and collecting custom metrics
|
|
32
|
+
- **Utility functions for logging PySpark DataFrames** (e.g., row count, schema, samples, and basic statistics)
|
|
33
|
+
|
|
34
|
+
Main Components:
|
|
35
|
+
----------------
|
|
36
|
+
- `ColoredFormatter`: Colorized terminal output for quick identification of log levels
|
|
37
|
+
- `JSONFormatter`: JSON-formatted logs for external tool integration
|
|
38
|
+
- Functions to create handlers (console, file, rotation by time or size)
|
|
39
|
+
- `LogTimer`: Measure execution time of code blocks (context manager or decorator)
|
|
40
|
+
- `LogMetrics`: Collect and log custom metrics (counters, timers, values)
|
|
41
|
+
- **`log_spark_dataframe_info`: Easy, structured logging for PySpark DataFrames**
|
|
42
|
+
|
|
43
|
+
This toolkit is recommended for data pipelines, ETLs, and projects where traceability, auditability, and log performance are critical requirements.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
This README.md covers:
|
|
48
|
+
|
|
49
|
+
- Purpose
|
|
50
|
+
- Installation
|
|
51
|
+
- Main Features
|
|
52
|
+
- Best Practices
|
|
53
|
+
- Usage Example
|
|
54
|
+
- Spark Integration
|
|
55
|
+
- Dependencies & License
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
# Logging-Toolkit
|
|
60
|
+
|
|
61
|
+
A library for configuring and managing logs in Python, focused on simplicity and performance.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
#### โจ Features
|
|
66
|
+
|
|
67
|
+
- ๐จ Colored logs for the terminal with different levels
|
|
68
|
+
- ๐ Automatic file rotation by time or size
|
|
69
|
+
- โก PySpark DataFrame integration
|
|
70
|
+
- ๐ JSON format for observability systems
|
|
71
|
+
- โฑ๏ธ Timing with LogTimer
|
|
72
|
+
- ๐ Metrics monitoring with LogMetrics
|
|
73
|
+
- ๐ง Hierarchical logger configuration
|
|
74
|
+
- ๐ Optimized performance for critical applications
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## ๐ฆ Installation
|
|
79
|
+
|
|
80
|
+
#### Install via pip:
|
|
81
|
+
```bash
|
|
82
|
+
pip install logging-toolkit
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### For development:
|
|
86
|
+
```bash
|
|
87
|
+
git clone https://github.com/thaissateodoro/logging-toolkit.git
|
|
88
|
+
cd logging-toolkit
|
|
89
|
+
pip install -e ".[dev]"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
## ๐ Functions and Classes Overview
|
|
94
|
+
|
|
95
|
+
Main Functions
|
|
96
|
+
```
|
|
97
|
+
| Name | Type | Description |
|
|
98
|
+
|---------------------------|----------|--------------------------------------------------------------------------------------|
|
|
99
|
+
| `configure_basic_logging` | Function | Configures root logger for colored console logging. |
|
|
100
|
+
| `setup_file_logging` | Function | Configures a logger with file output (rotation), optional console, JSON formatting. |
|
|
101
|
+
| `LogTimer` | Class | Context manager and decorator to log execution time of code blocks or functions. |
|
|
102
|
+
| `log_spark_dataframe_info`| Function | Logs schema, sample, stats of a PySpark DataFrame (row count, sample, stats, etc). |
|
|
103
|
+
| `LogMetrics` | Class | Utility for collecting, incrementing, timing, and logging custom processing metrics. |
|
|
104
|
+
| `get_logger` | Function | Returns a logger with custom handlers and caplog-friendly mode for pytest. |
|
|
105
|
+
```
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### Utility Classes
|
|
109
|
+
#### LogTimer
|
|
110
|
+
- Context manager: with LogTimer(logger, "operation"):
|
|
111
|
+
- Decorator: @LogTimer.decorator(logger, "function")
|
|
112
|
+
- Manual: timer.start() / timer.stop()
|
|
113
|
+
|
|
114
|
+
#### LogMetrics
|
|
115
|
+
- Counters: metrics.increment('counter')
|
|
116
|
+
- Timers: metrics.start('timer') / metrics.stop('timer')
|
|
117
|
+
- Context manager: with metrics.timer('operation'):
|
|
118
|
+
- Report: metrics.log_all()
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## ๐ Quick Start
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
import logging
|
|
126
|
+
from logging_metrics import setup_file_logging, LogTimer
|
|
127
|
+
|
|
128
|
+
# Basic configuration
|
|
129
|
+
logger = setup_file_logging(
|
|
130
|
+
logger_name="my_app",
|
|
131
|
+
log_dir="./logs",
|
|
132
|
+
console_level=logging.INFO, # Less verbose in console
|
|
133
|
+
level=logging.DEBUG # More detailed in the file
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# Simple usage
|
|
137
|
+
logger.info("Application started!")
|
|
138
|
+
|
|
139
|
+
# Timing operations
|
|
140
|
+
with LogTimer(logger, "Critical operation"):
|
|
141
|
+
# your code here
|
|
142
|
+
pass
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## ๐ Main Features
|
|
148
|
+
|
|
149
|
+
1. Logging configuration:
|
|
150
|
+
```python
|
|
151
|
+
import logging
|
|
152
|
+
from logging-metrics import configure_basic_logging
|
|
153
|
+
logger = configure_basic_logging()
|
|
154
|
+
logger.debug("Debug message") # Gray
|
|
155
|
+
logger.info("Info") # Green
|
|
156
|
+
logger.warning("Warning") # Yellow
|
|
157
|
+
logger.error("Error") # Red
|
|
158
|
+
logger.critical("Critical") # Bold red
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
2. Automatic Log Rotation:
|
|
162
|
+
```python
|
|
163
|
+
from logging-metrics import setup_file_logging, LogTimer
|
|
164
|
+
# Size-based rotation
|
|
165
|
+
logger = setup_file_logging(
|
|
166
|
+
logger_name="app",
|
|
167
|
+
log_dir="./logs",
|
|
168
|
+
max_bytes=10*1024*1024, # 10MB
|
|
169
|
+
rotation='size'
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Time-based rotation
|
|
173
|
+
logger = setup_file_logging(
|
|
174
|
+
logger_name="app",
|
|
175
|
+
log_dir="./logs",
|
|
176
|
+
rotation='time'
|
|
177
|
+
)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
3. Spark/Databricks Integration:
|
|
181
|
+
```python
|
|
182
|
+
from pyspark.sql import SparkSession
|
|
183
|
+
from logging_metrics import configure_basic_logging, log_spark_dataframe_info
|
|
184
|
+
|
|
185
|
+
spark = SparkSession.builder.getOrCreate()
|
|
186
|
+
df = spark.createDataFrame([(1, "Ana"), (2, "Bruno")], ["id", "nome"])
|
|
187
|
+
|
|
188
|
+
logger = configure_basic_logging()
|
|
189
|
+
print("Logger:", logger)
|
|
190
|
+
|
|
191
|
+
log_spark_dataframe_info(
|
|
192
|
+
df = df,logger = logger, name ="spark_app")
|
|
193
|
+
|
|
194
|
+
logger.info("Spark processing started")
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
4. โฑ Timing with LogTimer:
|
|
198
|
+
```python
|
|
199
|
+
from logging_metrics import LogTimer, configure_basic_logging
|
|
200
|
+
|
|
201
|
+
logger = configure_basic_logging()
|
|
202
|
+
# As a context manager
|
|
203
|
+
with LogTimer(logger, "DB query"):
|
|
204
|
+
logger.info("Test")
|
|
205
|
+
|
|
206
|
+
# As a decorator
|
|
207
|
+
@LogTimer.as_decorator(logger, "Data processing")
|
|
208
|
+
def process_data(data):
|
|
209
|
+
return data.transform()
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
5. ๐ Metrics Monitoring:
|
|
213
|
+
```python
|
|
214
|
+
from logging_metrics import LogMetrics, configure_basic_logging
|
|
215
|
+
import time
|
|
216
|
+
|
|
217
|
+
logger = configure_basic_logging()
|
|
218
|
+
|
|
219
|
+
metrics = LogMetrics(logger)
|
|
220
|
+
|
|
221
|
+
items = [10, 5, 80, 60, 'test1', 'test2']
|
|
222
|
+
|
|
223
|
+
# Start timer for total operation
|
|
224
|
+
metrics.start('total_processing')
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
for item in items:
|
|
228
|
+
# Increments the processed records counter
|
|
229
|
+
metrics.increment('records_processed')
|
|
230
|
+
|
|
231
|
+
# If it is an error (simulation)
|
|
232
|
+
if isinstance(item, str):
|
|
233
|
+
metrics.increment('errors')
|
|
234
|
+
|
|
235
|
+
# Simulates item processing
|
|
236
|
+
time.sleep(0.1)
|
|
237
|
+
|
|
238
|
+
# Custom value example
|
|
239
|
+
metrics.set('last_item', item)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# Finalize and log all metrics
|
|
243
|
+
elapsed = metrics.stop('total_processing')
|
|
244
|
+
|
|
245
|
+
# Logs all collected metrics
|
|
246
|
+
metrics.log_all()
|
|
247
|
+
|
|
248
|
+
# Output:
|
|
249
|
+
# --- Processing Metrics ---
|
|
250
|
+
# Counters:
|
|
251
|
+
# - records_processed: 6
|
|
252
|
+
# - errors_found: 2
|
|
253
|
+
# Values:
|
|
254
|
+
# - last_item: test2
|
|
255
|
+
# Completed timers:
|
|
256
|
+
# - total_processing: 0.60 seconds
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
6. Hierarchical Configuration:
|
|
260
|
+
```python
|
|
261
|
+
from logging_metrics import setup_file_logging
|
|
262
|
+
import logging
|
|
263
|
+
|
|
264
|
+
# Main logger
|
|
265
|
+
main_logger = setup_file_logging("my_app", log_dir="./logs")
|
|
266
|
+
|
|
267
|
+
# Sub-loggers organized hierarchically
|
|
268
|
+
db_logger = logging.getLogger("my_app.database")
|
|
269
|
+
api_logger = logging.getLogger("my_app.api")
|
|
270
|
+
auth_logger = logging.getLogger("my_app.auth")
|
|
271
|
+
|
|
272
|
+
# Module-specific configuration
|
|
273
|
+
db_logger.setLevel(logging.DEBUG) # More verbose for DB
|
|
274
|
+
api_logger.setLevel(logging.INFO) # Normal for API
|
|
275
|
+
auth_logger.setLevel(logging.WARNING) # Only warnings/errors for auth
|
|
276
|
+
|
|
277
|
+
db_logger.debug("querying the database")
|
|
278
|
+
db_logger.info("consultation successfully completed")
|
|
279
|
+
db_logger.error("Error connecting to database!")
|
|
280
|
+
|
|
281
|
+
auth_logger.debug("doing authentication")
|
|
282
|
+
auth_logger.info("authentication successfully completed")
|
|
283
|
+
api_logger.debug("querying the api")
|
|
284
|
+
api_logger.info("consultation successfully completed")
|
|
285
|
+
api_logger.error("Error querying the api")
|
|
286
|
+
auth_logger.error("Auth error!")
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
7. ๐ JSON Format for Observability:
|
|
290
|
+
```python
|
|
291
|
+
from logging_metrics import setup_file_logging
|
|
292
|
+
|
|
293
|
+
# JSON logs for integration with ELK, Grafana, etc.
|
|
294
|
+
logger = setup_file_logging(
|
|
295
|
+
logger_name="microservice",
|
|
296
|
+
log_dir="./logs",
|
|
297
|
+
json_format = True
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
logger.info("User logged in", extra={"user_id": 12345, "action": "login"})
|
|
301
|
+
|
|
302
|
+
# Example JSON output:
|
|
303
|
+
# {
|
|
304
|
+
# "timestamp": "2024-08-05T10:30:00.123Z",
|
|
305
|
+
# "level": "INFO",
|
|
306
|
+
# "name": "microservice",
|
|
307
|
+
# "message": "User logged in",
|
|
308
|
+
# "module": "user-api",
|
|
309
|
+
# "function": "<module>",
|
|
310
|
+
# "line": 160,
|
|
311
|
+
# "taskName": null,
|
|
312
|
+
# "user_id": 12345,
|
|
313
|
+
# "action": "login"
|
|
314
|
+
# }
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## ๐ Best Practices
|
|
320
|
+
|
|
321
|
+
1. Configure logging once at the start:
|
|
322
|
+
```python
|
|
323
|
+
# In main.py or __init__.py
|
|
324
|
+
logger = setup_file_logging("my_app", log_dir="./logs")
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
2. Use logger hierarchy:
|
|
328
|
+
```python
|
|
329
|
+
# Organize by modules/features
|
|
330
|
+
db_logger = logging.getLogger("app.database")
|
|
331
|
+
api_logger = logging.getLogger("app.api")
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
3. Different levels for console and file:
|
|
335
|
+
```python
|
|
336
|
+
logger = setup_file_logging(
|
|
337
|
+
console_level=logging.WARNING, # Less verbose in console
|
|
338
|
+
level=logging.DEBUG # More detailed in the file
|
|
339
|
+
)
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
4. Use LogTimer for critical operations:
|
|
343
|
+
```python
|
|
344
|
+
with LogTimer(logger, "Complex query"):
|
|
345
|
+
result = run_heavy_query()
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
5. Monitor metrics in long processes:
|
|
349
|
+
```python
|
|
350
|
+
metrics = LogMetrics(logger)
|
|
351
|
+
for batch in batches:
|
|
352
|
+
with metrics.timer('batch_processing'):
|
|
353
|
+
process_batch(batch)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## โ Avoid
|
|
359
|
+
- Configuring loggers multiple times
|
|
360
|
+
- Using print() instead of logger
|
|
361
|
+
- Excessive logging in critical loops
|
|
362
|
+
- Exposing sensitive information in logs
|
|
363
|
+
- Ignoring log file rotation
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## ๐ง Advanced Configuration
|
|
368
|
+
|
|
369
|
+
Example of full configuration:
|
|
370
|
+
```python
|
|
371
|
+
from logging_metrics import setup_file_logging, LogMetrics
|
|
372
|
+
import logging
|
|
373
|
+
|
|
374
|
+
# Main configuration with all options
|
|
375
|
+
logger = setup_file_logging(
|
|
376
|
+
logger_name="my_app",
|
|
377
|
+
log_folder: str = "unknown/"
|
|
378
|
+
log_dir="./logs",
|
|
379
|
+
level=logging.DEBUG,
|
|
380
|
+
console_level=logging.INFO,
|
|
381
|
+
rotation='time',
|
|
382
|
+
log_format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
383
|
+
date_format="%Y-%m-%d %H:%M:%S",
|
|
384
|
+
max_bytes=50*1024*1024, # 50MB
|
|
385
|
+
backup_count=10,
|
|
386
|
+
add_console= True
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
# Sub-module configuration
|
|
390
|
+
modules = ['database', 'api', 'auth', 'cache']
|
|
391
|
+
for module in modules:
|
|
392
|
+
module_logger = logging.getLogger(f"my_app.{module}")
|
|
393
|
+
module_logger.setLevel(logging.INFO)
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## ๐งช Complete Example
|
|
399
|
+
|
|
400
|
+
```python
|
|
401
|
+
import logging
|
|
402
|
+
from logging_metrics import setup_file_logging, LogTimer, LogMetrics
|
|
403
|
+
|
|
404
|
+
def main():
|
|
405
|
+
# Initial configuration
|
|
406
|
+
logger = setup_file_logging(
|
|
407
|
+
logger_name="data_processor",
|
|
408
|
+
log_dir="./logs",
|
|
409
|
+
console_level=logging.INFO,
|
|
410
|
+
level=logging.DEBUG
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
# Sub-loggers
|
|
414
|
+
db_logger = logging.getLogger("data_processor.database")
|
|
415
|
+
api_logger = logging.getLogger("data_processor.api")
|
|
416
|
+
|
|
417
|
+
# Metrics
|
|
418
|
+
metrics = LogMetrics(logger)
|
|
419
|
+
|
|
420
|
+
logger.info("Application started")
|
|
421
|
+
|
|
422
|
+
try:
|
|
423
|
+
# Main processing with timing
|
|
424
|
+
with LogTimer(logger, "Full processing"):
|
|
425
|
+
metrics.start('total_processing')
|
|
426
|
+
|
|
427
|
+
# Simulate processing
|
|
428
|
+
for i in range(1000):
|
|
429
|
+
metrics.increment('records_processed')
|
|
430
|
+
|
|
431
|
+
if i % 100 == 0:
|
|
432
|
+
logger.info(f"Processed {i} records")
|
|
433
|
+
|
|
434
|
+
# Simulate occasional error
|
|
435
|
+
if i % 250 == 0:
|
|
436
|
+
metrics.increment('errors_recovered')
|
|
437
|
+
logger.warning(f"Recovered error at record {i}")
|
|
438
|
+
|
|
439
|
+
metrics.stop('total_processing')
|
|
440
|
+
metrics.log_all()
|
|
441
|
+
|
|
442
|
+
logger.info("Processing successfully completed")
|
|
443
|
+
|
|
444
|
+
except Exception as e:
|
|
445
|
+
logger.error(f"Error during processing: {e}", exc_info=True)
|
|
446
|
+
raise
|
|
447
|
+
|
|
448
|
+
if __name__ == "__main__":
|
|
449
|
+
main()
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## ๐งช Tests
|
|
455
|
+
|
|
456
|
+
The library has a complete test suite to ensure quality and reliability.
|
|
457
|
+
|
|
458
|
+
#### Running the tests:
|
|
459
|
+
```bash
|
|
460
|
+
# Install development dependencies
|
|
461
|
+
pip install -e ".[dev]"
|
|
462
|
+
|
|
463
|
+
# Run all tests
|
|
464
|
+
make test
|
|
465
|
+
|
|
466
|
+
# Tests with coverage
|
|
467
|
+
make test-cov
|
|
468
|
+
|
|
469
|
+
# Specific tests
|
|
470
|
+
pytest test/test_file_logging.py -v
|
|
471
|
+
|
|
472
|
+
# Tests with different verbosity levels
|
|
473
|
+
pytest test/ -v # Verbose
|
|
474
|
+
pytest test/ -s # No output capture
|
|
475
|
+
pytest test/ --tb=short # Short traceback
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
#### Test Structure
|
|
479
|
+
```
|
|
480
|
+
test/
|
|
481
|
+
โโโ conftest.py # Shared pytest fixtures and test configurations
|
|
482
|
+
โโโ Makefile # Automation commands for testing, linting, and build tasks
|
|
483
|
+
โโโ pytest.ini # Global pytest configuration settings
|
|
484
|
+
โโโ run_tests.py # Script to run all tests automatically
|
|
485
|
+
โโโ test-requirements.txt # Development and test dependencies
|
|
486
|
+
โโโ TEST_GUIDE.md # Quick guide: how to run and interpret tests
|
|
487
|
+
โโโ test_logging_metrics.py # Automated tests for the logging_metrics library
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
#### Current coverage
|
|
491
|
+
```
|
|
492
|
+
# Coverage report
|
|
493
|
+
Name Stmts Miss Cover
|
|
494
|
+
-----------------------------------------------
|
|
495
|
+
src/logging_metrics/__init__.py 12 0 100%
|
|
496
|
+
src/logging_metrics/console.py 45 2 96%
|
|
497
|
+
src/logging_metrics/file.py 78 3 96%
|
|
498
|
+
src/logging_metrics/spark.py 32 1 97%
|
|
499
|
+
src/logging_metrics/timer.py 56 2 96%
|
|
500
|
+
src/logging_metrics/metrics.py 89 4 96%
|
|
501
|
+
-----------------------------------------------
|
|
502
|
+
TOTAL 312 12 96%
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
#### Running tests in different environments
|
|
506
|
+
```bash
|
|
507
|
+
# Test in multiple Python versions with tox
|
|
508
|
+
pip install tox
|
|
509
|
+
|
|
510
|
+
tox
|
|
511
|
+
|
|
512
|
+
# Specific configurations
|
|
513
|
+
tox -e py38 # Python 3.8
|
|
514
|
+
tox -e py39 # Python 3.9
|
|
515
|
+
tox -e py310 # Python 3.10
|
|
516
|
+
tox -e py311 # Python 3.11
|
|
517
|
+
tox -e py312 # Python 3.12
|
|
518
|
+
tox -e lint # Only linting
|
|
519
|
+
tox -e coverage # Only coverage
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
#### Running tests in CI/CD
|
|
523
|
+
Tests are run automatically in:
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
## ๐ง Requirements
|
|
529
|
+
|
|
530
|
+
Python: >= 3.8
|
|
531
|
+
|
|
532
|
+
Dependencies:
|
|
533
|
+
|
|
534
|
+
- pytz (for timezone handling)
|
|
535
|
+
- pyspark
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## ๐ Changelog
|
|
540
|
+
|
|
541
|
+
v0.1.2 (Current)
|
|
542
|
+
- Initial stable version
|
|
543
|
+
- LogTimer and LogMetrics
|
|
544
|
+
- Spark integration
|
|
545
|
+
- Colored logs
|
|
546
|
+
- JSON log support
|
|
547
|
+
- Fixed file rotation bug on Windows
|
|
548
|
+
- Expanded documentation with more examples
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
## ๐ค Contributing
|
|
553
|
+
|
|
554
|
+
#### Contributions are welcome!
|
|
555
|
+
1. Fork the project
|
|
556
|
+
2. Create your feature branch (`git checkout -b feature/logging-toolkit`)
|
|
557
|
+
3. Commit your changes (`git commit -m 'Add logging-toolkit'`)
|
|
558
|
+
4. Push to the branch (`git push origin feature/logging-toolkit`)
|
|
559
|
+
5. Open a Pull Request
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## License
|
|
564
|
+
|
|
565
|
+
MIT License. See LICENSE for details.
|