rebrandly-otel 0.1.9__py3-none-any.whl → 0.1.10__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.
Potentially problematic release.
This version of rebrandly-otel might be problematic. Click here for more details.
- rebrandly_otel/rebrandly_otel.py +75 -47
- {rebrandly_otel-0.1.9.dist-info → rebrandly_otel-0.1.10.dist-info}/METADATA +1 -1
- rebrandly_otel-0.1.10.dist-info/RECORD +11 -0
- rebrandly_otel-0.1.9.dist-info/RECORD +0 -11
- {rebrandly_otel-0.1.9.dist-info → rebrandly_otel-0.1.10.dist-info}/WHEEL +0 -0
- {rebrandly_otel-0.1.9.dist-info → rebrandly_otel-0.1.10.dist-info}/licenses/LICENSE +0 -0
- {rebrandly_otel-0.1.9.dist-info → rebrandly_otel-0.1.10.dist-info}/top_level.txt +0 -0
rebrandly_otel/rebrandly_otel.py
CHANGED
|
@@ -99,6 +99,9 @@ class RebrandlyOTEL:
|
|
|
99
99
|
return wrapper
|
|
100
100
|
return decorator
|
|
101
101
|
|
|
102
|
+
# Fix for the lambda_handler method in rebrandly_otel.py
|
|
103
|
+
# Replace the lambda_handler method (around line 132) with this fixed version:
|
|
104
|
+
|
|
102
105
|
def lambda_handler(self,
|
|
103
106
|
name: Optional[str] = None,
|
|
104
107
|
attributes: Optional[Dict[str, Any]] = None,
|
|
@@ -107,22 +110,6 @@ class RebrandlyOTEL:
|
|
|
107
110
|
skip_aws_link: bool = True):
|
|
108
111
|
"""
|
|
109
112
|
Decorator specifically for Lambda handlers with automatic flushing.
|
|
110
|
-
|
|
111
|
-
Args:
|
|
112
|
-
name: Optional span name (defaults to 'lambda.{function_name}')
|
|
113
|
-
attributes: Additional span attributes
|
|
114
|
-
kind: Span kind (defaults to SERVER)
|
|
115
|
-
auto_flush: If True, automatically flush after handler completes
|
|
116
|
-
|
|
117
|
-
Usage:
|
|
118
|
-
@lambda_handler()
|
|
119
|
-
def my_handler(event, context): ...
|
|
120
|
-
|
|
121
|
-
@lambda_handler(name="custom_span_name")
|
|
122
|
-
def my_handler(event, context): ...
|
|
123
|
-
|
|
124
|
-
@lambda_handler(name="my_span", attributes={"env": "prod"})
|
|
125
|
-
def my_handler(event, context): ...
|
|
126
113
|
"""
|
|
127
114
|
def decorator(func):
|
|
128
115
|
@functools.wraps(func)
|
|
@@ -150,50 +137,91 @@ class RebrandlyOTEL:
|
|
|
150
137
|
# Increment invocations counter
|
|
151
138
|
self.meter.GlobalMetrics.invocations.add(1, {'function': span_name})
|
|
152
139
|
|
|
153
|
-
#
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
else
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
140
|
+
# Determine if we should extract context from AWS message
|
|
141
|
+
extracted_context = None
|
|
142
|
+
if not skip_aws_link and event is not None and 'Records' in event and len(event['Records']) > 0:
|
|
143
|
+
first_record = event['Records'][0]
|
|
144
|
+
|
|
145
|
+
# Check different message formats
|
|
146
|
+
if 'messageAttributes' in first_record or 'MessageAttributes' in first_record:
|
|
147
|
+
# SQS format
|
|
148
|
+
extracted_context = self.extract_context(first_record)
|
|
149
|
+
elif 'Sns' in first_record and 'MessageAttributes' in first_record['Sns']:
|
|
150
|
+
# SNS format
|
|
151
|
+
extracted_context = self.extract_context(first_record)
|
|
152
|
+
|
|
153
|
+
# Create span - use extracted context if available
|
|
154
|
+
if extracted_context:
|
|
155
|
+
token = self.attach_context(extracted_context)
|
|
156
|
+
try:
|
|
157
|
+
with self.span(span_name, attributes=span_attributes, kind=kind) as span_context:
|
|
158
|
+
# Add event type as span event
|
|
159
|
+
if event is not None:
|
|
160
|
+
span_context.add_event("lambda.invocation.start",
|
|
161
|
+
attributes={"event.type": type(event).__name__})
|
|
162
|
+
|
|
163
|
+
result = func(event, context) if event is not None else func()
|
|
164
|
+
|
|
165
|
+
# Handle result
|
|
166
|
+
self._process_lambda_result(result, span_context, span_name)
|
|
167
|
+
finally:
|
|
168
|
+
self.detach_context(token)
|
|
169
|
+
else:
|
|
170
|
+
# No context extraction needed
|
|
171
|
+
with self.span(span_name, attributes=span_attributes, kind=kind) as span_context:
|
|
172
|
+
# Add event type as span event
|
|
173
|
+
if event is not None:
|
|
174
|
+
span_context.add_event("lambda.invocation.start",
|
|
175
|
+
attributes={"event.type": type(event).__name__})
|
|
176
|
+
|
|
177
|
+
result = func(event, context) if event is not None else func()
|
|
178
|
+
|
|
179
|
+
# Handle result
|
|
180
|
+
self._process_lambda_result(result, span_context, span_name)
|
|
181
|
+
|
|
182
|
+
return result
|
|
183
183
|
|
|
184
184
|
except Exception as e:
|
|
185
185
|
# Increment error counter
|
|
186
186
|
self.meter.GlobalMetrics.error_invocations.add(1, {'function': span_name, 'error': type(e).__name__})
|
|
187
|
+
|
|
188
|
+
# Log error with context
|
|
189
|
+
self.logger.logger.error(f"Lambda execution failed: {e}", exc_info=True)
|
|
187
190
|
raise
|
|
188
191
|
|
|
189
192
|
finally:
|
|
193
|
+
# Record duration
|
|
194
|
+
duration = (datetime.now() - start_func).total_seconds() * 1000
|
|
195
|
+
self.meter.GlobalMetrics.duration.record(duration, {'function': span_name})
|
|
196
|
+
|
|
190
197
|
if auto_flush:
|
|
191
|
-
self.logger.logger.info(f"[OTEL] Lambda handler '{span_name}' completed, flushing telemetry...")
|
|
198
|
+
self.logger.logger.info(f"[OTEL] Lambda handler '{span_name}' completed in {duration:.2f}ms, flushing telemetry...")
|
|
192
199
|
self.force_flush(start_datetime=start_func)
|
|
193
200
|
|
|
194
201
|
return wrapper
|
|
195
202
|
return decorator
|
|
196
203
|
|
|
204
|
+
def _process_lambda_result(self, result, span_context, span_name):
|
|
205
|
+
"""Helper method to process Lambda result and update span accordingly"""
|
|
206
|
+
if isinstance(result, dict):
|
|
207
|
+
if 'statusCode' in result:
|
|
208
|
+
span_context.set_attribute("http.status_code", result['statusCode'])
|
|
209
|
+
# Set span status based on HTTP status code
|
|
210
|
+
if result['statusCode'] >= 400:
|
|
211
|
+
span_context.set_status(Status(StatusCode.ERROR, f"HTTP {result['statusCode']}"))
|
|
212
|
+
else:
|
|
213
|
+
span_context.set_status(Status(StatusCode.OK))
|
|
214
|
+
|
|
215
|
+
# Add completion event
|
|
216
|
+
span_context.add_event("lambda.invocation.complete",
|
|
217
|
+
attributes={"success": result.get('statusCode', 200) < 400})
|
|
218
|
+
else:
|
|
219
|
+
span_context.set_status(Status(StatusCode.OK))
|
|
220
|
+
span_context.add_event("lambda.invocation.complete", attributes={"success": True})
|
|
221
|
+
|
|
222
|
+
# Increment success counter
|
|
223
|
+
self.meter.GlobalMetrics.successful_invocations.add(1, {'function': span_name})
|
|
224
|
+
|
|
197
225
|
def aws_message_handler(self,
|
|
198
226
|
name: Optional[str] = None,
|
|
199
227
|
attributes: Optional[Dict[str, Any]] = None,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
rebrandly_otel/__init__.py,sha256=AHcEKWq4KRafIF_x_Y8jiIQ5crNG1nbEwdnlGaEP6js,287
|
|
2
|
+
rebrandly_otel/logs.py,sha256=92jaxzI5hCHnKHu3lsSAa7K_SPHQgL46AlQUESsYNds,3724
|
|
3
|
+
rebrandly_otel/metrics.py,sha256=57jwrn8e1u66BOO7fcFrmtE3Rpt4VDixG9I78K-zrUU,8537
|
|
4
|
+
rebrandly_otel/otel_utils.py,sha256=uJmfz2NspSnTVJXGKoaLUl1CYb0ow6VHKjmg2d_rdwg,1704
|
|
5
|
+
rebrandly_otel/rebrandly_otel.py,sha256=KSzrGSdUgqXZO1C0RBrBLNcAh-9oR5wqSWLJc0-Itww,21626
|
|
6
|
+
rebrandly_otel/traces.py,sha256=EiZMWNerzAisn_2MEcE9u1zVkRlZZrbnY3PVzVWWOuI,7048
|
|
7
|
+
rebrandly_otel-0.1.10.dist-info/licenses/LICENSE,sha256=KMXHvTwP62S2q-SG7CFfMU_09rUwxiqlM0izaYGdcgY,1103
|
|
8
|
+
rebrandly_otel-0.1.10.dist-info/METADATA,sha256=27eO_Dw6gLu-4FLXTW9rMj7zVmpImBHwKhAUjebmDWw,9628
|
|
9
|
+
rebrandly_otel-0.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
rebrandly_otel-0.1.10.dist-info/top_level.txt,sha256=26PSC1gjVUl8tTH5QfKbFevjVV4E2yojoukEfiTScvM,15
|
|
11
|
+
rebrandly_otel-0.1.10.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
rebrandly_otel/__init__.py,sha256=AHcEKWq4KRafIF_x_Y8jiIQ5crNG1nbEwdnlGaEP6js,287
|
|
2
|
-
rebrandly_otel/logs.py,sha256=92jaxzI5hCHnKHu3lsSAa7K_SPHQgL46AlQUESsYNds,3724
|
|
3
|
-
rebrandly_otel/metrics.py,sha256=57jwrn8e1u66BOO7fcFrmtE3Rpt4VDixG9I78K-zrUU,8537
|
|
4
|
-
rebrandly_otel/otel_utils.py,sha256=uJmfz2NspSnTVJXGKoaLUl1CYb0ow6VHKjmg2d_rdwg,1704
|
|
5
|
-
rebrandly_otel/rebrandly_otel.py,sha256=e8G6Tw6Wlauc7rjrrauRcDqD6phRxiq7x7z2nJ1MRfs,19819
|
|
6
|
-
rebrandly_otel/traces.py,sha256=EiZMWNerzAisn_2MEcE9u1zVkRlZZrbnY3PVzVWWOuI,7048
|
|
7
|
-
rebrandly_otel-0.1.9.dist-info/licenses/LICENSE,sha256=KMXHvTwP62S2q-SG7CFfMU_09rUwxiqlM0izaYGdcgY,1103
|
|
8
|
-
rebrandly_otel-0.1.9.dist-info/METADATA,sha256=3k0tqqcRbWfS2bhJk_HuH9w8bVeauSR5Lk0FNtS_lzw,9627
|
|
9
|
-
rebrandly_otel-0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
-
rebrandly_otel-0.1.9.dist-info/top_level.txt,sha256=26PSC1gjVUl8tTH5QfKbFevjVV4E2yojoukEfiTScvM,15
|
|
11
|
-
rebrandly_otel-0.1.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|