Log Request Duration with Axios Interceptors

Tracking API response times is essential for monitoring application performance, identifying bottlenecks, and debugging slow network calls. This article demonstrates how to measure and log end-to-end HTTP request duration metrics using Axios request and response interceptors to capture start times, calculate elapsed durations, and handle both successful and failed requests seamlessly.

How Axios Interceptors Measure Request Duration

Axios interceptors allow you to hook into HTTP requests before they are sent and after a response is received. To measure duration, the request interceptor attaches a high-resolution timestamp to the request configuration object. When the response arrives—or if an error occurs—the response interceptor calculates the difference between the current time and the initial timestamp.

Implementation

Using the standard performance.now() API provides sub-millisecond precision, making it ideal for accurate timing metrics.

import axios from 'axios';

// Create a custom Axios instance
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
});

// Request Interceptor: Attach start time
apiClient.interceptors.request.use(
  (config) => {
    config.metadata = { startTime: performance.now() };
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// Response Interceptor: Calculate and log duration
apiClient.interceptors.response.use(
  (response) => {
    const { config } = response;
    if (config?.metadata?.startTime) {
      const duration = performance.now() - config.metadata.startTime;
      console.log(
        `[HTTP Success] ${config.method?.toUpperCase()} ${config.url} - Duration: ${duration.toFixed(2)}ms`
      );
    }
    return response;
  },
  (error) => {
    const { config } = error;
    if (config?.metadata?.startTime) {
      const duration = performance.now() - config.metadata.startTime;
      console.error(
        `[HTTP Error] ${config.method?.toUpperCase()} ${config.url} - Status: ${
          error.response?.status || 'Network Error'
        } - Duration: ${duration.toFixed(2)}ms`
      );
    }
    return Promise.reject(error);
  }
);

export default apiClient;

Key Considerations