diff --git a/google/cloud/spanner_v1/_opentelemetry_tracing.py b/google/cloud/spanner_v1/_opentelemetry_tracing.py index 8f9f8559ef..8e6cb5d5a9 100644 --- a/google/cloud/spanner_v1/_opentelemetry_tracing.py +++ b/google/cloud/spanner_v1/_opentelemetry_tracing.py @@ -18,15 +18,39 @@ from google.api_core.exceptions import GoogleAPICallError from google.cloud.spanner_v1 import SpannerClient +from google.cloud.spanner_v1 import gapic_version as LIB_VERSION try: from opentelemetry import trace from opentelemetry.trace.status import Status, StatusCode + from opentelemetry.semconv.attributes import ( + OTEL_SCOPE_NAME, + OTEL_SCOPE_VERSION, + ) HAS_OPENTELEMETRY_INSTALLED = True except ImportError: HAS_OPENTELEMETRY_INSTALLED = False +LIB_FQNAME = 'cloud.google.com/python/spanner' +TRACER_NAME = LIB_FQNAME +TRACER_VERSION = LIB_VERSION + + +def get_tracer(tracer_provider=None): + """ + get_tracer is a utility to unify and simplify retrieval of the tracer, without + leaking implementation details given that retrieving a tracer requires providing + the full qualified library name and version. + When the tracer_provider is set, it'll retrieve the tracer from it, otherwise + it'll fall back to the global tracer provider and use this library's specific semantics. + """ + if not tracer_provider: + # Acquire the global tracer provider. + tracer_provider = trace.get_tracer_provider() + + return tracer_provider.get_tracer(TRACER_NAME, TRACER_VERSION) + @contextmanager def trace_call(name, session, extra_attributes=None): @@ -35,7 +59,7 @@ def trace_call(name, session, extra_attributes=None): yield None return - tracer = trace.get_tracer(__name__) + tracer = get_tracer() # Set base attributes that we know for every trace created attributes = { @@ -43,6 +67,8 @@ def trace_call(name, session, extra_attributes=None): "db.url": SpannerClient.DEFAULT_ENDPOINT, "db.instance": session._database.name, "net.host.name": SpannerClient.DEFAULT_ENDPOINT, + OTEL_SCOPE_NAME: LIB_FQNAME, + OTEL_SCOPE_VERSION: LIB_VERSION, } if extra_attributes: diff --git a/setup.py b/setup.py index 98b1a61748..9efd0f3626 100644 --- a/setup.py +++ b/setup.py @@ -47,9 +47,10 @@ ] extras = { "tracing": [ - "opentelemetry-api >= 1.1.0", - "opentelemetry-sdk >= 1.1.0", - "opentelemetry-instrumentation >= 0.20b0, < 0.23dev", + "opentelemetry-api >= 1.24.0", + "opentelemetry-sdk >= 1.24.0", + "opentelemetry-instrumentation >= 0.46b0", + "opentelemetry-semantic-conventions >= 0.46b0", ], "libcst": "libcst >= 0.2.5", } diff --git a/testing/constraints-3.7.txt b/testing/constraints-3.7.txt index 20170203f5..ec9cd244b5 100644 --- a/testing/constraints-3.7.txt +++ b/testing/constraints-3.7.txt @@ -10,9 +10,10 @@ grpc-google-iam-v1==0.12.4 libcst==0.2.5 proto-plus==1.22.0 sqlparse==0.4.4 -opentelemetry-api==1.1.0 -opentelemetry-sdk==1.1.0 -opentelemetry-instrumentation==0.20b0 +opentelemetry-api>=1.24.0 +opentelemetry-sdk>=1.24.0 +opentelemetry-instrumentation==0.46b0 +opentelemetry-semantic-conventions==0.46b0 protobuf==3.20.2 deprecated==1.2.14 grpc-interceptor==0.15.4 diff --git a/tests/_helpers.py b/tests/_helpers.py index 42178fd439..cae5eb9c8e 100644 --- a/tests/_helpers.py +++ b/tests/_helpers.py @@ -9,12 +9,17 @@ InMemorySpanExporter, ) from opentelemetry.trace.status import StatusCode + from opentelemetry.semconv.attributes import ( + OTEL_SCOPE_NAME, + OTEL_SCOPE_VERSION, + ) trace.set_tracer_provider(TracerProvider()) HAS_OPENTELEMETRY_INSTALLED = True except ImportError: HAS_OPENTELEMETRY_INSTALLED = False + OTEL_SCOPE_NAME = "otel.scope.name" StatusCode = mock.Mock() diff --git a/tests/unit/test__opentelemetry_tracing.py b/tests/unit/test__opentelemetry_tracing.py index 25870227bf..43c5ffe867 100644 --- a/tests/unit/test__opentelemetry_tracing.py +++ b/tests/unit/test__opentelemetry_tracing.py @@ -12,7 +12,11 @@ from google.api_core.exceptions import GoogleAPICallError from google.cloud.spanner_v1 import _opentelemetry_tracing -from tests._helpers import OpenTelemetryBase, HAS_OPENTELEMETRY_INSTALLED +from tests._helpers import ( + OpenTelemetryBase, + HAS_OPENTELEMETRY_INSTALLED, + OTEL_SCOPE_NAME, +) def _make_rpc_error(error_cls, trailing_metadata=None): @@ -59,6 +63,7 @@ def test_trace_call(self): "db.type": "spanner", "db.url": "spanner.googleapis.com", "net.host.name": "spanner.googleapis.com", + OTEL_SCOPE_NAME: "cloud.google.com/python/spanner", } expected_attributes.update(extra_attributes) @@ -84,6 +89,7 @@ def test_trace_error(self): "db.type": "spanner", "db.url": "spanner.googleapis.com", "net.host.name": "spanner.googleapis.com", + OTEL_SCOPE_NAME: "cloud.google.com/python/spanner", } expected_attributes.update(extra_attributes) @@ -110,6 +116,7 @@ def test_trace_grpc_error(self): "db.type": "spanner", "db.url": "spanner.googleapis.com:443", "net.host.name": "spanner.googleapis.com:443", + OTEL_SCOPE_NAME: "cloud.google.com/python/spanner", } expected_attributes.update(extra_attributes) @@ -133,6 +140,7 @@ def test_trace_codeless_error(self): "db.type": "spanner", "db.url": "spanner.googleapis.com:443", "net.host.name": "spanner.googleapis.com:443", + OTEL_SCOPE_NAME: "cloud.google.com/python/spanner", } expected_attributes.update(extra_attributes)