DEV Community

choco
choco

Posted on

Send request-id from Apollo Gateway to link logs

Introduction

My work project uses Apollo Gateway (Federation). Currently, the API logs are output, but it is difficult to determine which GraphQL queries were executed within a single request.

In this case, I tried to improve it by using Apollo Gateway's RemoteGraphQLDataSource to add an ID to the request header so that it can be referenced from each application's GraphQL context.

app-sturucture

This article uses NestJS. Tool versions are below.

  • Node.js v18.12.1
  • Apollo Server v3.11.1
  • NestJS v9.2.1
  • yarn v1.22.19
  • @nestjs/cli v9.1.5

Setting up Gateway

First, set up request-id to send applications. Set header generated by Apollo Server context in RemoteGraphQLDataSource.willSendRequest.

import { IntrospectAndCompose, RemoteGraphQLDataSource } from '@apollo/gateway';
import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { v4 } from 'uuid';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
      driver: ApolloGatewayDriver,
      server: {
        cors: true,
        context: () => {
          return { requestId: v4() };
        },
      },
      gateway: {
        supergraphSdl: new IntrospectAndCompose({
          subgraphs: [
            { name: 'posts', url: 'http://localhost:3001/graphql' },
            { name: 'users', url: 'http://localhost:3002/graphql' },
          ],
        }),
        buildService: ({ url }) =>
          new RemoteGraphQLDataSource<{ requestId: string }>({
            url,
            willSendRequest: ({ request, context }) => {
              request.http.headers.set('x-request-id', context.requestId);
            },
          }),
      },
    }),
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Add request-id to the application's log

Next, implement ApolloServerPlugin to output the log. As shown in the figure, applications can obtain request-id from the GraphQL context.

import { Plugin } from '@nestjs/apollo';
import { ExpressContext } from 'apollo-server-express';
import {
  ApolloServerPlugin,
  GraphQLRequestContext,
  GraphQLRequestListener,
} from 'apollo-server-plugin-base';

@Plugin()
export class LoggingPlugin implements ApolloServerPlugin {
  async requestDidStart(
    requestContext: GraphQLRequestContext<ExpressContext>
  ): Promise<GraphQLRequestListener<ExpressContext>> {
    return {
      willSendResponse: async ({ context }) => {
        const {
          request: { query, variables },
        } = requestContext;
        console.log({
          query,
          variables: JSON.stringify(variables),
          request_id: context.req.headers['x-request-id'],
        });
      },
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

Output log to check request-id added

The rough setup is completed. If you want to run it, clone the repository below.

https://github.com/choco14t/example-gateway-logging

Run applications.

cd application-posts && yarn start
cd application-posts && yarn start
cd gateway && yarn start
Enter fullscreen mode Exit fullscreen mode

Then run the query in http://localhost:3000/graphql.

query QueryPosts {
  posts {
    id
    title
    user {
      id
      name
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

When executed, the following log should be output.

post-app-log

user-app-log

Send the same request-id to applications. It sounds good!!

Conclusion

This article showed how to improve logging using a gateway.

I hope this information will be helpful to those who are operating applications using Apollo Gateway or considering using Apollo Gateway.

References


If you found this article helpful, please react to the article and follow me on Twitter!

https://twitter.com/choco14t_en

Top comments (0)