1

I'm writing a Pingora proxy instance. It uses multiple async functions from a trait to indicate various stages. There is a common context that I can provide. I am trying to instrument the whole request lifecycle, however, since Tokio/Pingora can call the stage functions at anytime or on any thread. This does present some challenges to measuring the stages underneath the whole request parent span.

How can I get the current parent span to be active once the functions are called back?

What I'm using:

  • The Open Telemetry crates
  • The Tokio tracing crate

I've tried:

  • storing the various flavors of Span in my context
  • storing the current tracing context in my context then calling .attach()

What I'm looking for in a tracing graph:

|-- Request/Parent Span ---------------------------------------|
  |-- Stage 1 Span --|
                         |-- Stage 2 Span --|
                                             |-- Upstream --|
2
  • Are you primarily interfacing with tracing within your application which is configured to export OpenTelemetry data via the tracing-opentelemetry subscriber? Or are you doing something else? Commented Aug 18 at 19:50
  • @kmdreko Iโ€™m up for anything. Would be nice to stick with the tracing crate to allow for more stuff later Commented Aug 18 at 21:59

1 Answer 1

3

In the tracing crate, you can get a handle to the current span (via Span::current) and store that with your request (or keep a hold of one created by info_span! and friends). When your request is being handled you can .enter() the span or use it as the parent of a sub-span.

For you I would recommend using #[instrument] on your methods and use the stored span as the parent. There is a similar example listed in the docs but here's how it might look for you:

struct Request {
    span: tracing::Span
}

impl Request {
    #[instrument(parent = &self.span, skip(self))]
    async fn stage_1(&self) {}

    #[instrument(parent = &self.span, skip(self))]
    async fn stage_2(&self) {}

    #[instrument(parent = &self.span, skip(self))]
    async fn upstream(&self) {}
}

The outer span will close when all references to it are dropped.

Your Answer

By clicking โ€œPost Your Answerโ€, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.