Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix: for open-telemetry status code spec change #362

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions 13 google/cloud/spanner_v1/_opentelemetry_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@

try:
from opentelemetry import trace
from opentelemetry.trace.status import Status, StatusCanonicalCode
from opentelemetry.instrumentation.utils import http_status_to_canonical_code
from opentelemetry.trace.status import Status, StatusCode

HAS_OPENTELEMETRY_INSTALLED = True
except ImportError:
Expand Down Expand Up @@ -53,13 +52,9 @@ def trace_call(name, session, extra_attributes=None):
name, kind=trace.SpanKind.CLIENT, attributes=attributes
) as span:
try:
span.set_status(Status(StatusCode.OK))
yield span
except GoogleAPICallError as error:
if error.code is not None:
span.set_status(Status(http_status_to_canonical_code(error.code)))
elif error.grpc_status_code is not None:
span.set_status(
# OpenTelemetry's StatusCanonicalCode maps 1-1 with grpc status codes
Status(StatusCanonicalCode(error.grpc_status_code.value[0]))
)
span.set_status(Status(StatusCode.ERROR))
span.record_exception(error)
raise
6 changes: 3 additions & 3 deletions 6 setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
]
extras = {
"tracing": [
"opentelemetry-api >= 0.11b0",
"opentelemetry-sdk >= 0.11b0",
"opentelemetry-instrumentation >= 0.11b0",
"opentelemetry-api >= 1.1.0",
"opentelemetry-sdk >= 1.1.0",
"opentelemetry-instrumentation >= 0.20b0",
],
"libcst": "libcst >= 0.2.5",
}
Expand Down
6 changes: 3 additions & 3 deletions 6 testing/constraints-3.6.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ grpc-google-iam-v1==0.12.3
libcst==0.2.5
proto-plus==1.13.0
sqlparse==0.3.0
opentelemetry-api==0.11b0
opentelemetry-sdk==0.11b0
opentelemetry-instrumentation==0.11b0
opentelemetry-api==1.1.0
opentelemetry-sdk==1.1.0
opentelemetry-instrumentation==0.20b0
57 changes: 40 additions & 17 deletions 57 tests/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,72 @@
import mock

try:
from opentelemetry import trace as trace_api
from opentelemetry.trace.status import StatusCanonicalCode

from opentelemetry.sdk.trace import TracerProvider, export
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
InMemorySpanExporter,
)
from opentelemetry.trace.status import StatusCode

trace.set_tracer_provider(TracerProvider())

HAS_OPENTELEMETRY_INSTALLED = True
except ImportError:
HAS_OPENTELEMETRY_INSTALLED = False

StatusCanonicalCode = mock.Mock()
StatusCode = mock.Mock()

_TEST_OT_EXPORTER = None
_TEST_OT_PROVIDER_INITIALIZED = False


def get_test_ot_exporter():
global _TEST_OT_EXPORTER

if _TEST_OT_EXPORTER is None:
_TEST_OT_EXPORTER = InMemorySpanExporter()
return _TEST_OT_EXPORTER


def use_test_ot_exporter():
global _TEST_OT_PROVIDER_INITIALIZED

if _TEST_OT_PROVIDER_INITIALIZED:
return

provider = trace.get_tracer_provider()
if not hasattr(provider, "add_span_processor"):
return
provider.add_span_processor(SimpleSpanProcessor(get_test_ot_exporter()))
_TEST_OT_PROVIDER_INITIALIZED = True


class OpenTelemetryBase(unittest.TestCase):
def setUp(self):
@classmethod
def setUpClass(cls):
if HAS_OPENTELEMETRY_INSTALLED:
self.original_tracer_provider = trace_api.get_tracer_provider()
self.tracer_provider = TracerProvider()
self.memory_exporter = InMemorySpanExporter()
span_processor = export.SimpleExportSpanProcessor(self.memory_exporter)
self.tracer_provider.add_span_processor(span_processor)
trace_api.set_tracer_provider(self.tracer_provider)
use_test_ot_exporter()
cls.ot_exporter = get_test_ot_exporter()

def tearDown(self):
if HAS_OPENTELEMETRY_INSTALLED:
trace_api.set_tracer_provider(self.original_tracer_provider)
self.ot_exporter.clear()

