Merge branch 'master' into dbindex-redis
This commit is contained in:
commit
13976b5275
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Update asyncpg instrumentation to follow semantic conventions
|
||||||
|
([#188](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/188))
|
||||||
|
|
||||||
## Version 0.12b0
|
## Version 0.12b0
|
||||||
|
|
||||||
Released 2020-08-14
|
Released 2020-08-14
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,30 @@ _APPLIED = "_opentelemetry_tracer"
|
||||||
|
|
||||||
|
|
||||||
def _hydrate_span_from_args(connection, query, parameters) -> dict:
|
def _hydrate_span_from_args(connection, query, parameters) -> dict:
|
||||||
span_attributes = {"db.type": "sql"}
|
"""Get network and database attributes from connection."""
|
||||||
|
span_attributes = {"db.system": "postgresql"}
|
||||||
|
|
||||||
|
# connection contains _params attribute which is a namedtuple ConnectionParameters.
|
||||||
|
# https://github.com/MagicStack/asyncpg/blob/master/asyncpg/connection.py#L68
|
||||||
|
|
||||||
params = getattr(connection, "_params", None)
|
params = getattr(connection, "_params", None)
|
||||||
span_attributes["db.instance"] = getattr(params, "database", None)
|
dbname = getattr(params, "database", None)
|
||||||
span_attributes["db.user"] = getattr(params, "user", None)
|
if dbname:
|
||||||
|
span_attributes["db.name"] = dbname
|
||||||
|
user = getattr(params, "user", None)
|
||||||
|
if user:
|
||||||
|
span_attributes["db.user"] = user
|
||||||
|
|
||||||
|
# connection contains _addr attribute which is either a host/port tuple, or unix socket string
|
||||||
|
# https://magicstack.github.io/asyncpg/current/_modules/asyncpg/connection.html
|
||||||
|
addr = getattr(connection, "_addr", None)
|
||||||
|
if isinstance(addr, tuple):
|
||||||
|
span_attributes["net.peer.name"] = addr[0]
|
||||||
|
span_attributes["net.peer.ip"] = addr[1]
|
||||||
|
span_attributes["net.transport"] = "IP.TCP"
|
||||||
|
elif isinstance(addr, str):
|
||||||
|
span_attributes["net.peer.name"] = addr
|
||||||
|
span_attributes["net.transport"] = "Unix"
|
||||||
|
|
||||||
if query is not None:
|
if query is not None:
|
||||||
span_attributes["db.statement"] = query
|
span_attributes["db.statement"] = query
|
||||||
|
|
@ -105,10 +124,10 @@ class AsyncPGInstrumentor(BaseInstrumentor):
|
||||||
tracer = getattr(asyncpg, _APPLIED)
|
tracer = getattr(asyncpg, _APPLIED)
|
||||||
|
|
||||||
exception = None
|
exception = None
|
||||||
|
params = getattr(instance, "_params", {})
|
||||||
|
name = args[0] if args[0] else params.get("database", "postgresql")
|
||||||
|
|
||||||
with tracer.start_as_current_span(
|
with tracer.start_as_current_span(name, kind=SpanKind.CLIENT) as span:
|
||||||
"postgresql", kind=SpanKind.CLIENT
|
|
||||||
) as span:
|
|
||||||
if span.is_recording():
|
if span.is_recording():
|
||||||
span_attributes = _hydrate_span_from_args(
|
span_attributes = _hydrate_span_from_args(
|
||||||
instance,
|
instance,
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ from opentelemetry.trace.status import StatusCode
|
||||||
POSTGRES_HOST = os.getenv("POSTGRESQL_HOST", "localhost")
|
POSTGRES_HOST = os.getenv("POSTGRESQL_HOST", "localhost")
|
||||||
POSTGRES_PORT = int(os.getenv("POSTGRESQL_PORT", "5432"))
|
POSTGRES_PORT = int(os.getenv("POSTGRESQL_PORT", "5432"))
|
||||||
POSTGRES_DB_NAME = os.getenv("POSTGRESQL_DB_NAME", "opentelemetry-tests")
|
POSTGRES_DB_NAME = os.getenv("POSTGRESQL_DB_NAME", "opentelemetry-tests")
|
||||||
POSTGRES_PASSWORD = os.getenv("POSTGRESQL_HOST ", "testpassword")
|
POSTGRES_PASSWORD = os.getenv("POSTGRESQL_PASSWORD", "testpassword")
|
||||||
POSTGRES_USER = os.getenv("POSTGRESQL_HOST ", "testuser")
|
POSTGRES_USER = os.getenv("POSTGRESQL_USER", "testuser")
|
||||||
|
|
||||||
|
|
||||||
def async_call(coro):
|
def async_call(coro):
|
||||||
|
|
@ -41,34 +41,28 @@ class TestFunctionalAsyncPG(TestBase):
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
AsyncPGInstrumentor().uninstrument()
|
AsyncPGInstrumentor().uninstrument()
|
||||||
|
|
||||||
|
def check_span(self, span):
|
||||||
|
self.assertEqual(span.attributes["db.system"], "postgresql")
|
||||||
|
self.assertEqual(span.attributes["db.name"], POSTGRES_DB_NAME)
|
||||||
|
self.assertEqual(span.attributes["db.user"], POSTGRES_USER)
|
||||||
|
self.assertEqual(span.attributes["net.peer.name"], POSTGRES_HOST)
|
||||||
|
self.assertEqual(span.attributes["net.peer.ip"], POSTGRES_PORT)
|
||||||
|
|
||||||
def test_instrumented_execute_method_without_arguments(self, *_, **__):
|
def test_instrumented_execute_method_without_arguments(self, *_, **__):
|
||||||
async_call(self._connection.execute("SELECT 42;"))
|
async_call(self._connection.execute("SELECT 42;"))
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
||||||
self.assertEqual(
|
self.check_span(spans[0])
|
||||||
spans[0].attributes,
|
self.assertEqual(spans[0].name, "SELECT 42;")
|
||||||
{
|
self.assertEqual(spans[0].attributes["db.statement"], "SELECT 42;")
|
||||||
"db.type": "sql",
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.statement": "SELECT 42;",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_instrumented_fetch_method_without_arguments(self, *_, **__):
|
def test_instrumented_fetch_method_without_arguments(self, *_, **__):
|
||||||
async_call(self._connection.fetch("SELECT 42;"))
|
async_call(self._connection.fetch("SELECT 42;"))
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
self.assertEqual(
|
self.check_span(spans[0])
|
||||||
spans[0].attributes,
|
self.assertEqual(spans[0].attributes["db.statement"], "SELECT 42;")
|
||||||
{
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.statement": "SELECT 42;",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_instrumented_transaction_method(self, *_, **__):
|
def test_instrumented_transaction_method(self, *_, **__):
|
||||||
async def _transaction_execute():
|
async def _transaction_execute():
|
||||||
|
|
@ -79,35 +73,16 @@ class TestFunctionalAsyncPG(TestBase):
|
||||||
|
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(3, len(spans))
|
self.assertEqual(3, len(spans))
|
||||||
self.assertEqual(
|
self.check_span(spans[0])
|
||||||
{
|
self.assertEqual(spans[0].attributes["db.statement"], "BEGIN;")
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.statement": "BEGIN;",
|
|
||||||
},
|
|
||||||
spans[0].attributes,
|
|
||||||
)
|
|
||||||
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
||||||
self.assertEqual(
|
|
||||||
{
|
self.check_span(spans[1])
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
self.assertEqual(spans[1].attributes["db.statement"], "SELECT 42;")
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.statement": "SELECT 42;",
|
|
||||||
},
|
|
||||||
spans[1].attributes,
|
|
||||||
)
|
|
||||||
self.assertIs(StatusCode.UNSET, spans[1].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[1].status.status_code)
|
||||||
self.assertEqual(
|
|
||||||
{
|
self.check_span(spans[2])
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
self.assertEqual(spans[2].attributes["db.statement"], "COMMIT;")
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.statement": "COMMIT;",
|
|
||||||
},
|
|
||||||
spans[2].attributes,
|
|
||||||
)
|
|
||||||
self.assertIs(StatusCode.UNSET, spans[2].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[2].status.status_code)
|
||||||
|
|
||||||
def test_instrumented_failed_transaction_method(self, *_, **__):
|
def test_instrumented_failed_transaction_method(self, *_, **__):
|
||||||
|
|
@ -120,37 +95,19 @@ class TestFunctionalAsyncPG(TestBase):
|
||||||
|
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(3, len(spans))
|
self.assertEqual(3, len(spans))
|
||||||
self.assertEqual(
|
|
||||||
{
|
self.check_span(spans[0])
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
self.assertEqual(spans[0].attributes["db.statement"], "BEGIN;")
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.statement": "BEGIN;",
|
|
||||||
},
|
|
||||||
spans[0].attributes,
|
|
||||||
)
|
|
||||||
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
||||||
|
|
||||||
|
self.check_span(spans[1])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{
|
spans[1].attributes["db.statement"], "SELECT 42::uuid;"
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.statement": "SELECT 42::uuid;",
|
|
||||||
},
|
|
||||||
spans[1].attributes,
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
StatusCode.ERROR, spans[1].status.status_code,
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
{
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.statement": "ROLLBACK;",
|
|
||||||
},
|
|
||||||
spans[2].attributes,
|
|
||||||
)
|
)
|
||||||
|
self.assertEqual(StatusCode.ERROR, spans[1].status.status_code)
|
||||||
|
|
||||||
|
self.check_span(spans[2])
|
||||||
|
self.assertEqual(spans[2].attributes["db.statement"], "ROLLBACK;")
|
||||||
self.assertIs(StatusCode.UNSET, spans[2].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[2].status.status_code)
|
||||||
|
|
||||||
def test_instrumented_method_doesnt_capture_parameters(self, *_, **__):
|
def test_instrumented_method_doesnt_capture_parameters(self, *_, **__):
|
||||||
|
|
@ -158,19 +115,8 @@ class TestFunctionalAsyncPG(TestBase):
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
||||||
self.assertEqual(
|
self.check_span(spans[0])
|
||||||
spans[0].attributes,
|
self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;")
|
||||||
{
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
# This shouldn't be set because we don't capture parameters by
|
|
||||||
# default
|
|
||||||
#
|
|
||||||
# "db.statement.parameters": "('1',)",
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.statement": "SELECT $1;",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestFunctionalAsyncPG_CaptureParameters(TestBase):
|
class TestFunctionalAsyncPG_CaptureParameters(TestBase):
|
||||||
|
|
@ -197,50 +143,46 @@ class TestFunctionalAsyncPG_CaptureParameters(TestBase):
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
AsyncPGInstrumentor().uninstrument()
|
AsyncPGInstrumentor().uninstrument()
|
||||||
|
|
||||||
|
def check_span(self, span):
|
||||||
|
self.assertEqual(span.attributes["db.system"], "postgresql")
|
||||||
|
self.assertEqual(span.attributes["db.name"], POSTGRES_DB_NAME)
|
||||||
|
self.assertEqual(span.attributes["db.user"], POSTGRES_USER)
|
||||||
|
self.assertEqual(span.attributes["net.peer.name"], POSTGRES_HOST)
|
||||||
|
self.assertEqual(span.attributes["net.peer.ip"], POSTGRES_PORT)
|
||||||
|
|
||||||
def test_instrumented_execute_method_with_arguments(self, *_, **__):
|
def test_instrumented_execute_method_with_arguments(self, *_, **__):
|
||||||
async_call(self._connection.execute("SELECT $1;", "1"))
|
async_call(self._connection.execute("SELECT $1;", "1"))
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
self.assertIs(StatusCode.UNSET, spans[0].status.status_code)
|
||||||
|
|
||||||
|
self.check_span(spans[0])
|
||||||
|
self.assertEqual(spans[0].name, "SELECT $1;")
|
||||||
|
self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
spans[0].attributes,
|
spans[0].attributes["db.statement.parameters"], "('1',)"
|
||||||
{
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.statement.parameters": "('1',)",
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.statement": "SELECT $1;",
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_instrumented_fetch_method_with_arguments(self, *_, **__):
|
def test_instrumented_fetch_method_with_arguments(self, *_, **__):
|
||||||
async_call(self._connection.fetch("SELECT $1;", "1"))
|
async_call(self._connection.fetch("SELECT $1;", "1"))
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
|
|
||||||
|
self.check_span(spans[0])
|
||||||
|
self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
spans[0].attributes,
|
spans[0].attributes["db.statement.parameters"], "('1',)"
|
||||||
{
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.statement.parameters": "('1',)",
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.statement": "SELECT $1;",
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_instrumented_executemany_method_with_arguments(self, *_, **__):
|
def test_instrumented_executemany_method_with_arguments(self, *_, **__):
|
||||||
async_call(self._connection.executemany("SELECT $1;", [["1"], ["2"]]))
|
async_call(self._connection.executemany("SELECT $1;", [["1"], ["2"]]))
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
|
|
||||||
|
self.check_span(spans[0])
|
||||||
|
self.assertEqual(spans[0].attributes["db.statement"], "SELECT $1;")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{
|
spans[0].attributes["db.statement.parameters"], "([['1'], ['2']],)"
|
||||||
"db.type": "sql",
|
|
||||||
"db.statement": "SELECT $1;",
|
|
||||||
"db.statement.parameters": "([['1'], ['2']],)",
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
},
|
|
||||||
spans[0].attributes,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_instrumented_execute_interface_error_method(self, *_, **__):
|
def test_instrumented_execute_interface_error_method(self, *_, **__):
|
||||||
|
|
@ -248,13 +190,9 @@ class TestFunctionalAsyncPG_CaptureParameters(TestBase):
|
||||||
async_call(self._connection.execute("SELECT 42;", 1, 2, 3))
|
async_call(self._connection.execute("SELECT 42;", 1, 2, 3))
|
||||||
spans = self.memory_exporter.get_finished_spans()
|
spans = self.memory_exporter.get_finished_spans()
|
||||||
self.assertEqual(len(spans), 1)
|
self.assertEqual(len(spans), 1)
|
||||||
|
|
||||||
|
self.check_span(spans[0])
|
||||||
|
self.assertEqual(spans[0].attributes["db.statement"], "SELECT 42;")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
spans[0].attributes,
|
spans[0].attributes["db.statement.parameters"], "(1, 2, 3)"
|
||||||
{
|
|
||||||
"db.type": "sql",
|
|
||||||
"db.instance": POSTGRES_DB_NAME,
|
|
||||||
"db.user": POSTGRES_USER,
|
|
||||||
"db.statement.parameters": "(1, 2, 3)",
|
|
||||||
"db.statement": "SELECT 42;",
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue