warpzone-sdk 15.1.1__py3-none-any.whl → 15.1.1.dev1__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.
warpzone/db/client.py CHANGED
@@ -195,10 +195,12 @@ class WarpzoneDatabaseClient:
195
195
  include_validity_period_columns (bool, optional): Whether to include
196
196
  validity period columns in the result;
197
197
  (`valid_from_time_utc`, `valid_to_time_utc`).
198
- Defaults to False.
198
+ Defaults to False. If set to True while using `columns`-argument, make sure
199
+ to include these columns in the `columns`-list.
199
200
  include_generated_columns (bool, optional): Whether to include generated
200
201
  columns in the result; (e.g. `valid_from_time_utc`, `valid_to_time_utc`).
201
- Defaults to False.
202
+ Defaults to False. If set to True while using `columns`-argument, make sure
203
+ to include these columns in the `columns`-list.
202
204
 
203
205
  Returns:
204
206
  pd.DataFrame: The result of the query.
@@ -250,12 +252,10 @@ class WarpzoneDatabaseClient:
250
252
  for field in table.schema().fields:
251
253
  if field.generated_as is not None:
252
254
  generated_cols.append(field.column_name)
253
- pd_df = pd_df.drop(columns=generated_cols, errors="ignore")
255
+ pd_df = pd_df.drop(columns=generated_cols)
254
256
 
255
257
  # Drop valid-from/to columns
256
258
  if not include_validity_period_columns:
257
- pd_df = pd_df.drop(
258
- columns=["valid_from_time_utc", "valid_to_time_utc"], errors="ignore"
259
- )
259
+ pd_df = pd_df.drop(columns=["valid_from_time_utc", "valid_to_time_utc"])
260
260
 
261
261
  return pd_df
@@ -1,13 +1,16 @@
1
+ import inspect
1
2
  import logging
2
3
  import os
3
4
  import threading
4
5
  from contextlib import contextmanager
6
+ from functools import wraps
5
7
  from logging import StreamHandler
8
+ from typing import Callable
6
9
 
7
10
  from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter
8
11
  from opentelemetry import context, trace
9
12
  from opentelemetry.sdk.resources import SERVICE_NAME, Resource
10
- from opentelemetry.sdk.trace import TracerProvider
13
+ from opentelemetry.sdk.trace import Tracer, TracerProvider
11
14
  from opentelemetry.sdk.trace.export import BatchSpanProcessor
12
15
  from opentelemetry.sdk.trace.sampling import ALWAYS_ON
13
16
  from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
@@ -15,7 +18,104 @@ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapProp
15
18
  logger = logging.getLogger(__name__)
16
19
  logger.addHandler(StreamHandler())
17
20
 
18
- tracer = trace.get_tracer(__name__)
21
+
22
+ class WarpzoneTracer:
23
+ """Wrapper around OpenTelemetry tracer with additional trace decorator method"""
24
+
25
+ def __init__(self, otel_tracer: Tracer):
26
+ # Store the original tracer instead of calling super().__init__
27
+ # because we want to wrap an existing tracer, not create a new one
28
+ self._tracer = otel_tracer
29
+
30
+ def __getattr__(self, name):
31
+ """Delegate all attributes to the underlying tracer"""
32
+ return getattr(self._tracer, name)
33
+
34
+ def trace_function(
35
+ self,
36
+ name: str = None,
37
+ set_args_as_attributes: bool = False,
38
+ on_input: Callable = None,
39
+ on_output: Callable = None,
40
+ ):
41
+ """
42
+ Decorator to trace a function using this tracer object.
43
+
44
+ This decorator wraps functions with OpenTelemetry tracing, allowing for:
45
+ - Automatically create spans for function execution
46
+ - Customize the span name
47
+ - Add custom attributes to the span
48
+ - Add custom logic for inputs and outputs
49
+
50
+ Args:
51
+ name: Optional name for the span. If not provided, uses the function name.
52
+ set_args_as_attributes: If True, sets function arguments as attributes.
53
+ on_input: Optional callback called with (span, *args, **kwargs) before.
54
+ on_output: Optional callback called with (span, result) after.
55
+
56
+ Example:
57
+ # Simple tracing with function name
58
+ tracer = get_tracer(__name__)
59
+
60
+ @tracer.trace_function()
61
+ def my_function():
62
+ pass
63
+
64
+ # Custom tracing with input/output callbacks
65
+ @tracer.trace_function(
66
+ on_input=lambda span, new_data, existing_data, now: (
67
+ span.set_attribute("new_records", len(new_data)),
68
+ span.set_attribute("existing_records", len(existing_data)),
69
+ ),
70
+ on_output=lambda span, result: (
71
+ span.set_attribute("merged_records", len(result))
72
+ ),
73
+ )
74
+ def merge_new_and_existing(new_data, existing_data, now):
75
+ pass
76
+ """
77
+
78
+ def decorator(func: Callable) -> Callable:
79
+ @wraps(func)
80
+ def wrapper(*args, **kwargs):
81
+ span_name = name or func.__name__
82
+ with self._tracer.start_as_current_span(span_name) as span:
83
+ if set_args_as_attributes:
84
+ # Get parameter names from function signature
85
+ sig = inspect.signature(func)
86
+ param_names = list(sig.parameters.keys())
87
+
88
+ # Set positional arguments with their parameter names
89
+ for i, arg in enumerate(args):
90
+ if i < len(param_names):
91
+ span.set_attribute(param_names[i], str(arg))
92
+ else:
93
+ # Fallback for *args if there are more args than params
94
+ span.set_attribute(f"arg_{i}", str(arg))
95
+
96
+ # Set keyword arguments
97
+ for key, value in kwargs.items():
98
+ span.set_attribute(str(key), str(value))
99
+
100
+ # Call on_input callback if provided
101
+ if on_input:
102
+ on_input(span, *args, **kwargs)
103
+
104
+ result = func(*args, **kwargs)
105
+
106
+ # Call on_output callback if provided
107
+ if on_output:
108
+ on_output(span, result)
109
+
110
+ return result
111
+
112
+ return wrapper
113
+
114
+ return decorator
115
+
116
+
117
+ tracer = WarpzoneTracer(trace.get_tracer(__name__))
118
+
19
119
 
