rebrandly-otel 0.1.19__tar.gz → 0.1.22__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.19 → rebrandly_otel-0.1.22}/PKG-INFO +47 -1
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/README.md +46 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/rebrandly_otel.egg-info/PKG-INFO +47 -1
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/rebrandly_otel.egg-info/SOURCES.txt +1 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/setup.py +1 -1
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/__init__.py +4 -1
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/metrics.py +1 -1
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/otel_utils.py +22 -2
- rebrandly_otel-0.1.22/src/pymysql_instrumentation.py +206 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/rebrandly_otel.py +8 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/LICENSE +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/rebrandly_otel.egg-info/dependency_links.txt +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/rebrandly_otel.egg-info/top_level.txt +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/setup.cfg +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/fastapi_support.py +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/flask_support.py +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/logs.py +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/src/traces.py +0 -0
- {rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/tests/test_usage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rebrandly_otel
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.22
|
|
4
4
|
Summary: Python OTEL wrapper by Rebrandly
|
|
5
5
|
Home-page: https://github.com/rebrandly/rebrandly-otel-python
|
|
6
6
|
Author: Antonio Romano
|
|
@@ -447,6 +447,52 @@ if __name__ == "__main__":
|
|
|
447
447
|
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
448
448
|
```
|
|
449
449
|
|
|
450
|
+
### PyMySQL Database Instrumentation
|
|
451
|
+
|
|
452
|
+
The SDK provides connection-level instrumentation for PyMySQL that automatically traces all queries without requiring you to instrument each query individually.
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
import pymysql
|
|
456
|
+
from rebrandly_otel import otel, logger, instrument_pymysql
|
|
457
|
+
|
|
458
|
+
# Initialize OTEL
|
|
459
|
+
otel.initialize()
|
|
460
|
+
|
|
461
|
+
# Create and instrument your connection
|
|
462
|
+
connection = pymysql.connect(
|
|
463
|
+
host='localhost',
|
|
464
|
+
user='your_user',
|
|
465
|
+
password='your_password',
|
|
466
|
+
database='your_database'
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
# Instrument the connection - all queries are now automatically traced
|
|
470
|
+
connection = instrument_pymysql(otel, connection, options={
|
|
471
|
+
'slow_query_threshold_ms': 1000, # Queries over 1s flagged as slow
|
|
472
|
+
'capture_bindings': False # Set True to capture query parameters
|
|
473
|
+
})
|
|
474
|
+
|
|
475
|
+
# Use normally - all queries automatically traced
|
|
476
|
+
with connection.cursor() as cursor:
|
|
477
|
+
cursor.execute("SELECT * FROM users WHERE id = %s", (123,))
|
|
478
|
+
result = cursor.fetchone()
|
|
479
|
+
logger.info(f"Found user: {result}")
|
|
480
|
+
|
|
481
|
+
connection.close()
|
|
482
|
+
otel.force_flush()
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Features:
|
|
486
|
+
- Automatic span creation for all queries
|
|
487
|
+
- Query operation detection (SELECT, INSERT, UPDATE, etc.)
|
|
488
|
+
- Slow query detection and flagging
|
|
489
|
+
- Duration tracking
|
|
490
|
+
- Error recording with exception details
|
|
491
|
+
- Optional query parameter capture (disabled by default for security)
|
|
492
|
+
|
|
493
|
+
Environment configuration:
|
|
494
|
+
- `PYMYSQL_SLOW_QUERY_THRESHOLD_MS`: Threshold for slow query detection (default: 1500ms)
|
|
495
|
+
|
|
450
496
|
### More examples
|
|
451
497
|
You can find More examples [here](examples)
|
|
452
498
|
|
|
@@ -426,6 +426,52 @@ if __name__ == "__main__":
|
|
|
426
426
|
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
427
427
|
```
|
|
428
428
|
|
|
429
|
+
### PyMySQL Database Instrumentation
|
|
430
|
+
|
|
431
|
+
The SDK provides connection-level instrumentation for PyMySQL that automatically traces all queries without requiring you to instrument each query individually.
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
import pymysql
|
|
435
|
+
from rebrandly_otel import otel, logger, instrument_pymysql
|
|
436
|
+
|
|
437
|
+
# Initialize OTEL
|
|
438
|
+
otel.initialize()
|
|
439
|
+
|
|
440
|
+
# Create and instrument your connection
|
|
441
|
+
connection = pymysql.connect(
|
|
442
|
+
host='localhost',
|
|
443
|
+
user='your_user',
|
|
444
|
+
password='your_password',
|
|
445
|
+
database='your_database'
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
# Instrument the connection - all queries are now automatically traced
|
|
449
|
+
connection = instrument_pymysql(otel, connection, options={
|
|
450
|
+
'slow_query_threshold_ms': 1000, # Queries over 1s flagged as slow
|
|
451
|
+
'capture_bindings': False # Set True to capture query parameters
|
|
452
|
+
})
|
|
453
|
+
|
|
454
|
+
# Use normally - all queries automatically traced
|
|
455
|
+
with connection.cursor() as cursor:
|
|
456
|
+
cursor.execute("SELECT * FROM users WHERE id = %s", (123,))
|
|
457
|
+
result = cursor.fetchone()
|
|
458
|
+
logger.info(f"Found user: {result}")
|
|
459
|
+
|
|
460
|
+
connection.close()
|
|
461
|
+
otel.force_flush()
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Features:
|
|
465
|
+
- Automatic span creation for all queries
|
|
466
|
+
- Query operation detection (SELECT, INSERT, UPDATE, etc.)
|
|
467
|
+
- Slow query detection and flagging
|
|
468
|
+
- Duration tracking
|
|
469
|
+
- Error recording with exception details
|
|
470
|
+
- Optional query parameter capture (disabled by default for security)
|
|
471
|
+
|
|
472
|
+
Environment configuration:
|
|
473
|
+
- `PYMYSQL_SLOW_QUERY_THRESHOLD_MS`: Threshold for slow query detection (default: 1500ms)
|
|
474
|
+
|
|
429
475
|
### More examples
|
|
430
476
|
You can find More examples [here](examples)
|
|
431
477
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rebrandly_otel
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.22
|
|
4
4
|
Summary: Python OTEL wrapper by Rebrandly
|
|
5
5
|
Home-page: https://github.com/rebrandly/rebrandly-otel-python
|
|
6
6
|
Author: Antonio Romano
|
|
@@ -447,6 +447,52 @@ if __name__ == "__main__":
|
|
|
447
447
|
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
448
448
|
```
|
|
449
449
|
|
|
450
|
+
### PyMySQL Database Instrumentation
|
|
451
|
+
|
|
452
|
+
The SDK provides connection-level instrumentation for PyMySQL that automatically traces all queries without requiring you to instrument each query individually.
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
import pymysql
|
|
456
|
+
from rebrandly_otel import otel, logger, instrument_pymysql
|
|
457
|
+
|
|
458
|
+
# Initialize OTEL
|
|
459
|
+
otel.initialize()
|
|
460
|
+
|
|
461
|
+
# Create and instrument your connection
|
|
462
|
+
connection = pymysql.connect(
|
|
463
|
+
host='localhost',
|
|
464
|
+
user='your_user',
|
|
465
|
+
password='your_password',
|
|
466
|
+
database='your_database'
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
# Instrument the connection - all queries are now automatically traced
|
|
470
|
+
connection = instrument_pymysql(otel, connection, options={
|
|
471
|
+
'slow_query_threshold_ms': 1000, # Queries over 1s flagged as slow
|
|
472
|
+
'capture_bindings': False # Set True to capture query parameters
|
|
473
|
+
})
|
|
474
|
+
|
|
475
|
+
# Use normally - all queries automatically traced
|
|
476
|
+
with connection.cursor() as cursor:
|
|
477
|
+
cursor.execute("SELECT * FROM users WHERE id = %s", (123,))
|
|
478
|
+
result = cursor.fetchone()
|
|
479
|
+
logger.info(f"Found user: {result}")
|
|
480
|
+
|
|
481
|
+
connection.close()
|
|
482
|
+
otel.force_flush()
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Features:
|
|
486
|
+
- Automatic span creation for all queries
|
|
487
|
+
- Query operation detection (SELECT, INSERT, UPDATE, etc.)
|
|
488
|
+
- Slow query detection and flagging
|
|
489
|
+
- Duration tracking
|
|
490
|
+
- Error recording with exception details
|
|
491
|
+
- Optional query parameter capture (disabled by default for security)
|
|
492
|
+
|
|
493
|
+
Environment configuration:
|
|
494
|
+
- `PYMYSQL_SLOW_QUERY_THRESHOLD_MS`: Threshold for slow query detection (default: 1500ms)
|
|
495
|
+
|
|
450
496
|
### More examples
|
|
451
497
|
You can find More examples [here](examples)
|
|
452
498
|
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
from .rebrandly_otel import *
|
|
3
3
|
from .flask_support import setup_flask
|
|
4
4
|
from .fastapi_support import setup_fastapi
|
|
5
|
+
from .pymysql_instrumentation import instrument_pymysql
|
|
5
6
|
|
|
6
7
|
# Explicitly define what's available
|
|
7
8
|
__all__ = [
|
|
9
|
+
'otel',
|
|
8
10
|
'lambda_handler',
|
|
9
11
|
'span',
|
|
10
12
|
'aws_message_span',
|
|
@@ -16,5 +18,6 @@ __all__ = [
|
|
|
16
18
|
'aws_message_handler',
|
|
17
19
|
'shutdown',
|
|
18
20
|
'setup_flask',
|
|
19
|
-
'setup_fastapi'
|
|
21
|
+
'setup_fastapi',
|
|
22
|
+
'instrument_pymysql'
|
|
20
23
|
]
|
|
@@ -111,7 +111,7 @@ class RebrandlyMeter:
|
|
|
111
111
|
histogram_view = View(
|
|
112
112
|
instrument_type=Histogram,
|
|
113
113
|
instrument_name="*",
|
|
114
|
-
aggregation=ExplicitBucketHistogramAggregation((0.
|
|
114
|
+
aggregation=ExplicitBucketHistogramAggregation((0.001, 0.004, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5)) # todo <-- define buckets
|
|
115
115
|
)
|
|
116
116
|
views.append(histogram_view)
|
|
117
117
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
6
|
import grpc
|
|
7
|
+
import json
|
|
7
8
|
|
|
8
9
|
from opentelemetry.sdk.resources import Resource
|
|
9
10
|
from opentelemetry.semconv.attributes import service_attributes
|
|
@@ -21,7 +22,7 @@ def create_resource(name: str = None, version: str = None) -> Resource:
|
|
|
21
22
|
service_attributes.SERVICE_NAME: name,
|
|
22
23
|
service_attributes.SERVICE_VERSION: version,
|
|
23
24
|
process_attributes.PROCESS_RUNTIME_VERSION: f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
|
24
|
-
deployment_attributes.
|
|
25
|
+
deployment_attributes.DEPLOYMENT_ENVIRONMENT_NAME: os.environ.get('ENV', os.environ.get('ENVIRONMENT', os.environ.get('NODE_ENV', 'local')))
|
|
25
26
|
}
|
|
26
27
|
)
|
|
27
28
|
return resource
|
|
@@ -86,4 +87,23 @@ def get_millis_batch_time():
|
|
|
86
87
|
return int(os.environ.get('BATCH_EXPORT_TIME_MILLIS', 100))
|
|
87
88
|
except Exception as e:
|
|
88
89
|
print(f"[OTEL Utils] Warning: Invalid BATCH_EXPORT_TIME_MILLIS value, using default 5000ms: {e}")
|
|
89
|
-
return 5000
|
|
90
|
+
return 5000
|
|
91
|
+
|
|
92
|
+
def extract_event_from(message) -> str | None:
|
|
93
|
+
body = None
|
|
94
|
+
if 'body' in message:
|
|
95
|
+
body = message['body']
|
|
96
|
+
if 'Body' in message:
|
|
97
|
+
body = message['Body']
|
|
98
|
+
if 'Message' in message:
|
|
99
|
+
body = message['Message']
|
|
100
|
+
if 'Sns' in message and 'Message' in message['Sns']:
|
|
101
|
+
body = message['Sns']['Message']
|
|
102
|
+
if body is not None:
|
|
103
|
+
try:
|
|
104
|
+
jbody = json.loads(body)
|
|
105
|
+
if 'event' in jbody:
|
|
106
|
+
return jbody['event']
|
|
107
|
+
except:
|
|
108
|
+
pass
|
|
109
|
+
return None
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PyMySQL instrumentation for Rebrandly OTEL SDK
|
|
3
|
+
Provides query tracing and slow query detection
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import time
|
|
8
|
+
import functools
|
|
9
|
+
from opentelemetry.trace import Status, StatusCode, SpanKind
|
|
10
|
+
|
|
11
|
+
# Environment configuration
|
|
12
|
+
SLOW_QUERY_THRESHOLD_MS = int(os.getenv('PYMYSQL_SLOW_QUERY_THRESHOLD_MS', '1500'))
|
|
13
|
+
MAX_QUERY_LENGTH = 2000 # Truncate long queries
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def instrument_pymysql(otel_instance, connection, options=None):
|
|
17
|
+
"""
|
|
18
|
+
Instrument a PyMySQL connection for OpenTelemetry tracing
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
otel_instance: The RebrandlyOTEL instance
|
|
22
|
+
connection: The PyMySQL connection to instrument
|
|
23
|
+
options: Configuration options dict with:
|
|
24
|
+
- slow_query_threshold_ms: Threshold for slow query detection (default: 1500ms)
|
|
25
|
+
- capture_bindings: Include query bindings in spans (default: False for security)
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
The instrumented connection
|
|
29
|
+
"""
|
|
30
|
+
if options is None:
|
|
31
|
+
options = {}
|
|
32
|
+
|
|
33
|
+
slow_query_threshold_ms = options.get('slow_query_threshold_ms', SLOW_QUERY_THRESHOLD_MS)
|
|
34
|
+
capture_bindings = options.get('capture_bindings', False)
|
|
35
|
+
|
|
36
|
+
if not connection:
|
|
37
|
+
print('[Rebrandly OTEL PyMySQL] No connection provided for instrumentation')
|
|
38
|
+
return connection
|
|
39
|
+
|
|
40
|
+
if not otel_instance or not hasattr(otel_instance, 'tracer'):
|
|
41
|
+
print('[Rebrandly OTEL PyMySQL] No valid OTEL instance provided for instrumentation')
|
|
42
|
+
return connection
|
|
43
|
+
|
|
44
|
+
# Get tracer from RebrandlyOTEL instance
|
|
45
|
+
tracer = otel_instance.tracer
|
|
46
|
+
|
|
47
|
+
# Wrap the cursor method to return instrumented cursors
|
|
48
|
+
original_cursor = connection.cursor
|
|
49
|
+
|
|
50
|
+
def instrumented_cursor(*args, **kwargs):
|
|
51
|
+
cursor = original_cursor(*args, **kwargs)
|
|
52
|
+
return _instrument_cursor(cursor, tracer, slow_query_threshold_ms, capture_bindings)
|
|
53
|
+
|
|
54
|
+
connection.cursor = instrumented_cursor
|
|
55
|
+
|
|
56
|
+
return connection
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _instrument_cursor(cursor, tracer, slow_query_threshold_ms, capture_bindings):
|
|
60
|
+
"""
|
|
61
|
+
Instrument a cursor's execute methods
|
|
62
|
+
"""
|
|
63
|
+
original_execute = cursor.execute
|
|
64
|
+
original_executemany = cursor.executemany
|
|
65
|
+
|
|
66
|
+
@functools.wraps(original_execute)
|
|
67
|
+
def instrumented_execute(query, args=None):
|
|
68
|
+
return _trace_query(
|
|
69
|
+
original_execute,
|
|
70
|
+
tracer,
|
|
71
|
+
slow_query_threshold_ms,
|
|
72
|
+
capture_bindings,
|
|
73
|
+
query,
|
|
74
|
+
args,
|
|
75
|
+
many=False
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@functools.wraps(original_executemany)
|
|
79
|
+
def instrumented_executemany(query, args):
|
|
80
|
+
return _trace_query(
|
|
81
|
+
original_executemany,
|
|
82
|
+
tracer,
|
|
83
|
+
slow_query_threshold_ms,
|
|
84
|
+
capture_bindings,
|
|
85
|
+
query,
|
|
86
|
+
args,
|
|
87
|
+
many=True
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
cursor.execute = instrumented_execute
|
|
91
|
+
cursor.executemany = instrumented_executemany
|
|
92
|
+
|
|
93
|
+
return cursor
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _trace_query(func, tracer, slow_query_threshold_ms, capture_bindings, query, args, many=False):
|
|
97
|
+
"""
|
|
98
|
+
Trace a query execution with OpenTelemetry
|
|
99
|
+
"""
|
|
100
|
+
operation = _extract_operation(query)
|
|
101
|
+
truncated_query = _truncate_query(query)
|
|
102
|
+
|
|
103
|
+
# Start span
|
|
104
|
+
span_name = f"pymysql.{'executemany' if many else 'execute'}"
|
|
105
|
+
|
|
106
|
+
with tracer.start_span(
|
|
107
|
+
name=span_name,
|
|
108
|
+
kind=SpanKind.CLIENT
|
|
109
|
+
) as span:
|
|
110
|
+
# Set database attributes
|
|
111
|
+
span.set_attribute('db.system', 'mysql')
|
|
112
|
+
span.set_attribute('db.operation.name', operation)
|
|
113
|
+
span.set_attribute('db.statement', truncated_query)
|
|
114
|
+
|
|
115
|
+
# Add bindings if enabled (be cautious with sensitive data)
|
|
116
|
+
if capture_bindings and args:
|
|
117
|
+
if many:
|
|
118
|
+
span.set_attribute('db.bindings_count', len(args))
|
|
119
|
+
else:
|
|
120
|
+
span.set_attribute('db.bindings', str(args))
|
|
121
|
+
|
|
122
|
+
start_time = time.time()
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
# Execute the query
|
|
126
|
+
result = func(query, args)
|
|
127
|
+
|
|
128
|
+
# Calculate duration
|
|
129
|
+
duration_ms = (time.time() - start_time) * 1000
|
|
130
|
+
span.set_attribute('db.duration_ms', duration_ms)
|
|
131
|
+
|
|
132
|
+
# Check for slow query
|
|
133
|
+
if duration_ms >= slow_query_threshold_ms:
|
|
134
|
+
span.set_attribute('db.slow_query', True)
|
|
135
|
+
span.add_event('slow_query_detected', {
|
|
136
|
+
'db.duration_ms': duration_ms,
|
|
137
|
+
'db.threshold_ms': slow_query_threshold_ms
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
# Set success status
|
|
141
|
+
span.set_status(Status(StatusCode.OK))
|
|
142
|
+
|
|
143
|
+
return result
|
|
144
|
+
|
|
145
|
+
except Exception as error:
|
|
146
|
+
# Calculate duration even on error
|
|
147
|
+
duration_ms = (time.time() - start_time) * 1000
|
|
148
|
+
span.set_attribute('db.duration_ms', duration_ms)
|
|
149
|
+
|
|
150
|
+
# Record exception
|
|
151
|
+
span.record_exception(error)
|
|
152
|
+
span.set_status(Status(StatusCode.ERROR, str(error)))
|
|
153
|
+
|
|
154
|
+
raise
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _extract_operation(sql):
|
|
158
|
+
"""
|
|
159
|
+
Extract operation type from SQL statement
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
sql: SQL query string
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Operation type (SELECT, INSERT, UPDATE, etc.)
|
|
166
|
+
"""
|
|
167
|
+
if not sql:
|
|
168
|
+
return 'unknown'
|
|
169
|
+
|
|
170
|
+
normalized = sql.strip().upper()
|
|
171
|
+
|
|
172
|
+
if normalized.startswith('SELECT'):
|
|
173
|
+
return 'SELECT'
|
|
174
|
+
if normalized.startswith('INSERT'):
|
|
175
|
+
return 'INSERT'
|
|
176
|
+
if normalized.startswith('UPDATE'):
|
|
177
|
+
return 'UPDATE'
|
|
178
|
+
if normalized.startswith('DELETE'):
|
|
179
|
+
return 'DELETE'
|
|
180
|
+
if normalized.startswith('CREATE'):
|
|
181
|
+
return 'CREATE'
|
|
182
|
+
if normalized.startswith('DROP'):
|
|
183
|
+
return 'DROP'
|
|
184
|
+
if normalized.startswith('ALTER'):
|
|
185
|
+
return 'ALTER'
|
|
186
|
+
if normalized.startswith('TRUNCATE'):
|
|
187
|
+
return 'TRUNCATE'
|
|
188
|
+
|
|
189
|
+
return 'unknown'
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _truncate_query(sql):
|
|
193
|
+
"""
|
|
194
|
+
Truncate long queries for span attributes
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
sql: SQL query string
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Truncated query
|
|
201
|
+
"""
|
|
202
|
+
if not sql:
|
|
203
|
+
return ''
|
|
204
|
+
if len(sql) <= MAX_QUERY_LENGTH:
|
|
205
|
+
return sql
|
|
206
|
+
return sql[:MAX_QUERY_LENGTH] + '... [truncated]'
|
|
@@ -12,6 +12,7 @@ from opentelemetry import baggage, propagate, context
|
|
|
12
12
|
from .traces import RebrandlyTracer
|
|
13
13
|
from .metrics import RebrandlyMeter
|
|
14
14
|
from .logs import RebrandlyLogger
|
|
15
|
+
from .otel_utils import extract_event_from
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
T = TypeVar('T')
|
|
@@ -262,6 +263,9 @@ class RebrandlyOTEL:
|
|
|
262
263
|
span_function = self.span
|
|
263
264
|
if record is not None and (('MessageAttributes' in record or 'messageAttributes' in record) or ('Sns' in record and 'MessageAttributes' in record['Sns'])):
|
|
264
265
|
span_function = self.aws_message_span
|
|
266
|
+
evt = extract_event_from(record)
|
|
267
|
+
if evt:
|
|
268
|
+
span_attributes['event.type'] = evt
|
|
265
269
|
|
|
266
270
|
with span_function(span_name, message=record, attributes=span_attributes, kind=kind) as span_context:
|
|
267
271
|
# Add processing start event with standardized name
|
|
@@ -487,6 +491,10 @@ class RebrandlyOTEL:
|
|
|
487
491
|
if 'awsRegion' in message:
|
|
488
492
|
combined_attributes['cloud.region'] = message['awsRegion']
|
|
489
493
|
|
|
494
|
+
evt = extract_event_from(message)
|
|
495
|
+
if evt:
|
|
496
|
+
combined_attributes['event.type'] = evt
|
|
497
|
+
|
|
490
498
|
|
|
491
499
|
# Use the tracer's start_span method directly to ensure it works
|
|
492
500
|
# This creates a child span of whatever is currently active
|
|
File without changes
|
{rebrandly_otel-0.1.19 → rebrandly_otel-0.1.22}/rebrandly_otel.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|