The most useful tool to track down bugs and improve performance (after a stack trace) is network request monitoring. In a REST API, no problem. Each request hits a unique endpoint. We can collect network requests, which developers can filter by status code or endpoint.

In GraphQL all requests hit the same endpoint. And therein lies the problem.

We want something like this:

Typical REST architecture
Typical REST architecture

But we only have this:

GraphQL endpoint
Single GraphQL Endpoint

Here at Embrace we came up with a solution that allows developers to have their cake and eat it too. We call it custom GraphQL breakouts. Here’s how it works.

A developer can set custom headers on their network requests. We watch for these headers, and if we see them, we categorize that request under that custom header instead of the normal “/graphql” endpoint.

That way, the developer can label their requests however they want.

Turning this:

GraphQL endpoint
Single GraphQL Endpoint

Into this:

Custom GraphQL endpoints
Custom GraphQL Endpoints

And the best part is that it’s very simple to do. One of our customers, OKCupid, dynamically adds these headers by reusing a custom query name they’re already creating for Apollo. Here’s how simple their implementation is:

// Courtesy of Adam at OKCupid

httpClient.addInterceptor(chain -> {
	Request originalRequest = chain.request();
    Request.Builder newRequestBuilder = originalRequest.newBuilder();
    /*
    If the request was made by the Apollo GraphQL library, they will take our
    query name and apply it as one of their headers. We can pull that out,
    and pass that to x-emb-path so that Embrace can break out stats for each
    of our unique GraphQL queries.
    */
    String gqlQueryName = originalRequest.headers().get("X-APOLLO-OPERATION-NAME");
    if (gqlQueryName != null && !gqlQueryName.isEmpty()) {
    	String combinedPath = "/graphql/" + gqlQueryName;
        newRequestBuilder.header("x-emb-path", combinedPath);
    }
    Request newRequest = newRequestBuilder.build();
    return chain.proceed(newRequest);
});
Code provided by superstar Android dev Adam McNeilly – check him out here!

Now, they’re able to monitor their requests however they’d like. The world is at peace.

And we’re happy to help.

We’re Embrace, a data driven toolset to help mobile engineers build better experiences. If you’d like to learn more, check out our website, or request a demo.