warpzone-sdk 15.0.0.dev6__py3-none-any.whl → 15.0.0.dev7__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.
@@ -1,4 +1,5 @@
1
1
  import inspect
2
+ import threading
2
3
  from contextlib import contextmanager
3
4
  from typing import Callable
4
5
 
@@ -9,18 +10,40 @@ from opentelemetry import trace
9
10
  from warpzone.function.types import SingleArgumentCallable
10
11
  from warpzone.monitor import traces
11
12
 
12
- # Configure Azure Monitor at import to ensure proper telemetry setup.
13
- # The trace context is set per-invocation in run_in_trace_context to ensure
14
- # proper operation ID correlation for each function execution.
15
- configure_azure_monitor()
13
+ # Thread-safe lazy initialization of Azure Monitor
14
+ _azure_monitor_configured = False
15
+ _azure_monitor_lock = threading.Lock()
16
+
17
+
18
+ def _ensure_azure_monitor_configured():
19
+ """Ensure Azure Monitor is configured exactly once, thread-safely."""
20
+ global _azure_monitor_configured
21
+ if _azure_monitor_configured:
22
+ return
23
+
24
+ with _azure_monitor_lock:
25
+ # Double-check after acquiring lock
26
+ if _azure_monitor_configured:
27
+ return
28
+
29
+ # Disable OpenTelemetry logging instrumentation - let Azure Functions
30
+ # handle log correlation via its native thread-local storage mechanism.
31
+ # This prevents conflicts between OpenTelemetry's context-based correlation
32
+ # and Azure Functions' invocation_id-based correlation which can cause
33
+ # logs to leak between concurrent function invocations.
34
+ configure_azure_monitor(
35
+ disable_logging=True,
36
+ )
37
+
38
+ # Apply trace filtering to suppress all Azure SDK traces except Service Bus
39
+ tracer_provider = trace.get_tracer_provider()
40
+ if hasattr(tracer_provider, "_active_span_processor"):
41
+ original_processor = tracer_provider._active_span_processor
42
+ filtered_processor = traces.AzureSDKTraceFilter(original_processor)
43
+ tracer_provider._active_span_processor = filtered_processor
44
+
45
+ _azure_monitor_configured = True
16
46
 
17
- # Apply trace filtering to suppress all Azure SDK traces except Service Bus
18
- tracer_provider = trace.get_tracer_provider()
19
- if hasattr(tracer_provider, "_active_span_processor"):
20
- # Wrap the existing span processor with our filter
21
- original_processor = tracer_provider._active_span_processor
22
- filtered_processor = traces.AzureSDKTraceFilter(original_processor)
23
- tracer_provider._active_span_processor = filtered_processor
24
47
 
25
48
  SUBJECT_IDENTIFIER = "<Subject>"
26
49
 
@@ -51,6 +74,8 @@ def monitor(main: SingleArgumentCallable) -> Callable:
51
74
  - return value
52
75
  description: return value of original function
