Monitoring and metrics

How to monitor Apollo Server's performance

Understanding the behavior of GraphQL execution inside of Apollo Server is critical to developing and running a production GraphQL layer. Apollo Server enables GraphQL monitoring in Apollo Engine and provides more primitive native mechanisms to log each phase of a GraphQL request.

Apollo Engine

Apollo Engine provides an integrated hub for all GraphQL performance data that is free for one million queries per month. With an API key from the Engine UI, Apollo Server reports performance and error data out-of-band. Apollo Engine then aggregates and displays information for queries, requests, the schema, and errors. By leveraging this data, Apollo Engine offers alerts via Slack and Datadog integrations.

To set up Apollo Server with Engine, click here to get an Engine API key. This API key can be passed directly to the Apollo Server constructor.

const { ApolloServer } = require("apollo-server");

const server = new ApolloSever({
  typeDefs,
  resolvers,
  engine: {
    apiKey: "YOUR API KEY HERE"
  }
});

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

The API key can also be set with the ENGINE_API_KEY environment variable. Setting an environment variable can be done in commandline as seen below or with the dotenv npm package.

#Replace YOUR_API_KEY with the api key for you service in the Engine UI
ENGINE_API_KEY=YOUR_API_KEY node start-server.js

Logging

Apollo Server provides two ways to log a server: per input, response, and errors or periodically throughout a request’s lifecycle. Treating the GraphQL execution as a black box by logging the inputs and outputs of the system allows developers to diagnose issues quickly without being mired by lower level logs. Once a problem has been found at a high level, the lower level logs enable accurate tracing of how a request was handled.

High Level Logging

To log, Apollo Server provides: formatError and formatResponse. This example uses console.log to record the information, servers can use other more sophisticated tools.

const server = new ApolloServer({
  typeDefs,
  resolvers,
  formatError: error => {
    console.log(error);
    return error;
  },
  formatResponse: response => {
    console.log(response);
    return response;
  },
});

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

Granular Logs

For more advanced cases, Apollo Server provides an experimental api that accepts an array of graphql-extensions to the extensions field. These extensions receive a variety of lifecycle calls for each phase of a GraphQL request and can keep state, such as the request headers.

const { ApolloServer }  = require('apollo-server');
const LoggingExtension = require('./logging');

const server = new ApolloServer({
  typeDefs,
  resolvers,
  extensions: [() => new LoggingExtension()]
});

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

For example the logFunction from Apollo Server 1 can be implemented as an extension and could be modified to add additional state or functionality. The example uses a beta of graphql-extensions, which can be added to a project with npm install graphql-extensions@beta.

Edit on GitHub
// search box