azpaddypy 0.2.1__py3-none-any.whl → 0.2.3__py3-none-any.whl
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.
- azpaddypy/mgmt/logging.py +234 -160
- azpaddypy-0.2.3.dist-info/METADATA +19 -0
- azpaddypy-0.2.3.dist-info/RECORD +9 -0
- azpaddypy-0.2.1.dist-info/METADATA +0 -10
- azpaddypy-0.2.1.dist-info/RECORD +0 -9
- {azpaddypy-0.2.1.dist-info → azpaddypy-0.2.3.dist-info}/WHEEL +0 -0
- {azpaddypy-0.2.1.dist-info → azpaddypy-0.2.3.dist-info}/licenses/LICENSE +0 -0
- {azpaddypy-0.2.1.dist-info → azpaddypy-0.2.3.dist-info}/top_level.txt +0 -0
azpaddypy/mgmt/logging.py
CHANGED
@@ -4,21 +4,27 @@ import json
|
|
4
4
|
import functools
|
5
5
|
import time
|
6
6
|
import asyncio
|
7
|
-
from typing import Optional, Dict, Any, Union,
|
7
|
+
from typing import Optional, Dict, Any, Union, Callable
|
8
8
|
from datetime import datetime
|
9
9
|
from azure.monitor.opentelemetry import configure_azure_monitor
|
10
|
+
from opentelemetry.metrics import get_meter_provider
|
11
|
+
from opentelemetry.trace import get_tracer_provider
|
12
|
+
from opentelemetry._logs import get_logger_provider
|
10
13
|
from opentelemetry import trace
|
11
14
|
from opentelemetry.trace import Status, StatusCode, Span
|
12
|
-
from opentelemetry.sdk.trace import TracerProvider
|
13
|
-
from opentelemetry.sdk.resources import Resource
|
14
15
|
from opentelemetry import baggage
|
15
16
|
from opentelemetry.context import Context
|
16
17
|
|
17
18
|
|
18
19
|
class AzureLogger:
|
19
20
|
"""
|
20
|
-
|
21
|
-
|
21
|
+
A comprehensive logging class for Azure applications.
|
22
|
+
|
23
|
+
This logger integrates with Azure Monitor OpenTelemetry for distributed
|
24
|
+
tracing and structured logging, providing advanced capabilities for
|
25
|
+
|
26
|
+
It supports correlation tracking, baggage propagation, and automated
|
27
|
+
tracing for functions and dependencies.
|
22
28
|
"""
|
23
29
|
|
24
30
|
def __init__(
|
@@ -29,6 +35,7 @@ class AzureLogger:
|
|
29
35
|
log_level: int = logging.INFO,
|
30
36
|
enable_console_logging: bool = True,
|
31
37
|
custom_resource_attributes: Optional[Dict[str, str]] = None,
|
38
|
+
clean_legacy_logging: bool = True,
|
32
39
|
):
|
33
40
|
"""
|
34
41
|
Initialize the Azure Logger with OpenTelemetry tracing
|
@@ -40,7 +47,20 @@ class AzureLogger:
|
|
40
47
|
log_level: Logging level (default: INFO)
|
41
48
|
enable_console_logging: Enable console output for local development
|
42
49
|
custom_resource_attributes: Additional resource attributes
|
50
|
+
clean_legacy_logging: A flag to clean up legacy logging providers.
|
43
51
|
"""
|
52
|
+
if clean_legacy_logging:
|
53
|
+
# cleaning stale loggers
|
54
|
+
logger_provider = get_logger_provider()
|
55
|
+
if logger_provider:
|
56
|
+
logger_provider.shutdown()
|
57
|
+
tracer_provider = get_tracer_provider()
|
58
|
+
if tracer_provider:
|
59
|
+
tracer_provider.shutdown()
|
60
|
+
meter_provider = get_meter_provider()
|
61
|
+
if meter_provider:
|
62
|
+
meter_provider.shutdown()
|
63
|
+
|
44
64
|
self.service_name = service_name
|
45
65
|
self.service_version = service_version
|
46
66
|
self.connection_string = connection_string or os.getenv(
|
@@ -97,7 +117,12 @@ class AzureLogger:
|
|
97
117
|
)
|
98
118
|
|
99
119
|
def _setup_console_handler(self):
|
100
|
-
"""
|
120
|
+
"""Sets up a console handler for logging to the standard output.
|
121
|
+
|
122
|
+
This is useful for local development and debugging purposes. The handler
|
123
|
+
is configured with a structured formatter to ensure log messages are
|
124
|
+
consistent and easy to read.
|
125
|
+
"""
|
101
126
|
console_handler = logging.StreamHandler()
|
102
127
|
formatter = logging.Formatter(
|
103
128
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(pathname)s:%(lineno)d"
|
@@ -106,11 +131,22 @@ class AzureLogger:
|
|
106
131
|
self.logger.addHandler(console_handler)
|
107
132
|
|
108
133
|
def set_correlation_id(self, correlation_id: str):
|
109
|
-
"""
|
134
|
+
"""Sets a correlation ID for tracking a request or transaction.
|
135
|
+
|
136
|
+
This ID is automatically included in all subsequent logs and traces,
|
137
|
+
allowing for easy filtering and correlation of telemetry data.
|
138
|
+
|
139
|
+
Args:
|
140
|
+
correlation_id: The unique identifier for the transaction.
|
141
|
+
"""
|
110
142
|
self._correlation_id = correlation_id
|
111
143
|
|
112
144
|
def get_correlation_id(self) -> Optional[str]:
|
113
|
-
"""
|
145
|
+
"""Retrieves the current correlation ID.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
The current correlation ID if it has been set, otherwise None.
|
149
|
+
"""
|
114
150
|
return self._correlation_id
|
115
151
|
|
116
152
|
def set_baggage(self, key: str, value: str) -> Context:
|
@@ -128,27 +164,38 @@ class AzureLogger:
|
|
128
164
|
|
129
165
|
def get_baggage(self, key: str) -> Optional[str]:
|
130
166
|
"""
|
131
|
-
|
167
|
+
Retrieves a baggage item from the current OpenTelemetry context.
|
132
168
|
|
133
169
|
Args:
|
134
|
-
key:
|
170
|
+
key: The baggage key.
|
135
171
|
|
136
172
|
Returns:
|
137
|
-
|
173
|
+
The baggage value if it exists, otherwise None.
|
138
174
|
"""
|
139
175
|
return baggage.get_baggage(key)
|
140
176
|
|
141
177
|
def get_all_baggage(self) -> Dict[str, str]:
|
142
178
|
"""
|
143
|
-
|
179
|
+
Retrieves all baggage items from the current OpenTelemetry context.
|
144
180
|
|
145
181
|
Returns:
|
146
|
-
|
182
|
+
A dictionary containing all baggage items.
|
147
183
|
"""
|
148
184
|
return dict(baggage.get_all())
|
149
185
|
|
150
186
|
def _enhance_extra(self, extra: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
151
|
-
"""
|
187
|
+
"""
|
188
|
+
Enriches log records with contextual information.
|
189
|
+
|
190
|
+
This method adds service details, correlation IDs, trace context,
|
191
|
+
and baggage items to the log's `extra` dictionary.
|
192
|
+
|
193
|
+
Args:
|
194
|
+
extra: An optional dictionary of custom data to include.
|
195
|
+
|
196
|
+
Returns:
|
197
|
+
The enhanced dictionary with added contextual data.
|
198
|
+
"""
|
152
199
|
enhanced_extra = {
|
153
200
|
"service_name": self.service_name,
|
154
201
|
"service_version": self.service_version,
|
@@ -176,15 +223,15 @@ class AzureLogger:
|
|
176
223
|
return enhanced_extra
|
177
224
|
|
178
225
|
def debug(self, message: str, extra: Optional[Dict[str, Any]] = None):
|
179
|
-
"""
|
226
|
+
"""Logs a debug message with enhanced context."""
|
180
227
|
self.logger.debug(message, extra=self._enhance_extra(extra))
|
181
228
|
|
182
229
|
def info(self, message: str, extra: Optional[Dict[str, Any]] = None):
|
183
|
-
"""
|
230
|
+
"""Logs an info message with enhanced context."""
|
184
231
|
self.logger.info(message, extra=self._enhance_extra(extra))
|
185
232
|
|
186
233
|
def warning(self, message: str, extra: Optional[Dict[str, Any]] = None):
|
187
|
-
"""
|
234
|
+
"""Logs a warning message with enhanced context."""
|
188
235
|
self.logger.warning(message, extra=self._enhance_extra(extra))
|
189
236
|
|
190
237
|
def error(
|
@@ -193,11 +240,11 @@ class AzureLogger:
|
|
193
240
|
extra: Optional[Dict[str, Any]] = None,
|
194
241
|
exc_info: bool = True,
|
195
242
|
):
|
196
|
-
"""
|
243
|
+
"""Logs an error message with enhanced context and exception info."""
|
197
244
|
self.logger.error(message, extra=self._enhance_extra(extra), exc_info=exc_info)
|
198
245
|
|
199
246
|
def critical(self, message: str, extra: Optional[Dict[str, Any]] = None):
|
200
|
-
"""
|
247
|
+
"""Logs a critical message with enhanced context."""
|
201
248
|
self.logger.critical(message, extra=self._enhance_extra(extra))
|
202
249
|
|
203
250
|
def log_function_execution(
|
@@ -208,13 +255,16 @@ class AzureLogger:
|
|
208
255
|
extra: Optional[Dict[str, Any]] = None,
|
209
256
|
):
|
210
257
|
"""
|
211
|
-
|
258
|
+
Logs a custom event for a function's execution metrics.
|
259
|
+
|
260
|
+
This captures performance data such as duration and success status,
|
261
|
+
which can be queried in Azure Monitor.
|
212
262
|
|
213
263
|
Args:
|
214
|
-
function_name:
|
215
|
-
duration_ms:
|
216
|
-
success:
|
217
|
-
extra: Additional custom properties
|
264
|
+
function_name: The name of the executed function.
|
265
|
+
duration_ms: The execution duration in milliseconds.
|
266
|
+
success: A flag indicating whether the function executed successfully.
|
267
|
+
extra: Additional custom properties to include in the log.
|
218
268
|
"""
|
219
269
|
log_data = {
|
220
270
|
"function_name": function_name,
|
@@ -310,13 +360,105 @@ class AzureLogger:
|
|
310
360
|
|
311
361
|
return span
|
312
362
|
|
363
|
+
def _setup_span_for_function_trace(
|
364
|
+
self,
|
365
|
+
span: Span,
|
366
|
+
func: Callable,
|
367
|
+
is_async: bool,
|
368
|
+
log_args: bool,
|
369
|
+
args: tuple,
|
370
|
+
kwargs: dict,
|
371
|
+
):
|
372
|
+
"""Helper to set up span attributes for function tracing."""
|
373
|
+
span.set_attribute("function.name", func.__name__)
|
374
|
+
span.set_attribute("function.module", func.__module__)
|
375
|
+
span.set_attribute("service.name", self.service_name)
|
376
|
+
span.set_attribute("function.is_async", is_async)
|
377
|
+
|
378
|
+
if self._correlation_id:
|
379
|
+
span.set_attribute("correlation.id", self._correlation_id)
|
380
|
+
|
381
|
+
if log_args:
|
382
|
+
if args:
|
383
|
+
span.set_attribute("function.args_count", len(args))
|
384
|
+
if kwargs:
|
385
|
+
span.set_attribute("function.kwargs_count", len(kwargs))
|
386
|
+
|
387
|
+
def _handle_function_success(
|
388
|
+
self,
|
389
|
+
span: Span,
|
390
|
+
func: Callable,
|
391
|
+
duration_ms: float,
|
392
|
+
result: Any,
|
393
|
+
log_result: bool,
|
394
|
+
log_execution: bool,
|
395
|
+
is_async: bool,
|
396
|
+
args: tuple,
|
397
|
+
kwargs: dict,
|
398
|
+
):
|
399
|
+
"""Helper to handle successful function execution tracing."""
|
400
|
+
span.set_attribute("function.duration_ms", duration_ms)
|
401
|
+
span.set_attribute("function.success", True)
|
402
|
+
span.set_status(Status(StatusCode.OK))
|
403
|
+
|
404
|
+
if log_result and result is not None:
|
405
|
+
span.set_attribute("function.has_result", True)
|
406
|
+
span.set_attribute("function.result_type", type(result).__name__)
|
407
|
+
|
408
|
+
if log_execution:
|
409
|
+
self.log_function_execution(
|
410
|
+
func.__name__,
|
411
|
+
duration_ms,
|
412
|
+
True,
|
413
|
+
{
|
414
|
+
"args_count": len(args) if args else 0,
|
415
|
+
"kwargs_count": len(kwargs) if kwargs else 0,
|
416
|
+
"is_async": is_async,
|
417
|
+
},
|
418
|
+
)
|
419
|
+
|
420
|
+
log_prefix = "Async function" if is_async else "Function"
|
421
|
+
self.debug(f"{log_prefix} execution completed: {func.__name__}")
|
422
|
+
|
423
|
+
def _handle_function_exception(
|
424
|
+
self,
|
425
|
+
span: Span,
|
426
|
+
func: Callable,
|
427
|
+
duration_ms: float,
|
428
|
+
e: Exception,
|
429
|
+
log_execution: bool,
|
430
|
+
is_async: bool,
|
431
|
+
):
|
432
|
+
"""Helper to handle failed function execution tracing."""
|
433
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
434
|
+
span.record_exception(e)
|
435
|
+
span.set_attribute("function.duration_ms", duration_ms)
|
436
|
+
span.set_attribute("function.success", False)
|
437
|
+
span.set_attribute("error.type", type(e).__name__)
|
438
|
+
span.set_attribute("error.message", str(e))
|
439
|
+
|
440
|
+
if log_execution:
|
441
|
+
self.log_function_execution(
|
442
|
+
func.__name__,
|
443
|
+
duration_ms,
|
444
|
+
False,
|
445
|
+
{
|
446
|
+
"error_type": type(e).__name__,
|
447
|
+
"error_message": str(e),
|
448
|
+
"is_async": is_async,
|
449
|
+
},
|
450
|
+
)
|
451
|
+
|
452
|
+
log_prefix = "Async function" if is_async else "Function"
|
453
|
+
self.error(f"{log_prefix} execution failed: {func.__name__} - {str(e)}")
|
454
|
+
|
313
455
|
def trace_function(
|
314
456
|
self,
|
315
457
|
function_name: Optional[str] = None,
|
316
458
|
log_args: bool = False,
|
317
459
|
log_result: bool = False,
|
318
460
|
log_execution: bool = True,
|
319
|
-
):
|
461
|
+
) -> Callable:
|
320
462
|
"""
|
321
463
|
Decorator to automatically trace function execution with comprehensive logging.
|
322
464
|
Supports both synchronous and asynchronous functions.
|
@@ -332,166 +474,64 @@ class AzureLogger:
|
|
332
474
|
@functools.wraps(func)
|
333
475
|
async def async_wrapper(*args, **kwargs):
|
334
476
|
span_name = function_name or f"{func.__module__}.{func.__name__}"
|
335
|
-
|
336
477
|
with self.tracer.start_as_current_span(span_name) as span:
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
span.set_attribute("service.name", self.service_name)
|
341
|
-
span.set_attribute("function.is_async", True)
|
342
|
-
|
343
|
-
if self._correlation_id:
|
344
|
-
span.set_attribute("correlation.id", self._correlation_id)
|
345
|
-
|
346
|
-
if log_args and args:
|
347
|
-
span.set_attribute("function.args_count", len(args))
|
348
|
-
if log_args and kwargs:
|
349
|
-
span.set_attribute("function.kwargs_count", len(kwargs))
|
350
|
-
|
478
|
+
self._setup_span_for_function_trace(
|
479
|
+
span, func, True, log_args, args, kwargs
|
480
|
+
)
|
351
481
|
start_time = time.time()
|
352
|
-
|
353
482
|
try:
|
354
483
|
self.debug(
|
355
484
|
f"Starting async function execution: {func.__name__}"
|
356
485
|
)
|
357
|
-
|
358
486
|
result = await func(*args, **kwargs)
|
359
487
|
duration_ms = (time.time() - start_time) * 1000
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
)
|
371
|
-
|
372
|
-
if log_execution:
|
373
|
-
self.log_function_execution(
|
374
|
-
func.__name__,
|
375
|
-
duration_ms,
|
376
|
-
True,
|
377
|
-
{
|
378
|
-
"args_count": len(args) if args else 0,
|
379
|
-
"kwargs_count": len(kwargs) if kwargs else 0,
|
380
|
-
"is_async": True,
|
381
|
-
},
|
382
|
-
)
|
383
|
-
|
384
|
-
self.debug(
|
385
|
-
f"Async function execution completed: {func.__name__}"
|
488
|
+
self._handle_function_success(
|
489
|
+
span,
|
490
|
+
func,
|
491
|
+
duration_ms,
|
492
|
+
result,
|
493
|
+
log_result,
|
494
|
+
log_execution,
|
495
|
+
True,
|
496
|
+
args,
|
497
|
+
kwargs,
|
386
498
|
)
|
387
499
|
return result
|
388
|
-
|
389
500
|
except Exception as e:
|
390
501
|
duration_ms = (time.time() - start_time) * 1000
|
391
|
-
|
392
|
-
|
393
|
-
span.set_status(Status(StatusCode.ERROR, str(e)))
|
394
|
-
span.record_exception(e)
|
395
|
-
span.set_attribute("function.duration_ms", duration_ms)
|
396
|
-
span.set_attribute("function.success", False)
|
397
|
-
span.set_attribute("error.type", type(e).__name__)
|
398
|
-
span.set_attribute("error.message", str(e))
|
399
|
-
|
400
|
-
if log_execution:
|
401
|
-
self.log_function_execution(
|
402
|
-
func.__name__,
|
403
|
-
duration_ms,
|
404
|
-
False,
|
405
|
-
{
|
406
|
-
"error_type": type(e).__name__,
|
407
|
-
"error_message": str(e),
|
408
|
-
"is_async": True,
|
409
|
-
},
|
410
|
-
)
|
411
|
-
|
412
|
-
self.error(
|
413
|
-
f"Async function execution failed: {func.__name__} - {str(e)}"
|
502
|
+
self._handle_function_exception(
|
503
|
+
span, func, duration_ms, e, log_execution, True
|
414
504
|
)
|
415
505
|
raise
|
416
506
|
|
417
507
|
@functools.wraps(func)
|
418
508
|
def sync_wrapper(*args, **kwargs):
|
419
509
|
span_name = function_name or f"{func.__module__}.{func.__name__}"
|
420
|
-
|
421
510
|
with self.tracer.start_as_current_span(span_name) as span:
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
span.set_attribute("service.name", self.service_name)
|
426
|
-
span.set_attribute("function.is_async", False)
|
427
|
-
|
428
|
-
if self._correlation_id:
|
429
|
-
span.set_attribute("correlation.id", self._correlation_id)
|
430
|
-
|
431
|
-
if log_args and args:
|
432
|
-
span.set_attribute("function.args_count", len(args))
|
433
|
-
if log_args and kwargs:
|
434
|
-
span.set_attribute("function.kwargs_count", len(kwargs))
|
435
|
-
|
511
|
+
self._setup_span_for_function_trace(
|
512
|
+
span, func, False, log_args, args, kwargs
|
513
|
+
)
|
436
514
|
start_time = time.time()
|
437
|
-
|
438
515
|
try:
|
439
516
|
self.debug(f"Starting function execution: {func.__name__}")
|
440
|
-
|
441
517
|
result = func(*args, **kwargs)
|
442
518
|
duration_ms = (time.time() - start_time) * 1000
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
if log_execution:
|
456
|
-
self.log_function_execution(
|
457
|
-
func.__name__,
|
458
|
-
duration_ms,
|
459
|
-
True,
|
460
|
-
{
|
461
|
-
"args_count": len(args) if args else 0,
|
462
|
-
"kwargs_count": len(kwargs) if kwargs else 0,
|
463
|
-
"is_async": False,
|
464
|
-
},
|
465
|
-
)
|
466
|
-
|
467
|
-
self.debug(f"Function execution completed: {func.__name__}")
|
519
|
+
self._handle_function_success(
|
520
|
+
span,
|
521
|
+
func,
|
522
|
+
duration_ms,
|
523
|
+
result,
|
524
|
+
log_result,
|
525
|
+
log_execution,
|
526
|
+
False,
|
527
|
+
args,
|
528
|
+
kwargs,
|
529
|
+
)
|
468
530
|
return result
|
469
|
-
|
470
531
|
except Exception as e:
|
471
532
|
duration_ms = (time.time() - start_time) * 1000
|
472
|
-
|
473
|
-
|
474
|
-
span.set_status(Status(StatusCode.ERROR, str(e)))
|
475
|
-
span.record_exception(e)
|
476
|
-
span.set_attribute("function.duration_ms", duration_ms)
|
477
|
-
span.set_attribute("function.success", False)
|
478
|
-
span.set_attribute("error.type", type(e).__name__)
|
479
|
-
span.set_attribute("error.message", str(e))
|
480
|
-
|
481
|
-
if log_execution:
|
482
|
-
self.log_function_execution(
|
483
|
-
func.__name__,
|
484
|
-
duration_ms,
|
485
|
-
False,
|
486
|
-
{
|
487
|
-
"error_type": type(e).__name__,
|
488
|
-
"error_message": str(e),
|
489
|
-
"is_async": False,
|
490
|
-
},
|
491
|
-
)
|
492
|
-
|
493
|
-
self.error(
|
494
|
-
f"Function execution failed: {func.__name__} - {str(e)}"
|
533
|
+
self._handle_function_exception(
|
534
|
+
span, func, duration_ms, e, log_execution, False
|
495
535
|
)
|
496
536
|
raise
|
497
537
|
|
@@ -604,6 +644,9 @@ class AzureLogger:
|
|
604
644
|
|
605
645
|
|
606
646
|
# Factory functions for easy instantiation
|
647
|
+
_loggers: Dict[Any, "AzureLogger"] = {}
|
648
|
+
|
649
|
+
|
607
650
|
def create_app_logger(
|
608
651
|
service_name: str,
|
609
652
|
service_version: str = "1.0.0",
|
@@ -611,9 +654,11 @@ def create_app_logger(
|
|
611
654
|
log_level: int = logging.INFO,
|
612
655
|
enable_console_logging: bool = True,
|
613
656
|
custom_resource_attributes: Optional[Dict[str, str]] = None,
|
657
|
+
clean_legacy_logging: bool = True,
|
614
658
|
) -> AzureLogger:
|
615
659
|
"""
|
616
|
-
Factory function to create an AzureLogger instance
|
660
|
+
Factory function to create an AzureLogger instance. If a logger with the
|
661
|
+
same configuration has already been created, it will be returned.
|
617
662
|
|
618
663
|
Args:
|
619
664
|
service_name: Name of your service/application
|
@@ -622,18 +667,45 @@ def create_app_logger(
|
|
622
667
|
log_level: Logging level
|
623
668
|
enable_console_logging: Enable console output
|
624
669
|
custom_resource_attributes: Additional resource attributes
|
670
|
+
clean_legacy_logging: Whether to clean up legacy logging providers.
|
625
671
|
|
626
672
|
Returns:
|
627
673
|
Configured AzureLogger instance
|
628
674
|
"""
|
629
|
-
|
675
|
+
resolved_connection_string = connection_string or os.getenv(
|
676
|
+
"APPLICATIONINSIGHTS_CONNECTION_STRING"
|
677
|
+
)
|
678
|
+
|
679
|
+
attr_items = (
|
680
|
+
tuple(sorted(custom_resource_attributes.items()))
|
681
|
+
if custom_resource_attributes
|
682
|
+
else None
|
683
|
+
)
|
684
|
+
|
685
|
+
params_key = (
|
686
|
+
service_name,
|
687
|
+
service_version,
|
688
|
+
resolved_connection_string,
|
689
|
+
log_level,
|
690
|
+
enable_console_logging,
|
691
|
+
attr_items,
|
692
|
+
clean_legacy_logging,
|
693
|
+
)
|
694
|
+
|
695
|
+
if params_key in _loggers:
|
696
|
+
return _loggers[params_key]
|
697
|
+
|
698
|
+
logger = AzureLogger(
|
630
699
|
service_name=service_name,
|
631
700
|
service_version=service_version,
|
632
701
|
connection_string=connection_string,
|
633
702
|
log_level=log_level,
|
634
703
|
enable_console_logging=enable_console_logging,
|
635
704
|
custom_resource_attributes=custom_resource_attributes,
|
705
|
+
clean_legacy_logging=clean_legacy_logging,
|
636
706
|
)
|
707
|
+
_loggers[params_key] = logger
|
708
|
+
return logger
|
637
709
|
|
638
710
|
|
639
711
|
def create_function_logger(
|
@@ -641,6 +713,7 @@ def create_function_logger(
|
|
641
713
|
function_name: str,
|
642
714
|
service_version: str = "1.0.0",
|
643
715
|
connection_string: Optional[str] = None,
|
716
|
+
clean_legacy_logging: bool = True,
|
644
717
|
) -> AzureLogger:
|
645
718
|
"""
|
646
719
|
Factory function specifically for Azure Functions
|
@@ -665,4 +738,5 @@ def create_function_logger(
|
|
665
738
|
service_version=service_version,
|
666
739
|
connection_string=connection_string,
|
667
740
|
custom_resource_attributes=custom_attributes,
|
741
|
+
clean_legacy_logging=clean_legacy_logging,
|
668
742
|
)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: azpaddypy
|
3
|
+
Version: 0.2.3
|
4
|
+
Summary: Comprehensive Python logger for Azure, integrating OpenTelemetry for advanced, structured, and distributed tracing.
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
7
|
+
Classifier: Operating System :: OS Independent
|
8
|
+
Requires-Python: >=3.11
|
9
|
+
Description-Content-Type: text/markdown
|
10
|
+
License-File: LICENSE
|
11
|
+
Requires-Dist: azure-monitor-opentelemetry==1.6.10
|
12
|
+
Provides-Extra: dev
|
13
|
+
Requires-Dist: trio>=0.22.2; extra == "dev"
|
14
|
+
Requires-Dist: azure-functions>=1.17.0; extra == "dev"
|
15
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
16
|
+
Requires-Dist: pytest-asyncio>=0.21.1; extra == "dev"
|
17
|
+
Requires-Dist: anyio>=3.7.1; extra == "dev"
|
18
|
+
Requires-Dist: pip; extra == "dev"
|
19
|
+
Dynamic: license-file
|
@@ -0,0 +1,9 @@
|
|
1
|
+
azpaddypy/mgmt/__init__.py,sha256=5-0eZuJMZlCONZNJ5hEvWXfvLIM36mg7FsEVs32bY_A,183
|
2
|
+
azpaddypy/mgmt/logging.py,sha256=LI7pvMuiUbT-RoW5wImyWxZTzexxvA6IDSD4RVyxCkg,26918
|
3
|
+
azpaddypy/test_function/__init__.py,sha256=0NjUl36wvUWV79GpRwBFkgkBaC6uDZsTdaSVOIHMFEU,3481
|
4
|
+
azpaddypy/test_function/function_app.py,sha256=6nX54-iq0L1l_hZpD6E744-j79oLxdaldFyWDCpwH7c,3867
|
5
|
+
azpaddypy-0.2.3.dist-info/licenses/LICENSE,sha256=hQ6t0g2QaewGCQICHqTckBFbMVakGmoyTAzDpmEYV4c,1089
|
6
|
+
azpaddypy-0.2.3.dist-info/METADATA,sha256=vEWDGAtY5Cxvz3qLRA9fJEeUjFObLaElceLsZGsyDi0,799
|
7
|
+
azpaddypy-0.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
+
azpaddypy-0.2.3.dist-info/top_level.txt,sha256=hsDuboDhT61320ML8X479ezSTwT3rrlDWz1_Z45B2cs,10
|
9
|
+
azpaddypy-0.2.3.dist-info/RECORD,,
|
@@ -1,10 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: azpaddypy
|
3
|
-
Version: 0.2.1
|
4
|
-
Summary: Add your description here
|
5
|
-
Classifier: Operating System :: OS Independent
|
6
|
-
Requires-Python: >=3.11
|
7
|
-
Description-Content-Type: text/markdown
|
8
|
-
License-File: LICENSE
|
9
|
-
Requires-Dist: azure-monitor-opentelemetry==1.6.10
|
10
|
-
Dynamic: license-file
|
azpaddypy-0.2.1.dist-info/RECORD
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
azpaddypy/mgmt/__init__.py,sha256=5-0eZuJMZlCONZNJ5hEvWXfvLIM36mg7FsEVs32bY_A,183
|
2
|
-
azpaddypy/mgmt/logging.py,sha256=9u114Ji-cwBMUf8D02i_b_Ei2dZc3TaIUH4uJv_tmSc,25451
|
3
|
-
azpaddypy/test_function/__init__.py,sha256=0NjUl36wvUWV79GpRwBFkgkBaC6uDZsTdaSVOIHMFEU,3481
|
4
|
-
azpaddypy/test_function/function_app.py,sha256=6nX54-iq0L1l_hZpD6E744-j79oLxdaldFyWDCpwH7c,3867
|
5
|
-
azpaddypy-0.2.1.dist-info/licenses/LICENSE,sha256=hQ6t0g2QaewGCQICHqTckBFbMVakGmoyTAzDpmEYV4c,1089
|
6
|
-
azpaddypy-0.2.1.dist-info/METADATA,sha256=ShjmEYaQg37Y05nj6Jv4zdm2KlU2Bkfo1ya0z5IdnUo,304
|
7
|
-
azpaddypy-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
-
azpaddypy-0.2.1.dist-info/top_level.txt,sha256=hsDuboDhT61320ML8X479ezSTwT3rrlDWz1_Z45B2cs,10
|
9
|
-
azpaddypy-0.2.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|