Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add indicator if SpanContext was propagated from remote parent #516

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def setUp(self):
context = trace_api.SpanContext(
trace_id=0x000000000000000000000000DEADBEEF,
span_id=0x00000000DEADBEF0,
is_remote=False,
)

self._test_span = trace.Span("test_span", context=context)
Expand Down Expand Up @@ -133,9 +134,15 @@ def test_translate_to_jaeger(self):
start_times[2] + durations[2],
)

span_context = trace_api.SpanContext(trace_id, span_id)
parent_context = trace_api.SpanContext(trace_id, parent_id)
other_context = trace_api.SpanContext(trace_id, other_id)
span_context = trace_api.SpanContext(
trace_id, span_id, is_remote=False
)
parent_context = trace_api.SpanContext(
trace_id, parent_id, is_remote=False
)
other_context = trace_api.SpanContext(
trace_id, other_id, is_remote=False
)

event_attributes = {
"annotation_bool": True,
Expand Down
15 changes: 11 additions & 4 deletions ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ def test_log_event(self):
def test_span_context(self):
"""Test construction of `SpanContextShim` objects."""

otel_context = trace.SpanContext(1234, 5678)
otel_context = trace.SpanContext(1234, 5678, is_remote=False)
context = opentracingshim.SpanContextShim(otel_context)

self.assertIsInstance(context, opentracing.SpanContext)
Expand All @@ -476,7 +476,9 @@ def test_span_on_error(self):
def test_inject_http_headers(self):
"""Test `inject()` method for Format.HTTP_HEADERS."""

otel_context = trace.SpanContext(trace_id=1220, span_id=7478)
otel_context = trace.SpanContext(
trace_id=1220, span_id=7478, is_remote=False
)
context = opentracingshim.SpanContextShim(otel_context)

headers = {}
Expand All @@ -487,7 +489,9 @@ def test_inject_http_headers(self):
def test_inject_text_map(self):
"""Test `inject()` method for Format.TEXT_MAP."""

otel_context = trace.SpanContext(trace_id=1220, span_id=7478)
otel_context = trace.SpanContext(
trace_id=1220, span_id=7478, is_remote=False
)
context = opentracingshim.SpanContextShim(otel_context)

# Verify Format.TEXT_MAP
Expand All @@ -499,7 +503,9 @@ def test_inject_text_map(self):
def test_inject_binary(self):
"""Test `inject()` method for Format.BINARY."""

otel_context = trace.SpanContext(trace_id=1220, span_id=7478)
otel_context = trace.SpanContext(
trace_id=1220, span_id=7478, is_remote=False
)
context = opentracingshim.SpanContextShim(otel_context)

# Verify exception for non supported binary format.
Expand Down Expand Up @@ -561,6 +567,7 @@ def extract(
trace.SpanContext(
trace_id=int(trace_id_list[0]),
span_id=int(span_id_list[0]),
is_remote=True,
)
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,16 @@ def test_translate_to_collector(self):
span_context = trace_api.SpanContext(
trace_id,
span_id,
is_remote=False,
trace_flags=TraceFlags(TraceFlags.SAMPLED),
trace_state=trace_api.TraceState({"testKey": "testValue"}),
)
parent_context = trace_api.SpanContext(trace_id, parent_id)
other_context = trace_api.SpanContext(trace_id, span_id)
parent_context = trace_api.SpanContext(
trace_id, parent_id, is_remote=False
)
other_context = trace_api.SpanContext(
trace_id, span_id, is_remote=False
)
event_attributes = {
"annotation_bool": True,
"annotation_string": "annotation_test",
Expand Down Expand Up @@ -279,7 +284,10 @@ def test_export(self):
trace_id = 0x6E0C63257DE34C926F9EFCD03927272E
span_id = 0x34BF92DEEFC58C92
span_context = trace_api.SpanContext(
trace_id, span_id, trace_flags=TraceFlags(TraceFlags.SAMPLED)
trace_id,
span_id,
is_remote=False,
trace_flags=TraceFlags(TraceFlags.SAMPLED),
)
otel_spans = [
trace.Span(
Expand Down
14 changes: 11 additions & 3 deletions ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def setUp(self):
context = trace_api.SpanContext(
trace_id=0x000000000000000000000000DEADBEEF,
span_id=0x00000000DEADBEF0,
is_remote=False,
)

self._test_span = trace.Span("test_span", context=context)
Expand Down Expand Up @@ -114,10 +115,17 @@ def test_export(self):
)

span_context = trace_api.SpanContext(
trace_id, span_id, trace_flags=TraceFlags(TraceFlags.SAMPLED)
trace_id,
span_id,
is_remote=False,
trace_flags=TraceFlags(TraceFlags.SAMPLED),
)
parent_context = trace_api.SpanContext(
trace_id, parent_id, is_remote=False
)
other_context = trace_api.SpanContext(
trace_id, other_id, is_remote=False
)
parent_context = trace_api.SpanContext(trace_id, parent_id)
other_context = trace_api.SpanContext(trace_id, other_id)

event_attributes = {
"annotation_bool": True,
Expand Down
17 changes: 12 additions & 5 deletions opentelemetry-api/src/opentelemetry/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,14 @@ class SpanContext:
span_id: This span's ID.
trace_flags: Trace options to propagate.
trace_state: Tracing-system-specific info to propagate.
is_remote: True if propagated from a remote parent.
"""

def __init__(
self,
trace_id: int,
span_id: int,
is_remote: bool,
trace_flags: "TraceFlags" = DEFAULT_TRACE_OPTIONS,
trace_state: "TraceState" = DEFAULT_TRACE_STATE,
) -> None:
Expand All @@ -336,13 +338,17 @@ def __init__(
self.span_id = span_id
self.trace_flags = trace_flags
self.trace_state = trace_state
self.is_remote = is_remote

def __repr__(self) -> str:
return "{}(trace_id={}, span_id={}, trace_state={!r})".format(
return (
"{}(trace_id={}, span_id={}, trace_state={!r}, is_remote={})"
).format(
type(self).__name__,
format_trace_id(self.trace_id),
format_span_id(self.span_id),
self.trace_state,
self.is_remote,
)

def is_valid(self) -> bool:
Expand Down Expand Up @@ -402,10 +408,11 @@ def set_status(self, status: Status) -> None:
INVALID_SPAN_ID = 0x0000000000000000
INVALID_TRACE_ID = 0x00000000000000000000000000000000
INVALID_SPAN_CONTEXT = SpanContext(
INVALID_TRACE_ID,
INVALID_SPAN_ID,
DEFAULT_TRACE_OPTIONS,
DEFAULT_TRACE_STATE,
trace_id=INVALID_TRACE_ID,
span_id=INVALID_SPAN_ID,
is_remote=False,
trace_flags=DEFAULT_TRACE_OPTIONS,
trace_state=DEFAULT_TRACE_STATE,
)
INVALID_SPAN = DefaultSpan(INVALID_SPAN_CONTEXT)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def extract(
span_context = trace.SpanContext(
trace_id=int(trace_id, 16),
span_id=int(span_id, 16),
is_remote=True,
trace_flags=trace.TraceFlags(trace_flags),
trace_state=tracestate,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def test_headers_with_tracestate(self):
self.assertEqual(
span_context.trace_state, {"foo": "1", "bar": "2", "baz": "3"}
)
self.assertTrue(span_context.is_remote)
output = {} # type:typing.Dict[str, str]
span = trace.DefaultSpan(span_context)

Expand Down Expand Up @@ -155,7 +156,7 @@ def test_no_send_empty_tracestate(self):
"""
output = {} # type:typing.Dict[str, str]
span = trace.DefaultSpan(
trace.SpanContext(self.TRACE_ID, self.SPAN_ID)
trace.SpanContext(self.TRACE_ID, self.SPAN_ID, is_remote=False)
)
ctx = set_span_in_context(span)
FORMAT.inject(dict.__setitem__, output, ctx)
Expand Down
6 changes: 5 additions & 1 deletion opentelemetry-api/tests/trace/test_defaultspan.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
class TestDefaultSpan(unittest.TestCase):
def test_ctor(self):
context = trace.SpanContext(
1, 1, trace.DEFAULT_TRACE_OPTIONS, trace.DEFAULT_TRACE_STATE
1,
1,
is_remote=False,
trace_flags=trace.DEFAULT_TRACE_OPTIONS,
trace_state=trace.DEFAULT_TRACE_STATE,
)
span = trace.DefaultSpan(context)
self.assertEqual(context, span.get_context())
Expand Down
42 changes: 32 additions & 10 deletions opentelemetry-api/tests/trace/test_sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
class TestSampler(unittest.TestCase):
def test_always_on(self):
no_record_always_on = sampling.ALWAYS_ON.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT
),
0xDEADBEF1,
0xDEADBEF2,
"unsampled parent, sampling on",
Expand All @@ -34,7 +36,9 @@ def test_always_on(self):
self.assertEqual(no_record_always_on.attributes, {})

sampled_always_on = sampling.ALWAYS_ON.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED
),
0xDEADBEF1,
0xDEADBEF2,
"sampled parent, sampling on",
Expand All @@ -44,7 +48,9 @@ def test_always_on(self):

def test_always_off(self):
no_record_always_off = sampling.ALWAYS_OFF.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT
),
0xDEADBEF1,
0xDEADBEF2,
"unsampled parent, sampling off",
Expand All @@ -53,7 +59,9 @@ def test_always_off(self):
self.assertEqual(no_record_always_off.attributes, {})

sampled_always_on = sampling.ALWAYS_OFF.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED
),
0xDEADBEF1,
0xDEADBEF2,
"sampled parent, sampling off",
Expand All @@ -63,7 +71,9 @@ def test_always_off(self):

def test_default_on(self):
no_record_default_on = sampling.DEFAULT_ON.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT
),
0xDEADBEF1,
0xDEADBEF2,
"unsampled parent, sampling on",
Expand All @@ -72,7 +82,9 @@ def test_default_on(self):
self.assertEqual(no_record_default_on.attributes, {})

