Skip to content
Open
1 change: 1 addition & 0 deletions .changelog/5667.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`opentelemetry-exporter-otlp`: Include trace flags in spans exported by the OTLPSpanExporter
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,12 @@ def _encode_resource_spans(
return json_resource_spans


def _span_flags(parent_span_context: SpanContext | None) -> int:
flags = JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
def _span_flags(
span_context: SpanContext | None,
parent_span_context: SpanContext | None,
) -> int:
flags = int(span_context.trace_flags) if span_context else 0
flags |= JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
if parent_span_context and parent_span_context.is_remote:
flags |= JSONSpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
return int(flags)
Expand All @@ -109,7 +113,7 @@ def _encode_span(sdk_span: ReadableSpan) -> JSONSpan:
dropped_attributes_count=sdk_span.dropped_attributes,
dropped_events_count=sdk_span.dropped_events,
dropped_links_count=sdk_span.dropped_links,
flags=_span_flags(sdk_span.parent),
flags=_span_flags(span_context, sdk_span.parent),
)


Expand All @@ -134,7 +138,7 @@ def _encode_links(links: Collection[Link]) -> list[JSONSpan.Link]:
span_id=_encode_span_id(link.context.span_id),
attributes=_encode_attributes(link.attributes),
dropped_attributes_count=link.dropped_attributes,
flags=_span_flags(link.context),
flags=_span_flags(link.context, link.context),
)
for link in links
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import Event, SpanContext
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
from opentelemetry.trace import Link, SpanKind
from opentelemetry.trace import Link, SpanKind, TraceFlags
from opentelemetry.trace.span import TraceState
from opentelemetry.trace.status import Status, StatusCode
from tests import (
Expand Down Expand Up @@ -93,7 +93,12 @@ def test_encode_span_events(self):
self.assertEqual(encoded.events[0].attributes[0].key, "event_key")

def test_encode_span_links(self):
link_ctx = SpanContext(TRACE_ID, 0x2222222222222222, is_remote=False)
link_ctx = SpanContext(
TRACE_ID,
0x2222222222222222,
is_remote=False,
trace_flags=TraceFlags.SAMPLED,
)
link = Link(context=link_ctx, attributes={"link_key": True})
span = make_span(links=(link,))
result = encode_spans([span])
Expand All @@ -108,7 +113,7 @@ def test_encode_span_links(self):
self.assertEqual(encoded.links[0].attributes[0].key, "link_key")
self.assertEqual(
encoded.links[0].flags,
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK),
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK | TraceFlags.SAMPLED),
)

def test_encode_span_status(self):
Expand Down Expand Up @@ -141,7 +146,11 @@ def test_encode_span_parent(self):
)
self.assertEqual(
encoded.flags,
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK | JSONSpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK),
int(
JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
| JSONSpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
| TraceFlags.SAMPLED
),
)

def test_encode_span_no_parent(self):
Expand All @@ -152,7 +161,7 @@ def test_encode_span_no_parent(self):
self.assertIsNone(encoded.parent_span_id)
self.assertEqual(
encoded.flags,
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK),
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK | TraceFlags.SAMPLED),
)

def test_encode_span_grouping_by_resource(self):
Expand Down Expand Up @@ -248,27 +257,46 @@ def test_span_kind_map(self):
def test_span_flags(self):
cases = [
(
"remote_parent",
"sampled_remote_parent",
SpanContext(
TRACE_ID,
0x1110,
is_remote=False,
trace_flags=TraceFlags.SAMPLED,
),
SpanContext(TRACE_ID, 0x1111, is_remote=True),
int(
JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
| JSONSpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
| TraceFlags.SAMPLED
),
),
(
"local_parent",
"unsampled_local_parent",
SpanContext(
TRACE_ID,
0x2220,
is_remote=False,
trace_flags=TraceFlags.DEFAULT,
),
SpanContext(TRACE_ID, 0x2222, is_remote=False),
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK),
),
(
"no_parent",
SpanContext(
TRACE_ID,
0x3330,
is_remote=False,
trace_flags=TraceFlags.SAMPLED,
),
None,
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK),
int(JSONSpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK | TraceFlags.SAMPLED),
),
]
for name, context, expected_flags in cases:
for name, span_context, parent_context, expected_flags in cases:
with self.subTest(name=name):
self.assertEqual(_span_flags(context), expected_flags)
self.assertEqual(_span_flags(span_context, parent_context), expected_flags)

def test_encode_status_translations(self):
cases = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ def _encode_resource_spans(
return pb2_resource_spans


def _span_flags(parent_span_context: SpanContext | None) -> int:
flags = PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
def _span_flags(
span_context: SpanContext | None,
parent_span_context: SpanContext | None,
) -> int:
flags = int(span_context.trace_flags) if span_context else 0
flags |= PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
if parent_span_context and parent_span_context.is_remote:
flags |= PB2SpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
return flags
Expand All @@ -115,7 +119,7 @@ def _encode_span(sdk_span: ReadableSpan) -> PB2SPan:
dropped_attributes_count=sdk_span.dropped_attributes,
dropped_events_count=sdk_span.dropped_events,
dropped_links_count=sdk_span.dropped_links,
flags=_span_flags(sdk_span.parent),
flags=_span_flags(span_context, sdk_span.parent),
)