def assertNoSpans(self):
if HAS_OPENTELEMETRY_INSTALLED:
span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 0)

def assertSpanAttributes(
self, name, status=StatusCanonicalCode.OK, attributes=None, span=None
self, name, status=StatusCode.OK, attributes=None, span=None
):
if HAS_OPENTELEMETRY_INSTALLED:
if not span:
span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
span = span_list[0]

self.assertEqual(span.name, name)
self.assertEqual(span.status.canonical_code, status)
self.assertEqual(span.status.status_code, status)
self.assertEqual(dict(span.attributes), attributes)
13 changes: 10 additions & 3 deletions 13 tests/system/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,8 @@ class TestSessionAPI(OpenTelemetryBase, _TestData):

@classmethod
def setUpClass(cls):
# Call SetUpClass from parent (OpenTelemetryBase)
super(TestSessionAPI, cls).setUpClass()
pool = BurstyPool(labels={"testcase": "session_api"})
ddl_statements = EMULATOR_DDL_STATEMENTS if USE_EMULATOR else DDL_STATEMENTS
cls._db = Config.INSTANCE.database(
Expand All @@ -1187,6 +1189,8 @@ def tearDown(self):
super(TestSessionAPI, self).tearDown()
for doomed in self.to_delete:
doomed.delete()
if HAS_OPENTELEMETRY_INSTALLED:
self.ot_exporter.clear() # Clear any ot spans from above step.

def test_session_crud(self):
retry_true = RetryResult(operator.truth)
Expand All @@ -1211,7 +1215,7 @@ def test_batch_insert_then_read(self):
self._check_rows_data(rows)

if HAS_OPENTELEMETRY_INSTALLED:
span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 4)
self.assertSpanAttributes(
"CloudSpanner.GetSession",
Expand Down Expand Up @@ -1355,7 +1359,7 @@ def test_transaction_read_and_insert_then_rollback(self):
self.assertEqual(rows, [])

if HAS_OPENTELEMETRY_INSTALLED:
span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 8)
self.assertSpanAttributes(
"CloudSpanner.CreateSession",
Expand Down Expand Up @@ -1736,6 +1740,9 @@ def test_transaction_batch_update_w_parent_span(self):
retry = RetryInstanceState(_has_all_ddl)
retry(self._db.reload)()

if HAS_OPENTELEMETRY_INSTALLED:
self.ot_exporter.clear() # Clear any ot spans from above steps.

session = self._db.session()
session.create()
self.to_delete.append(session)
Expand Down Expand Up @@ -1768,7 +1775,7 @@ def unit_of_work(transaction, self):
with tracer.start_as_current_span("Test Span"):
session.run_in_transaction(unit_of_work, self)

span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 6)
self.assertEqual(
list(map(lambda span: span.name, span_list)),
Expand Down
20 changes: 9 additions & 11 deletions 20 tests/unit/test__opentelemetry_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

try:
from opentelemetry import trace as trace_api
from opentelemetry.trace.status import StatusCanonicalCode
from opentelemetry.trace.status import StatusCode
except ImportError:
pass

Expand Down Expand Up @@ -69,13 +69,13 @@ def test_trace_call(self):

expected_attributes["after_setup_attribute"] = 1

span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
span = span_list[0]
self.assertEqual(span.kind, trace_api.SpanKind.CLIENT)
self.assertEqual(span.attributes, expected_attributes)
self.assertEqual(span.name, "CloudSpanner.Test")
self.assertEqual(span.status.canonical_code, StatusCanonicalCode.OK)
self.assertEqual(span.status.status_code, StatusCode.OK)

def test_trace_error(self):
extra_attributes = {"db.instance": "database_name"}
Expand All @@ -95,15 +95,13 @@ def test_trace_error(self):

raise _make_rpc_error(InvalidArgument)

span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
span = span_list[0]
self.assertEqual(span.kind, trace_api.SpanKind.CLIENT)
self.assertEqual(dict(span.attributes), expected_attributes)
self.assertEqual(span.name, "CloudSpanner.Test")
self.assertEqual(
span.status.canonical_code, StatusCanonicalCode.INVALID_ARGUMENT
)
self.assertEqual(span.status.status_code, StatusCode.ERROR)

def test_trace_grpc_error(self):
extra_attributes = {"db.instance": "database_name"}
Expand All @@ -123,10 +121,10 @@ def test_trace_grpc_error(self):

raise DataLoss("error")

span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
span = span_list[0]
self.assertEqual(span.status.canonical_code, StatusCanonicalCode.DATA_LOSS)
self.assertEqual(span.status.status_code, StatusCode.ERROR)

def test_trace_codeless_error(self):
extra_attributes = {"db.instance": "database_name"}
Expand All @@ -144,7 +142,7 @@ def test_trace_codeless_error(self):
) as span:
raise GoogleAPICallError("error")

