(instrumentation-sqlite3): trace connections made with dbapi2.connect (#873)

* Change wrap_connect method

* Wrap both connect defs

* Add tests

* Add CHANGELOG entry
This commit is contained in:
Srikanth Chekuri
2022-01-26 05:49:25 +05:30
committed by GitHub
parent ec5b73c626
commit 571c3780e6
3 changed files with 36 additions and 11 deletions

View File

@ -34,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `opentelemetry-instrumentation-django` Django: fix issue preventing detection of MIDDLEWARE_CLASSES
- `opentelemetry-instrumentation-sqlite3` Instrumentation now works with `dbapi2.connect`
## [1.8.0-0.27b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.8.0-0.27b0) - 2021-12-17
### Added

View File

@ -40,6 +40,7 @@ API
"""
import sqlite3
from sqlite3 import dbapi2
from typing import Collection
from opentelemetry.instrumentation import dbapi
@ -54,6 +55,8 @@ _DATABASE_SYSTEM = "sqlite"
class SQLite3Instrumentor(BaseInstrumentor):
_TO_WRAP = [sqlite3, dbapi2]
def instrumentation_dependencies(self) -> Collection[str]:
return _instruments
@ -63,9 +66,10 @@ class SQLite3Instrumentor(BaseInstrumentor):
"""
tracer_provider = kwargs.get("tracer_provider")
for module in self._TO_WRAP:
dbapi.wrap_connect(
__name__,
sqlite3,
module,
"connect",
_DATABASE_SYSTEM,
_CONNECTION_ATTRIBUTES,
@ -75,7 +79,8 @@ class SQLite3Instrumentor(BaseInstrumentor):
def _uninstrument(self, **kwargs):
""" "Disable SQLite3 instrumentation"""
dbapi.unwrap_connect(sqlite3, "connect")
for module in self._TO_WRAP:
dbapi.unwrap_connect(module, "connect")
@staticmethod
def instrument_connection(connection, tracer_provider=None):

View File

@ -13,6 +13,7 @@
# limitations under the License.
import sqlite3
from sqlite3 import dbapi2
from opentelemetry import trace as trace_api
from opentelemetry.instrumentation.sqlite3 import SQLite3Instrumentor
@ -25,10 +26,14 @@ class TestSQLite3(TestBase):
super().setUpClass()
cls._connection = None
cls._cursor = None
cls._connection2 = None
cls._cursor2 = None
cls._tracer = cls.tracer_provider.get_tracer(__name__)
SQLite3Instrumentor().instrument(tracer_provider=cls.tracer_provider)
cls._connection = sqlite3.connect(":memory:")
cls._cursor = cls._connection.cursor()
cls._connection2 = dbapi2.connect(":memory:")
cls._cursor2 = cls._connection2.cursor()
@classmethod
def tearDownClass(cls):
@ -36,9 +41,14 @@ class TestSQLite3(TestBase):
cls._cursor.close()
if cls._connection:
cls._connection.close()
if cls._cursor2:
cls._cursor2.close()
if cls._connection2:
cls._connection2.close()
def validate_spans(self, span_name):
spans = self.memory_exporter.get_finished_spans()
self.memory_exporter.clear()
self.assertEqual(len(spans), 2)
for span in spans:
if span.name == "rootSpan":
@ -62,14 +72,22 @@ class TestSQLite3(TestBase):
self._cursor.execute(stmt)
self.validate_spans("CREATE")
with self._tracer.start_as_current_span("rootSpan"):
self._cursor2.execute(stmt)
self.validate_spans("CREATE")
def test_executemany(self):
"""Should create a child span for executemany"""
stmt = "INSERT INTO test (id) VALUES (?)"
with self._tracer.start_as_current_span("rootSpan"):
data = [("1",), ("2",), ("3",)]
with self._tracer.start_as_current_span("rootSpan"):
self._cursor.executemany(stmt, data)
self.validate_spans("INSERT")
with self._tracer.start_as_current_span("rootSpan"):
self._cursor2.executemany(stmt, data)
self.validate_spans("INSERT")
def test_callproc(self):
"""Should create a child span for callproc"""
with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(