Skip to content

Commit

Permalink
fix: use standardized OpenTelemetry attributes when tracing
Browse files Browse the repository at this point in the history
This change modernizes trace span attributes by using OpenTelemetry's
semantic conventions that are standardized and allow for much
better common ground adoption by broader systems, even more as
Google Cloud Tracing & Monitoring pushes towards OpenTelemetry more.

With this change we've made the replacement of these fields, directly
with imports from the package `opentelemetry.semconv.attributes` as:

* "db.type"       => DB_SYSTEM aka "db.system"
* "db.url"        => DB_CONNECTION_STRING aka "db.system"
* "db.instance"   => DB_NAME aka "db.name"
* "net.host.name" => NET_HOST_NAME aka "net.host.name"

Fixes googleapis#1170
  • Loading branch information
odeke-em committed Jul 25, 2024
1 parent fe20d41 commit 3e99517
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 56 deletions.
2 changes: 1 addition & 1 deletion docs/opentelemetry-tracing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ To take advantage of these traces, we first need to install OpenTelemetry:

.. code-block:: sh
pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation
pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation opentelemetry-semantic-conventions
# [Optional] Installs the cloud monitoring exporter, however you can use any exporter of your choice
pip install opentelemetry-exporter-google-cloud
Expand Down
9 changes: 5 additions & 4 deletions google/cloud/spanner_v1/_opentelemetry_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
try:
from opentelemetry import trace
from opentelemetry.trace.status import Status, StatusCode
from opentelemetry.semconv.attributes import DB_SYSTEM, DB_NAME, DB_CONNECTION_STRING, NET_HOST_NAME

HAS_OPENTELEMETRY_INSTALLED = True
except ImportError:
Expand All @@ -39,10 +40,10 @@ def trace_call(name, session, extra_attributes=None):

# Set base attributes that we know for every trace created
attributes = {
"db.type": "spanner",
"db.url": SpannerClient.DEFAULT_ENDPOINT,
"db.instance": session._database.name,
"net.host.name": SpannerClient.DEFAULT_ENDPOINT,
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: SpannerClient.DEFAULT_ENDPOINT,
DB_NAME: session._database.name,
NET_HOST_NAME: SpannerClient.DEFAULT_ENDPOINT,
}

if extra_attributes:
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"opentelemetry-api >= 1.1.0",
"opentelemetry-sdk >= 1.1.0",
"opentelemetry-instrumentation >= 0.20b0, < 0.23dev",
"opentelemetry-semantic-conventions >= 0.20b0",
],
"libcst": "libcst >= 0.2.5",
}
Expand Down
1 change: 1 addition & 0 deletions testing/constraints-3.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ sqlparse==0.4.4
opentelemetry-api==1.1.0
opentelemetry-sdk==1.1.0
opentelemetry-instrumentation==0.20b0
opentelemetry-semantic-conventions==0.20b0
protobuf==3.20.2
deprecated==1.2.14
grpc-interceptor==0.15.4
3 changes: 3 additions & 0 deletions tests/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
InMemorySpanExporter,
)
from opentelemetry.trace.status import StatusCode
from opentelemetry.semconv.attributes import (
DB_SYSTEM, DB_NAME, DB_CONNECTION_STRING, NET_HOST_NAME
)

trace.set_tracer_provider(TracerProvider())

Expand Down
8 changes: 4 additions & 4 deletions tests/system/test_session_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,10 +341,10 @@ def assert_span_attributes(

def _make_attributes(db_instance, **kwargs):
attributes = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"net.host.name": "spanner.googleapis.com",
"db.instance": db_instance,
ot_helpers.DB_SYSTEM: "google.cloud.spanner",
ot_helpers.DB_CONNECTION_STRING: "spanner.googleapis.com",
ot_helpers.DB_NAME: db_instance,
ot_helpers.NET_HOST_NAME: "spanner.googleapis.com",
}
attributes.update(kwargs)

Expand Down
46 changes: 27 additions & 19 deletions tests/unit/test__opentelemetry_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@
try:
from opentelemetry import trace as trace_api
from opentelemetry.trace.status import StatusCode
from opentelemetry.semconv.attributes import (
DB_SYSTEM, DB_NAME, DB_CONNECTION_STRING, NET_HOST_NAME
)
except ImportError:
pass

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, StatusCode, DB_SYSTEM, DB_NAME,
DB_CONNECTION_STRING, NET_HOST_NAME
)

def _make_rpc_error(error_cls, trailing_metadata=None):
import grpc
Expand Down Expand Up @@ -51,14 +56,14 @@ class TestTracing(OpenTelemetryBase):
def test_trace_call(self):
extra_attributes = {
"attribute1": "value1",
# Since our database is mocked, we have to override the db.instance parameter so it is a string
"db.instance": "database_name",
# Since our database is mocked, we have to override the DB_NAME parameter so it is a string
DB_NAME: "database_name",
}

expected_attributes = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
NET_HOST_NAME: "spanner.googleapis.com",
}
expected_attributes.update(extra_attributes)

Expand All @@ -78,13 +83,14 @@ def test_trace_call(self):
self.assertEqual(span.status.status_code, StatusCode.OK)

def test_trace_error(self):
extra_attributes = {"db.instance": "database_name"}
extra_attributes = {DB_NAME: "database_name"}

expected_attributes = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
NET_HOST_NAME: "spanner.googleapis.com",
}

expected_attributes.update(extra_attributes)

with self.assertRaises(GoogleAPICallError):
Expand All @@ -104,13 +110,14 @@ def test_trace_error(self):
self.assertEqual(span.status.status_code, StatusCode.ERROR)

