mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 20:52:57 +08:00
DB-API instrumentor populates span after sqlcomment creation, not before (#2935)
This commit is contained in:
@ -44,6 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
([#2635](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2635))
|
([#2635](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2635))
|
||||||
- `opentelemetry-instrumentation` Add support for string based dotted module paths in unwrap
|
- `opentelemetry-instrumentation` Add support for string based dotted module paths in unwrap
|
||||||
([#2919](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2919))
|
([#2919](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2919))
|
||||||
|
- `opentelemetry-instrumentation-dbapi` Add sqlcomment to `db.statement` attribute
|
||||||
|
([#2935](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2935))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -492,49 +492,54 @@ class CursorTracer:
|
|||||||
with self._db_api_integration._tracer.start_as_current_span(
|
with self._db_api_integration._tracer.start_as_current_span(
|
||||||
name, kind=SpanKind.CLIENT
|
name, kind=SpanKind.CLIENT
|
||||||
) as span:
|
) as span:
|
||||||
self._populate_span(span, cursor, *args)
|
if span.is_recording():
|
||||||
if args and self._commenter_enabled:
|
if args and self._commenter_enabled:
|
||||||
try:
|
try:
|
||||||
args_list = list(args)
|
args_list = list(args)
|
||||||
|
|
||||||
# lazy capture of mysql-connector client version using cursor
|
# lazy capture of mysql-connector client version using cursor
|
||||||
if (
|
if (
|
||||||
self._db_api_integration.database_system == "mysql"
|
self._db_api_integration.database_system == "mysql"
|
||||||
and self._db_api_integration.connect_module.__name__
|
and self._db_api_integration.connect_module.__name__
|
||||||
== "mysql.connector"
|
== "mysql.connector"
|
||||||
and not self._db_api_integration.commenter_data[
|
and not self._db_api_integration.commenter_data[
|
||||||
"mysql_client_version"
|
"mysql_client_version"
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
self._db_api_integration.commenter_data[
|
self._db_api_integration.commenter_data[
|
||||||
"mysql_client_version"
|
"mysql_client_version"
|
||||||
] = cursor._cnx._cmysql.get_client_info()
|
] = cursor._cnx._cmysql.get_client_info()
|
||||||
|
|
||||||
commenter_data = dict(
|
commenter_data = dict(
|
||||||
self._db_api_integration.commenter_data
|
self._db_api_integration.commenter_data
|
||||||
)
|
)
|
||||||
if self._commenter_options.get(
|
if self._commenter_options.get(
|
||||||
"opentelemetry_values", True
|
"opentelemetry_values", True
|
||||||
):
|
):
|
||||||
commenter_data.update(**_get_opentelemetry_values())
|
commenter_data.update(
|
||||||
|
**_get_opentelemetry_values()
|
||||||
|
)
|
||||||
|
|
||||||
# Filter down to just the requested attributes.
|
# Filter down to just the requested attributes.
|
||||||
commenter_data = {
|
commenter_data = {
|
||||||
k: v
|
k: v
|
||||||
for k, v in commenter_data.items()
|
for k, v in commenter_data.items()
|
||||||
if self._commenter_options.get(k, True)
|
if self._commenter_options.get(k, True)
|
||||||
}
|
}
|
||||||
statement = _add_sql_comment(
|
statement = _add_sql_comment(
|
||||||
args_list[0], **commenter_data
|
args_list[0], **commenter_data
|
||||||
)
|
)
|
||||||
|
|
||||||
args_list[0] = statement
|
args_list[0] = statement
|
||||||
args = tuple(args_list)
|
args = tuple(args_list)
|
||||||
|
|
||||||
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
|
_logger.exception(
|
||||||
|
"Exception while generating sql comment: %s", exc
|
||||||
|
)
|
||||||
|
|
||||||
|
self._populate_span(span, cursor, *args)
|
||||||
|
|
||||||
except Exception as exc: # pylint: disable=broad-except
|
|
||||||
_logger.exception(
|
|
||||||
"Exception while generating sql comment: %s", exc
|
|
||||||
)
|
|
||||||
return query_method(*args, **kwargs)
|
return query_method(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from opentelemetry import context
|
from opentelemetry import context
|
||||||
@ -306,6 +307,44 @@ class TestDBApiIntegration(TestBase):
|
|||||||
r"Select 1 /\*dbapi_level='1.0',dbapi_threadsafety='unknown',driver_paramstyle='unknown',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
|
r"Select 1 /\*dbapi_level='1.0',dbapi_threadsafety='unknown',driver_paramstyle='unknown',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_executemany_comment_matches_db_statement_attribute(self):
|
||||||
|
connect_module = mock.MagicMock()
|
||||||
|
connect_module.__version__ = mock.MagicMock()
|
||||||
|
connect_module.__libpq_version__ = 123
|
||||||
|
connect_module.apilevel = 123
|
||||||
|
connect_module.threadsafety = 123
|
||||||
|
connect_module.paramstyle = "test"
|
||||||
|
|
||||||
|
db_integration = dbapi.DatabaseApiIntegration(
|
||||||
|
"testname",
|
||||||
|
"postgresql",
|
||||||
|
enable_commenter=True,
|
||||||
|
commenter_options={"db_driver": False, "dbapi_level": False},
|
||||||
|
connect_module=connect_module,
|
||||||
|
)
|
||||||
|
mock_connection = db_integration.wrapped_connection(
|
||||||
|
mock_connect, {}, {}
|
||||||
|
)
|
||||||
|
cursor = mock_connection.cursor()
|
||||||
|
cursor.executemany("Select 1;")
|
||||||
|
self.assertRegex(
|
||||||
|
cursor.query,
|
||||||
|
r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
|
||||||
|
)
|
||||||
|
spans_list = self.memory_exporter.get_finished_spans()
|
||||||
|
self.assertEqual(len(spans_list), 1)
|
||||||
|
span = spans_list[0]
|
||||||
|
self.assertRegex(
|
||||||
|
span.attributes[SpanAttributes.DB_STATEMENT],
|
||||||
|
r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/",
|
||||||
|
)
|
||||||
|
|
||||||
|
cursor_span_id = re.search(r"[a-zA-Z0-9_]{16}", cursor.query).group()
|
||||||
|
db_statement_span_id = re.search(
|
||||||
|
r"[a-zA-Z0-9_]{16}", span.attributes[SpanAttributes.DB_STATEMENT]
|
||||||
|
).group()
|
||||||
|
self.assertEqual(cursor_span_id, db_statement_span_id)
|
||||||
|
|
||||||
def test_compatible_build_version_psycopg_psycopg2_libpq(self):
|
def test_compatible_build_version_psycopg_psycopg2_libpq(self):
|
||||||
connect_module = mock.MagicMock()
|
connect_module = mock.MagicMock()
|
||||||
connect_module.__name__ = "test"
|
connect_module.__name__ = "test"
|
||||||
|
Reference in New Issue
Block a user