Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log apollo-server GraphQL query and variables per request

When using apollo-server 2.2.1 or later, how can one log, for each request, the query and the variables?

This seems like a simple requirement and common use case, but the documentation is very vague, and the query object passed to formatResponse no longer has the queryString and variables properties.

like image 474
Dan Dascalescu Avatar asked Jan 20 '19 02:01

Dan Dascalescu


People also ask

How do I check logs in GraphQL?

Analyzing your logs with CloudWatch Logs InsightsIn the CloudWatch console , choose Logs Insights, select the AWS AppSync log group for your GraphQL API, and then choose AWS AppSync queries under Sample queries. The results of CloudWatch Logs Insights queries can be exported to CloudWatch dashboards.

How do I get data from a GraphQL query?

GraphQL Request is a library that doesn't require you to set up a client or a Provider component. It is essentially a function that just accepts an endpoint and a query. Very similar to an HTTP client, you just have to pass in those two values and you get back your data.


2 Answers

Amit's answer works (today), but IMHO it is a bit hacky and it may not work as expected in the future, or it may not work correctly in some scenarios.

For instance, the first thing that I thought when I saw it was: "that may not work if the query is invalid", it turns out that today it does work when the query is invalid. Because with the current implementation the context is evaluated before the the query is validated. However, that's an implementation detail that can change in the future. For instance, what if one day the apollo team decides that it would be a performance win to evaluate the context only after the query has been parsed and validated? That's actually what I was expecting :-)

What I'm trying to say is that if you just want to log something quick in order to debug something in your dev environment, then Amit's solution is definitely the way to go.

However, if what you want is to register logs for a production environment, then using the context function is probably not the best idea. In that case, I would install the graphql-extensions and I would use them for logging, something like:

const { print } = require('graphql');

class BasicLogging {
  requestDidStart({queryString, parsedQuery, variables}) {
    const query = queryString || print(parsedQuery);
    console.log(query);
    console.log(variables);
  }

  willSendResponse({graphqlResponse}) {
    console.log(JSON.stringify(graphqlResponse, null, 2));
  }
}

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

Edit:

As Dan pointed out, there is no need to install the graphql-extensions package because it has been integrated inside the apollo-server-core package.

like image 181
Josep Avatar answered Sep 25 '22 15:09

Josep


With the new plugins API, you can use a very similar approach to Josep's answer, except that you structure the code a bit differently.

const BASIC_LOGGING = {
    requestDidStart(requestContext) {
        console.log("request started");
        console.log(requestContext.request.query);
        console.log(requestContext.request.variables);
        return {
            didEncounterErrors(requestContext) {
                console.log("an error happened in response to query " + requestContext.request.query);
                console.log(requestContext.errors);
            }
        };
    },

    willSendResponse(requestContext) {
        console.log("response sent", requestContext.response);
    }
};


const server = new ApolloServer(
    {
        schema,
        plugins: [BASIC_LOGGING]
    }
)

server.listen(3003, '0.0.0.0').then(({ url }) => {
    console.log(`GraphQL API ready at ${url}`);
});
like image 29
amoe Avatar answered Sep 22 '22 15:09

amoe