sampled_default_on = sampling.DEFAULT_ON.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED
),
0xDEADBEF1,
0xDEADBEF2,
"sampled parent, sampling on",
Expand All @@ -82,7 +94,9 @@ def test_default_on(self):

def test_default_off(self):
no_record_default_off = sampling.DEFAULT_OFF.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT
),
0xDEADBEF1,
0xDEADBEF2,
"unsampled parent, sampling off",
Expand All @@ -91,7 +105,9 @@ def test_default_off(self):
self.assertEqual(no_record_default_off.attributes, {})

sampled_default_off = sampling.DEFAULT_OFF.should_sample(
trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED),
trace.SpanContext(
0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED
),
0xDEADBEF1,
0xDEADBEF2,
"sampled parent, sampling off",
Expand Down Expand Up @@ -120,7 +136,10 @@ def test_probability_sampler(self):
self.assertFalse(
sampler.should_sample(
trace.SpanContext(
0xDEADBEF0, 0xDEADBEF1, trace_flags=TO_DEFAULT
0xDEADBEF0,
0xDEADBEF1,
is_remote=False,
trace_flags=TO_DEFAULT,
),
0x7FFFFFFFFFFFFFFF,
0xDEADBEEF,
Expand All @@ -130,7 +149,10 @@ def test_probability_sampler(self):
self.assertTrue(
sampler.should_sample(
trace.SpanContext(
0xDEADBEF0, 0xDEADBEF1, trace_flags=TO_SAMPLED
0xDEADBEF0,
0xDEADBEF1,
is_remote=False,
trace_flags=TO_SAMPLED,
),
0x8000000000000000,
0xDEADBEEF,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def extract(
# trace an span ids are encoded in hex, so must be converted
trace_id=int(trace_id, 16),
span_id=int(span_id, 16),
is_remote=True,
trace_flags=trace.TraceFlags(options),
trace_state=trace.TraceState(),
)
Expand Down
6 changes: 5 additions & 1 deletion opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,11 @@ def start_span( # pylint: disable=too-many-locals
trace_state = parent_context.trace_state

context = trace_api.SpanContext(
trace_id, generate_span_id(), trace_flags, trace_state
trace_id,
generate_span_id(),
is_remote=False,
trace_flags=trace_flags,
trace_state=trace_state,
)

# The sampler decides whether to create a real or no-op span at the
Expand Down
4 changes: 4 additions & 0 deletions opentelemetry-sdk/tests/context/propagation/test_b3_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def get_child_parent_new_carrier(old_carrier):
trace_api.SpanContext(
parent_context.trace_id,
trace.generate_span_id(),
is_remote=False,
trace_flags=parent_context.trace_flags,
trace_state=parent_context.trace_state,
),
Expand Down Expand Up @@ -90,6 +91,7 @@ def test_extract_multi_header(self):
new_carrier[FORMAT.PARENT_SPAN_ID_KEY],
b3_format.format_span_id(parent.context.span_id),
)
self.assertTrue(parent.context.is_remote)
self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1")

def test_extract_single_header(self):
Expand All @@ -111,6 +113,7 @@ def test_extract_single_header(self):
b3_format.format_span_id(child.context.span_id),
)
self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1")
self.assertTrue(parent.context.is_remote)

child, parent, new_carrier = get_child_parent_new_carrier(
{
Expand All @@ -134,6 +137,7 @@ def test_extract_single_header(self):
new_carrier[FORMAT.PARENT_SPAN_ID_KEY],
b3_format.format_span_id(parent.context.span_id),
)
self.assertTrue(parent.context.is_remote)
self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1")

def test_extract_header_precedence(self):
Expand Down
Loading