Skip to content
This repository was archived by the owner on Jul 11, 2022. It is now read-only.

Commit 9771cc9

Browse files
bhavin192yurishkuro
authored andcommitted
Add support for references (#241)
* Add support for references - Checks if all the given references are valid - If the parent is not set then sets the first reference as parent of the span - Allows to pass one Reference object or list of them Signed-off-by: Bhavin Gandhi <[email protected]> * Add tests for the references support Signed-off-by: Bhavin Gandhi <[email protected]> * Avoid allocation if references are None Signed-off-by: Yuri Shkuro <[email protected]>
1 parent de9ad06 commit 9771cc9

File tree

5 files changed

+87
-11
lines changed

5 files changed

+87
-11
lines changed

jaeger_client/span.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ class Span(opentracing.Span):
3232
'logs', 'tags', 'update_lock']
3333

3434
def __init__(self, context, tracer, operation_name,
35-
tags=None, start_time=None):
35+
tags=None, start_time=None, references=None):
3636
super(Span, self).__init__(context=context, tracer=tracer)
3737
self.operation_name = operation_name
3838
self.start_time = start_time or time.time()
3939
self.end_time = None
4040
self.update_lock = threading.Lock()
41+
self.references = references
4142
# we store tags and logs as Thrift objects to avoid extra allocations
4243
self.tags = []
4344
self.logs = []

jaeger_client/thrift.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import six
16+
from opentracing.tracer import ReferenceType
1617

1718
import jaeger_client.thrift_gen.jaeger.ttypes as ttypes
1819
import jaeger_client.thrift_gen.sampling.SamplingManager as sampling_manager
@@ -160,6 +161,26 @@ def make_process(service_name, tags, max_length):
160161
)
161162

162163

