apollographql / router

A configurable, high-performance routing runtime for Apollo Federation 🚀
https://www.apollographql.com/docs/router/
Other
791 stars 261 forks source link

Providing trace_id though context to Rhai scripts #1935

Closed risyasin closed 1 year ago

risyasin commented 1 year ago

Is your feature request related to a problem? Please describe. Previously with @apollo/gateway, We were able to provide additional information on supergraph responses such as trace_id (or request_id). This information allows developers to diagnose problems quickly even from the customers' feedback, especially when response.body contains this information. In Alphasense we provide extensive support to customers that use graphql. Since we are in the transition to router, we need the same or similar experience with it.

Describe the solution you'd like After some research, it's revealed that a clean and optional feature can be implemented via Rhai script integration through the supergraph's request/response context. Can we provide Span::current().context().span().span_context().trace_id() through the context? So 3rd party scripts can get this information with their rhai scripts. I have reasoning for using context because similar information that can only be used in diagnostics such as client_name and client_version are already provided in context entries.

Describe alternatives you've considered One poor alternative can be exposing the whole Span through response/request.context. But I hardly believe it's needed, and it feels overkill.

garypen commented 1 year ago

This is a common requirement and we added functionality to the router to expose this information to plugins as a TraceId. It was added fairly recently: https://github.com/apollographql/router/issues/1536

The functionality isn't currently exposed to rhai scripts, but the intention is to add support for this directly, rather than adding it to the context. A new rhai module would be provided (apollo?) to encapsulate this functionality.

A rhai script using this would look something like:

import "apollo" as apollo;

fn subgraph_service(service, subgraph) {
    let span_id = apollo::trace_id();
    print(`span: ${span_id}`};
}

Note: Names and use may vary from this example. The implementation hasn't started and the interface is likely to vary from this, however I think this is reasonably illustrative.

garypen commented 1 year ago

I thought about this a bit and concluded it would be best to simply add a traceid() function to the same module that we currently import into the execution context. see PR #1937 for details.

risyasin commented 1 year ago

Thanks! I can confirm that I could access to Root span Id with traceid(). I've used below the snippet as an example. (Note that, no module import is needed now)

fn supergraph_service(service) {
    const response_callback = Fn("process_response");
    service.map_response(response_callback);
}

fn process_response(response) {
    let span_id = traceid();
    print(span_id);
}

So, closing issue.