rebrandly-otel 0.1.17__tar.gz → 0.1.18__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.

Potentially problematic release.


This version of rebrandly-otel might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rebrandly_otel
3
- Version: 0.1.17
3
+ Version: 0.1.18
4
4
  Summary: Python OTEL wrapper by Rebrandly
5
5
  Home-page: https://github.com/rebrandly/rebrandly-otel-python
6
6
  Author: Antonio Romano
@@ -102,22 +102,9 @@ The SDK automatically registers and tracks the following metrics:
102
102
 
103
103
  ### Standard Metrics
104
104
 
105
- - **`invocations`** (Counter): Total number of function invocations
106
- - **`successful_invocations`** (Counter): Number of successful completions
107
- - **`error_invocations`** (Counter): Number of failed invocations
108
- - **`duration`** (Histogram): Execution duration in milliseconds
109
105
  - **`cpu_usage_percentage`** (Gauge): CPU utilization percentage
110
106
  - **`memory_usage_bytes`** (Gauge): Memory usage in bytes
111
107
 
112
- ### Global Metrics Access
113
-
114
- ```python
115
- from rebrandly_otel import meter
116
-
117
- # Access pre-configured metrics
118
- meter.GlobalMetrics.invocations.add(1, {'function': 'my_function'})
119
- meter.GlobalMetrics.duration.record(150.5, {'source': 'api'})
120
- ```
121
108
 
122
109
  ### Custom Metrics
123
110
 
@@ -195,10 +182,8 @@ Automatically detects and labels Lambda triggers:
195
182
  ### Automatic Metrics
196
183
 
197
184
  For Lambda functions, the SDK automatically captures:
198
- - Function duration
199
185
  - Memory usage
200
186
  - CPU utilization
201
- - Invocation counts by status
202
187
 
203
188
  ### Context Extraction
204
189
 
@@ -81,22 +81,9 @@ The SDK automatically registers and tracks the following metrics:
81
81
 
82
82
  ### Standard Metrics
83
83
 
84
- - **`invocations`** (Counter): Total number of function invocations
85
- - **`successful_invocations`** (Counter): Number of successful completions
86
- - **`error_invocations`** (Counter): Number of failed invocations
87
- - **`duration`** (Histogram): Execution duration in milliseconds
88
84
  - **`cpu_usage_percentage`** (Gauge): CPU utilization percentage
89
85
  - **`memory_usage_bytes`** (Gauge): Memory usage in bytes
90
86
 
91
- ### Global Metrics Access
92
-
93
- ```python
94
- from rebrandly_otel import meter
95
-
96
- # Access pre-configured metrics
97
- meter.GlobalMetrics.invocations.add(1, {'function': 'my_function'})
98
- meter.GlobalMetrics.duration.record(150.5, {'source': 'api'})
99
- ```
100
87
 
101
88
  ### Custom Metrics
102
89
 
@@ -174,10 +161,8 @@ Automatically detects and labels Lambda triggers:
174
161
  ### Automatic Metrics
175
162
 
176
163
  For Lambda functions, the SDK automatically captures:
177
- - Function duration
178
164
  - Memory usage
179
165
  - CPU utilization
180
- - Invocation counts by status
181
166
 
182
167
  ### Context Extraction
183
168
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rebrandly_otel
3
- Version: 0.1.17
3
+ Version: 0.1.18
4
4
  Summary: Python OTEL wrapper by Rebrandly
5
5
  Home-page: https://github.com/rebrandly/rebrandly-otel-python
6
6
  Author: Antonio Romano
@@ -102,22 +102,9 @@ The SDK automatically registers and tracks the following metrics:
102
102
 
103
103
  ### Standard Metrics
104
104
 
105
- - **`invocations`** (Counter): Total number of function invocations
106
- - **`successful_invocations`** (Counter): Number of successful completions
107
- - **`error_invocations`** (Counter): Number of failed invocations
108
- - **`duration`** (Histogram): Execution duration in milliseconds
109
105
  - **`cpu_usage_percentage`** (Gauge): CPU utilization percentage
110
106
  - **`memory_usage_bytes`** (Gauge): Memory usage in bytes
