warpzone-sdk 15.0.0.dev1__tar.gz → 15.0.0.dev2__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.
Files changed (58) hide show
  1. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/PKG-INFO +1 -1
  2. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/pyproject.toml +1 -1
  3. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/monitor.py +12 -2
  4. warpzone_sdk-15.0.0.dev2/warpzone/monitor/traces.py +99 -0
  5. warpzone_sdk-15.0.0.dev1/warpzone/monitor/traces.py +0 -51
  6. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/README.md +0 -0
  7. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/__init__.py +0 -0
  8. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/blobstorage/__init__.py +0 -0
  9. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/blobstorage/client.py +0 -0
  10. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/db/__init__.py +0 -0
  11. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/db/client.py +0 -0
  12. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/__init__.py +0 -0
  13. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/data_types.py +0 -0
  14. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/generated_columns.py +0 -0
  15. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/lock_client.py +0 -0
  16. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/schema.py +0 -0
  17. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/slicing.py +0 -0
  18. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/store.py +0 -0
  19. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/deltastorage/table.py +0 -0
  20. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/enums/__init__.py +0 -0
  21. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/enums/topicenum.py +0 -0
  22. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/__init__.py +0 -0
  23. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/checks.py +0 -0
  24. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/functionize.py +0 -0
  25. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/integrations.py +0 -0
  26. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/process.py +0 -0
  27. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/processors/__init__.py +0 -0
  28. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/processors/dependencies.py +0 -0
  29. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/processors/outputs.py +0 -0
  30. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/processors/triggers.py +0 -0
  31. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/signature.py +0 -0
  32. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/function/types.py +0 -0
  33. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/healthchecks/__init__.py +0 -0
  34. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/healthchecks/model.py +0 -0
  35. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/monitor/__init__.py +0 -0
  36. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/monitor/logs.py +0 -0
  37. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/servicebus/data/__init__.py +0 -0
  38. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/servicebus/data/client.py +0 -0
  39. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/servicebus/events/__init__.py +0 -0
  40. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/servicebus/events/client.py +0 -0
  41. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/servicebus/events/triggers.py +0 -0
  42. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/db/__init__.py +0 -0
  43. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/db/base_client.py +0 -0
  44. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/db/client.py +0 -0
  45. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/db/table_config.py +0 -0
  46. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/tables/__init__.py +0 -0
  47. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/tables/client.py +0 -0
  48. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/tables/entities.py +0 -0
  49. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tablestorage/tables/helpers.py +0 -0
  50. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/testing/__init__.py +0 -0
  51. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/testing/assertions.py +0 -0
  52. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/testing/data.py +0 -0
  53. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/testing/matchers.py +0 -0
  54. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tools/__init__.py +0 -0
  55. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/tools/copy.py +0 -0
  56. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/transform/__init__.py +0 -0
  57. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/transform/data.py +0 -0
  58. {warpzone_sdk-15.0.0.dev1 → warpzone_sdk-15.0.0.dev2}/warpzone/transform/schema.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warpzone-sdk
3
- Version: 15.0.0.dev1
3
+ Version: 15.0.0.dev2
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "warpzone-sdk"
3
- version = "15.0.0.dev1"
3
+ version = "15.0.0.dev2"
4
4
  description = "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
  authors = [{ name = "Team Enigma", email = "enigma@energinet.dk" }]
6
6
  requires-python = ">=3.10"
@@ -1,15 +1,25 @@
1
- import asyncio
1
+ import inspect
2
2
  from contextlib import contextmanager
3
3
  from typing import Callable
4
4
 
5
5
  import azure.functions as func
6
6
  from azure.monitor.opentelemetry import configure_azure_monitor
7
+ from opentelemetry import trace
7
8
 
8
9
  from warpzone.function.types import SingleArgumentCallable
9
10
  from warpzone.monitor import logs, traces
10
11
 
12
+ # Configure Azure Monitor first
11
13
  configure_azure_monitor()
12
14
 
15
+ # Apply trace filtering to suppress all Azure SDK traces except Service Bus
16
+ tracer_provider = trace.get_tracer_provider()
17
+ if hasattr(tracer_provider, "_active_span_processor"):
18
+ # Wrap the existing span processor with our filter
19
+ original_processor = tracer_provider._active_span_processor
20
+ filtered_processor = traces.AzureSDKTraceFilter(original_processor)
21
+ tracer_provider._active_span_processor = filtered_processor
22
+
13
23
  SUBJECT_IDENTIFIER = "<Subject>"
14
24
 
15
25
  tracer = traces.get_tracer(__name__)
@@ -54,7 +64,7 @@ def monitor(main: SingleArgumentCallable) -> Callable:
54
64
  result = main(arg)
55
65
  return result
56
66
 
57
- if asyncio.iscoroutinefunction(main):
67
+ if inspect.iscoroutinefunction(main):
58
68
  return wrapper_async
59
69
  else:
60
70
  return wrapper
