This project is no longer maintained and has been archived/deprecated
Beautify Axios Logging Messages.
When you send request with axios library, it's very helpful to see request/response details.
Others libraries just outputs it's details in one line, which is not really helpful, when payload is big. So, we decided to improve this situation
and create Axios Logger
Basically This package is working as Axios's interceptors
$ npm install @new10com/axios-logger
By default axios-logger
is using log4js library under the hood for logging.
You can use AxiosLogger.default()
method if you don't want to customize your logger details
const instance = axios.create()
const axiosLogger = AxiosLogger.default()
instance.interceptors.request.use((config) => {
axiosLogger.logRequest(config)
return config
})
instance.get('https://jsonplaceholder.typicode.com/users')
Request details will be logged this way:
┌────── Request ──────────────────────────────────────────────────────────────────────────────────────────────
URL: https://jsonplaceholder.typicode.com/users
Method: @GET
Headers:
└ Accept: "application/json, text/plain, */*"
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────
Or you can use custom log4js
instance with settings that you need:
log4js.configure({
appenders: { axios: { type: 'console', layout: { type: 'colored' }, level: 'debug' } },
categories: { default: { appenders: ['axios'], level: 'debug' } },
})
const log4jsLogger = log4js.getLogger('axios')
const axiosLogger = AxiosLogger.from(log4jsLogger)
const instance = axios.create()
instance.interceptors.request.use((config) => {
axiosLogger.logRequest(config)
return config
})
In case you don't want to use log4js
library, but some other library, then you can use static AxiosLogger.using
method. The only requirement is that this methods should confrm LogFn
interface:
interface LogFn {
(msg: string, ...args: any[]): void;
(obj: object, msg?: string, ...args: any[]): void;
}
const consola = require('consola')
const axiosLogger = AxiosLogger.using(consola.info, consola.error)
const instance = axios.create()
instance.interceptors.request.use((config) => {
axiosLogger.logRequest(config)
return config
})
const instance = axios.create()
const axiosLogger = AxiosLogger.default()
instance.interceptors.response.use((response) => {
axiosLogger.logResponse(response)
return response
})
instance.get('https://jsonplaceholder.typicode.com/users')
Logged response will look like this:
┌────── Response ──────────────────────────────────────────────────────────────────────────────────────────────
URL: https://jsonplaceholder.typicode.com/users
Method: @GET
Status: 200 OK
Headers
┌ date: "Tue, 15 Sep 2020 07:52:33 GMT"
├ content-type: "application/json; charset=utf-8"
├ transfer-encoding: "chunked"
├ connection: "close"
├ x-powered-by: "Express"
├ x-ratelimit-limit: "1000"
├ x-ratelimit-remaining: "998"
├ x-ratelimit-reset: "1599014805"
├ vary: "Origin, Accept-Encoding"
├ access-control-allow-credentials: "true"
├ cache-control: "max-age=43200"
├ pragma: "no-cache"
├ expires: "-1"
└ cf-ray: "5d30c4d63ff00bf9-AMS"
Body:
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
]
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────
You can inject logError
right after logRequest
or logResponse
.
const instance = axios.create()
const axiosLogger = AxiosLogger.default()
instance.interceptors.request.use((config) => {
axiosLogger.logRequest(config)
return config
}, (error) => {
axiosLogger.logErrorDetails(error)
return Promise.reject(error)
})
instance.interceptors.response.use((response) => {
axiosLogger.logResponse(response)
return response
}, (error) => {
axiosLogger.logErrorDetails(error)
return Promise.reject(error)
})
In case of error, you gonna get logged request
, response
and error
all together:
┌────── Request ──────────────────────────────────────────────────────────────────────────────────────────────
URL: https://doodle.com/users
Method: @GET
Headers:
┌ Accept: "application/json, text/plain, */*"
└ Authorization: "{Super-Secret-Token}"
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌────── Response ──────────────────────────────────────────────────────────────────────────────────────────────
URL: https://doodle.com/users
Method: @GET
Status: 400 Bad Request
Headers
┌
├ Content: "application/json"
└
Body:
{
\t"error": "Failure"
}
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌────── Response Error ──────────────────────────────────────────────────────────────────────────────────────────────
Message: @Request failed with status code 400
StackTrace: @Error: Request failed with status code 400
at createAxiosError (${baseDir}/node_modules/axios-mock-adapter/src/utils.js:148:15)
at Object.settle (${baseDir}/node_modules/axios-mock-adapter/src/utils.js:127:9)
at handleRequest (${baseDir}/node_modules/axios-mock-adapter/src/handle_request.js:67:13)
at ${baseDir}/node_modules/axios-mock-adapter/src/index.js:26:9
at new Promise (<anonymous>)
at MockAdapter.<anonymous> (${baseDir}/node_modules/axios-mock-adapter/src/index.js:25:14)
at dispatchRequest (${baseDir}/node_modules/axios/lib/core/dispatchRequest.js:52:10)
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────`
Axios Logger has several options that can be configured. Configuration has some default settings, but they can be easily overridden.
If you would like to have a different indentation of the logs, then you can do it by passing config object:
const config = {indent: 4, indentChar: '\t'}
const logger = AxiosLogger.default()
// or you can use from method
const log4jsLogger = log4js.getLogger('axios')
const axiosLogger = AxiosLogger.from(log4jsLogger, config)
In case when you don't want to log some confidential information, you would like to hide them and this is now possible in Axios Logger as well:
// One way to specify list of "confidential" keys is to use environment variable
process.env.LOGGER_REDACTABLE_KEYS = 'username,password'
const envObfuscation: IConfig = {obfuscation: {obfuscate: true}}
const envLogger = AxiosLogger.default(envObfuscation)
// Another way is to directly pass this list of confidential keys to config
let config: IConfig = {obfuscation: {obfuscate: true, redactableKeys: ['username', 'password']}}
const logger = AxiosLogger.default(config)
// In case when you want to have some custom behaviour on how to obfuscate, you can pass custom function to config
config: IConfig = {obfuscation: {obfuscate: true, redactableKeys: ['username', 'password']}, obfuscation: {
obfuscate: true,
redactableKeys: ['Authorization', 'username', 'password'],
replaceVal: (value: any, key: string) => {
if (DEFAULT_REDACTABLE_KEYS.includes(key)) {
return 'VALUE_FROM_FUNCTION'
}
return value
},
},}
// Or if you don't like REDACTED value as a replacement for your confidential data, you can specify a different replacement value
config: IConfig = {obfuscation: {obfuscate: true, redactableKeys: ['username', 'password']}, obfuscation: {
obfuscate: true,
redactableKeys: ['Authorization', 'username', 'password'],
replaceVal: 'MY_CUSTOM_REPLACEMENT',
},}
In case you would like to reduce amount of details that are logged for request/response, you can disable logging headers of body for either request, response or both:
// Request
// If you want to disabled logging request headers
const config = { request: { shouldLogHeaders: false } }
// If you want to ommit request headers and body
const config = { request: { shouldLogHeaders: false , shouldLogBody: false} }
// Response
// If you want to disabled logging response headers
const config = { response: { shouldLogHeaders: false } }
// If you want to ommit response headers and body
const config = { response: { shouldLogHeaders: false , shouldLogBody: false} }
// Request and Response
// If you want to disabled logging request and response headers
const config = { request: { shouldLogHeaders: false }, response: { shouldLogHeaders: false } }
// If you want to ommit request+response headers and body
const config = { request: { shouldLogHeaders: false , shouldLogBody: false}, response: { shouldLogHeaders: false , shouldLogBody: false} }
In case you would like to skip logging request/response body for requests/responses that are too long, you can do so by passing maxBodyLength to config:
// Request
// If you want to limit lenght of request body to 1KB
const config = { request: { maxLogContentLength: 1024 } } // lenght of request body will be limited to 1KB
// Response
// If you want to limit lenght of resonse body to 1KB
const config = { request: { maxLogContentLength: 1024 } } // lenght of request body will be limited to 1KB
Suggestions and MR's are welcome :)
Made with contributors-img.