111
107
 
112
- ### Global Metrics Access
113
-
114
- ```python
115
- from rebrandly_otel import meter
116
-
117
- # Access pre-configured metrics
118
- meter.GlobalMetrics.invocations.add(1, {'function': 'my_function'})
119
- meter.GlobalMetrics.duration.record(150.5, {'source': 'api'})
120
- ```
121
108
 
122
109
  ### Custom Metrics
123
110
 
@@ -195,10 +182,8 @@ Automatically detects and labels Lambda triggers:
195
182
  ### Automatic Metrics
196
183
 
197
184
  For Lambda functions, the SDK automatically captures:
198
- - Function duration
199
185
  - Memory usage
200
186
  - CPU utilization
201
- - Invocation counts by status
202
187
 
203
188
  ### Context Extraction
204
189
 
@@ -6,6 +6,7 @@ rebrandly_otel.egg-info/SOURCES.txt
6
6
  rebrandly_otel.egg-info/dependency_links.txt
7
7
  rebrandly_otel.egg-info/top_level.txt
8
8
  src/__init__.py
9
+ src/fastapi_support.py
9
10
  src/flask_support.py
10
11
  src/logs.py
11
12
  src/metrics.py
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="rebrandly_otel",
8
- version="0.1.17",
8
+ version="0.1.18",
9
9
  author="Antonio Romano",
10
10
  author_email="antonio@rebrandly.com",
11
11
  description="Python OTEL wrapper by Rebrandly",
@@ -1,6 +1,7 @@
1
1
  # src/__init__.py
2
2
  from .rebrandly_otel import *
3
- from .flask_support import *
3
+ from .flask_support import setup_flask
4
+ from .fastapi_support import setup_fastapi
4
5
 
5
6
  # Explicitly define what's available
