add param to control collection of db.statement.parameters

This commit is contained in:
stschenk
2020-11-06 09:37:28 -08:00
parent 28c1331e57
commit 8afbd83e8c
4 changed files with 64 additions and 3 deletions

View File

@ -199,7 +199,11 @@ class TestAiopgIntegration(TestBase):
"user": "user",
}
db_integration = AiopgIntegration(
self.tracer, "testcomponent", "testtype", connection_attributes
self.tracer,
"testcomponent",
"testtype",
connection_attributes,
capture_parameters=True,
)
mock_connection = async_call(
db_integration.wrapped_connection(

View File

@ -2,6 +2,9 @@
## Unreleased
Stop capturing query parameters by default
([#????](https://github.com/open-telemetry/opentelemetry-python/pull/???))
## Version 0.13b0
Released 2020-09-17

View File

@ -62,6 +62,7 @@ def trace_integration(
database_type: str = "",
connection_attributes: typing.Dict = None,
tracer_provider: typing.Optional[TracerProvider] = None,
capture_parameters: bool = False,
):
"""Integrate with DB API library.
https://www.python.org/dev/peps/pep-0249/
@ -76,6 +77,7 @@ def trace_integration(
user in Connection object.
tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to
use. If ommited the current configured one is used.
capture_parameters: Configure if db.statement.parameters should be captured.
"""
wrap_connect(
__name__,
@ -86,6 +88,7 @@ def trace_integration(
connection_attributes,
version=__version__,
tracer_provider=tracer_provider,
capture_parameters=capture_parameters,
)
@ -98,6 +101,7 @@ def wrap_connect(
connection_attributes: typing.Dict = None,
version: str = "",
tracer_provider: typing.Optional[TracerProvider] = None,
capture_parameters: bool = False,
):
"""Integrate with DB API library.
https://www.python.org/dev/peps/pep-0249/
@ -111,6 +115,8 @@ def wrap_connect(
database_type: The Database type. For any SQL database, "sql".
connection_attributes: Attribute names for database, port, host and
user in Connection object.
capture_parameters: Configure if db.statement.parameters should be captured.
"""
# pylint: disable=unused-argument
@ -127,6 +133,7 @@ def wrap_connect(
connection_attributes=connection_attributes,
version=version,
tracer_provider=tracer_provider,
capture_parameters=capture_parameters,
)
return db_integration.wrapped_connection(wrapped, args, kwargs)
@ -159,6 +166,7 @@ def instrument_connection(
connection_attributes: typing.Dict = None,
version: str = "",
tracer_provider: typing.Optional[TracerProvider] = None,
capture_parameters=False,
):
"""Enable instrumentation in a database connection.
@ -170,7 +178,7 @@ def instrument_connection(
database_type: The Database type. For any SQL database, "sql".
connection_attributes: Attribute names for database, port, host and
user in a connection object.
capture_parameters: Configure if db.statement.parameters should be captured.
Returns:
An instrumented connection.
"""
@ -181,6 +189,7 @@ def instrument_connection(
connection_attributes=connection_attributes,
version=version,
tracer_provider=tracer_provider,
capture_parameters=capture_parameters,
)
db_integration.get_connection_attributes(connection)
return get_traced_connection_proxy(connection, db_integration)
@ -211,6 +220,7 @@ class DatabaseApiIntegration:
connection_attributes=None,
version: str = "",
tracer_provider: typing.Optional[TracerProvider] = None,
capture_parameters: bool = False,
):
self.connection_attributes = connection_attributes
if self.connection_attributes is None:
@ -223,6 +233,7 @@ class DatabaseApiIntegration:
self._name = name
self._version = version
self._tracer_provider = tracer_provider
self.capture_parameters = capture_parameters
self.database_component = database_component
self.database_type = database_type
self.connection_props = {}
@ -327,7 +338,7 @@ class TracedCursor:
) in self._db_api_integration.span_attributes.items():
span.set_attribute(attribute_key, attribute_value)
if len(args) > 1:
if self._db_api_integration.capture_parameters and len(args) > 1:
span.set_attribute("db.statement.parameters", str(args[1]))
def traced_execution(

View File

@ -53,6 +53,49 @@ class TestDBApiIntegration(TestBase):
self.assertEqual(span.name, "testcomponent.testdatabase")
self.assertIs(span.kind, trace_api.SpanKind.CLIENT)
self.assertEqual(span.attributes["component"], "testcomponent")
self.assertEqual(span.attributes["db.type"], "testtype")
self.assertEqual(span.attributes["db.instance"], "testdatabase")
self.assertEqual(span.attributes["db.statement"], "Test query")
self.assertFalse("db.statement.parameters" in span.attributes)
self.assertEqual(span.attributes["db.user"], "testuser")
self.assertEqual(span.attributes["net.peer.name"], "testhost")
self.assertEqual(span.attributes["net.peer.port"], 123)
self.assertIs(
span.status.status_code, trace_api.status.StatusCode.UNSET,
)
def test_span_succeeded_without_capture_of_statement_parameters(self):
connection_props = {
"database": "testdatabase",
"server_host": "testhost",
"server_port": 123,
"user": "testuser",
}
connection_attributes = {
"database": "database",
"port": "server_port",
"host": "server_host",
"user": "user",
}
db_integration = dbapi.DatabaseApiIntegration(
self.tracer,
"testcomponent",
"testtype",
connection_attributes,
capture_parameters=True,
)
mock_connection = db_integration.wrapped_connection(
mock_connect, {}, connection_props
)
cursor = mock_connection.cursor()
cursor.execute("Test query", ("param1Value", False))
spans_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(spans_list), 1)
span = spans_list[0]
self.assertEqual(span.name, "testcomponent.testdatabase")
self.assertIs(span.kind, trace_api.SpanKind.CLIENT)
self.assertEqual(span.attributes["component"], "testcomponent")
self.assertEqual(span.attributes["db.type"], "testtype")
self.assertEqual(span.attributes["db.instance"], "testdatabase")