53
76
  """
77
+ # Ensure Azure Monitor is configured before any function runs
78
+ _ensure_azure_monitor_configured()
54
79
 
55
80
  async def wrapper_async(arg, context: func.Context):
56
81
  with run_in_trace_context(context):
@@ -64,12 +64,11 @@ class AzureSDKTraceFilter(SpanProcessor):
64
64
 
65
65
  @contextmanager
66
66
  def set_trace_context(trace_parent: str, span_name: str = "function_execution"):
67
- """Context manager for setting the trace context with a recording span.
67
+ """Context manager for setting the trace context.
68
68
 
69
- Creates a child span of the propagated trace context. This is necessary
70
- because the LoggingHandler requires a recording span to properly correlate
71
- logs with the trace. A NonRecordingSpan (which is what TraceContextTextMapPropagator
72
- creates) may not be correctly handled during log batching/export.
69
+ Attaches the propagated trace context and creates a child span for tracing.
70
+ Note: Log correlation is handled by Azure Functions' native mechanism,
71
+ not OpenTelemetry, so this primarily affects span/dependency tracking.
73
72
 
74
73
  Args:
75
74
  trace_parent (str): Trace parent ID from the incoming request
@@ -78,15 +77,12 @@ def set_trace_context(trace_parent: str, span_name: str = "function_execution"):
78
77
  carrier = {"traceparent": trace_parent}
79
78
  ctx = TraceContextTextMapPropagator().extract(carrier=carrier)
80
79
 
81
- # Explicitly attach the extracted context first
82
80
  token = context.attach(ctx)
83
81
  try:
84
- # Now start a recording span as a child of the propagated context
85
82
  tracer = trace.get_tracer(__name__)
86
83
  with tracer.start_as_current_span(span_name):
87
84
  yield
88
85
  finally:
89
- # Explicitly detach to restore previous context
90
86
  context.detach(token)
91
87
 
92
88
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warpzone-sdk
3
- Version: 15.0.0.dev6
3
+ Version: 15.0.0.dev7
4
4
  Summary: The main objective of this package is to centralize logic used to interact with Azure Functions, Azure Service Bus and Azure Table Storage
5
5
  Author: Team Enigma
6
6
  Author-email: enigma@energinet.dk
@@ -17,7 +17,7 @@ warpzone/function/__init__.py,sha256=rJOZBpWsUgjMc7YtXMJ1rLGm45KB1AhDJ_Y2ISiSISc
17
17
  warpzone/function/checks.py,sha256=B9YqThymf16ac_fVAYKilv20ru5v9nwXgHlbxYIaG98,1018
18
18
  warpzone/function/functionize.py,sha256=bSV0QvwKbD9Vo3a_8cc1rgV2rzTdMMvidinyXItBfvs,2128
19
19
  warpzone/function/integrations.py,sha256=sDt2BTx6a4mVc-33wTITP9XQVPustwj7rkX4urTyOqo,4018
20
- warpzone/function/monitor.py,sha256=MsVMUQXn346pqY5l14NZdm4ELOTeHHQLX0_HxKTdx5Q,2293
20
+ warpzone/function/monitor.py,sha256=8KKBNBvZYGZnXCt8qsQyR0-apiNZEaeFQDrsKktJp8c,3137
21
21
  warpzone/function/process.py,sha256=nbUVywM8ChfUwuaqFisgaD98aNRgeZkK4g5sbtuBdRs,2339
22
22
  warpzone/function/processors/__init__.py,sha256=DhIdSWLBcIeSO8IJdxPqGIhgwwnkDN6_Xqwy93BCLeA,46
23
23
  warpzone/function/processors/dependencies.py,sha256=m17BwdKyQEvzCPxpQZpAW5l1uYRIHWmweDz3XJskmpA,1259
@@ -29,7 +29,7 @@ warpzone/healthchecks/__init__.py,sha256=9gc_Mt2szs8sDSwy0V4l3JZ6d9hX41xTpZCkDP2
29
29
  warpzone/healthchecks/model.py,sha256=mM7DnrirLbUpBPPfi82MUPP654D0eOR2_F65TmzsPD0,1187
30
30
  warpzone/monitor/__init__.py,sha256=ggI5fIUu-szgC44ICzuOmpYrIoVOKPbsMT3zza9ssD4,87
31
31
  warpzone/monitor/logs.py,sha256=fabjaB5SfHynvvfp2Js3IG-owqU5jZ3lTnnmTTjD6JM,1320
32
- warpzone/monitor/traces.py,sha256=a_YXgbu5EuzmfwpqZE1hZgxo9U2B3pg5hfft3baQjzA,4153
32
+ warpzone/monitor/traces.py,sha256=wYjV8LYS4ntNbMwbvLvbmZ4x4PDrY-Iv04CAKrqWPqI,3865
33
33
  warpzone/servicebus/data/__init__.py,sha256=lnc0uiaGLF0qMi_rWhCpRSFvaj0CJEiMCAl6Yqn1ZiA,21
34
34
  warpzone/servicebus/data/client.py,sha256=zECS3JwedhYnDk8PntYgIYpBF_uu9YN38KzpPFK7CKs,6511
35
35
  warpzone/servicebus/events/__init__.py,sha256=lnc0uiaGLF0qMi_rWhCpRSFvaj0CJEiMCAl6Yqn1ZiA,21
@@ -52,6 +52,6 @@ warpzone/tools/copy.py,sha256=5fddotMZkXZO8avzUbGOhvs0cp8mce95pNpy0oPVjnQ,2596
52
52
  warpzone/transform/__init__.py,sha256=ruGa7tl-v4ndlWpULE1jSGU_a4_iRc3V6eyNr5xKP9E,27
53
53
  warpzone/transform/data.py,sha256=Abb8PcrgMbbNCJkkIUdtrTHdlY0OfXid387qw1nDpFY,2362
54
54
  warpzone/transform/schema.py,sha256=nbSQtDMvXkyqGKuwhuFCF0WsEDsaNyoPYpMKvbsKlv8,2423
55
- warpzone_sdk-15.0.0.dev6.dist-info/METADATA,sha256=g6e82wSSw24_h3IlByIcT_R8GenBJHaK6vqh64ukRGw,7398
56
- warpzone_sdk-15.0.0.dev6.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
57
- warpzone_sdk-15.0.0.dev6.dist-info/RECORD,,
55
+ warpzone_sdk-15.0.0.dev7.dist-info/METADATA,sha256=VCSSn6RIquWlfpcgQ99g7hxkxMgpTBxITxoItY-hQ-U,7398
56
+ warpzone_sdk-15.0.0.dev7.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
57
+ warpzone_sdk-15.0.0.dev7.dist-info/RECORD,,