Skip to content

Commit 0f894f1

Browse files
authored
fix: update to support the open-telemetry status code spec change (#358)
* fix: for opentelemetry status code spec change * fix: corrected open telemetry tests to work with latest open telemetry specs * fix: correct open telemetry tests status code * fix: open telemetry schema related changes and fixes for tests to work with in memory exporter * fix: variable name correction for ot_exporter * fix: correct variable name from memeory_exporter to ot_exporter * fix: remove patch for opentelemetry.util.time with _constant_time as it was not used * refactor: correct opentelemetry.util.time to opentelemetry.util._time * ci: update packages for open telemetry * refactor: increased version of open telemetry as per new specs * fix: changed opentelemetry dependency version * updated constraints file with opentelemetry-instrumentation >= 0.20b0 * fix: added ot_exporter clear call after reload to clear out the exporter memeory * fix: removed repeated constraints for different versions of python
1 parent 6598dea commit 0f894f1

File tree

10 files changed

+94
-71
lines changed

10 files changed

+94
-71
lines changed

google/cloud/spanner_v1/_opentelemetry_tracing.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121

2222
try:
2323
from opentelemetry import trace
24-
from opentelemetry.trace.status import Status, StatusCanonicalCode
25-
from opentelemetry.instrumentation.utils import http_status_to_canonical_code
24+
from opentelemetry.trace.status import Status, StatusCode
2625

2726
HAS_OPENTELEMETRY_INSTALLED = True
2827
except ImportError:
@@ -53,13 +52,9 @@ def trace_call(name, session, extra_attributes=None):
5352
name, kind=trace.SpanKind.CLIENT, attributes=attributes
5453
) as span:
5554
try:
55+
span.set_status(Status(StatusCode.OK))
5656
yield span
5757
except GoogleAPICallError as error:
58-
if error.code is not None:
59-
span.set_status(Status(http_status_to_canonical_code(error.code)))
60-
elif error.grpc_status_code is not None:
61-
span.set_status(
62-
# OpenTelemetry's StatusCanonicalCode maps 1-1 with grpc status codes
63-
Status(StatusCanonicalCode(error.grpc_status_code.value[0]))
64-
)
58+
span.set_status(Status(StatusCode.ERROR))
59+
span.record_exception(error)
6560
raise

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
]
3838
extras = {
3939
"tracing": [
40-
"opentelemetry-api >= 0.11b0",
41-
"opentelemetry-sdk >= 0.11b0",
42-
"opentelemetry-instrumentation >= 0.11b0",
40+
"opentelemetry-api >= 1.1.0",
41+
"opentelemetry-sdk >= 1.1.0",
42+
"opentelemetry-instrumentation >= 0.20b0",
4343
],
4444
"libcst": "libcst >= 0.2.5",
4545
}

testing/constraints-3.6.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ grpc-google-iam-v1==0.12.3
1111
libcst==0.2.5
1212
proto-plus==1.13.0
1313
sqlparse==0.3.0
14-
opentelemetry-api==0.11b0
15-
opentelemetry-sdk==0.11b0
16-
opentelemetry-instrumentation==0.11b0
14+
opentelemetry-api==1.1.0
15+
opentelemetry-sdk==1.1.0
16+
opentelemetry-instrumentation==0.20b0

tests/_helpers.py

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,72 @@
22
import mock
33

44
try:
5-
from opentelemetry import trace as trace_api
6-
from opentelemetry.trace.status import StatusCanonicalCode
7-
8-
from opentelemetry.sdk.trace import TracerProvider, export
5+
from opentelemetry import trace
6+
from opentelemetry.sdk.trace import TracerProvider
7+
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
98
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
109
InMemorySpanExporter,
1110
)
11+
from opentelemetry.trace.status import StatusCode
12+
13+
trace.set_tracer_provider(TracerProvider())
1214

1315
HAS_OPENTELEMETRY_INSTALLED = True
1416
except ImportError:
1517
HAS_OPENTELEMETRY_INSTALLED = False
1618

