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

feat(leptos-axum): propagate trace context to server functions #2340

Merged
merged 2 commits into from
Feb 22, 2024

Conversation

janu-cambrelen
Copy link
Contributor

What

This PR modifies the handle_server_fns_inner function within the Axum integration to enable trace context propagation to server functions.

Why

Parent contexts — whether passed from the client or created via middleware — were not associated with downstream spans. This led to disjointed and incomplete traces. With this change, downstream spans will now be properly associated with their upstream context:

#[server]
#[cfg_attr(feature = "ssr", tracing::instrument)]
pub async fn some_server_fn() -> Result<(), ServerFnError> {
    use server_imports::*;
    
    // The generated `__some_server_fn` span will now be a child of the propagated parent span.
    // Furthermore, any child events or spans herein will also share the common trace ID.

    Ok(())
}

How

By introducing two changes:

  1. Capturing Current Span: Before spawning the task that contains/runs server functions, the current span is captured via let current_span = tracing::Span::current().
  2. Entering Span Scope: Inside the task, a guard is created using current_span.enter(). This ensures that the current span is set as the active span for the duration of the task.

@benwis
Copy link
Contributor

benwis commented Feb 22, 2024

I'd love to have better tracing support. Does it work well on regular pages?

@benwis benwis merged commit 0a73487 into leptos-rs:main Feb 22, 2024
59 of 60 checks passed
@janu-cambrelen
Copy link
Contributor Author

I'd love to have better tracing support. Does it work well on regular pages?

Sure thing, @benwis! It can work with requests from a Leptos frontend or any other client as long as the necessary trace context headers are present in the request. Otherwise, a new span can be created via middleware and serve as the parent span to any tracing activities within server functions. Prior to this change, the trace context was lost at the server function; now, instrumented requests from server functions can be traced across a distributed system / service boundaries with continuity.

As far as better tracing support, perhaps a feature flagged/gated OpenTelemetry implementation can be useful. However, it can become rather complex pretty quickly. An example of how to implement it for those using SSR can be useful, though. I will give it some thought.

I appreciate the quick review and thank you for your contributions.

@benwis
Copy link
Contributor

benwis commented Feb 23, 2024

It's great to see someone else with interest, I spent some time fiddling with tracing with Honeycomb a while baack, and I could never quite get the internal leptos tracing on route request to be included in the same span as the initial trace from the tower middleware. So I'm hoping you have better luck than me

@janu-cambrelen
Copy link
Contributor Author

Worked like a charm for me! This change may have been the missing piece for you. May be worth another attempt if you're interested. If you do decide to go down that rabbit hole again, feel free to ping me. I'd be happy to assist.

@pythoneer
Copy link

@janu-cambrelen do you know if that would work with sentry(-tracing .. etc)? If yes, how would that look like, i guess you would #[tracing::instrument] the server functions, like in your example but i don't really get what the leptos/client side would look like to "start" a span in the browser and sync the trace ID.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants