Skip to content

Latest commit

 

History

History
184 lines (144 loc) · 6.58 KB

File metadata and controls

184 lines (144 loc) · 6.58 KB
title description sidebar_position
Monitoring GraphQL Requests
Best practices for monitoring GraphQL network requests with the Embrace SDK
4

Monitoring GraphQL Requests

Generally, network requests made to a REST API each hit its own unique endpoint. From a monitoring perspective, this is helpful because developers can clearly see rolled up network metrics by path.

GraphQL is a bit different in that each request hits the same /graphql endpoint. Thus, it can be difficult to monitor requests that may perform different actions.

Here we will show you how to configure your integration so you see different GraphQL requests broken out by "path" in the Dashboard.

Override Paths of Requests

It's possible to override the path of a network request that the Embrace SDK captures. iOS 5.X and Android allows this override by setting the x-emb-path header on the request. For example, if your network request is made to https://example.com/graphql, and you set the x-emb-path header to /graphql/friends_list, the request will be reported as https://example.com/graphql/friends_list.

In iOS 6.X, you can hook into a callback that lets you modify the captured request directly.

:::warning Important The x-emb-path value must meet the following requirements or it will be ignored.

  • Must be a string with a length in the range from 1 to 1024 characters
  • Must start with a /
  • Must only contain ASCII characters :::
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import EmbraceIO

/* Create class to handle modifying captured requests */
class ApolloDataSource: NSObject, URLSessionRequestsDataSource {
    func modifiedRequest(for request: URLRequest) -> URLRequest {

        if let header = request.value(forHTTPHeaderField: "X-APOLLO-OPERATION-NAME") {
            var modified = request
            modified.url = request.url?.appendingPathComponent(header)  // modify the URL that is recorded
            return modified
        }

        return request
    }
}

/* When initializing Embrace, pass this object to the URLSessionCaptureServce */
let options = Embrace.Options(
                // ...
                captureServices:
                    CaptureServiceBuilder()
                        .addDefaults()
                        .add( .urlSession(options: .init(requestsDataSource: ApolloDataSource())) )
                        .build()
                ,
                // ...
              )
import Foundation
import Apollo

// MARK: - Singleton Wrapper

class Network {
  static let shared = Network()

  // Configure the network transport to use the singleton as the delegate.
  private lazy var networkTransport = HTTPNetworkTransport(
    url: URL(string: "http://localhost:8080/graphql")!,
    delegate: self
  )

  // Use the configured network transport in your Apollo client.
  private(set) lazy var apollo = ApolloClient(networkTransport: self.networkTransport)
}

// MARK: - Pre-flight delegate

extension Network: HTTPNetworkTransportPreflightDelegate {

  func networkTransport(_ networkTransport: HTTPNetworkTransport,
                        willSend request: inout URLRequest) {

    // Get the existing headers, or create new ones if they're nil
    var headers = request.allHTTPHeaderFields ?? [String: String]()
    let gqlQueryNameOpt = headers["X-APOLLO-OPERATION-NAME"]
    // Add any new headers you need
    if let gqlQueryName = gqlQueryNameOpt {
        headers["x-emb-path"] = "/graphql/" + gqlQueryName

        // Re-assign the updated headers to the request.
        request.allHTTPHeaderFields = headers
    }
}
}
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 stats are broken out for each unique GraphQL query.
     */
    String combinedPath = ""
    String gqlQueryName = originalRequest.headers().get("X-APOLLO-OPERATION-NAME");
    if (gqlQueryName != null && !gqlQueryName.isEmpty()) {
        combinedPath = "/graphql/" + gqlQueryName;
        newRequestBuilder.header("x-emb-path", combinedPath);
    }
    Request newRequest = newRequestBuilder.build();
    try {
        return chain.proceed(newRequest);
    } catch (Exception e) {
        throw new EmbraceCustomPathException(combinedPath, e);
    }
});

Configuring Network Grouping Rules

After setting up the path override, you may find that your GraphQL operations appear correctly in the session timeline but are missing or inconsistent in the Network section of the dashboard.

This happens because the Embrace backend automatically groups network paths with high cardinality into wildcard entries. For example, if your app tracks many distinct GraphQL operations (/graphql/getUser, /graphql/createOrder, /graphql/deleteItem, etc.), the backend may collapse them into a single wildcard entry like /graphql/*. When this occurs, individual operations will not appear as their own entries in the Network section, even though they are being captured and sent correctly.

You can verify that the requests are being captured by checking the session timeline for a session where the GraphQL calls were made. If the individual paths appear there (e.g., /graphql/getUser), the SDK integration is working and the issue is with how the dashboard groups the paths.

To resolve this, create network grouping rules for each GraphQL operation you want to track individually:

  1. Navigate to the Network section in the Embrace dashboard.
  2. Locate the wildcarded GraphQL endpoint.
  3. Click the pencil icon next to the path, or click Create rule in the tooltip that reads "There is no matching grouping rule for this endpoint."
  4. Enter the full path for the operation you want to track, e.g., example.com/graphql/getUser.
  5. Repeat for each GraphQL operation you want to monitor separately.

Once the rules are in place, each operation will have its own Network Path Details page with per-operation metrics including latency, error rates, and individual session matching.

:::info Note Network grouping rules apply going forward. Historical data that was already grouped under a wildcard will not be retroactively split. :::