warpzone-sdk 15.0.0.dev2__py3-none-any.whl → 15.0.0.dev4__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.
@@ -7,9 +7,11 @@ from azure.monitor.opentelemetry import configure_azure_monitor
7
7
  from opentelemetry import trace
8
8
 
9
9
  from warpzone.function.types import SingleArgumentCallable
10
- from warpzone.monitor import logs, traces
10
+ from warpzone.monitor import traces
11
11
 
12
- # Configure Azure Monitor first
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.
13
15
  configure_azure_monitor()
14
16
 
15
17
  # Apply trace filtering to suppress all Azure SDK traces except Service Bus
@@ -22,16 +24,11 @@ if hasattr(tracer_provider, "_active_span_processor"):
22
24
 
23
25
  SUBJECT_IDENTIFIER = "<Subject>"
24
26
 
25
- tracer = traces.get_tracer(__name__)
26
- logger = logs.get_logger(__name__)
27
-
28
27
 
29
28
  @contextmanager
30
29
  def run_in_trace_context(context: func.Context):
31
30
  trace_context = context.trace_context
32
- with traces.set_trace_context(
33
- trace_context.trace_parent, trace_context.trace_state
34
- ):
31
+ with traces.set_trace_context(trace_context.trace_parent):
35
32
  yield
36
33
 
37
34
 
warpzone/monitor/logs.py CHANGED
@@ -17,8 +17,18 @@ logging.getLogger("azure.monitor.opentelemetry.exporter").setLevel(logging.WARNI
17
17
 
18
18
 
19
19
  def get_logger(name: str):
20
- # set up standard logger
20
+ """Get a logger instance.
21
+
22
+ The logger will automatically use the current OpenTelemetry trace context
23
+ for correlation in Application Insights. The trace context is set by the
24
+ monitor decorator's run_in_trace_context context manager.
25
+
26
+ Args:
27
+ name: Logger name, typically __name__
28
+
29
+ Returns:
30
+ A configured logger instance
31
+ """
21
32
  logger = logging.getLogger(name)
22
33
  logger.setLevel(logging.INFO)
23
-
24
34
  return logger
@@ -31,8 +31,15 @@ class AzureSDKTraceFilter(SpanProcessor):
31
31
 
32
32
  def on_end(self, span: ReadableSpan) -> None:
33
33
  """Called when a span is ended. Filter based on span attributes."""
34
+ # Safely get span name, handling None or mock objects
35
+ span_name = getattr(span, "name", None)
36
+ if span_name is None or not isinstance(span_name, str):
37
+ # Pass through spans without valid names (e.g., in test mocks)
38
+ self.wrapped_processor.on_end(span)
39
+ return
40
+
34
41
  # Check if service bus span - always allow
35
- if "servicebus.message" in span.name.lower():
42
+ if "servicebus.message" in span_name.lower():
36
43
  self.wrapped_processor.on_end(span)
37
44
  return
38
45
 
@@ -56,21 +63,36 @@ class AzureSDKTraceFilter(SpanProcessor):
56
63
 
57
64
 
58
65
  @contextmanager
59
- def set_trace_context(trace_parent: str, trace_state: str = ""):
60
- """Context manager for setting the trace context
66
+ def set_trace_context(trace_parent: str):
67
+ """Context manager for setting the trace context.
68
+
69
+ Attaches the propagated trace context with a NonRecordingSpan so that
70
+ logs emitted within this context are properly correlated with the trace
71
+ created by Azure Functions.
72
+
73
+ The NonRecordingSpan is necessary because the LoggingHandler needs an
74
+ actual span (not just a SpanContext) to extract trace correlation IDs.
75
+ Using NonRecordingSpan avoids creating duplicate spans while still
76
+ providing the trace_id and span_id for log correlation.
61
77
 
62
78
  Args:
63
- trace_parent (str): Trace parent ID
64
- trace_state (str, optional): Trace state. Defaults to "".
79
+ trace_parent (str): Trace parent ID from the incoming request
65
80
  """
66
- carrier = {"traceparent": trace_parent, "tracestate": trace_state}
81
+ carrier = {"traceparent": trace_parent}
67
82
  ctx = TraceContextTextMapPropagator().extract(carrier=carrier)
68
83
 
69
- token = context.attach(ctx) # attach context before run
84
+ # Get the span from the extracted context - this is a NonRecordingSpan
85
+ # created by the propagator with the correct trace_id and span_id
86
+ span = trace.get_current_span(ctx)
87
+
88
+ # Set this span as the current span in context
89
+ ctx = trace.set_span_in_context(span)
90
+
91
+ token = context.attach(ctx)
70
92
  try:
71
93
  yield
72
94
  finally:
73
- context.detach(token) # detach context after run
95
+ context.detach(token)
74
96
 
75
97
 
76
98
  def get_tracer(name: str):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warpzone-sdk
3
- Version: 15.0.0.dev2
3
+ Version: 15.0.0.dev4
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=F7_eRq0XjsAOvOHgURguFU0FozC8jXt_ev8CyhkOgms,2157
20
+ warpzone/function/monitor.py,sha256=qBvnSTSX--6_6qccTZrGPO1iS5nz2tNZlHdhE1XBrbs,2214
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
@@ -28,8 +28,8 @@ warpzone/function/types.py,sha256=5m2hRrnLC3eqIlAH5-MM9_wKjMZ6lYawZtCOVStyFuY,72
28
28
  warpzone/healthchecks/__init__.py,sha256=9gc_Mt2szs8sDSwy0V4l3JZ6d9hX41xTpZCkDP2qsY4,2108
29
29
  warpzone/healthchecks/model.py,sha256=mM7DnrirLbUpBPPfi82MUPP654D0eOR2_F65TmzsPD0,1187
30
30
  warpzone/monitor/__init__.py,sha256=ggI5fIUu-szgC44ICzuOmpYrIoVOKPbsMT3zza9ssD4,87
31
- warpzone/monitor/logs.py,sha256=V1A2ImqbPo4c-hDr2qWAZlpr2muyVar30eI9mF2_rzE,986
32
- warpzone/monitor/traces.py,sha256=PhhYeZlPc7EOSq9KVsHdKOwEIivDHCV-RwZnDNVL7ic,3244
31
+ warpzone/monitor/logs.py,sha256=fabjaB5SfHynvvfp2Js3IG-owqU5jZ3lTnnmTTjD6JM,1320
32
+ warpzone/monitor/traces.py,sha256=B_1_fmUNUwHRKB-IYfhWSw5VRluVvn1NQqSYTqNV0wA,4158
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.dev2.dist-info/METADATA,sha256=bYOwFSbmKdxOJO06Uv7jlMskEFAxwRVsbiG8BeNNq0Y,7398
56
- warpzone_sdk-15.0.0.dev2.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
57
- warpzone_sdk-15.0.0.dev2.dist-info/RECORD,,
55
+ warpzone_sdk-15.0.0.dev4.dist-info/METADATA,sha256=jxPQ1HTdmdO0ePXvZAFg58OmIGw38qssEwnc6o9eTAI,7398
56
+ warpzone_sdk-15.0.0.dev4.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
57
+ warpzone_sdk-15.0.0.dev4.dist-info/RECORD,,