Reputation: 47
How can I manually set a parentID if I send a span to another thread and wait for it to complete? Case is that I wan't to do 2 rest calls in parallel under a delegator and when I pass along the span I loose the parentID for some reason.
Example code:
tracer_provider = TracerProvider()
console_span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
tracer_provider.add_span_processor(console_span_processor)
trace.set_tracer_provider(tracer_provider)
class SubMethod(Thread):
def __init__(self, event: Event, name: str):
super().__init__()
self.event = event
self.name = name
self.parent = None
self.done = Event()
def run(self) -> None:
self.done.clear()
while True:
self.event.wait()
self.sub_method(self.parent, self.name)
self.parent = None
self.done.set()
self.done.clear()
def done_event(self):
return self.done
def set_parent(self, parent: Span):
self.parent = parent
def sub_method(self, span: Span, name: str):
with trace.get_tracer("Sub").start_as_current_span(name, links=[Link(span.get_span_context())]) as child:
sleep(1)
with trace.get_tracer("Sub").start_as_current_span(name + "->A", links=[Link(child.get_span_context())]) as sub_child:
sleep(1)
sub_child.set_attribute("asd", "asd")
def test_trace_with_methods():
event = Event()
event.clear()
sub1 = SubMethod(event, "A->A")
sub2 = SubMethod(event, "A->B")
sub1.start()
sub2.start()
with trace.get_tracer("Test").start_as_current_span("A") as parent:
sleep(1)
sub1.set_parent(parent)
sub2.set_parent(parent)
event.set()
event.clear()
sub1.done_event().wait()
sub2.done_event().wait()
Output in console:
tests/test_utils.py {
"name": "A->A->A",
"context": {
"trace_id": "0x9c407a3651c194c0fbfb85b5927017a0",
"span_id": "0x205bca6e22f611ef",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0x8e35e5c37299be5a",
"start_time": "2022-04-22T12:39:42.520765Z",
"end_time": "2022-04-22T12:39:43.527002Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"asd": "asd"
},
"events": [],
"links": [
{
"context": {
"trace_id": "0x9c407a3651c194c0fbfb85b5927017a0",
"span_id": "0x8e35e5c37299be5a",
"trace_state": "[]"
},
"attributes": {}
}
],
"resource": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.11.1",
"service.name": "unknown_service"
}
}
{
"name": "A->A",
"context": {
"trace_id": "0x9c407a3651c194c0fbfb85b5927017a0",
"span_id": "0x8e35e5c37299be5a",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": null,
"start_time": "2022-04-22T12:39:41.514560Z",
"end_time": "2022-04-22T12:39:43.529754Z",
"status": {
"status_code": "UNSET"
},
"attributes": {},
"events": [],
"links": [
{
"context": {
"trace_id": "0x7e78052411918b921aa25a95aab601c3",
"span_id": "0x3b585aa12caa8e08",
"trace_state": "[]"
},
"attributes": {}
}
],
"resource": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.11.1",
"service.name": "unknown_service"
}
}
{
"name": "A->B->A",
"context": {
"trace_id": "0x3623444de52074132ed1ec996cc94fbf",
"span_id": "0xd0042794d8fc3471",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0x415dfe16a6278f4e",
"start_time": "2022-04-22T12:39:42.521046Z",
"end_time": "2022-04-22T12:39:43.529371Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"asd": "asd"
},
"events": [],
"links": [
{
"context": {
"trace_id": "0x3623444de52074132ed1ec996cc94fbf",
"span_id": "0x415dfe16a6278f4e",
"trace_state": "[]"
},
"attributes": {}
}
],
"resource": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.11.1",
"service.name": "unknown_service"
}
}
{
"name": "A->B",
"context": {
"trace_id": "0x3623444de52074132ed1ec996cc94fbf",
"span_id": "0x415dfe16a6278f4e",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": null,
"start_time": "2022-04-22T12:39:41.516332Z",
"end_time": "2022-04-22T12:39:43.530239Z",
"status": {
"status_code": "UNSET"
},
"attributes": {},
"events": [],
"links": [
{
"context": {
"trace_id": "0x7e78052411918b921aa25a95aab601c3",
"span_id": "0x3b585aa12caa8e08",
"trace_state": "[]"
},
"attributes": {}
}
],
"resource": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.11.1",
"service.name": "unknown_service"
}
}
{
"name": "A",
"context": {
"trace_id": "0x7e78052411918b921aa25a95aab601c3",
"span_id": "0x3b585aa12caa8e08",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": null,
"start_time": "2022-04-22T12:39:40.508204Z",
"end_time": "2022-04-22T12:39:43.531210Z",
"status": {
"status_code": "UNSET"
},
"attributes": {},
"events": [],
"links": [],
"resource": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.11.1",
"service.name": "unknown_service"
}
}
I do wait for the subspans to complete so I don't see a reason to disconnect the parent here.
Upvotes: 1
Views: 1933
Reputation: 2274
You should use set_span_in_context
and pass the returned context in your child spans.
...
from opentelemetry.trace.propagation import set_span_in_context
...
class SubMethod(Thread):
...
def sub_method(self, span: Span, name: str):
ctx = set_span_in_context(span)
with trace.get_tracer("Sub").start_as_current_span(name, ctx) as child:
...
Upvotes: 3