Jan 20, 2019

Introducing GraphQL Jaeger tracing middleware

After releasing the post about tracing basics with an example of setting up tracing with a GraphQL service, I thought of a solution to make the development of tracing features for this kind of services even easier - the result of that effort is called graphql-middleware-jaeger.

The simple functionality of this package is to configure an OpenCensus tracer instance, register the Jaeger exporter to push collected spans to a running Jaeger service, and wrap tracing magic around the actual GraphQL resolver. This way, you can simply configure the middleware and wrap it around your wanted resolvers, making it the most simple solution for adding tracing to GraphQL out there.

If the package install fails due to a grpc build error, I'd recommend to add something like a yarn resolution to bump up your grpc version, because tooling like OpenCensus might use an outdated version

import { graphqlJaegerMiddleware } from 'graphql-middleware-jaeger';
import { makeExecutableSchema } from 'graphql-tools';
import { applyMiddleware } from 'graphql-middleware';

...

// Construct the tracing middleware
const tracingMiddleware = graphqlJaegerMiddleware<IContext>(
  // First argument are OpenCensus tracer options
  { logLevel: 3, samplingRate: 1 },
  // followed by Jaeger exporter settings
  { host: 'tracing', serviceName: 'example-service' },
  // and finally middleware options
  { rootSpanOptions: { name: 'graphqlRequest' } },
  {
    // This hook will be executed before resolving the GraphQL schema
    preResolve: [
      ({ context, rootSpan }) => {
        // Context equals the resolver context
        const { req } = context;
        rootSpan.addAttribute('ip', req.ip);
      }
    ]
  }
);

// Bind the middleware to both Query & Mutation resolvers
const withTracing = {
  Query: tracingMiddleware,
  Mutation: tracingMiddleware
};

// And build the wrapped schema
const schema = applyMiddleware(
  makeExecutableSchema({ typeDefs, resolvers }),
  withTracing
);

The full example code can be found here.

And that's already it for this post, no more explanation needed 😄. If you're interested in using the package for your next project, please give it a shot! The complete source code is available on GitHub.