Apollo-client: How to log HTTP request and response with ApolloClient

Created on 16 Oct 2018  路  10Comments  路  Source: apollographql/apollo-client

This seems like a very simple task but I've spent quite some time searching without any mentions about this.

I want to see the outgoing request headers and params, and the responses headers and status code

I tried both ApolloClient from 'apollo-client' and 'apollo-boost' libraries, like

 const client = new ApolloClient({
  uri: 'https://www.myapp.no/api/',
  request: async (operation) => {

    console.log(operation)

    operation.setContext({
      headers: {
        authorization: tokenHeader,
        'Content-Type': 'application/json'
      }
    })
  },
  onError: (error) => {
    if (error.graphQLErrors) {
      console.log('ApolloClient graphQLErrors')
      console.log(graphQLErrors)
    }
    if (error.networkError) {
      console.log('ApolloClient networkError')
      console.log(graphQLErrors)
    }
  }
})

The operation object only show variables and query information. How to log the actual HTTP requests and response under the hood?

By HTTP request, I want to log status code, header, body

Versions
npx: installed 1 in 2.09s

System:
OS: macOS 10.14
Binaries:
Node: 8.11.4 - ~/.nodenv/versions/8.11.4/bin/node
npm: 6.4.1 - ~/.nodenv/versions/8.11.4/bin/npm
Browsers:
Chrome: 69.0.3497.100
Firefox: 62.0.3
Safari: 12.0
npmPackages:
apollo-boost: ^0.1.16 => 0.1.16

Most helpful comment

I just created a custom middleware for that:

import { ApolloLink } from 'apollo-link';

const logLink = new ApolloLink((operation, forward) => {
  console.time(operation.operationName);
  return forward(operation).map(result => {
    console.timeEnd(operation.operationName);
    return result;
  });
});

export default logLink;

All 10 comments

I'm also interested - trying to debug app latency and logging query response timing vs render would be helpful.

struggled with the same issue, especially due debug of server-side-rendering + 3rd party api,
ended up by inserting
console.log(chosenURI, options)
into node_modules/apollo-link-http/lib/httpLink.js near the fetcher(chosenURI, options) call
and now it provided method/headers/body

thats was match better than simple errors like
Error: Network error: Response not successful: Received status code 500 at new ApolloError (webpack-internal:///./node_modules/apollo-client/errors/ApolloError.js:46:28)

would be better to have something more clear

I use ApolloClient mostly for its caching, which does not work either. I stopped using this library.

I ended up tuning the fetch method to log at least the requests:
```
const DEBUG = true

const httpLink = new HttpLink({
uri: GRAPHQL_URL,
fetch: (...pl) => {
if (!DEBUG) return fetch(...pl)
const [_, options] = pl
const body = JSON.parse(options.body)
console.log(馃摗${body.operationName || ''}\n${body.query}, body.variables)
return fetch(...pl)
}
})```

To anyone else ending up here on this issue wanting to log the response.

  const responseLogger = new ApolloLink((operation, forward) => {
    return forward(operation).map(result => {
      console.info(operation.getContext().response.headers)
      return result
    })
  })

Then insert the responseLogger in your ApolloLink.from chain.

new ApolloClient({
  ...
  link: ApolloLink.from([
    responseLogger,
    ...
  ])
})

@lasseborly this only logs the response and not the request body.
I think @musemind way is the only way. I just wonder which fetch function to use

I just created a custom middleware for that:

import { ApolloLink } from 'apollo-link';

const logLink = new ApolloLink((operation, forward) => {
  console.time(operation.operationName);
  return forward(operation).map(result => {
    console.timeEnd(operation.operationName);
    return result;
  });
});

export default logLink;

For those who want all the info and not just the time, slight modification to @HaNdTriX post:

import { ApolloLink } from '@apollo/client';

const logLink = new ApolloLink((operation, forward) => {
    console.info('request', operation.getContext());
    return forward(operation).map((result) => {
        console.info('response', operation.getContext());
        return result;
    });
});

export default logLink;

Also, in Apollo client init:

const linkConfig = [];

linkConfig.push(logLink);

return new ApolloClient({
        ...cache, etc.
        link: ApolloLink.from(linkConfig),
    });

@mliq Could you elaborate? I tried to implement it like that

export const client = new ApolloClient({
  link: ApolloLink.from(linkConfig),
  uri: urls[process.env.NODE_ENV],
  request: (op) => {
    let accessToken = "";
    if (process.browser) accessToken = localStorage.accessToken || "";

    op.setContext({
      headers: {
        authorization: accessToken,
      },
    });
  },
  onError: ({ graphQLErrors, networkError }) => {
    if (graphQLErrors)
      graphQLErrors.map(({ message, locations, path, extensions }) => {
        console.log('*** ERROR GraphQL START ***');
        //...
      });

    if (networkError) {
      console.log('*** ERROR GraphQL (networkError) START ***');
      //...
    }
  },
});

But when I load a page I have this log ApolloBoost was initialized with unsupported options: link and no other log. Did I miss something?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

paldepind picture paldepind  路  66Comments

sandervanhooft picture sandervanhooft  路  72Comments

dotansimha picture dotansimha  路  44Comments

jbaxleyiii picture jbaxleyiii  路  43Comments

joenoon picture joenoon  路  43Comments