164+
def make_ref_type(span_ref_type):
165+
if span_ref_type == ReferenceType.FOLLOWS_FROM:
166+
return ttypes.SpanRefType.FOLLOWS_FROM
167+
return ttypes.SpanRefType.CHILD_OF
168+
169+
170+
def make_references(references):
171+
if not references:
172+
return None
173+
list_of_span_refs = list()
174+
for span_ref in references:
175+
list_of_span_refs.append(ttypes.SpanRef(
176+
refType=make_ref_type(span_ref.type),
177+
traceIdLow=id_to_int(_id_to_low(span_ref.referenced_context.trace_id)),
178+
traceIdHigh=id_to_int(_id_to_high(span_ref.referenced_context.trace_id)),
179+
spanId=id_to_int(span_ref.referenced_context.span_id),
180+
))
181+
return list_of_span_refs
182+
183+
163184
def make_jaeger_batch(spans, process):
164185
batch = ttypes.Batch(
165186
spans=[],
@@ -173,7 +194,7 @@ def make_jaeger_batch(spans, process):
173194
spanId=id_to_int(span.span_id),
174195
parentSpanId=id_to_int(span.parent_id) or 0,
175196
operationName=span.operation_name,
176-
# references = references, # TODO
197+
references=make_references(span.references),
177198
flags=span.context.flags,
178199
startTime=timestamp_micros(span.start_time),
179200
duration=timestamp_micros(span.end_time - span.start_time),

jaeger_client/tracer.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def start_span(self,
123123
:param child_of: shortcut for 'child_of' reference
124124
:param references: (optional) either a single Reference object or a
125125
list of Reference objects that identify one or more parent
126-
SpanContexts. (See the Reference documentation for detail)
126+
SpanContexts. (See the opentracing.Reference documentation for detail)
127127
:param tags: optional dictionary of Span Tags. The caller gives up
128128
ownership of that dictionary, because the Tracer may use it as-is
129129
to avoid extra data copying.
@@ -133,11 +133,6 @@ def start_span(self,
133133
:return: Returns an already-started Span instance.
134134
"""
135135
parent = child_of
136-
if references:
137-
if isinstance(references, list):
138-
# TODO only the first reference is currently used
139-
references = references[0]
140-
parent = references.referenced_context
141136

142137
# allow Span to be passed as reference, not just SpanContext
143138
if isinstance(parent, Span):
@@ -146,6 +141,19 @@ def start_span(self,
146141
rpc_server = tags and \
147142
tags.get(ext_tags.SPAN_KIND) == ext_tags.SPAN_KIND_RPC_SERVER
148143

144+
valid_references = None
145+
if references:
146+
valid_references = list()
147+
if not isinstance(references, list):
148+
references = [references]
149+
for reference in references:
150+
if reference.referenced_context is not None:
151+
valid_references.append(reference)
152+
153+
# setting first reference as parent
154+
if valid_references and (parent is None or not parent.has_trace):
155+
parent = valid_references[0].referenced_context
156+
149157
if parent is None or not parent.has_trace:
150158
trace_id = self._random_id(self.max_trace_id_bits)
151159
span_id = self._random_id(constants._max_id_bits)
@@ -183,7 +191,7 @@ def start_span(self,
183191
baggage=baggage)
184192
span = Span(context=span_ctx, tracer=self,
185193
operation_name=operation_name,
186-
tags=tags, start_time=start_time)
194+
tags=tags, start_time=start_time, references=valid_references)
187195

188196
self._emit_span_metrics(span=span, join=rpc_server)
189197

tests/test_thrift.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import jaeger_client.thrift_gen.jaeger.ttypes as ttypes
1818
import jaeger_client.thrift_gen.sampling.SamplingManager as sampling_manager
19-
from opentracing import child_of
19+
from opentracing import child_of, follows_from
2020
from jaeger_client import ProbabilisticSampler, RateLimitingSampler
2121
from jaeger_client import thrift, Span, SpanContext
2222
from jaeger_client.thrift_gen.agent import Agent as Agent
@@ -175,3 +175,14 @@ def test_parse_sampling_strategy():
175175
resp.strategyType = 'x'
176176
s, e = thrift.parse_sampling_strategy(response=resp)
177177
assert s is None and e is not None
178+
179+
180+
def test_parse_span_references(tracer):
181+
span = tracer.start_span('test')
182+
span2 = tracer.start_span('test2')
183+
follow_span = tracer.start_span('test-follow', references=[follows_from(span.context),
184+
child_of(span2.context)])
185+
span.finish()
186+
span2.finish()
187+
follow_span.finish()
188+
_marshall_span(follow_span)

tests/test_tracer.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import pytest
2121
import tornado.httputil
2222

23-
from opentracing import Format, child_of
23+
from opentracing import Format, child_of, follows_from
2424
from opentracing.ext import tags as ext_tags
2525
from jaeger_client import ConstSampler, SpanContext, Tracer
2626
from jaeger_client import constants as c
@@ -129,6 +129,41 @@ def test_child_span(tracer):
129129
tracer.close()
130130

131131

132+
def test_follows_from(tracer):
133+
span = tracer.start_span('test')
134+
span1 = tracer.start_span('test2')
135+
follow_span = tracer.start_span('follow-span', references=[follows_from(span.context),
136+
follows_from(span1.context),
137+
follows_from(None)])
138+
span.finish()
139+
span1.finish()
140+
follow_span.finish()
141+
tracer.reporter.report_span.assert_called_once()
142+
assert len(follow_span.references) == 2
143+
assert follow_span.context.parent_id == span.context.span_id
144+
for reference in follow_span.references:
145+
assert reference.referenced_context is not None
146+
147+
span = tracer.start_span('test')
148+
follow_span = tracer.start_span(references=follows_from(span.context))
149+
span.finish()
150+
follow_span.finish()
151+
tracer.reporter.report_span.assert_called_once()
152+
assert isinstance(follow_span.references, list)
153+
154+
span = tracer.start_span('test')
155+
parent_span = tracer.start_span('test-parent')
156+
child_span = tracer.start_span('test-child', child_of=parent_span,
157+
references=follows_from(span.context))
158+
span.finish()
159+
parent_span.finish()
160+
child_span.finish()
161+
tracer.reporter.report_span.assert_called_once()
162+
assert child_span.context.parent_id == parent_span.context.span_id
163+
assert len(child_span.references) == 1
164+
tracer.close()
165+
166+
132167
def test_sampler_effects(tracer):
133168
tracer.sampler = ConstSampler(True)
134169
span = tracer.start_span('test')

0 commit comments

Comments
 (0)