17-
StatusCanonicalCode = mock.Mock()
19+
StatusCode = mock.Mock()
20+
21+
_TEST_OT_EXPORTER = None
22+
_TEST_OT_PROVIDER_INITIALIZED = False
23+
24+
25+
def get_test_ot_exporter():
26+
global _TEST_OT_EXPORTER
27+
28+
if _TEST_OT_EXPORTER is None:
29+
_TEST_OT_EXPORTER = InMemorySpanExporter()
30+
return _TEST_OT_EXPORTER
31+
32+
33+
def use_test_ot_exporter():
34+
global _TEST_OT_PROVIDER_INITIALIZED
35+
36+
if _TEST_OT_PROVIDER_INITIALIZED:
37+
return
38+
39+
provider = trace.get_tracer_provider()
40+
if not hasattr(provider, "add_span_processor"):
41+
return
42+
provider.add_span_processor(SimpleSpanProcessor(get_test_ot_exporter()))
43+
_TEST_OT_PROVIDER_INITIALIZED = True
1844

1945

2046
class OpenTelemetryBase(unittest.TestCase):
21-
def setUp(self):
47+
@classmethod
48+
def setUpClass(cls):
2249
if HAS_OPENTELEMETRY_INSTALLED:
23-
self.original_tracer_provider = trace_api.get_tracer_provider()
24-
self.tracer_provider = TracerProvider()
25-
self.memory_exporter = InMemorySpanExporter()
26-
span_processor = export.SimpleExportSpanProcessor(self.memory_exporter)
27-
self.tracer_provider.add_span_processor(span_processor)
28-
trace_api.set_tracer_provider(self.tracer_provider)
50+
use_test_ot_exporter()
51+
cls.ot_exporter = get_test_ot_exporter()
2952

3053
def tearDown(self):
3154
if HAS_OPENTELEMETRY_INSTALLED:
32-
trace_api.set_tracer_provider(self.original_tracer_provider)
55+
self.ot_exporter.clear()
3356

3457
def assertNoSpans(self):
3558
if HAS_OPENTELEMETRY_INSTALLED:
36-
span_list = self.memory_exporter.get_finished_spans()
59+
span_list = self.ot_exporter.get_finished_spans()
3760
self.assertEqual(len(span_list), 0)
3861

3962
def assertSpanAttributes(
40-
self, name, status=StatusCanonicalCode.OK, attributes=None, span=None
63+
self, name, status=StatusCode.OK, attributes=None, span=None
4164
):
4265
if HAS_OPENTELEMETRY_INSTALLED:
4366
if not span:
44-
span_list = self.memory_exporter.get_finished_spans()
67+
span_list = self.ot_exporter.get_finished_spans()
4568
self.assertEqual(len(span_list), 1)
4669
span = span_list[0]
4770

4871
self.assertEqual(span.name, name)
49-
self.assertEqual(span.status.canonical_code, status)
72+
self.assertEqual(span.status.status_code, status)
5073
self.assertEqual(dict(span.attributes), attributes)

tests/system/test_system.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,8 @@ class TestSessionAPI(OpenTelemetryBase, _TestData):
11651165

