Published April 21, 2024
Distributed tracing is crucial for debugging and improving system performance. Instead of looking at the performance of each service in isolation, distributed tracing links traces across services to show how a request flows through a system. For instance, a trace might start in a React web client, pass through a Next.js API, and continue across subsequent HTTP calls, keeping all activities under one umbrella. This not only simplifies tracking but also provides a clear, consolidated view of how different parts of your application interact.

In this post, we’ll go over a practical example of how tracing across multiple services work in the context of a modern NextJS application.
Here’s the exact github repo we’ll be pulling the example from:
GitHub: Distributed Tracing Example
We will demonstrate how to use LaunchDarkly to connect a NextJS application with an external service by passing HTTP headers in the following steps:
Fetch request, passing the x-highlight-request header which contains a generated sessionId and requestId.sessionId and requestId to it’s local trace, then passes the x-highlight-request header to a third service, this time written in Golang.x-highlight-request header and associates it to the local trace.Client-side integration is as easy as injecting <HighlightInit /> into your web app.
<HighlightInit /> once, preferably in a layout.tsx file or _app.tsx file.<HighlightInit /> accepts props that correspond to the JavaScript SDK’s options arguments.We’ll use the browser’s Fetch API to call a Next.js API function. LaunchDarkly monkey patches window.fetch and adds the x-highlight-request header automatically, so use Fetch as you normally would.
See the full list of monkey patches in our docs.
First, create a wrapper function. The Next.js SDK wrapper functions capture incoming headers and wrap the handler in a custom span named highlight-run-with-headers.
In this case, we’re using the App Router, so we’ll follow the Next.js App Router Guide.
Next, we wrap our GET handler function. Note that we wrap our handler function with withAppRouterHighlight, and we forward request.headers along with the next HTTP request.
The x-highlight-request header is only header that matters in this example.
LaunchDarkly supports multiple Go libraries. In this case we’re using the LaunchDarkly chi SDK.
See a working example of LaunchDarkly chi implementation on GitHub.
First, we configure the highlight-go SDK.
Next we add the Chi middleware.
The highlightChi.Middleware function will automatically associate the current request with the incoming x-highlight-request header.
We used the x-highlight-request header in this example, but we also tested OpenTelemetry’s native JavaScript Propagation example using the W3C traceparent header.
Instead of passing x-highlight-request header, it is possible to pass a traceparent header across HTTP calls. It’s a bit involved, but it works great. See the links below for example code:
request.headers along as before.traceparent header with a local trace.All three services, the web client, the Next.js API function, and the Golang backend, now feed their data to the same LaunchDarkly project.
For the purposes of example, we can even visualize this data in our product (and open source application monitoring tool), LaunchDarkly!
This example shows four separate spans, all of which are nested under a single trace. And of course, these traces are accessible from LaunchDarkly’s Session Replay tab, because the session was generated in the web client and propagated throughout the entire distributed “call stack”.
highlight-run-with-headers is generated by the AppRouterHighlight wrapper function in Next.js.fetch GET https://localhost:3010/test is generated by the Next.js Fetch request.highlight.chi is created by LaunchDarkly’s chi middleware.go-custom-span is a custom span that we used in our example code for demonstration purposes. It wraps a call to time.Sleep(1 * time.Second) to mimic slow code execution.
highlight-run-with-headers

go-custom-span