span_list = self.memory_exporter.get_finished_spans()
span_list = self.ot_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
span = span_list[0]
self.assertEqual(span.status.canonical_code, StatusCanonicalCode.UNKNOWN)
self.assertEqual(span.status.status_code, StatusCode.ERROR)
4 changes: 2 additions & 2 deletions 4 tests/unit/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


import unittest
from tests._helpers import OpenTelemetryBase, StatusCanonicalCode
from tests._helpers import OpenTelemetryBase, StatusCode

TABLE_NAME = "citizens"
COLUMNS = ["email", "first_name", "last_name", "age"]
Expand Down Expand Up @@ -207,7 +207,7 @@ def test_commit_grpc_error(self):

self.assertSpanAttributes(
"CloudSpanner.Commit",
status=StatusCanonicalCode.UNKNOWN,
status=StatusCode.ERROR,
attributes=dict(BASE_ATTRIBUTES, num_mutations=1),
)

Expand Down
14 changes: 7 additions & 7 deletions 14 tests/unit/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import mock
from tests._helpers import (
OpenTelemetryBase,
StatusCanonicalCode,
StatusCode,
HAS_OPENTELEMETRY_INSTALLED,
)

Expand Down Expand Up @@ -192,7 +192,7 @@ def test_create_error(self):

self.assertSpanAttributes(
"CloudSpanner.CreateSession",
status=StatusCanonicalCode.UNKNOWN,
status=StatusCode.ERROR,
attributes=TestSession.BASE_ATTRIBUTES,
)

Expand Down Expand Up @@ -311,7 +311,7 @@ def test_exists_error(self):

self.assertSpanAttributes(
"CloudSpanner.GetSession",
status=StatusCanonicalCode.UNKNOWN,
status=StatusCode.ERROR,
attributes=TestSession.BASE_ATTRIBUTES,
)

Expand Down Expand Up @@ -427,7 +427,7 @@ def test_delete_miss(self):

self.assertSpanAttributes(
"CloudSpanner.DeleteSession",
status=StatusCanonicalCode.NOT_FOUND,
status=StatusCode.ERROR,
attributes=TestSession.BASE_ATTRIBUTES,
)

Expand All @@ -451,7 +451,7 @@ def test_delete_error(self):

self.assertSpanAttributes(
"CloudSpanner.DeleteSession",
status=StatusCanonicalCode.UNKNOWN,
status=StatusCode.ERROR,
attributes=TestSession.BASE_ATTRIBUTES,
)

Expand Down Expand Up @@ -1190,7 +1190,7 @@ def _time(_results=[1, 1.5]):

with mock.patch("time.time", _time):
if HAS_OPENTELEMETRY_INSTALLED:
with mock.patch("opentelemetry.util.time", _ConstantTime()):
with mock.patch("opentelemetry.util._time", _ConstantTime()):
with mock.patch("time.sleep") as sleep_mock:
with self.assertRaises(Aborted):
session.run_in_transaction(
Expand Down Expand Up @@ -1263,7 +1263,7 @@ def _time(_results=[1, 2, 4, 8]):

with mock.patch("time.time", _time):
if HAS_OPENTELEMETRY_INSTALLED:
with mock.patch("opentelemetry.util.time", _ConstantTime()):
with mock.patch("opentelemetry.util._time", _ConstantTime()):
with mock.patch("time.sleep") as sleep_mock:
with self.assertRaises(Aborted):
session.run_in_transaction(unit_of_work, timeout_secs=8)
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.