Skip to content

Commit 4f71fba

Browse files
ocelotltoumorokoshi
authored andcommitted
Set status properly on end (#358)
In accordance with the specification, a trace status should always be set on an ended span.
1 parent 4fca8c9 commit 4f71fba

File tree

3 files changed

+43
-26
lines changed

3 files changed

+43
-26
lines changed

opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ def on_end(self, span: "Span") -> None:
6767
"""
6868

6969
def shutdown(self) -> None:
70-
"""Called when a :class:`opentelemetry.sdk.trace.Tracer` is shutdown."""
70+
"""Called when a :class:`opentelemetry.sdk.trace.Tracer` is shutdown.
71+
"""
7172

7273

7374
class MultiSpanProcessor(SpanProcessor):
@@ -299,16 +300,17 @@ def end(self, end_time: Optional[int] = None) -> None:
299300
raise RuntimeError("Calling end() on a not started span.")
300301
has_ended = self.end_time is not None
301302
if not has_ended:
303+
if self.status is None:
304+
self.status = Status(canonical_code=StatusCanonicalCode.OK)
305+
302306
self._end_time = (
303307
end_time if end_time is not None else time_ns()
304308
)
309+
305310
if has_ended:
306311
logger.warning("Calling end() on an ended span.")
307312
return
308313

309-
if self.status is None:
310-
self.set_status(Status(canonical_code=StatusCanonicalCode.OK))
311-
312314
self.span_processor.on_end(self)
313315

314316
def update_name(self, name: str) -> None:

opentelemetry-sdk/tests/trace/test_trace.py

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import shutil
1616
import subprocess
1717
import unittest
18+
from logging import ERROR, WARNING
1819
from unittest import mock
1920

2021
from opentelemetry import trace as trace_api
@@ -167,8 +168,10 @@ def test_instrumentation_info(self):
167168

168169
def test_invalid_instrumentation_info(self):
169170
tracer_source = trace.TracerSource()
170-
tracer1 = tracer_source.get_tracer("")
171-
tracer2 = tracer_source.get_tracer(None)
171+
with self.assertLogs(level=ERROR):
172+
tracer1 = tracer_source.get_tracer("")
173+
with self.assertLogs(level=ERROR):
174+
tracer2 = tracer_source.get_tracer(None)
172175
self.assertEqual(
173176
tracer1.instrumentation_info, tracer2.instrumentation_info
174177
)
@@ -567,7 +570,8 @@ def test_start_span(self):
567570

568571
span.start()
569572
start_time = span.start_time
570-
span.start()
573+
with self.assertLogs(level=WARNING):
574+
span.start()
571575
self.assertEqual(start_time, span.start_time)
572576

573577
self.assertIs(span.status, None)
@@ -596,36 +600,45 @@ def test_span_override_start_and_end_time(self):
596600
def test_ended_span(self):
597601
""""Events, attributes are not allowed after span is ended"""
598602

599-
with self.tracer.start_as_current_span("root") as root:
600-
# everything should be empty at the beginning
601-
self.assertEqual(len(root.attributes), 0)
602-
self.assertEqual(len(root.events), 0)
603-
self.assertEqual(len(root.links), 0)
603+
root = self.tracer.start_span("root")
604604

605-
# call end first time
606-
root.end()
607-
end_time0 = root.end_time
605+
# everything should be empty at the beginning
606+
self.assertEqual(len(root.attributes), 0)
607+
self.assertEqual(len(root.events), 0)
608+
self.assertEqual(len(root.links), 0)
609+
610+
# call end first time
611+
root.end()
612+
end_time0 = root.end_time
608613

609-
# call it a second time
614+
# call it a second time
615+
with self.assertLogs(level=WARNING):
610616
root.end()
611-
# end time shouldn't be changed
612-
self.assertEqual(end_time0, root.end_time)
617+
# end time shouldn't be changed
618+
self.assertEqual(end_time0, root.end_time)
613619

620+
with self.assertLogs(level=WARNING):
614621
root.set_attribute("component", "http")
615-
self.assertEqual(len(root.attributes), 0)
622+
self.assertEqual(len(root.attributes), 0)
616623

624+
with self.assertLogs(level=WARNING):
617625
root.add_event("event1")
618-
self.assertEqual(len(root.events), 0)
626+
self.assertEqual(len(root.events), 0)
619627

628+
with self.assertLogs(level=WARNING):
620629
root.update_name("xxx")
621-
self.assertEqual(root.name, "root")
630+
self.assertEqual(root.name, "root")
622631

623-
new_status = trace_api.status.Status(
624-
trace_api.status.StatusCanonicalCode.CANCELLED,
625-
"Test description",
626-
)
632+
new_status = trace_api.status.Status(
633+
trace_api.status.StatusCanonicalCode.CANCELLED, "Test description",
634+
)
635+
636+
with self.assertLogs(level=WARNING):
627637
root.set_status(new_status)
628-
self.assertIs(root.status, None)
638+
self.assertEqual(
639+
root.status.canonical_code,
640+
trace_api.status.StatusCanonicalCode.OK,
641+
)
629642

630643
def test_error_status(self):
631644
try:

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
[pytest]
22
addopts = -rs -v
3+
log_cli = true
4+
log_cli_level = warning

0 commit comments

Comments
 (0)