Skip to content

Commit 7a73fb6

Browse files
authored
Fix subspan export bug (census-instrumentation#545)
Fix a bug in ContextTracer that duplicated the root span on export.
1 parent 1e38211 commit 7a73fb6

File tree

3 files changed

+63
-22
lines changed

3 files changed

+63
-22
lines changed

opencensus/trace/tracers/context_tracer.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -152,27 +152,25 @@ def get_span_datas(self, span):
152152
:rtype: list of opencensus.trace.span_data.SpanData
153153
:return list of SpanData tuples
154154
"""
155-
span_tree = list(iter(span))
156155
span_datas = [
157156
span_data_module.SpanData(
158-
name=span.name,
157+
name=ss.name,
159158
context=self.span_context,
160-
span_id=span.span_id,
161-
parent_span_id=span.parent_span.span_id if
162-
span.parent_span else None,
163-
attributes=span.attributes,
164-
start_time=span.start_time,
165-
end_time=span.end_time,
166-
child_span_count=len(span.children),
167-
stack_trace=span.stack_trace,
168-
time_events=span.time_events,
169-
links=span.links,
170-
status=span.status,
171-
same_process_as_parent_span=span.same_process_as_parent_span,
172-
span_kind=span.span_kind
173-
159+
span_id=ss.span_id,
160+
parent_span_id=ss.parent_span.span_id if
161+
ss.parent_span else None,
162+
attributes=ss.attributes,
163+
start_time=ss.start_time,
164+
end_time=ss.end_time,
165+
child_span_count=len(ss.children),
166+
stack_trace=ss.stack_trace,
167+
time_events=ss.time_events,
168+
links=ss.links,
169+
status=ss.status,
170+
same_process_as_parent_span=ss.same_process_as_parent_span,
171+
span_kind=ss.span_kind
174172
)
175-
for ss in span_tree
173+
for ss in span
176174
]
177175

178176
return span_datas

tests/system/trace/basic_trace/basic_trace_system_test.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616

1717

1818
def func_to_trace():
19-
import time
2019
print('Test simple tracing...')
21-
time.sleep(2)
2220

2321

2422
class TestBasicTrace(unittest.TestCase):
@@ -65,8 +63,15 @@ def test_tracer(self):
6563
self.assertEqual(trace_json.get('traceId'), trace_id)
6664
self.assertEqual(len(spans), 2)
6765

66+
self.assertSetEqual(
67+
{ss['displayName']['value'] for ss in spans},
68+
{'child_span', 'root_span'})
69+
6870
for span in spans:
69-
if span.get('displayName').get('value') == 'root_span':
70-
self.assertEqual(str(span.get('parentSpanId')), span_id)
71+
if span['displayName']['value'] == 'root_span':
72+
self.assertEqual(span['parentSpanId'], span_id)
73+
self.assertEqual(span['childSpanCount'], 1)
7174
else:
72-
self.assertEqual(span.get('parentSpanId'), parent_span_id)
75+
self.assertEqual(span['displayName']['value'], 'child_span')
76+
self.assertEqual(span['parentSpanId'], parent_span_id)
77+
self.assertEqual(span['childSpanCount'], 0)

tests/unit/trace/tracers/test_context_tracer.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,44 @@ def test_finish_with_spans(self):
6767

6868
self.assertEqual(tracer._spans_list, [])
6969

70+
def test_finish_with_tracer_subspans(self):
71+
tracer = context_tracer.ContextTracer()
72+
parent = tracer.start_span('parent')
73+
child = tracer.start_span('child')
74+
self.assertEqual(child.parent_span, parent)
75+
tracer.exporter = mock.Mock()
76+
tracer.finish()
77+
78+
self.assertEqual(tracer.exporter.export.call_count, 2)
79+
[[[[c_sd]], _], [[[p_sd]], _]] = tracer.exporter.export.call_args_list
80+
81+
self.assertEqual(p_sd.span_id, parent.span_id)
82+
self.assertIsNone(parent.parent_span.span_id)
83+
self.assertIsNone(p_sd.parent_span_id)
84+
self.assertEqual(c_sd.span_id, child.span_id)
85+
self.assertEqual(c_sd.parent_span_id, parent.span_id)
86+
87+
self.assertEqual(tracer._spans_list, [])
88+
89+
def test_finish_with_span_subspans(self):
90+
tracer = context_tracer.ContextTracer()
91+
parent = tracer.start_span('parent')
92+
child = parent.span('child')
93+
self.assertEqual(child.parent_span, parent)
94+
tracer.exporter = mock.Mock()
95+
tracer.finish()
96+
97+
self.assertEqual(tracer.exporter.export.call_count, 1)
98+
[[[[c_sd, p_sd]], _]] = tracer.exporter.export.call_args_list
99+
100+
self.assertEqual(p_sd.span_id, parent.span_id)
101+
self.assertIsNone(parent.parent_span.span_id)
102+
self.assertIsNone(p_sd.parent_span_id)
103+
self.assertEqual(c_sd.span_id, child.span_id)
104+
self.assertEqual(c_sd.parent_span_id, parent.span_id)
105+
106+
self.assertEqual(tracer._spans_list, [])
107+
70108
def test_end_leftover_spans(self):
71109
tracer = context_tracer.ContextTracer()
72110
tracer._spans_list = [span.Span(name='span')]

0 commit comments

Comments
 (0)