20
120
  _TRACING_LOCK = threading.Lock()
21
121
  TRACING_IS_CONFIGURED = False
@@ -81,8 +181,8 @@ def set_trace_context(trace_parent: str, trace_state: str = ""):
81
181
 
82
182
 
83
183
  def get_tracer(name: str):
84
- tracer = trace.get_tracer(name)
85
- return tracer
184
+ otel_tracer = trace.get_tracer(name)
185
+ return WarpzoneTracer(otel_tracer)
86
186
 
87
187
 
88
188
  def get_current_diagnostic_id() -> str:
@@ -111,14 +211,14 @@ _SB_TRACE_NAMESPACE = "Microsoft.ServiceBus"
111
211
 
112
212
 
113
213
  @contextmanager
114
- def servicebus_send_span(subject: str) -> trace.Span:
214
+ def servicebus_send_span(subject: str):
115
215
  """Start span for Service Bus message tracing.
116
216
 
117
217
  Args:
118
218
  subject: The message subject (used as span name for easy identification)
119
219
 
120
220
  Yields:
121
- trace.Span: the span
221
+ Span: the span
122
222
  """
123
223
  with tracer.start_as_current_span(
124
224
  subject, kind=trace.SpanKind.PRODUCER
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warpzone-sdk
3
- Version: 15.1.1
3
+ Version: 15.1.1.dev1
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
@@ -2,7 +2,7 @@ warpzone/__init__.py,sha256=Ay7znIadokCdHHqsPlWAqhdg-zdWhXHNtxVinViYm7o,1533
2
2
  warpzone/blobstorage/__init__.py,sha256=lnc0uiaGLF0qMi_rWhCpRSFvaj0CJEiMCAl6Yqn1ZiA,21
3
3
  warpzone/blobstorage/client.py,sha256=YwDV83acoCeHS_D_ydsTYwnf56rSTy9CKpsxqeoXmBs,4638
4
4
  warpzone/db/__init__.py,sha256=lnc0uiaGLF0qMi_rWhCpRSFvaj0CJEiMCAl6Yqn1ZiA,21
5
- warpzone/db/client.py,sha256=TdzfpgC81floe0WM7JGNbQpVz1esj1uXjnIZ9kTZmlY,9518
5
+ warpzone/db/client.py,sha256=tqY_ANThnO72rBaB4sydigLhlSFwCmadg_6rVZwjO8M,9688
6
6
  warpzone/deltastorage/__init__.py,sha256=cV8sGT2N_N5Z-E179NMW5O7q3FUDrb3j5f-yVNlNPv0,152
7
7
  warpzone/deltastorage/data_types.py,sha256=tWjLO_0ig7-tYxSHShvrd0znA7FFDnS-wBuFClUQG2U,2059
8
8
  warpzone/deltastorage/generated_columns.py,sha256=Dr_bihM7v9JKCgBXxc3JQC2P2mUGobXsReRKOl6jDO4,4765
@@ -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=gXT2cxR4tlZER54zd7D49ZQBVyitLaqj13_cUoILuyM,109
31
31
  warpzone/monitor/logs.py,sha256=q3SUQCtG1ii0B9GkVs2l8kgZ5b5bI2qI6L0SoOW2QTY,3147
32
- warpzone/monitor/traces.py,sha256=Xc_po1LxJFy5jtNWxIVphIInl_d89Zw3Rb21PsdQhQA,4170
32
+ warpzone/monitor/traces.py,sha256=IJf5CjWeh3Th2GPwvmdlhJRdVoPHgHFuZeOw2VeNu1A,7962
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.1.1.dist-info/METADATA,sha256=6WeGlAAYB3qDhdzNl4bS3GFiEzmAasRu-kakPJ3LqSM,7279
56
- warpzone_sdk-15.1.1.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
57
- warpzone_sdk-15.1.1.dist-info/RECORD,,
55
+ warpzone_sdk-15.1.1.dev1.dist-info/METADATA,sha256=cGg0TkCeji-1k162MizWD0MvGbG2k5xBY42NkeXol-c,7284
56
+ warpzone_sdk-15.1.1.dev1.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
57
+ warpzone_sdk-15.1.1.dev1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.3.1
2
+ Generator: poetry-core 2.3.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any