松开 opentelemetry span 的 parentid

Looses parentid of opentelemetry span

如果我将 span 发送到另一个线程并等待它完成,如何手动设置 parentID?案例是我不想在委托人下并行进行 2 个休息调用,当我传递跨度时,出于某种原因我失去了 parentID。

示例代码:

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()

控制台输出:

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"
    }
}

我确实在等待 subspans 完成,所以我看不到在这里断开父级连接的理由。

您应该使用 set_span_in_context 并在您的子 span 中传递返回的上下文。

...
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:


    ...