8000 BUG#35733608: Server stmt spans right after the cnx aren't related to… · mysql/mysql-connector-python@5b38aa8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5b38aa8

Browse files
committed
BUG#35733608: Server stmt spans right after the cnx aren't related to the connector's cnx span
Server statement spans immediately after the connection aren't related to the connector's connection span. When connecting to a MySQL server via connector-python, and executing operations, where OpenTelemetry is enabled on both sides, the server-side statement spans generated during the connector's connection span aren't related to it. With this patch, all spans generated on the server side at connection time get related to the connector's connection span. Change-Id: I817b8b8d8c8bfa172ee234b258d3da0d3079cdbf
1 parent 949f37f commit 5b38aa8

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ v8.2.0
1515
- WL#15623: Improve the authentication module
1616
- WL#15218: Support WebAuthn authentication
1717
- BUG#35755852: Django config raise_on_warnings is ignored without isolation_level
18+
- BUG#35733608: Server stmt spans right after the cnx aren't related to the connector's cnx span
1819
- BUG#35547876: C/Python 8.1.0 type check build fails in the pb2 branch
1920
- BUG#35544123: Kerberos unit tests configuration is outdated
2021
- BUG#35503506: Query on information_schema.columns returns bytes

lib/mysql/connector/opentelemetry/instrumentation.py

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import re
99

1010
from abc import ABC, abstractmethod
11+
from contextlib import nullcontext
1112
from typing import TYPE_CHECKING, Any, Callable, Collection, Dict, Optional, Union
1213

1314
# pylint: disable=cyclic-import
@@ -187,7 +188,22 @@ def set_connection_span_attrs(
187188
cnx_span.set_attributes(attrs)
188189

189190

190-
def instrument_execution(
191+
def with_connection_span_attached(method: Callable) -> Callable:
192+
"""Attach the connection span while executing a connection method."""
193+
194+
def wrapper(
195+
cnx: Union["MySQLConnection", "CMySQLConnection"], *args: Any, **kwargs: Any
196+
) -> Any:
197+
"""Context propagation decorator."""
198+
with trace.use_span(
199+
cnx._span, end_on_exit=False
200+
) if cnx._span and cnx._span.is_recording() else nullcontext():
201+
return method(cnx, *args, **kwargs)
202+
203+
return wrapper
204+
205+
206+
def _instrument_execution(
191207
query_method: Callable,
192208
tracer: trace.Tracer,
193209
connection_span_link: trace.Link,
@@ -288,7 +304,7 @@ def __init__(
288304

289305
def execute(self, *args: Any, **kwargs: Any) -> Any:
290306
"""Instruments execute method."""
291-
return instrument_execution(
307+
return _instrument_execution(
292308
self._wrapped.execute,
293309
self._tracer,
294310
self._connection_span_link,
@@ -299,7 +315,7 @@ def execute(self, *args: Any, **kwargs: Any) -> Any:
299315

300316
def executemany(self, *args: Any, **kwargs: Any) -> Any:
301317
"""Instruments executemany method."""
302-
return instrument_execution(
318+
return _instrument_execution(
303319
self._wrapped.executemany,
304320
self._tracer,
305321
self._connection_span_link,
@@ -310,7 +326,7 @@ def executemany(self, *args: Any, **kwargs: Any) -> Any:
310326

311327
def callproc(self, *args: Any, **kwargs: Any) -> Any:
312328
"""Instruments callproc method."""
313-
return instrument_execution(
329+
return _instrument_execution(
314330
self._wrapped.callproc,
315331
self._tracer,
316332
self._connection_span_link,
@@ -332,15 +348,20 @@ def __init__(self, wrapped: Union["MySQLConnection", "CMySQLConnection"]) -> Non
332348
_ = self._wrapped.sql_mode
333349

334350
def cursor(self, *args: Any, **kwargs: Any) -> TracedMySQLCursor:
335-
"""Wraps the cursor object."""
351+
"""Wraps the object method."""
336352
return TracedMySQLCursor(
337353
wrapped=self._wrapped.cursor(*args, **kwargs),
338354
tracer=self._tracer,
339355
connection_span=self._span,
340356
)
341357

358+
@with_connection_span_attached
359+
def cmd_change_user(self, *args: Any, **kwargs: Any) -> Any:
360+
"""Wraps the object method."""
361+
return self._wrapped.cmd_change_user(*args, **kwargs)
362+
342363

343-
def instrument_connect(
364+
def _instrument_connect(
344365
connect: Callable[
345366
..., Union["MySQLConnection", "CMySQLConnection", "PooledMySQLConnection"]
346367
],
@@ -376,19 +397,21 @@ def wrapper(
376397
)
377398
kwargs[OPTION_CNX_TRACER] = tracer
378399

379-
# Add basic net information.
380-
set_connection_span_attrs(None, kwargs[OPTION_CNX_SPAN], kwargs)
400+
# attach connection span
401+
with trace.use_span(kwargs[OPTION_CNX_SPAN], end_on_exit=False) as cnx_span:
402+
# Add basic net information.
403+
set_connection_span_attrs(None, cnx_span, kwargs)
381404

382-
# Connection may fail at this point, in case it does, basic net info is already
383-
# included so the user can check the net configuration she/he provided.
384-
cnx = connect(*args, **kwargs)
405+
# Connection may fail at this point, in case it does, basic net info is already
406+
# included so the user can check the net configuration she/he provided.
407+
cnx = connect(*args, **kwargs)
385408

386-
# connection went ok, let's refine the net information.
387-
set_connection_span_attrs(cnx, cnx._span, kwargs) # type: ignore[arg-type]
409+
# connection went ok, let's refine the net information.
410+
set_connection_span_attrs(cnx, cnx_span, kwargs) # type: ignore[arg-type]
388411

389-
return TracedMySQLConnection(
390-
wrapped=cnx, # type: ignore[return-value, arg-type]
391-
)
412+
return TracedMySQLConnection(
413+
wrapped=cnx, # type: ignore[return-value, arg-type]
414+
)
392415

393416
return wrapper
394417

@@ -427,7 +450,7 @@ def instrument(self, **kwargs: Any) -> None:
427450
if connector.connect != getattr(self, "_original_connect"):
428451
logger.warning("MySQL Connector/Python module already instrumented.")
429452
return
430-
connector.connect = instrument_connect(
453+
connector.connect = _instrument_connect(
431454
connect=getattr(self, "_original_connect"),
432455
tracer_provider=kwargs.get("tracer_provider"),
433456
)

0 commit comments

Comments
 (0)
0