azpaddypy 0.2.0__py3-none-any.whl → 0.2.2__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 +28 -88
- {azpaddypy-0.2.0.dist-info → azpaddypy-0.2.2.dist-info}/METADATA +1 -1
- azpaddypy-0.2.2.dist-info/RECORD +9 -0
- azpaddypy-0.2.0.dist-info/RECORD +0 -9
- {azpaddypy-0.2.0.dist-info → azpaddypy-0.2.2.dist-info}/WHEEL +0 -0
- {azpaddypy-0.2.0.dist-info → azpaddypy-0.2.2.dist-info}/licenses/LICENSE +0 -0
- {azpaddypy-0.2.0.dist-info → azpaddypy-0.2.2.dist-info}/top_level.txt +0 -0
azpaddypy/mgmt/logging.py
CHANGED
@@ -16,37 +16,17 @@ from opentelemetry.context import Context
|
|
16
16
|
|
17
17
|
|
18
18
|
class AzureLogger:
|
19
|
+
_instance = None
|
20
|
+
_initialized = False
|
19
21
|
"""
|
20
22
|
Comprehensive logging class for Azure Functions and Azure Web Apps
|
21
23
|
using Azure Monitor OpenTelemetry integration with advanced tracing capabilities.
|
22
24
|
"""
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def get_instance(
|
29
|
-
cls,
|
30
|
-
service_name: str,
|
31
|
-
service_version: str = "1.0.0",
|
32
|
-
connection_string: Optional[str] = None,
|
33
|
-
log_level: int = logging.INFO,
|
34
|
-
enable_console_logging: bool = True,
|
35
|
-
custom_resource_attributes: Optional[Dict[str, str]] = None,
|
36
|
-
):
|
37
|
-
"""
|
38
|
-
Get or create a singleton AzureLogger instance for a given service_name.
|
39
|
-
"""
|
40
|
-
if service_name not in cls._instances:
|
41
|
-
cls._instances[service_name] = cls(
|
42
|
-
service_name=service_name,
|
43
|
-
service_version=service_version,
|
44
|
-
connection_string=connection_string,
|
45
|
-
log_level=log_level,
|
46
|
-
enable_console_logging=enable_console_logging,
|
47
|
-
custom_resource_attributes=custom_resource_attributes,
|
48
|
-
)
|
49
|
-
return cls._instances[service_name]
|
26
|
+
def __new__(cls, *args, **kwargs):
|
27
|
+
if cls._instance is None:
|
28
|
+
cls._instance = super(AzureLogger, cls).__new__(cls)
|
29
|
+
return cls._instance
|
50
30
|
|
51
31
|
def __init__(
|
52
32
|
self,
|
@@ -57,26 +37,20 @@ class AzureLogger:
|
|
57
37
|
enable_console_logging: bool = True,
|
58
38
|
custom_resource_attributes: Optional[Dict[str, str]] = None,
|
59
39
|
):
|
60
|
-
|
61
|
-
if not AzureLogger._instances:
|
62
|
-
# Remove all handlers from all loggers except the one being initialized
|
63
|
-
for name, logger in logging.root.manager.loggerDict.items():
|
64
|
-
if isinstance(logger, logging.Logger) and name != service_name:
|
65
|
-
logger.handlers.clear()
|
66
|
-
# Reset OpenTelemetry tracer and meter providers
|
67
|
-
try:
|
68
|
-
from opentelemetry import trace, metrics
|
69
|
-
from opentelemetry.sdk.trace import TracerProvider
|
70
|
-
from opentelemetry.sdk.metrics import MeterProvider
|
71
|
-
|
72
|
-
trace.set_tracer_provider(TracerProvider())
|
73
|
-
metrics.set_meter_provider(MeterProvider())
|
74
|
-
except Exception as e:
|
75
|
-
print(f"Warning: Failed to reset OpenTelemetry providers: {e}")
|
76
|
-
# Prevent re-initialization if already exists
|
77
|
-
if hasattr(self, "_initialized") and self._initialized:
|
40
|
+
if self.__class__._initialized:
|
78
41
|
return
|
79
|
-
self._initialized = True
|
42
|
+
self.__class__._initialized = True
|
43
|
+
"""
|
44
|
+
Initialize the Azure Logger with OpenTelemetry tracing
|
45
|
+
|
46
|
+
Args:
|
47
|
+
service_name: Name of your service/application
|
48
|
+
service_version: Version of your service
|
49
|
+
connection_string: Application Insights connection string
|
50
|
+
log_level: Logging level (default: INFO)
|
51
|
+
enable_console_logging: Enable console output for local development
|
52
|
+
custom_resource_attributes: Additional resource attributes
|
53
|
+
"""
|
80
54
|
self.service_name = service_name
|
81
55
|
self.service_version = service_version
|
82
56
|
self.connection_string = connection_string or os.getenv(
|
@@ -111,19 +85,19 @@ class AzureLogger:
|
|
111
85
|
"Warning: No Application Insights connection string found. Telemetry disabled."
|
112
86
|
)
|
113
87
|
|
114
|
-
# Set up logger without
|
88
|
+
# Set up logger without instrumentor
|
115
89
|
self.logger = logging.getLogger(service_name)
|
116
90
|
self.logger.setLevel(log_level)
|
117
91
|
|
118
|
-
#
|
119
|
-
|
120
|
-
|
121
|
-
|
92
|
+
# Clear existing handlers to avoid duplicates
|
93
|
+
self.logger.handlers.clear()
|
94
|
+
|
95
|
+
# Add console handler for local development
|
96
|
+
if enable_console_logging:
|
97
|
+
self._setup_console_handler()
|
122
98
|
|
123
|
-
# Get tracer for manual span creation
|
124
|
-
|
125
|
-
AzureLogger._tracer = trace.get_tracer(__name__)
|
126
|
-
self.tracer = AzureLogger._tracer
|
99
|
+
# Get tracer for manual span creation
|
100
|
+
self.tracer = trace.get_tracer(__name__)
|
127
101
|
|
128
102
|
# Initialize correlation context
|
129
103
|
self._correlation_id = None
|
@@ -211,10 +185,6 @@ class AzureLogger:
|
|
211
185
|
|
212
186
|
return enhanced_extra
|
213
187
|
|
214
|
-
def exception(self, message: str, extra: Optional[Dict[str, Any]] = None):
|
215
|
-
"""Log debug message with enhanced context"""
|
216
|
-
self.logger.exception(message, extra=self._enhance_extra(extra))
|
217
|
-
|
218
188
|
def debug(self, message: str, extra: Optional[Dict[str, Any]] = None):
|
219
189
|
"""Log debug message with enhanced context"""
|
220
190
|
self.logger.debug(message, extra=self._enhance_extra(extra))
|
@@ -642,36 +612,6 @@ class AzureLogger:
|
|
642
612
|
except Exception as e:
|
643
613
|
self.warning(f"Failed to flush telemetry: {e}")
|
644
614
|
|
645
|
-
async def flush_async(self):
|
646
|
-
"""Asynchronously flush all pending telemetry data"""
|
647
|
-
if self._telemetry_enabled:
|
648
|
-
try:
|
649
|
-
from opentelemetry.sdk.trace import TracerProvider
|
650
|
-
|
651
|
-
tracer_provider = trace.get_tracer_provider()
|
652
|
-
if hasattr(tracer_provider, "force_flush"):
|
653
|
-
await asyncio.to_thread(
|
654
|
-
tracer_provider.force_flush, timeout_millis=5000
|
655
|
-
)
|
656
|
-
except Exception as e:
|
657
|
-
self.warning(f"Failed to async flush telemetry: {e}")
|
658
|
-
|
659
|
-
def add_handler(self, handler: logging.Handler):
|
660
|
-
"""Add a logging handler to the logger."""
|
661
|
-
self.logger.addHandler(handler)
|
662
|
-
|
663
|
-
def remove_handler(self, handler: logging.Handler):
|
664
|
-
"""Remove a logging handler from the logger."""
|
665
|
-
self.logger.removeHandler(handler)
|
666
|
-
|
667
|
-
def list_handlers(self) -> list:
|
668
|
-
"""List all handlers attached to the logger."""
|
669
|
-
return self.logger.handlers
|
670
|
-
|
671
|
-
def clear_handlers(self):
|
672
|
-
"""Remove all handlers from the logger."""
|
673
|
-
self.logger.handlers.clear()
|
674
|
-
|
675
615
|
|
676
616
|
# Factory functions for easy instantiation
|
677
617
|
def create_app_logger(
|
@@ -0,0 +1,9 @@
|
|
1
|
+
azpaddypy/mgmt/__init__.py,sha256=5-0eZuJMZlCONZNJ5hEvWXfvLIM36mg7FsEVs32bY_A,183
|
2
|
+
azpaddypy/mgmt/logging.py,sha256=A-56GNbSWAFnKNPcoa-NfTINbBWvJf-p4ZGxUz7M4uQ,25777
|
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.2.dist-info/licenses/LICENSE,sha256=hQ6t0g2QaewGCQICHqTckBFbMVakGmoyTAzDpmEYV4c,1089
|
6
|
+
azpaddypy-0.2.2.dist-info/METADATA,sha256=AM8Zw5IFOQVOQcd5zB2J473u1jSy9oDqOtoLpU-mhjc,304
|
7
|
+
azpaddypy-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
+
azpaddypy-0.2.2.dist-info/top_level.txt,sha256=hsDuboDhT61320ML8X479ezSTwT3rrlDWz1_Z45B2cs,10
|
9
|
+
azpaddypy-0.2.2.dist-info/RECORD,,
|
azpaddypy-0.2.0.dist-info/RECORD
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
azpaddypy/mgmt/__init__.py,sha256=5-0eZuJMZlCONZNJ5hEvWXfvLIM36mg7FsEVs32bY_A,183
|
2
|
-
azpaddypy/mgmt/logging.py,sha256=UYlep7e3TddWo1EtJliGg45Zv-22iSbIYdC8Iz1STKU,28462
|
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.0.dist-info/licenses/LICENSE,sha256=hQ6t0g2QaewGCQICHqTckBFbMVakGmoyTAzDpmEYV4c,1089
|
6
|
-
azpaddypy-0.2.0.dist-info/METADATA,sha256=EDK4QI8b__iy5AX6PmYxKsUmegQStO_y9WUzQiAZ5zw,304
|
7
|
-
azpaddypy-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
-
azpaddypy-0.2.0.dist-info/top_level.txt,sha256=hsDuboDhT61320ML8X479ezSTwT3rrlDWz1_Z45B2cs,10
|
9
|
-
azpaddypy-0.2.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|