11661166
@classmethod
11671167
def setUpClass(cls):
1168+
# Call SetUpClass from parent (OpenTelemetryBase)
1169+
super(TestSessionAPI, cls).setUpClass()
11681170
pool = BurstyPool(labels={"testcase": "session_api"})
11691171
ddl_statements = EMULATOR_DDL_STATEMENTS if USE_EMULATOR else DDL_STATEMENTS
11701172
cls._db = Config.INSTANCE.database(
@@ -1187,6 +1189,8 @@ def tearDown(self):
11871189
super(TestSessionAPI, self).tearDown()
11881190
for doomed in self.to_delete:
11891191
doomed.delete()
1192+
if HAS_OPENTELEMETRY_INSTALLED:
1193+
self.ot_exporter.clear() # Clear any ot spans from above step.
11901194

11911195
def test_session_crud(self):
11921196
retry_true = RetryResult(operator.truth)
@@ -1211,7 +1215,7 @@ def test_batch_insert_then_read(self):
12111215
self._check_rows_data(rows)
12121216

12131217
if HAS_OPENTELEMETRY_INSTALLED:
1214-
span_list = self.memory_exporter.get_finished_spans()
1218+
span_list = self.ot_exporter.get_finished_spans()
12151219
self.assertEqual(len(span_list), 4)
12161220
self.assertSpanAttributes(
12171221
"CloudSpanner.GetSession",
@@ -1355,7 +1359,7 @@ def test_transaction_read_and_insert_then_rollback(self):
13551359
self.assertEqual(rows, [])
13561360

13571361
if HAS_OPENTELEMETRY_INSTALLED:
1358-
span_list = self.memory_exporter.get_finished_spans()
1362+
span_list = self.ot_exporter.get_finished_spans()
13591363
self.assertEqual(len(span_list), 8)
13601364
self.assertSpanAttributes(
13611365
"CloudSpanner.CreateSession",
@@ -1736,6 +1740,9 @@ def test_transaction_batch_update_w_parent_span(self):
17361740
retry = RetryInstanceState(_has_all_ddl)
17371741
retry(self._db.reload)()
17381742

1743+
if HAS_OPENTELEMETRY_INSTALLED:
1744+
self.ot_exporter.clear() # Clear any ot spans from above steps.
1745+
17391746
session = self._db.session()
17401747
session.create()
17411748
self.to_delete.append(session)
@@ -1768,7 +1775,7 @@ def unit_of_work(transaction, self):
17681775
with tracer.start_as_current_span("Test Span"):
17691776
session.run_in_transaction(unit_of_work, self)
17701777

1771-
span_list = self.memory_exporter.get_finished_spans()
1778+
span_list = self.ot_exporter.get_finished_spans()
17721779
self.assertEqual(len(span_list), 6)
17731780
self.assertEqual(
17741781
list(map(lambda span: span.name, span_list)),

tests/unit/test__opentelemetry_tracing.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
try:
77
from opentelemetry import trace as trace_api
8-
from opentelemetry.trace.status import StatusCanonicalCode
8+
from opentelemetry.trace.status import StatusCode
99
except ImportError:
1010
pass
1111

@@ -69,13 +69,13 @@ def test_trace_call(self):
6969

7070
expected_attributes["after_setup_attribute"] = 1
7171

72-
span_list = self.memory_exporter.get_finished_spans()
72+
span_list = self.ot_exporter.get_finished_spans()
7373
self.assertEqual(len(span_list), 1)
7474
span = span_list[0]
7575
self.assertEqual(span.kind, trace_api.SpanKind.CLIENT)
7676
self.assertEqual(span.attributes, expected_attributes)
7777
self.assertEqual(span.name, "CloudSpanner.Test")
78-
self.assertEqual(span.status.canonical_code, StatusCanonicalCode.OK)
78+
self.assertEqual(span.status.status_code, StatusCode.OK)
7979

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

9696
raise _make_rpc_error(InvalidArgument)
9797

98-
span_list = self.memory_exporter.get_finished_spans()
98+
span_list = self.ot_exporter.get_finished_spans()
9999
self.assertEqual(len(span_list), 1)
100100
span = span_list[0]
101101
self.assertEqual(span.kind, trace_api.SpanKind.CLIENT)
102102
self.assertEqual(dict(span.attributes), expected_attributes)
103103
self.assertEqual(span.name, "CloudSpanner.Test")
104-
self.assertEqual(
105-
span.status.canonical_code, StatusCanonicalCode.INVALID_ARGUMENT
106-
)
104+
self.assertEqual(span.status.status_code, StatusCode.ERROR)
107105

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

124122
raise DataLoss("error")
125123

126-
span_list = self.memory_exporter.get_finished_spans()
124+
span_list = self.ot_exporter.get_finished_spans()
127125
self.assertEqual(len(span_list), 1)
128126
span = span_list[0]
129-
self.assertEqual(span.status.canonical_code, StatusCanonicalCode.DATA_LOSS)
127+
self.assertEqual(span.status.status_code, StatusCode.ERROR)
130128

131129
def test_trace_codeless_error(self):
132130
extra_attributes = {"db.instance": "database_name"}
@@ -144,7 +142,7 @@ def test_trace_codeless_error(self):
144142
) as span:
145143
raise GoogleAPICallError("error")
146144

147-
span_list = self.memory_exporter.get_finished_spans()
145+
span_list = self.ot_exporter.get_finished_spans()
148146
self.assertEqual(len(span_list), 1)
149147
span = span_list[0]
150-
self.assertEqual(span.status.canonical_code, StatusCanonicalCode.UNKNOWN)
148+
self.assertEqual(span.status.status_code, StatusCode.ERROR)

tests/unit/test_batch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515

1616
import unittest
17-
from tests._helpers import OpenTelemetryBase, StatusCanonicalCode
17+
from tests._helpers import OpenTelemetryBase, StatusCode
1818

1919
TABLE_NAME = "citizens"
2020
COLUMNS = ["email", "first_name", "last_name", "age"]
@@ -207,7 +207,7 @@ def test_commit_grpc_error(self):
207207

208208
self.assertSpanAttributes(
209209
"CloudSpanner.Commit",
210-
status=StatusCanonicalCode.UNKNOWN,
210+
status=StatusCode.ERROR,
211211
attributes=dict(BASE_ATTRIBUTES, num_mutations=1),
212212
)
213213

tests/unit/test_session.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import mock
1818
from tests._helpers import (
1919
OpenTelemetryBase,
20-
StatusCanonicalCode,
20+
StatusCode,
2121
HAS_OPENTELEMETRY_INSTALLED,
2222
)
2323

@@ -192,7 +192,7 @@ def test_create_error(self):
192192

193193
self.assertSpanAttributes(
194194
"CloudSpanner.CreateSession",
195-
status=StatusCanonicalCode.UNKNOWN,
195+
status=StatusCode.ERROR,
196196
attributes=TestSession.BASE_ATTRIBUTES,
197197
)
198198

@@ -311,7 +311,7 @@ def test_exists_error(self):
311311

312312
self.assertSpanAttributes(
313313
"CloudSpanner.GetSession",
314-
status=StatusCanonicalCode.UNKNOWN,
314+
status=StatusCode.ERROR,
315315
attributes=TestSession.BASE_ATTRIBUTES,
316316
)
317317

@@ -427,7 +427,7 @@ def test_delete_miss(self):
427427

428428
self.assertSpanAttributes(
429429
"CloudSpanner.DeleteSession",
430-
status=StatusCanonicalCode.NOT_FOUND,
430+
status=StatusCode.ERROR,
431431
attributes=TestSession.BASE_ATTRIBUTES,
432432
)
433433

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

452452
self.assertSpanAttributes(
453453
"CloudSpanner.DeleteSession",
454-
status=StatusCanonicalCode.UNKNOWN,
454+
status=StatusCode.ERROR,
455455
attributes=TestSession.BASE_ATTRIBUTES,
456456
)
457457

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

11911191
with mock.patch("time.time", _time):
11921192
if HAS_OPENTELEMETRY_INSTALLED:
1193-
with mock.patch("opentelemetry.util.time", _ConstantTime()):
1193+
with mock.patch("opentelemetry.util._time", _ConstantTime()):
11941194
with mock.patch("time.sleep") as sleep_mock:
11951195
with self.assertRaises(Aborted):
11961196
session.run_in_transaction(
@@ -1263,7 +1263,7 @@ def _time(_results=[1, 2, 4, 8]):
12631263

12641264
with mock.patch("time.time", _time):
12651265
if HAS_OPENTELEMETRY_INSTALLED:
1266-
with mock.patch("opentelemetry.util.time", _ConstantTime()):
1266+
with mock.patch("opentelemetry.util._time", _ConstantTime()):
12671267
with mock.patch("time.sleep") as sleep_mock:
12681268
with self.assertRaises(Aborted):
12691269
session.run_in_transaction(unit_of_work, timeout_secs=8)

0 commit comments

Comments
 (0)