@@ -137,3 +137,48 @@ def _make_credentials():
137137 from google .auth .credentials import AnonymousCredentials
138138
139139 return AnonymousCredentials ()
140+
141+
142+ from tests import _helpers as ot_helpers
143+
144+
145+ @pytest .mark .skipif (
146+ not ot_helpers .HAS_OPENTELEMETRY_INSTALLED ,
147+ reason = "Tracing requires OpenTelemetry" ,
148+ )
149+ def test_trace_call_keeps_span_error_status ():
150+ # Verifies that after our span's status was set to ERROR
151+ # that it doesn't unconditionally get changed to OK
152+ # per https://github.com/googleapis/python-spanner/issues/1246
153+ from opentelemetry .sdk .trace .export import SimpleSpanProcessor
154+ from opentelemetry .sdk .trace .export .in_memory_span_exporter import (
155+ InMemorySpanExporter ,
156+ )
157+ from google .cloud .spanner_v1 ._opentelemetry_tracing import trace_call
158+ from opentelemetry .trace .status import Status , StatusCode
159+ from opentelemetry .sdk .trace import TracerProvider
160+ from opentelemetry .sdk .trace .sampling import ALWAYS_ON
161+ from opentelemetry import trace
162+
163+ tracer_provider = TracerProvider (sampler = ALWAYS_ON )
164+ trace_exporter = InMemorySpanExporter ()
165+ tracer_provider .add_span_processor (SimpleSpanProcessor (trace_exporter ))
166+ observability_options = dict (tracer_provider = tracer_provider )
167+
168+ with trace_call (
169+ "VerifyBehavior" , observability_options = observability_options
170+ ) as span :
171+ span .set_status (Status (StatusCode .ERROR , "Our error exhibit" ))
172+
173+ span_list = trace_exporter .get_finished_spans ()
174+ got_statuses = []
175+
176+ for span in span_list :
177+ got_statuses .append (
178+ (span .name , span .status .status_code , span .status .description )
179+ )
180+
181+ want_statuses = [
182+ ("VerifyBehavior" , StatusCode .ERROR , "Our error exhibit" ),
183+ ]
184+ assert got_statuses == want_statuses
0 commit comments