rebrandly-otel 0.1.35__tar.gz → 0.2.2__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.
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/PKG-INFO +1 -1
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/rebrandly_otel.egg-info/PKG-INFO +1 -1
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/rebrandly_otel.egg-info/SOURCES.txt +1 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/setup.py +1 -1
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/fastapi_support.py +5 -1
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/flask_support.py +5 -1
- rebrandly_otel-0.2.2/src/http_utils.py +28 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/otel_utils.py +36 -7
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/rebrandly_otel.py +13 -11
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/LICENSE +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/README.md +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/rebrandly_otel.egg-info/dependency_links.txt +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/rebrandly_otel.egg-info/requires.txt +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/rebrandly_otel.egg-info/top_level.txt +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/setup.cfg +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/__init__.py +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/logs.py +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/metrics.py +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/pymysql_instrumentation.py +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/src/traces.py +0 -0
- {rebrandly_otel-0.1.35 → rebrandly_otel-0.2.2}/tests/test_usage.py +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"""FastAPI integration for Rebrandly OTEL SDK."""
|
|
3
3
|
import json
|
|
4
4
|
from rebrandly_otel import Status, StatusCode, SpanKind
|
|
5
|
+
from .http_utils import filter_important_headers
|
|
5
6
|
from fastapi import HTTPException, Depends
|
|
6
7
|
from starlette.requests import Request
|
|
7
8
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
@@ -49,11 +50,14 @@ def add_otel_middleware(otel, app):
|
|
|
49
50
|
# Start span for request
|
|
50
51
|
span_name = f"{request.method} {request.url.path}"
|
|
51
52
|
|
|
53
|
+
# Filter headers to keep only important ones
|
|
54
|
+
filtered_headers = filter_important_headers(headers)
|
|
55
|
+
|
|
52
56
|
# Build attributes dict, excluding None values
|
|
53
57
|
attributes = {
|
|
54
58
|
# Required HTTP attributes per semantic conventions
|
|
55
59
|
"http.request.method": request.method,
|
|
56
|
-
"http.request.headers": json.dumps(
|
|
60
|
+
"http.request.headers": json.dumps(filtered_headers, default=str),
|
|
57
61
|
"url.full": str(request.url),
|
|
58
62
|
"url.scheme": request.url.scheme,
|
|
59
63
|
"url.path": request.url.path,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import json
|
|
5
5
|
from rebrandly_otel import Status, StatusCode, SpanKind
|
|
6
|
+
from .http_utils import filter_important_headers
|
|
6
7
|
|
|
7
8
|
from flask import request, jsonify
|
|
8
9
|
from werkzeug.exceptions import HTTPException
|
|
@@ -40,11 +41,14 @@ def app_before_request(otel):
|
|
|
40
41
|
# Route will be available after request routing is done
|
|
41
42
|
span_name = f"{request.method} {request.path}"
|
|
42
43
|
|
|
44
|
+
# Filter headers to keep only important ones
|
|
45
|
+
filtered_headers = filter_important_headers(headers)
|
|
46
|
+
|
|
43
47
|
# Build attributes dict, excluding None values
|
|
44
48
|
attributes = {
|
|
45
49
|
# Required HTTP attributes per semantic conventions
|
|
46
50
|
"http.request.method": request.method,
|
|
47
|
-
"http.request.headers": json.dumps(
|
|
51
|
+
"http.request.headers": json.dumps(filtered_headers, default=str),
|
|
48
52
|
"url.full": request.url,
|
|
49
53
|
"url.scheme": request.scheme,
|
|
50
54
|
"url.path": request.path,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# http_utils.py
|
|
2
|
+
"""Shared HTTP utilities for Rebrandly OTEL SDK."""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def filter_important_headers(headers):
|
|
6
|
+
"""
|
|
7
|
+
Filter headers to keep only important ones for observability.
|
|
8
|
+
Excludes sensitive headers like authorization, cookies, and tokens.
|
|
9
|
+
"""
|
|
10
|
+
important_headers = [
|
|
11
|
+
'content-type',
|
|
12
|
+
'content-length',
|
|
13
|
+
'accept',
|
|
14
|
+
'accept-encoding',
|
|
15
|
+
'accept-language',
|
|
16
|
+
'host',
|
|
17
|
+
'x-forwarded-for',
|
|
18
|
+
'x-forwarded-proto',
|
|
19
|
+
'x-request-id',
|
|
20
|
+
'x-correlation-id',
|
|
21
|
+
'x-trace-id'
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
filtered = {}
|
|
25
|
+
for key, value in headers.items():
|
|
26
|
+
if key.lower() in important_headers:
|
|
27
|
+
filtered[key] = value
|
|
28
|
+
return filtered
|
|
@@ -17,13 +17,27 @@ def create_resource(name: str = None, version: str = None) -> Resource:
|
|
|
17
17
|
if version is None:
|
|
18
18
|
version = get_service_version()
|
|
19
19
|
|
|
20
|
+
resources_attributes = {
|
|
21
|
+
service_attributes.SERVICE_NAME: name,
|
|
22
|
+
service_attributes.SERVICE_VERSION: version,
|
|
23
|
+
process_attributes.PROCESS_RUNTIME_VERSION: f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
|
24
|
+
SERVICE_NAMESPACE: os.environ.get('ENV', os.environ.get('ENVIRONMENT', os.environ.get('NODE_ENV', 'local')))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if os.environ.get('OTEL_RESOURCE_ATTRIBUTES', None) is not None and os.environ.get('OTEL_RESOURCE_ATTRIBUTES', None).strip() != "":
|
|
28
|
+
try:
|
|
29
|
+
ora = os.environ.get('OTEL_RESOURCE_ATTRIBUTES')
|
|
30
|
+
spl = ora.split(',')
|
|
31
|
+
for attr in spl:
|
|
32
|
+
attr = attr.strip()
|
|
33
|
+
if attr != "" and '=' in attr:
|
|
34
|
+
# Split on first '=' only, in case value contains '='
|
|
35
|
+
k, v = attr.split('=', 1)
|
|
36
|
+
resources_attributes[k.strip()] = v.strip()
|
|
37
|
+
except Exception as e:
|
|
38
|
+
print(f"[OTEL Utils] Warning: Invalid OTEL_RESOURCE_ATTRIBUTES value: {e}")
|
|
20
39
|
resource = Resource.create(
|
|
21
|
-
|
|
22
|
-
service_attributes.SERVICE_NAME: name,
|
|
23
|
-
service_attributes.SERVICE_VERSION: version,
|
|
24
|
-
process_attributes.PROCESS_RUNTIME_VERSION: f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
|
25
|
-
SERVICE_NAMESPACE: os.environ.get('ENV', os.environ.get('ENVIRONMENT', os.environ.get('NODE_ENV', 'local')))
|
|
26
|
-
}
|
|
40
|
+
resources_attributes
|
|
27
41
|
)
|
|
28
42
|
return resource
|
|
29
43
|
|
|
@@ -55,6 +69,17 @@ def get_service_version(service_version: str = None) -> str:
|
|
|
55
69
|
return service_version
|
|
56
70
|
|
|
57
71
|
|
|
72
|
+
def get_subsystem_name(subsystem_name: str = None) -> str:
|
|
73
|
+
"""
|
|
74
|
+
Get subsystem name for Coralogix.
|
|
75
|
+
Checks OTEL_SUBSYSTEM_NAME or CX_SUBSYSTEM_NAME environment variables.
|
|
76
|
+
Returns None if not set (subsystem is optional).
|
|
77
|
+
"""
|
|
78
|
+
if subsystem_name is None:
|
|
79
|
+
return os.environ.get('OTEL_SUBSYSTEM_NAME', os.environ.get('CX_SUBSYSTEM_NAME', None))
|
|
80
|
+
return subsystem_name
|
|
81
|
+
|
|
82
|
+
|
|
58
83
|
def get_otlp_endpoint(otlp_endpoint: str = None) -> str | None:
|
|
59
84
|
endpoint = otlp_endpoint or os.environ.get('OTEL_EXPORTER_OTLP_ENDPOINT', None)
|
|
60
85
|
|
|
@@ -80,8 +105,12 @@ def get_otlp_endpoint(otlp_endpoint: str = None) -> str | None:
|
|
|
80
105
|
finally:
|
|
81
106
|
channel.close()
|
|
82
107
|
|
|
108
|
+
except grpc.FutureTimeoutError:
|
|
109
|
+
print(f"[OTEL] Error: Connection timeout to OTLP endpoint {endpoint}. Check if the collector is running and accessible.")
|
|
110
|
+
return None
|
|
83
111
|
except Exception as e:
|
|
84
|
-
print(f"[OTEL] Failed to connect to OTLP endpoint {endpoint}: {e}")
|
|
112
|
+
print(f"[OTEL] Error: Failed to connect to OTLP endpoint {endpoint}: {type(e).__name__}: {e}")
|
|
113
|
+
print(f"[OTEL] Telemetry data will not be exported. Verify endpoint configuration and network connectivity.")
|
|
85
114
|
return None
|
|
86
115
|
return endpoint
|
|
87
116
|
|
|
@@ -160,6 +160,7 @@ class RebrandlyOTEL:
|
|
|
160
160
|
token = otel_context.attach(extracted_context)
|
|
161
161
|
|
|
162
162
|
result = None
|
|
163
|
+
span = None
|
|
163
164
|
try:
|
|
164
165
|
|
|
165
166
|
# Create and execute within span
|
|
@@ -207,18 +208,19 @@ class RebrandlyOTEL:
|
|
|
207
208
|
|
|
208
209
|
except Exception as e:
|
|
209
210
|
|
|
210
|
-
# Add failed completion event with error attribute (
|
|
211
|
-
span
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
# Add failed completion event with error attribute (only if span exists)
|
|
212
|
+
if span is not None and hasattr(span, 'is_recording') and span.is_recording():
|
|
213
|
+
span.add_event("lambda.invocation.complete", {
|
|
214
|
+
'success': False,
|
|
215
|
+
'error': type(e).__name__
|
|
216
|
+
})
|
|
215
217
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
218
|
+
# Record the exception in the span
|
|
219
|
+
span.record_exception(e)
|
|
220
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
|
219
221
|
|
|
220
222
|
# Log error
|
|
221
|
-
|
|
223
|
+
print(f"Lambda execution failed: {e}")
|
|
222
224
|
raise
|
|
223
225
|
|
|
224
226
|
finally:
|
|
@@ -229,10 +231,10 @@ class RebrandlyOTEL:
|
|
|
229
231
|
|
|
230
232
|
# Force flush if enabled
|
|
231
233
|
if auto_flush:
|
|
232
|
-
|
|
234
|
+
print(f"[Rebrandly OTEL] Lambda '{span_name}', flushing...")
|
|
233
235
|
flush_success = self.force_flush(timeout_millis=1000)
|
|
234
236
|
if not flush_success:
|
|
235
|
-
|
|
237
|
+
print("[Rebrandly OTEL] Force flush may not have completed fully")
|
|
236
238
|
|
|
237
239
|
return wrapper
|
|
238
240
|
return decorator
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|