def test_trace_grpc_error(self):
extra_attributes = {"db.instance": "database_name"}
extra_attributes = {DB_NAME: "database_name"}

expected_attributes = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com:443",
"net.host.name": "spanner.googleapis.com:443",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
NET_HOST_NAME: "spanner.googleapis.com",
}

expected_attributes.update(extra_attributes)

with self.assertRaises(GoogleAPICallError):
Expand All @@ -127,13 +134,14 @@ def test_trace_grpc_error(self):
self.assertEqual(span.status.status_code, StatusCode.ERROR)

def test_trace_codeless_error(self):
extra_attributes = {"db.instance": "database_name"}
extra_attributes = {DB_NAME: "database_name"}

expected_attributes = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com:443",
"net.host.name": "spanner.googleapis.com:443",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
NET_HOST_NAME: "spanner.googleapis.com",
}

expected_attributes.update(extra_attributes)

with self.assertRaises(GoogleAPICallError):
Expand Down
17 changes: 12 additions & 5 deletions tests/unit/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@


import unittest
from tests._helpers import OpenTelemetryBase, StatusCode
from tests._helpers import (
OpenTelemetryBase,
StatusCode,
DB_SYSTEM,
DB_NAME,
DB_CONNECTION_STRING,
NET_HOST_NAME,
)
from google.cloud.spanner_v1 import RequestOptions

TABLE_NAME = "citizens"
Expand All @@ -24,10 +31,10 @@
["[email protected]", "Bharney", "Rhubble", 31],
]
BASE_ATTRIBUTES = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"db.instance": "testing",
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
DB_NAME: "testing",
NET_HOST_NAME: "spanner.googleapis.com",
}


Expand Down
13 changes: 8 additions & 5 deletions tests/unit/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
OpenTelemetryBase,
StatusCode,
HAS_OPENTELEMETRY_INSTALLED,
DB_SYSTEM,
DB_NAME,
DB_CONNECTION_STRING,
NET_HOST_NAME,
)


Expand All @@ -46,12 +50,11 @@ class TestSession(OpenTelemetryBase):
SESSION_NAME = DATABASE_NAME + "/sessions/" + SESSION_ID
DATABASE_ROLE = "dummy-role"
BASE_ATTRIBUTES = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"db.instance": DATABASE_NAME,
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
DB_NAME: DATABASE_NAME,
NET_HOST_NAME: "spanner.googleapis.com",
}

def _getTargetClass(self):
from google.cloud.spanner_v1.session import Session

Expand Down
20 changes: 12 additions & 8 deletions tests/unit/test_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
OpenTelemetryBase,
StatusCode,
HAS_OPENTELEMETRY_INSTALLED,
DB_SYSTEM,
DB_NAME,
DB_CONNECTION_STRING,
NET_HOST_NAME,
)
from google.cloud.spanner_v1.param_types import INT64
from google.api_core.retry import Retry
Expand All @@ -41,10 +45,10 @@
SECONDS = 3
MICROS = 123456
BASE_ATTRIBUTES = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"db.instance": "testing",
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
DB_NAME: "testing",
NET_HOST_NAME: "spanner.googleapis.com",
}
DIRECTED_READ_OPTIONS = {
"include_replicas": {
Expand Down Expand Up @@ -531,10 +535,10 @@ def test_iteration_w_multiple_span_creation(self):
self.assertEqual(
dict(span.attributes),
{
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"db.instance": "testing",
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
DB_NAME: "testing",
NET_HOST_NAME: "spanner.googleapis.com",
},
)

Expand Down
16 changes: 11 additions & 5 deletions tests/unit/test_spanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@

from google.api_core import gapic_v1

from tests._helpers import OpenTelemetryBase
from tests._helpers import (
OpenTelemetryBase,
DB_SYSTEM,
DB_NAME,
DB_CONNECTION_STRING,
NET_HOST_NAME,
)

TABLE_NAME = "citizens"
COLUMNS = ["email", "first_name", "last_name", "age"]
Expand Down Expand Up @@ -110,10 +116,10 @@ class TestTransaction(OpenTelemetryBase):
TRANSACTION_TAG = "transaction-tag"

BASE_ATTRIBUTES = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"db.instance": "testing",
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
DB_NAME: "testing",
NET_HOST_NAME: "spanner.googleapis.com",
}

def _getTargetClass(self):
Expand Down
17 changes: 12 additions & 5 deletions tests/unit/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@
from google.api_core.retry import Retry
from google.api_core import gapic_v1

from tests._helpers import OpenTelemetryBase, StatusCode
from tests._helpers import (
OpenTelemetryBase,
StatusCode,
DB_SYSTEM,
DB_NAME,
DB_CONNECTION_STRING,
NET_HOST_NAME,
)

TABLE_NAME = "citizens"
COLUMNS = ["email", "first_name", "last_name", "age"]
Expand Down Expand Up @@ -53,10 +60,10 @@ class TestTransaction(OpenTelemetryBase):
TRANSACTION_TAG = "transaction-tag"

BASE_ATTRIBUTES = {
"db.type": "spanner",
"db.url": "spanner.googleapis.com",
"db.instance": "testing",
"net.host.name": "spanner.googleapis.com",
DB_SYSTEM: "google.cloud.spanner",
DB_CONNECTION_STRING: "spanner.googleapis.com",
DB_NAME: "testing",
NET_HOST_NAME: "spanner.googleapis.com",
}

def _getTargetClass(self):
Expand Down

0 comments on commit 3e99517

Please sign in to comment.