@@ -0,0 +1,99 @@
1
+ from contextlib import contextmanager
2
+
3
+ from azure.core.settings import settings
4
+ from opentelemetry import context, trace
5
+ from opentelemetry.sdk.trace import ReadableSpan, SpanProcessor
6
+ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
7
+
8
+ settings.tracing_implementation = "opentelemetry"
9
+
10
+
11
+ class AzureSDKTraceFilter(SpanProcessor):
12
+ """Custom SpanProcessor to filter out Azure SDK traces except Service Bus.
13
+
14
+ It drops spans from Azure SDK libraries except Service Bus messages,
15
+ preventing them from being exported to Azure Monitor.
16
+ """
17
+
18
+ def __init__(self, wrapped_processor: SpanProcessor):
19
+ """Initialize with the actual processor to wrap.
20
+
21
+ Args:
22
+ wrapped_processor: The underlying processor (e.g., BatchSpanProcessor)
23
+ """
24
+ self.wrapped_processor = wrapped_processor
25
+
26
+ def on_start(
27
+ self, span: ReadableSpan, parent_context: context.Context = None
28
+ ) -> None:
29
+ """Called when a span is started."""
30
+ self.wrapped_processor.on_start(span, parent_context)
31
+
32
+ def on_end(self, span: ReadableSpan) -> None:
33
+ """Called when a span is ended. Filter based on span attributes."""
34
+ # Check if service bus span - always allow
35
+ if "servicebus.message" in span.name.lower():
36
+ self.wrapped_processor.on_end(span)
37
+ return
38
+
39
+ # Check if this is an Azure SDK span we want to suppress
40
+ instrumentation_scope = span.instrumentation_scope
41
+ if instrumentation_scope and instrumentation_scope.name:
42
+ # Suppress spans from Azure SDK libraries
43
+ if instrumentation_scope.name.startswith("azure."):
44
+ return # Drop this span
45
+
46
+ # Pass through all other spans
47
+ self.wrapped_processor.on_end(span)
48
+
49
+ def shutdown(self) -> None:
50
+ """Shutdown the wrapped processor."""
51
+ self.wrapped_processor.shutdown()
52
+
53
+ def force_flush(self, timeout_millis: int = 30000) -> bool:
54
+ """Force flush the wrapped processor."""
55
+ return self.wrapped_processor.force_flush(timeout_millis)
56
+
57
+
58
+ @contextmanager
59
+ def set_trace_context(trace_parent: str, trace_state: str = ""):
60
+ """Context manager for setting the trace context
61
+
62
+ Args:
63
+ trace_parent (str): Trace parent ID
64
+ trace_state (str, optional): Trace state. Defaults to "".
65
+ """
66
+ carrier = {"traceparent": trace_parent, "tracestate": trace_state}
67
+ ctx = TraceContextTextMapPropagator().extract(carrier=carrier)
68
+
69
+ token = context.attach(ctx) # attach context before run
70
+ try:
71
+ yield
72
+ finally:
73
+ context.detach(token) # detach context after run
74
+
75
+
76
+ def get_tracer(name: str):
77
+ tracer = trace.get_tracer(name)
78
+ return tracer
79
+
80
+
81
+ def get_current_diagnostic_id() -> str:
82
+ """Gets diagnostic id from current span
83
+
84
+ The diagnostic id is a concatenation of operation-id and parent-id
85
+
86
+ Returns:
87
+ str: diagnostic id
88
+ """
89
+ span = trace.get_current_span()
90
+
91
+ if not span.is_recording():
92
+ return ""
93
+
94
+ operation_id = "{:016x}".format(span.context.trace_id)
95
+ parent_id = "{:016x}".format(span.context.span_id)
96
+
97
+ diagnostic_id = f"00-{operation_id}-{parent_id}-01"
98
+
99
+ return diagnostic_id
@@ -1,51 +0,0 @@
1
- from contextlib import contextmanager
2
-
3
- from azure.core.settings import settings
4
- from opentelemetry import context, trace
5
- from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
6
-
7
- settings.tracing_implementation = "opentelemetry"
8
-
9
-
10
- @contextmanager
11
- def set_trace_context(trace_parent: str, trace_state: str = ""):
12
- """Context manager for setting the trace context
13
-
14
- Args:
15
- trace_parent (str): Trace parent ID
16
- trace_state (str, optional): Trace state. Defaults to "".
17
- """
18
- carrier = {"traceparent": trace_parent, "tracestate": trace_state}
19
- ctx = TraceContextTextMapPropagator().extract(carrier=carrier)
20
-
21
- token = context.attach(ctx) # attach context before run
22
- try:
23
- yield
24
- finally:
25
- context.detach(token) # detach context after run
26
-
27
-
28
- def get_tracer(name: str):
29
- tracer = trace.get_tracer(name)
30
- return tracer
31
-
32
-
33
- def get_current_diagnostic_id() -> str:
34
- """Gets diagnostic id from current span
35
-
36
- The diagnostic id is a concatenation of operation-id and parent-id
37
-
38
- Returns:
39
- str: diagnostic id
40
- """
41
- span = trace.get_current_span()
42
-
43
- if not span.is_recording():
44
- return ""
45
-
46
- operation_id = "{:016x}".format(span.context.trace_id)
47
- parent_id = "{:016x}".format(span.context.span_id)
48
-
49
- diagnostic_id = f"00-{operation_id}-{parent_id}-01"
50
-
51
- return diagnostic_id