Logging axios request and response headers

Viewed 1311

We are needing log the HTTP request that axios will send to the remote host, along with the response. This data will be stored in a database for a number of days before being automatically pruned.

The lifecycle we are looking at for the logging:

// creates the session that joins both the request and response
function createSession (url: string): string;
// log the request message as sent
function logRequest (sessionId: string, headers: Record<string, any>, body: Record<string, any> | string);
// log the request message as received
function logResponse (sessionId: string, headers: Record<string, any>, body: Record<string, any> | string);
// close the session, recording the final status and any error message
function closeSession(sessionId: string, status: number, error?: string);

We have looked at the request and response interceptors, but the issue we are having is that the request interceptor is before axios adds all the headers is going to send and the response interceptor doesn't seem to have access to the request, to be able to correlate the request and response.

Without needing to channel all this through a proxy to do the logging, how would you suggest doing this with axios?

1 Answers

Here's what I usually do:

In the request interceptor, I use some UUID library (or maybe the crypto core module of node) to generate a UUID, then attach it to the config object as a request ID, say config.reqId. Same config object should be accessible in response.config, or if an error occurs, in error.response.config and I can get the reqId from there. Then, if you have some script to parse the logs, you can correlate the request and response using this ID.

The disadvantage here is that, yes, the accurate req headers may not be logged.

Also, if you're just looking for the request object in response, then they should be accessible in response.request, going from what I checked in the axios docs. You can try that out.

const axios = require("axios");
const getNewUuid = require("./someUuidGeneratorUtilFunction.js");
const logger = require('./yourChoiceOfLogger.js');

const config = {
    BASE_URL: "https://your.baseurl.here"
}

const myAxiosInstance = axios.create({
    baseURL: config.BASE_URL,
    timeout: 30000,
})

myAxiosInstance.interceptors.request.use((config) => {
    const customUuid = getNewUuid();
    config.reqId = customUuid;
    const message = {
        reqId: customUuid,
        time: Date.now(),
        config: config
    }

    logger.info(message)
    return config;
})

myAxiosInstance.interceptors.response.use((response) => {
    const customUuid = response.config && response.config.reqId ? response.config.reqId : "";
    const message = {
        reqId: customUuid,
        time: Date.now(),
        status: response.status,
        data: response.data,
        headers: response.headers,
        logMessage: "RESPONSE RECEIVED"
    }
    logger.info(message)
    return response;
},(error) => {
    const customUuid = error.response && error.response.config && error.response.config.reqId ? error.response.config.reqId : "";
    
    const errorResponse = error.response ? error.response : {
        status: null,
        data: null,
        headers: null
    }
    const message = {
        reqId: customUuid,
        time: Date.now(),
        status: errorResponse.status,
        data: errorResponse.data,
        headers: errorResponse.headers,
        logMessage: error.message || "ERROR"
    }
    logger.error(message)
    return Promise.reject(error)
})

module.exports = myAxiosInstance;
Related