6
7
  __all__ = [
@@ -14,5 +15,6 @@ __all__ = [
14
15
  'force_flush',
15
16
  'aws_message_handler',
16
17
  'shutdown',
17
- 'setup_flask'
18
+ 'setup_flask',
19
+ 'setup_fastapi'
18
20
  ]
@@ -0,0 +1,198 @@
1
+ # fastapi_integration.py
2
+ """FastAPI integration for Rebrandly OTEL SDK."""
3
+ import json
4
+ from rebrandly_otel import Status, StatusCode, SpanKind
5
+ from fastapi import HTTPException, Depends
6
+ from starlette.requests import Request
7
+ from starlette.middleware.base import BaseHTTPMiddleware
8
+ from fastapi.responses import JSONResponse
9
+
10
+ import time
11
+
12
+ def setup_fastapi(otel , app):
13
+ """
14
+ Setup FastAPI application with OTEL instrumentation.
15
+
16
+ Example:
17
+ from fastapi import FastAPI
18
+ from rebrandly_otel import otel
19
+ from rebrandly_otel.fastapi_integration import setup_fastapi
20
+
21
+ app = FastAPI()
22
+ setup_fastapi(otel, app)
23
+ """
24
+
25
+ # Add middleware
26
+ add_otel_middleware(otel, app)
27
+
28
+ # Add exception handlers
29
+ app.add_exception_handler(HTTPException, lambda request, exc: fastapi_exception_handler(otel, request, exc))
30
+ app.add_exception_handler(Exception, lambda request, exc: fastapi_exception_handler(otel, request, exc))
31
+
32
+ return app
33
+
34
+ def add_otel_middleware(otel, app):
35
+ """
36
+ Add OTEL middleware to FastAPI application.
37
+ """
38
+
39
+ class OTELMiddleware(BaseHTTPMiddleware):
40
+ def __init__(self, app):
41
+ super().__init__(app)
42
+ self.otel = otel
43
+
44
+ async def dispatch(self, request: Request, call_next):
45
+ # Extract trace context from headers
46
+ headers = dict(request.headers)
47
+ token = self.otel.attach_context(headers)
48
+
49
+ # Start span for request
50
+ span_name = f"{request.method} {request.url.path}"
51
+
52
+ # Use start_as_current_span for proper context propagation
53
+ with self.otel.tracer.tracer.start_as_current_span(
54
+ span_name,
55
+ attributes={
56
+ # Required HTTP attributes per semantic conventions
57
+ "http.request.method": request.method,
58
+ "http.request.headers": json.dumps(request.headers, default=str),
59
+ "http.response.status_code": None, # Will be set after response
60
+ "url.full": str(request.url),
61
+ "url.scheme": request.url.scheme,
62
+ "url.path": request.url.path,
63
+ "url.query": request.url.query if request.url.query else None,
64
+ "user_agent.original": request.headers.get("user-agent"),
65
+ "http.route": None, # Will be set after routing
66
+ "network.protocol.version": "1.1", # FastAPI/Starlette typically uses HTTP/1.1
67
+ "server.address": request.url.hostname,
68
+ "server.port": request.url.port or (443 if request.url.scheme == 'https' else 80),
69
+ "client.address": request.client.host if request.client else None,
70
+ },
71
+ kind=SpanKind.SERVER
72
+ ) as span:
73
+ # Log request start
74
+ self.otel.logger.logger.info(f"Request started: {request.method} {request.url.path}",
75
+ extra={"http.method": request.method, "http.path": request.url.path})
76
+
77
+ # Store span in request state for access in routes
78
+ request.state.span = span
79
+ request.state.trace_token = token
80
+
81
+ start_time = time.time()
82
+
83
+ try:
84
+ # Process request
85
+ response = await call_next(request)
86
+
87
+ # After routing, update span name and route if available
88
+ if hasattr(request, 'scope') and 'path' in request.scope:
89
+ route = request.scope.get('path', request.url.path)
90
+ span.update_name(f"{request.method} {route}")
91
+ span.set_attribute("http.route", route)
92
+
93
+ # Set response attributes using new semantic conventions
94
+ span.set_attribute("http.response.status_code", response.status_code)
95
+ span.set_attribute("http.status_code", response.status_code) # Deprecated
96
+
97
+ # Set span status based on HTTP status code
98
+ if response.status_code >= 400:
99
+ span.set_status(Status(StatusCode.ERROR, f"HTTP {response.status_code}"))
100
+ else:
101
+ span.set_status(Status(StatusCode.OK))
102
+
103
+ # Log request completion
104
+ self.otel.logger.logger.info(f"Request completed: {response.status_code}",
105
+ extra={"http.status_code": response.status_code})
106
+ otel.force_flush(timeout_millis=100)
107
+ return response
108
+
109
+ except Exception as e:
110
+ # Record exception
111
+ span.record_exception(e)
112
+ span.set_status(Status(StatusCode.ERROR, str(e)))
113
+ span.add_event("exception", {
114
+ "exception.type": type(e).__name__,
115
+ "exception.message": str(e)
116
+ })
117
+
118
+ # Log error
119
+ self.otel.logger.logger.error(f"Unhandled exception: {e}",
120
+ exc_info=True,
121
+ extra={"exception.type": type(e).__name__})
122
+
123
+ raise
124
+
125
+ finally:
126
+ # Detach context
127
+ self.otel.detach_context(token)
128
+
129
+ # Add middleware to app
130
+ app.add_middleware(OTELMiddleware)
131
+
132
+ def fastapi_exception_handler(otel, request, exc):
133
+ """
134
+ Handle FastAPI exceptions and record them in the current span.
135
+ """
136
+
137
+ # Determine the status code
138
+ if isinstance(exc, HTTPException):
139
+ status_code = exc.status_code
140
+ error_detail = exc.detail
141
+ elif hasattr(exc, 'status_code'):
142
+ status_code = exc.status_code
143
+ error_detail = str(exc)
144
+ elif hasattr(exc, 'code'):
145
+ status_code = exc.code if isinstance(exc.code, int) else 500
146
+ error_detail = str(exc)
147
+ else:
148
+ status_code = 500
149
+ error_detail = str(exc)
150
+
151
+ # Record exception in span if available and still recording
152
+ if hasattr(request.state, 'span') and request.state.span.is_recording():
153
+ # Update both new and old attribute names for compatibility
154
+ request.state.span.set_attribute("http.response.status_code", status_code)
155
+ request.state.span.set_attribute("error.type", type(exc).__name__)
156
+
157
+ request.state.span.record_exception(exc)
158
+ request.state.span.set_status(Status(StatusCode.ERROR, str(exc)))
159
+ request.state.span.add_event("exception", {
160
+ "exception.type": type(exc).__name__,
161
+ "exception.message": str(exc)
162
+ })
163
+
164
+ # Log the error
165
+ otel.logger.logger.error(f"Unhandled exception: {exc} (status: {status_code})",
166
+ exc_info=True,
167
+ extra={
168
+ "exception.type": type(exc).__name__,
169
+ "http.status_code": status_code
170
+ })
171
+
172
+ # Return error response
173
+ return JSONResponse(
174
+ status_code=status_code,
175
+ content={
176
+ "error": error_detail,
177
+ "type": type(exc).__name__
178
+ }
179
+ )
180
+
181
+ # Optional: Dependency injection helper for accessing the span in routes
182
+ def get_current_span(request: Request):
183
+ """
184
+ FastAPI dependency to get the current span in route handlers.
185
+
186
+ Example:
187
+ from fastapi import Depends
188
+ from rebrandly_otel.fastapi_integration import get_current_span
189
+
190
+ @app.get("/example")
191
+ async def example(span = Depends(get_current_span)):
192
+ if span:
193
+ span.add_event("custom_event", {"key": "value"})
194
+ return {"status": "ok"}
195
+ """
196
+ if hasattr(request.state, 'span'):
197
+ return request.state.span
198
+ return None
@@ -1,15 +1,17 @@
1
1
  # flask_integration.py
2
2
  """Flask integration for Rebrandly OTEL SDK."""
3
- from typing import TYPE_CHECKING
4
- from opentelemetry.trace import Status, StatusCode, SpanKind
5
3
 
6
- if TYPE_CHECKING:
7
- from .rebrandly_otel import RebrandlyOTEL
4
+ import json
5
+ from rebrandly_otel import Status, StatusCode, SpanKind
8
6
 
9
- def setup_flask(otel: 'RebrandlyOTEL', app):
7
+ from flask import request, jsonify
8
+ from werkzeug.exceptions import HTTPException
9
+
10
+
11
+ def setup_flask(otel, app):
10
12
  """
11
13
  Setup Flask application with OTEL instrumentation.
12
-
14
+
13
15
  Example:
14
16
  from flask import Flask
15
17
  from rebrandly_otel import otel
@@ -23,31 +25,39 @@ def setup_flask(otel: 'RebrandlyOTEL', app):
23
25
  app.register_error_handler(Exception, lambda e: flask_error_handler(otel, e))
24
26
  return app
25
27
 
26
- def app_before_request(otel: 'RebrandlyOTEL'):
28
+ def app_before_request(otel):
27
29
  """
28
30
  Setup tracing for incoming Flask request.
29
31
  To be used with Flask's before_request hook.
30
32
  """
31
- from flask import request
32
33
 
33
34
  # Extract trace context from headers
34
35
  headers = dict(request.headers)
35
36
  token = otel.attach_context(headers)
36
37
  request.trace_token = token
37
38
 
39
+ # Determine span name - use route if available, otherwise just method
40
+ # Route will be available after request routing is done
41
+ span_name = f"{request.method} {request.path}"
42
+
38
43
  # Start span for request using start_as_current_span to make it the active span
39
44
  span = otel.tracer.tracer.start_as_current_span(
40
- f"{request.method} {request.path}",
45
+ span_name,
41
46
  attributes={
42
- "http.method": request.method,
43
- "http.url": request.url,
44
- "http.path": request.path,
45
- "http.scheme": request.scheme,
46
- "http.host": request.host,
47
- "http.user_agent": request.user_agent.string if request.user_agent else '',
48
- "http.remote_addr": request.remote_addr,
49
- "http.target": request.path,
50
- "span.kind": "server"
47
+ # Required HTTP attributes per semantic conventions
48
+ "http.request.method": request.method,
49
+ "http.request.headers": json.dumps(request.headers, default=str),
50
+ "http.response.status_code": None, # Will be set in after_request
51
+ "url.full": request.url,
52
+ "url.scheme": request.scheme,
53
+ "url.path": request.path,
54
+ "url.query": request.query_string.decode('utf-8') if request.query_string else None,
55
+ "user_agent.original": request.user_agent.string if request.user_agent else None,
56
+ "http.route": request.path, # Flask doesn't expose route pattern easily
57
+ "network.protocol.version": request.environ.get('SERVER_PROTOCOL', 'HTTP/1.1').split('/')[-1],
58
+ "server.address": request.host.split(':')[0],
59
+ "server.port": request.host.split(':')[1] if ':' in request.host else (443 if request.scheme == 'https' else 80),
60
+ "client.address": request.remote_addr,
51
61
  },
52
62
  kind=SpanKind.SERVER
53
63
  )
@@ -59,33 +69,22 @@ def app_before_request(otel: 'RebrandlyOTEL'):
59
69
  otel.logger.logger.info(f"Request started: {request.method} {request.path}",
60
70
  extra={"http.method": request.method, "http.path": request.path})
61
71
 
62
- def app_after_request(otel: 'RebrandlyOTEL', response):
72
+ def app_after_request(otel, response):
63
73
  """
64
74
  Cleanup tracing after Flask request completes.
65
75
  To be used with Flask's after_request hook.
66
76
  """
67
- from flask import request
68
77
 
69
78
  # Check if we have a span and it's still recording
70
79
  if hasattr(request, 'span') and request.span.is_recording():
71
- request.span.set_attribute("http.status_code", response.status_code)
80
+ # Update both new and old attribute names for compatibility
81
+ request.span.set_attribute("http.response.status_code", response.status_code)
72
82
 
73
83
  # Set span status based on HTTP status code
74
84
  if response.status_code >= 400:
75
85
  request.span.set_status(Status(StatusCode.ERROR, f"HTTP {response.status_code}"))
76
- # Record error metric
77
- otel.meter.GlobalMetrics.error_invocations.add(1, {
78
- "endpoint": request.path,
79
- "method": request.method,
80
- "status_code": response.status_code
81
- })
82
86
  else:
83
87
  request.span.set_status(Status(StatusCode.OK))
84
- # Record success metric
85
- otel.meter.GlobalMetrics.successful_invocations.add(1, {
86
- "endpoint": request.path,
87
- "method": request.method
88
- })
89
88
 
90
89
  # Properly close the span context manager
91
90
  if hasattr(request, 'span_context'):
@@ -102,21 +101,14 @@ def app_after_request(otel: 'RebrandlyOTEL', response):
102
101
  otel.logger.logger.info(f"Request completed: {response.status_code}",
103
102
  extra={"http.status_code": response.status_code})
104
103
 
105
- # Record general invocation metric
106
- otel.meter.GlobalMetrics.invocations.add(1, {
107
- "endpoint": request.path,
108
- "method": request.method
109
- })
110
-
104
+ otel.force_flush(timeout_millis=100)
111
105
  return response
112
106
 
113
- def flask_error_handler(otel: 'RebrandlyOTEL', exception):
107
+ def flask_error_handler(otel, exception):
114
108
  """
115
109
  Handle Flask exceptions and record them in the current span.
116
110
  To be used with Flask's errorhandler decorator.
117
111
  """
118
- from flask import request, jsonify
119
- from werkzeug.exceptions import HTTPException
120
112
 
121
113
  # Determine the status code
122
114
  if isinstance(exception, HTTPException):
@@ -130,15 +122,14 @@ def flask_error_handler(otel: 'RebrandlyOTEL', exception):
130
122
 
131
123
  # Record exception in span if available and still recording
132
124
  if hasattr(request, 'span') and request.span.is_recording():
133
- request.span.set_attribute("http.status_code", status_code)
125
+ request.span.set_attribute("http.response.status_code", status_code)
134
126
  request.span.set_attribute("error.type", type(exception).__name__)
135
127
 
136
128
  request.span.record_exception(exception)
137
129
  request.span.set_status(Status(StatusCode.ERROR, str(exception)))
138
130
  request.span.add_event("exception", {
139
131
  "exception.type": type(exception).__name__,
140
- "exception.message": str(exception),
141
- "http.status_code": status_code
132
+ "exception.message": str(exception)
142
133
  })
143
134
 
144
135
  # Only close the span if it's still recording (not already ended)
@@ -155,14 +146,6 @@ def flask_error_handler(otel: 'RebrandlyOTEL', exception):
155
146
  "http.status_code": status_code
156
147
  })
157
148
 
158
- # Record error metric with status code
159
- otel.meter.GlobalMetrics.error_invocations.add(1, {
160
- "endpoint": request.path if hasattr(request, 'path') else 'unknown',
161
- "method": request.method if hasattr(request, 'method') else 'unknown',
162
- "error": type(exception).__name__,
163
- "status_code": status_code
164
- })
165
-
166
149
  # Return error response with the determined status code
167
150
  return jsonify({
168
151
  "error": str(exception),
@@ -34,51 +34,24 @@ class RebrandlyMeter:
34
34
 
35
35
  # Standardized metric definitions aligned with Node.js
36
36
  DEFAULT_METRICS = {
37
- 'invocations': MetricDefinition(
38
- name='invocations',
39
- description='Number of invocations',
40
- unit='1',
41
- type=MetricType.COUNTER
42
- ),
43
- 'successful_invocations': MetricDefinition(
44
- name='successful_invocations',
45
- description='Number of successful invocations',
46
- unit='1',
47
- type=MetricType.COUNTER
48
- ),
49
- 'error_invocations': MetricDefinition(
50
- name='error_invocations',
51
- description='Number of error invocations',
52
- unit='1',
53
- type=MetricType.COUNTER
54
- ),
55
- 'duration': MetricDefinition(
56
- name='duration',
57
- description='Duration of execution in milliseconds',
58
- unit='ms',
59
- type=MetricType.HISTOGRAM
60
- ),
37
+ ## PROCESS
61
38
  'cpu_usage_percentage': MetricDefinition(
62
- name='cpu_usage_percentage',
63
- description='CPU usage percentage',
64
- unit='%',
39
+ name='process.cpu.utilization',
40
+ description='Difference in process.cpu.time since the last measurement, divided by the elapsed time and number of CPUs available to the process.',
41
+ unit='1',
65
42
  type=MetricType.GAUGE
66
43
  ),
67
44
  'memory_usage_bytes': MetricDefinition(
68
- name='memory_usage_bytes',
69
- description='Memory usage in bytes',
45
+ name='process.memory.used',
46
+ description='The amount of physical memory in use.',
70
47
  unit='By',
71
48
  type=MetricType.GAUGE
72
- ),
49
+ )
73
50
  }
74
51
 
75
52
  class GlobalMetrics:
76
53
  def __init__(self, rebrandly_meter):
77
54
  self.__rebrandly_meter = rebrandly_meter
78
- self.invocations: Counter = self.__rebrandly_meter.get_metric('invocations')
79
- self.successful_invocations: Counter = self.__rebrandly_meter.get_metric('successful_invocations')
80
- self.error_invocations: Counter = self.__rebrandly_meter.get_metric('error_invocations')
81
- self.duration: Histogram = self.__rebrandly_meter.get_metric('duration')
82
55
  self.cpu_usage_percentage: Gauge = self.__rebrandly_meter.get_metric('cpu_usage_percentage')
83
56
  self.memory_usage_bytes: Gauge = self.__rebrandly_meter.get_metric('memory_usage_bytes')
84
57
 
@@ -160,8 +160,6 @@ class RebrandlyOTEL:
160
160
 
161
161
  result = None
162
162
  try:
163
- # Increment invocation counter with standardized metric name
164
- self.meter.GlobalMetrics.invocations.add(1, {'function': span_name})
165
163
 
166
164
  # Create and execute within span
167
165
  with self.tracer.start_span(
@@ -204,17 +202,9 @@ class RebrandlyOTEL:
204
202
  complete_event_attrs['success'] = success
205
203
  span.add_event("lambda.invocation.complete", complete_event_attrs)
206
204
 
207
- # Increment success counter with standardized metric
208
- self.meter.GlobalMetrics.successful_invocations.add(1, {'function': span_name})
209
-
210
205
  return result
211
206
 
212
207
  except Exception as e:
213
- # Increment error counter with standardized metric
214
- self.meter.GlobalMetrics.error_invocations.add(1, {
215
- 'function': span_name,
216
- 'error': type(e).__name__
217
- })
218
208
 
219
209
  # Add failed completion event with error attribute (THIS IS THE KEY ADDITION)
220
210
  span.add_event("lambda.invocation.complete", {
@@ -236,13 +226,9 @@ class RebrandlyOTEL:
236
226
  from opentelemetry import context as otel_context
237
227
  otel_context.detach(token)
238
228
 
239
- # Record duration with standardized metric
240
- duration = (datetime.now() - start_time).total_seconds() * 1000
241
- self.meter.GlobalMetrics.duration.record(duration, {'function': span_name})
242
-
243
229
  # Force flush if enabled
244
230
  if auto_flush:
245
- self.logger.logger.info(f"[Rebrandly OTEL] Lambda '{span_name}' completed in {duration:.2f}ms, flushing...")
231
+ self.logger.logger.info(f"[Rebrandly OTEL] Lambda '{span_name}', flushing...")
246
232
  flush_success = self.force_flush(timeout_millis=1000)
247
233
  if not flush_success:
248
234
  self.logger.logger.warning("[Rebrandly OTEL] Force flush may not have completed fully")
@@ -272,9 +258,6 @@ class RebrandlyOTEL:
272
258
 
273
259
  result = None
274
260
  try:
275
- # Increment invocations counter with standardized metric
276
- self.meter.GlobalMetrics.invocations.add(1, {'handler': span_name})
277
-
278
261
  # Create span and execute function
279
262
  span_function = self.span
280
263
  if record is not None and ('MessageAttributes' in record or 'messageAttributes' in record):
@@ -318,18 +301,9 @@ class RebrandlyOTEL:
318
301
  complete_event_attrs['success'] = success
319
302
  span_context.add_event("message.processing.complete", complete_event_attrs)
320
303
 
321
- # Increment success counter with standardized metric
322
- self.meter.GlobalMetrics.successful_invocations.add(1, {'handler': span_name})
323
-
324
304
  return result
325
305
 
326
306
  except Exception as e:
327
- # Increment error counter with standardized metric
328
- self.meter.GlobalMetrics.error_invocations.add(1, {
329
- 'handler': span_name,
330
- 'error': type(e).__name__
331
- })
332
-
333
307
  # Record the exception in the span
334
308
  if 'span_context' in locals():
335
309
  span_context.record_exception(e)
@@ -345,10 +319,6 @@ class RebrandlyOTEL:
345
319
  raise
346
320
 
347
321
  finally:
348
- # Record duration with standardized metric
349
- duration = (datetime.now() - start_func).total_seconds() * 1000
350
- self.meter.GlobalMetrics.duration.record(duration, {'handler': span_name})
351
-
352
322
  if auto_flush:
353
323
  self.force_flush(start_datetime=start_func)
354
324
 
@@ -371,16 +341,14 @@ class RebrandlyOTEL:
371
341
 
372
342
  if start_datetime is not None:
373
343
  end_func = datetime.now()
374
- duration = (end_func - start_datetime).total_seconds() * 1000
375
344
  cpu_percent = psutil.cpu_percent(interval=0.1) # Shorter interval for Lambda
376
345
  memory = psutil.virtual_memory()
377
346
 
378
347
  # Record metrics using standardized names
379
- self.meter.GlobalMetrics.duration.record(duration, {'source': 'force_flush'})
380
348
  self.meter.GlobalMetrics.memory_usage_bytes.set(memory.used)
381
349
  self.meter.GlobalMetrics.cpu_usage_percentage.set(cpu_percent)
382
350
 
383
- print(f"Function duration: {duration}ms, Memory usage: {memory.percent}%, CPU usage: {cpu_percent}%")
351
+ print(f"Function Memory usage: {memory.percent}%, CPU usage: {cpu_percent}%")
384
352
 
385
353
  try:
386
354
  # Flush traces
File without changes