diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a0faa56ae..0e01dbe8bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#4139](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4139)) ### Fixed - +- `opentelemetry-instrumentation-mysql`: Refactor MySQL integration test mocks to use concrete DBAPI connection attributes, reducing noisy attribute type warnings. + ([#4116](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4116)) - `opentelemetry-instrumentation-cassandra`: Use `_instruments_any` instead of `_instruments` for driver dependencies so that having either `cassandra-driver` or `scylla-driver` installed is sufficient ([#4182](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4182)) - `opentelemetry-instrumentation-asyncpg`: Hydrate span attributes before creation so samplers can filter on database details diff --git a/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py b/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py index f97e97692e..2b95c76058 100644 --- a/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py +++ b/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py @@ -35,6 +35,50 @@ def connect_and_execute_query(): return cnx, query +def make_mysql_connection_mock(): + cnx = mock.MagicMock() + cnx.database = "test" + cnx.server_host = "localhost" + cnx.server_port = 3306 + + cursor = mock.MagicMock() + cursor._cnx = cnx + + cnx.cursor.return_value = cursor + return cnx + + +def make_mysql_commenter_mocks(client_version="foobaz"): + """Create mock objects for MySQL connector with SQL commenter support. + + Args: + client_version: The MySQL client version string to return from get_client_info() + + Returns: + Tuple of (mock_connect_module, mock_connection, mock_cursor) + """ + mock_connect_module = mock.MagicMock( + __name__="mysql.connector", + __version__="foobar", + threadsafety="123", + apilevel="123", + paramstyle="test", + ) + mock_connection = mock.MagicMock() + mock_connection.database = "test" + mock_connection.server_host = "localhost" + mock_connection.server_port = 3306 + + mock_cursor = mock_connect_module.connect().cursor() + mock_cursor._cnx = mock_connection + mock_cursor._cnx._cmysql.get_client_info.return_value = client_version + + mock_connection.cursor.return_value = mock_cursor + mock_connect_module.connect.return_value = mock_connection + + return mock_connect_module, mock_connection, mock_cursor + + class TestMysqlIntegration(TestBase): def tearDown(self): super().tearDown() @@ -44,6 +88,7 @@ def tearDown(self): @mock.patch("mysql.connector.connect") # pylint: disable=unused-argument def test_instrumentor(self, mock_connect): + mock_connect.return_value = make_mysql_connection_mock() MySQLInstrumentor().instrument() connect_and_execute_query() @@ -68,6 +113,7 @@ def test_instrumentor(self, mock_connect): @mock.patch("mysql.connector.connect") # pylint: disable=unused-argument def test_custom_tracer_provider(self, mock_connect): + mock_connect.return_value = make_mysql_connection_mock() resource = resources.Resource.create({}) result = self.create_tracer_provider(resource=resource) tracer_provider, exporter = result @@ -84,6 +130,7 @@ def test_custom_tracer_provider(self, mock_connect): @mock.patch("mysql.connector.connect") # pylint: disable=unused-argument def test_instrument_connection(self, mock_connect): + mock_connect.return_value = make_mysql_connection_mock() cnx, query = connect_and_execute_query() spans_list = self.memory_exporter.get_finished_spans() @@ -98,6 +145,7 @@ def test_instrument_connection(self, mock_connect): @mock.patch("mysql.connector.connect") def test_instrument_connection_no_op_tracer_provider(self, mock_connect): + mock_connect.return_value = make_mysql_connection_mock() tracer_provider = trace_api.NoOpTracerProvider() MySQLInstrumentor().instrument(tracer_provider=tracer_provider) connect_and_execute_query() @@ -128,17 +176,9 @@ def test_instrument_connection_enable_commenter_dbapi_kwargs( self.assertEqual(kwargs["enable_attribute_commenter"], True) def test_instrument_connection_with_dbapi_sqlcomment_enabled(self): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", + mock_connect_module, mock_connection, mock_cursor = ( + make_mysql_commenter_mocks() ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -166,17 +206,9 @@ def test_instrument_connection_with_dbapi_sqlcomment_enabled(self): def test_instrument_connection_with_dbapi_sqlcomment_enabled_stmt_enabled( self, ): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", + mock_connect_module, mock_connection, mock_cursor = ( + make_mysql_commenter_mocks() ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -205,17 +237,9 @@ def test_instrument_connection_with_dbapi_sqlcomment_enabled_stmt_enabled( def test_instrument_connection_with_dbapi_sqlcomment_enabled_with_options( self, ): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", + mock_connect_module, mock_connection, mock_cursor = ( + make_mysql_commenter_mocks() ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -248,18 +272,9 @@ def test_instrument_connection_with_dbapi_sqlcomment_enabled_with_options( def test_instrument_connection_with_dbapi_sqlcomment_not_enabled_default( self, ): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", + mock_connect_module, mock_connection, mock_cursor = ( + make_mysql_commenter_mocks() ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_cursor = mock_connect_module.connect().cursor() - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -301,18 +316,7 @@ def test_instrument_enable_commenter_dbapi_kwargs( def test_instrument_with_dbapi_sqlcomment_enabled( self, ): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", - ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_cursor = mock_connect_module.connect().cursor() - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor + mock_connect_module, _, mock_cursor = make_mysql_commenter_mocks() with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -341,18 +345,7 @@ def test_instrument_with_dbapi_sqlcomment_enabled( def test_instrument_with_dbapi_sqlcomment_enabled_stmt_enabled( self, ): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", - ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_cursor = mock_connect_module.connect().cursor() - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor + mock_connect_module, _, mock_cursor = make_mysql_commenter_mocks() with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -382,18 +375,7 @@ def test_instrument_with_dbapi_sqlcomment_enabled_stmt_enabled( def test_instrument_with_dbapi_sqlcomment_enabled_with_options( self, ): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", - ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_cursor = mock_connect_module.connect().cursor() - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor + mock_connect_module, _, mock_cursor = make_mysql_commenter_mocks() with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -427,18 +409,7 @@ def test_instrument_with_dbapi_sqlcomment_enabled_with_options( def test_instrument_with_dbapi_sqlcomment_not_enabled_default( self, ): - mock_connect_module = mock.MagicMock( - __name__="mysql.connector", - __version__="foobar", - threadsafety="123", - apilevel="123", - paramstyle="test", - ) - mock_cursor = mock_connect_module.connect().cursor() - mock_cursor._cnx._cmysql.get_client_info.return_value = "foobaz" - mock_cursor = mock_connect_module.connect().cursor() - mock_connection = mock.MagicMock() - mock_connection.cursor.return_value = mock_cursor + mock_connect_module, _, mock_cursor = make_mysql_commenter_mocks() with mock.patch( "opentelemetry.instrumentation.mysql.mysql.connector", @@ -462,6 +433,7 @@ def test_instrument_with_dbapi_sqlcomment_not_enabled_default( @mock.patch("mysql.connector.connect") # pylint: disable=unused-argument def test_uninstrument_connection(self, mock_connect): + mock_connect.return_value = make_mysql_connection_mock() MySQLInstrumentor().instrument() cnx, query = connect_and_execute_query()