Expand Down Expand Up @@ -146,7 +150,7 @@ def _encode_links(links: Sequence[Link]) -> Sequence[PB2SPan.Link]:
span_id=_encode_span_id(link.context.span_id),
attributes=_encode_attributes(link.attributes),
dropped_attributes_count=link.dropped_attributes,
flags=_span_flags(link.context),
flags=_span_flags(link.context, link.context),
)
pb2_links.append(encoded_link)
return pb2_links
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from opentelemetry.exporter.otlp.proto.common._internal.trace_encoder import (
_SPAN_KIND_MAP,
_encode_status,
_span_flags,
)
from opentelemetry.exporter.otlp.proto.common.trace_encoder import encode_spans
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
Expand All @@ -30,6 +31,7 @@
)
from opentelemetry.proto.trace.v1.trace_pb2 import ScopeSpans as PB2ScopeSpans
from opentelemetry.proto.trace.v1.trace_pb2 import Span as PB2SPan
from opentelemetry.proto.trace.v1.trace_pb2 import SpanFlags as PB2SpanFlags
from opentelemetry.proto.trace.v1.trace_pb2 import Status as PB2Status
from opentelemetry.sdk.trace import Event as SDKEvent
from opentelemetry.sdk.trace import Resource as SDKResource
Expand Down Expand Up @@ -248,7 +250,7 @@ def get_exhaustive_test_spans(
code=SDKStatusCode.ERROR.value,
message="Example description",
),
flags=0x300,
flags=0x301,
)
],
),
Expand Down Expand Up @@ -423,3 +425,48 @@ def test_encode_status_code_translations(self):
code=SDKStatusCode.ERROR.value,
),
)

def test_span_flags(self):
trace_id = 0x3E0C63257DE34C926F9EFCD03927272E
cases = [
(
"sampled_remote_parent",
SDKSpanContext(
trace_id,
0x1110,
is_remote=False,
trace_flags=SDKTraceFlags.SAMPLED,
),
SDKSpanContext(trace_id, 0x1111, is_remote=True),
(
PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
| PB2SpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
| SDKTraceFlags.SAMPLED
),
),
(
"unsampled_local_parent",
SDKSpanContext(
trace_id,
0x2220,
is_remote=False,
trace_flags=SDKTraceFlags.DEFAULT,
),
SDKSpanContext(trace_id, 0x2222, is_remote=False),
PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK,
),
(
"no_parent",
SDKSpanContext(
trace_id,
0x3330,
is_remote=False,
trace_flags=SDKTraceFlags.SAMPLED,
),
None,
(PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK | SDKTraceFlags.SAMPLED),
),
]
for name, span_context, parent_context, expected_flags in cases:
with self.subTest(name=name):
self.assertEqual(_span_flags(span_context, parent_context), expected_flags)
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
OtelComponentTypeValues,
)
from opentelemetry.test.mock_test_classes import IterEntryPoint
from opentelemetry.trace import TraceFlags

logger = getLogger(__name__)

Expand Down Expand Up @@ -178,6 +179,7 @@ def setUp(self):
trace_state={"a": "b", "c": "d"},
span_id=10217189687419569865,
trace_id=67545097771067222548457157018666467027,
trace_flags=TraceFlags.DEFAULT,
),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
from opentelemetry.test.spantestutil import (
get_span_with_dropped_attributes_events_links,
)
from opentelemetry.trace import TraceFlags

THIS_DIR = os.path.dirname(__file__)

Expand All @@ -86,6 +87,7 @@ def setUp(self):
trace_state={"a": "b", "c": "d"},
span_id=10217189687419569865,
trace_id=67545097771067222548457157018666467027,
trace_flags=TraceFlags.DEFAULT,
),
resource=SDKResource({"a": 1, "b": False}),
parent=Mock(span_id=12345),
Expand All @@ -96,6 +98,7 @@ def setUp(self):
**{
"context.trace_id": 1,
"context.span_id": 2,
"context.trace_flags": TraceFlags.DEFAULT,
"attributes": BoundedAttributes(attributes={"a": 1, "b": False}),
"dropped_attributes": 0,
"kind": OTLPSpan.SpanKind.SPAN_KIND_INTERNAL, # pylint: disable=no-member
Expand All @@ -111,6 +114,7 @@ def setUp(self):
trace_state={"a": "b", "c": "d"},
span_id=10217189687419569865,
trace_id=67545097771067222548457157018666467027,
trace_flags=TraceFlags.DEFAULT,
),
resource=SDKResource({"a": 2, "b": False}),
parent=Mock(span_id=12345),
Expand All @@ -123,6 +127,7 @@ def setUp(self):
trace_state={"a": "b", "c": "d"},
span_id=10217189687419569865,
trace_id=67545097771067222548457157018666467027,
trace_flags=TraceFlags.DEFAULT,
),
resource=SDKResource({"a": 1, "b": False}),
parent=Mock(span_id=12345),
Expand Down Expand Up @@ -678,6 +683,7 @@ def _create_span_with_status(status: SDKStatus):
trace_state={"a": "b", "c": "d"},
span_id=10217189687419569865,
trace_id=67545097771067222548457157018666467027,
trace_flags=TraceFlags.DEFAULT,
),
parent=Mock(span_id=12345),
instrumentation_scope=InstrumentationScope(name="name", version="version"),
Expand Down
Loading