Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@
Warning:
Capture of sqlcomment in ``db.statement``/``db.query.text`` may have high cardinality without platform normalization. See `Semantic Conventions for database spans <https://opentelemetry.io/docs/specs/semconv/database/database-spans/#generating-a-summary-of-the-query-text>`_ for more information.

Capture Parameters
******************
You can optionally enable capture of query parameters in the
``db.statement.parameters`` span attribute.

.. code:: python

from opentelemetry.instrumentation.mysql import MySQLInstrumentor

MySQLInstrumentor().instrument(capture_parameters=True)

API
---
"""
Expand Down Expand Up @@ -171,6 +182,7 @@ def _instrument(self, **kwargs):
enable_attribute_commenter = kwargs.get(
"enable_attribute_commenter", False
)
capture_parameters = kwargs.get("capture_parameters", False)

dbapi.wrap_connect(
__name__,
Expand All @@ -183,6 +195,7 @@ def _instrument(self, **kwargs):
enable_commenter=enable_sqlcommenter,
commenter_options=commenter_options,
enable_attribute_commenter=enable_attribute_commenter,
capture_parameters=capture_parameters,
)

def _uninstrument(self, **kwargs):
Expand All @@ -197,6 +210,7 @@ def instrument_connection(
enable_commenter=None,
commenter_options=None,
enable_attribute_commenter=None,
capture_parameters=False,
):
"""Enable instrumentation in a MySQL connection.

Expand All @@ -214,6 +228,8 @@ def instrument_connection(
Optional configurations for tags to be appended at the sql query.
enable_attribute_commenter:
Optional flag to enable/disable addition of sqlcomment to span attribute (default False). Requires enable_commenter=True.
capture_parameters:
Optional flag to enable/disable capture of query parameters (default False).

Returns:
An instrumented MySQL connection with OpenTelemetry tracing enabled.
Expand All @@ -229,6 +245,7 @@ def instrument_connection(
commenter_options=commenter_options,
connect_module=mysql.connector,
enable_attribute_commenter=enable_attribute_commenter,
capture_parameters=capture_parameters,
)

def uninstrument_connection(self, connection):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,28 @@ def test_instrument_connection_enable_commenter_dbapi_kwargs(
enable_commenter=True,
commenter_options={"foo": True},
enable_attribute_commenter=True,
capture_parameters=True,
)
cursor = cnx.cursor()
cursor.execute("SELECT * FROM test")
kwargs = mock_instrument_connection.call_args[1]
self.assertEqual(kwargs["enable_commenter"], True)
self.assertEqual(kwargs["commenter_options"], {"foo": True})
self.assertEqual(kwargs["enable_attribute_commenter"], True)
self.assertEqual(kwargs["capture_parameters"], True)

@mock.patch("opentelemetry.instrumentation.dbapi.instrument_connection")
@mock.patch("mysql.connector")
# pylint: disable=unused-argument
def test_instrument_connection_defaults_capture_parameters_dbapi_kwargs(
self,
mock_connect,
mock_instrument_connection,
):
cnx = mysql.connector.connect(database="test")
MySQLInstrumentor().instrument_connection(cnx)
kwargs = mock_instrument_connection.call_args[1]
self.assertEqual(kwargs["capture_parameters"], False)

def test_instrument_connection_with_dbapi_sqlcomment_enabled(self):
mock_connect_module, mock_connection, mock_cursor = (
Expand Down Expand Up @@ -324,6 +339,26 @@ def test_instrument_connection_with_dbapi_sqlcomment_not_enabled_default(
"Select 1;",
)

def test_instrument_connection_with_capture_parameters(self):
mock_connect_module, mock_connection, _ = make_mysql_commenter_mocks()

with mock.patch(
"opentelemetry.instrumentation.mysql.mysql.connector",
mock_connect_module,
):
cnx_proxy = MySQLInstrumentor().instrument_connection(
mock_connection,
capture_parameters=True,
)
cnx_proxy.cursor().execute("Select %s;", ("param1Value", False))

spans_list = self.memory_exporter.get_finished_spans()
span = spans_list[0]
self.assertEqual(
span.attributes["db.statement.parameters"],
"('param1Value', False)",
)

@mock.patch("opentelemetry.instrumentation.dbapi.wrap_connect")
@mock.patch("mysql.connector")
# pylint: disable=unused-argument
Expand All @@ -336,11 +371,25 @@ def test_instrument_enable_commenter_dbapi_kwargs(
enable_commenter=True,
commenter_options={"foo": True},
enable_attribute_commenter=True,
capture_parameters=True,
)
kwargs = mock_wrap_connect.call_args[1]
self.assertEqual(kwargs["enable_commenter"], True)
self.assertEqual(kwargs["commenter_options"], {"foo": True})
self.assertEqual(kwargs["enable_attribute_commenter"], True)
self.assertEqual(kwargs["capture_parameters"], True)

@mock.patch("opentelemetry.instrumentation.dbapi.wrap_connect")
@mock.patch("mysql.connector")
# pylint: disable=unused-argument
def test_instrument_defaults_capture_parameters_dbapi_kwargs(
self,
mock_connect,
mock_wrap_connect,
):
MySQLInstrumentor().instrument()
kwargs = mock_wrap_connect.call_args[1]
self.assertEqual(kwargs["capture_parameters"], False)

def test_instrument_with_dbapi_sqlcomment_enabled(
self,
Expand Down Expand Up @@ -462,6 +511,25 @@ def test_instrument_with_dbapi_sqlcomment_not_enabled_default(
"Select 1;",
)

def test_instrument_with_capture_parameters(self):
mock_connect_module, _, _ = make_mysql_commenter_mocks()

with mock.patch(
"opentelemetry.instrumentation.mysql.mysql.connector",
mock_connect_module,
):
MySQLInstrumentor()._instrument(capture_parameters=True)
cnx = mock_connect_module.connect(database="test")
cursor = cnx.cursor()
cursor.execute("Select %s;", ("param1Value", False))

spans_list = self.memory_exporter.get_finished_spans()
span = spans_list[0]
self.assertEqual(
span.attributes["db.statement.parameters"],
"('param1Value', False)",
)

@mock.patch("mysql.connector.connect")
# pylint: disable=unused-argument
def test_uninstrument_connection(self, mock_connect):
Expand Down
Loading