45
45
46
46
from opentelemetry import trace as trace_api
47
47
from opentelemetry .instrumentation .dbapi .version import __version__
48
- from opentelemetry .instrumentation .utils import unwrap
48
+ from opentelemetry .instrumentation .utils import _generate_sql_comment , unwrap
49
49
from opentelemetry .semconv .trace import SpanAttributes
50
- from opentelemetry .trace import SpanKind , TracerProvider , get_tracer
50
+ from opentelemetry .trace import Span , SpanKind , TracerProvider , get_tracer
51
51
52
- logger = logging .getLogger (__name__ )
52
+ _logger = logging .getLogger (__name__ )
53
53
54
54
55
55
def trace_integration (
@@ -59,6 +59,7 @@ def trace_integration(
59
59
connection_attributes : typing .Dict = None ,
60
60
tracer_provider : typing .Optional [TracerProvider ] = None ,
61
61
capture_parameters : bool = False ,
62
+ enable_commenter : bool = False ,
62
63
db_api_integration_factory = None ,
63
64
):
64
65
"""Integrate with DB API library.
@@ -84,6 +85,7 @@ def trace_integration(
84
85
version = __version__ ,
85
86
tracer_provider = tracer_provider ,
86
87
capture_parameters = capture_parameters ,
88
+ enable_commenter = enable_commenter ,
87
89
db_api_integration_factory = db_api_integration_factory ,
88
90
)
89
91
@@ -97,6 +99,7 @@ def wrap_connect(
97
99
version : str = "" ,
98
100
tracer_provider : typing .Optional [TracerProvider ] = None ,
99
101
capture_parameters : bool = False ,
102
+ enable_commenter : bool = False ,
100
103
db_api_integration_factory = None ,
101
104
):
102
105
"""Integrate with DB API library.
@@ -132,6 +135,7 @@ def wrap_connect_(
132
135
version = version ,
133
136
tracer_provider = tracer_provider ,
134
137
capture_parameters = capture_parameters ,
138
+ enable_commenter = enable_commenter ,
135
139
)
136
140
return db_integration .wrapped_connection (wrapped , args , kwargs )
137
141
@@ -140,7 +144,7 @@ def wrap_connect_(
140
144
connect_module , connect_method_name , wrap_connect_
141
145
)
142
146
except Exception as ex : # pylint: disable=broad-except
143
- logger .warning ("Failed to integrate with DB API. %s" , str (ex ))
147
+ _logger .warning ("Failed to integrate with DB API. %s" , str (ex ))
144
148
145
149
146
150
def unwrap_connect (
@@ -163,7 +167,8 @@ def instrument_connection(
163
167
connection_attributes : typing .Dict = None ,
164
168
version : str = "" ,
165
169
tracer_provider : typing .Optional [TracerProvider ] = None ,
166
- capture_parameters = False ,
170
+ capture_parameters : bool = False ,
171
+ enable_commenter : bool = False ,
167
172
):
168
173
"""Enable instrumentation in a database connection.
169
174
@@ -180,7 +185,7 @@ def instrument_connection(
180
185
An instrumented connection.
181
186
"""
182
187
if isinstance (connection , wrapt .ObjectProxy ):
183
- logger .warning ("Connection already instrumented" )
188
+ _logger .warning ("Connection already instrumented" )
184
189
return connection
185
190
186
191
db_integration = DatabaseApiIntegration (
@@ -190,6 +195,7 @@ def instrument_connection(
190
195
version = version ,
191
196
tracer_provider = tracer_provider ,
192
197
capture_parameters = capture_parameters ,
198
+ enable_commenter = enable_commenter ,
193
199
)
194
200
db_integration .get_connection_attributes (connection )
195
201
return get_traced_connection_proxy (connection , db_integration )
@@ -207,7 +213,7 @@ def uninstrument_connection(connection):
207
213
if isinstance (connection , wrapt .ObjectProxy ):
208
214
return connection .__wrapped__
209
215
210
- logger .warning ("Connection is not instrumented" )
216
+ _logger .warning ("Connection is not instrumented" )
211
217
return connection
212
218
213
219
@@ -220,6 +226,7 @@ def __init__(
220
226
version : str = "" ,
221
227
tracer_provider : typing .Optional [TracerProvider ] = None ,
222
228
capture_parameters : bool = False ,
229
+ enable_commenter : bool = False ,
223
230
):
224
231
self .connection_attributes = connection_attributes
225
232
if self .connection_attributes is None :
@@ -237,6 +244,7 @@ def __init__(
237
244
tracer_provider = tracer_provider ,
238
245
)
239
246
self .capture_parameters = capture_parameters
247
+ self .enable_commenter = enable_commenter
240
248
self .database_system = database_system
241
249
self .connection_props = {}
242
250
self .span_attributes = {}
@@ -313,8 +321,9 @@ def __exit__(self, *args, **kwargs):
313
321
314
322
315
323
class CursorTracer :
316
- def __init__ (self , db_api_integration : DatabaseApiIntegration ):
324
+ def __init__ (self , db_api_integration : DatabaseApiIntegration ) -> None :
317
325
self ._db_api_integration = db_api_integration
326
+ self ._commenter_enabled = self ._db_api_integration .enable_commenter
318
327
319
328
def _populate_span (
320
329
self ,
@@ -355,6 +364,22 @@ def get_statement(self, cursor, args): # pylint: disable=no-self-use
355
364
return statement .decode ("utf8" , "replace" )
356
365
return statement
357
366
367
+ @staticmethod
368
+ def _generate_comment (span : Span ) -> str :
369
+ span_context = span .get_span_context ()
370
+ meta = {}
371
+ if span_context .is_valid :
372
+ meta .update (
373
+ {
374
+ "trace_id" : span_context .trace_id ,
375
+ "span_id" : span_context .span_id ,
376
+ "trace_flags" : span_context .trace_flags ,
377
+ "trace_state" : span_context .trace_state .to_header (),
378
+ }
379
+ )
380
+ # TODO(schekuri): revisit to enrich with info such as route, db_driver etc...
381
+ return _generate_sql_comment (** meta )
382
+
358
383
def traced_execution (
359
384
self ,
360
385
cursor ,
@@ -374,6 +399,18 @@ def traced_execution(
374
399
name , kind = SpanKind .CLIENT
375
400
) as span :
376
401
self ._populate_span (span , cursor , * args )
402
+ if args and self ._commenter_enabled :
403
+ try :
404
+ comment = self ._generate_comment (span )
405
+ if isinstance (args [0 ], bytes ):
406
+ comment = comment .encode ("utf8" )
407
+ args_list = list (args )
408
+ args_list [0 ] += comment
409
+ args = tuple (args_list )
410
+ except Exception as exc : # pylint: disable=broad-except
411
+ _logger .exception (
412
+ "Exception while generating sql comment: %s" , exc
413
+ )
377
414
return query_method (* args , ** kwargs )
378
415
379
416
0 commit comments