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.
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 {}
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'],
});
},
};
}
}
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
Then run the query in http://localhost:3000/graphql.
query QueryPosts {
posts {
id
title
user {
id
name
}
}
}
When executed, the following log should be output.
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
- API Reference: @apollo/gateway - Apollo GraphQL Docs
- packages/apollo-server-express/src/ApolloServer.ts#L48-L51
If you found this article helpful, please react to the article and follow me on Twitter!
Top comments (0)