Measure Round-Trip Time Using Axios Interceptors
Measuring network round-trip time (RTT) is essential for monitoring API performance and diagnosing network latency issues in web applications. By utilizing Axios request and response interceptors, developers can attach high-resolution timestamps to outgoing requests and calculate the total elapsed time once a response or error is received. This guide provides a straightforward implementation for tracking RTT across your HTTP calls without modifying individual endpoint logic.
How Axios Interceptors Track RTT
Axios interceptors act as middleware for HTTP requests. To calculate RTT:
- Request Interceptor: Records a start timestamp and stores it inside the request's custom configuration object.
- Response Interceptor: Reads the start timestamp upon receiving the response, captures an end timestamp, and calculates the difference.
- Error Interceptor: Performs the same calculation for failed network requests to ensure latency metrics are not lost during outages or errors.
Using performance.now() instead of
Date.now() is recommended because it provides millisecond
timestamps with microsecond precision and is unaffected by system clock
adjustments.
Implementation Example
The following code demonstrates how to configure an Axios instance to measure and log RTT for all outgoing requests:
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) => {
// Add custom metadata property to the config object
config.metadata = { startTime: performance.now() };
return config;
},
(error) => {
return Promise.reject(error);
}
);
// Response Interceptor: Calculate duration on success
apiClient.interceptors.response.use(
(response) => {
if (response.config && response.config.metadata) {
const endTime = performance.now();
const rtt = endTime - response.config.metadata.startTime;
// Attach duration to response object or dispatch to analytics
response.duration = rtt;
console.log(`[HTTP Success] ${response.config.method?.toUpperCase()} ${response.config.url} - RTT: ${rtt.toFixed(2)} ms`);
}
return response;
},
(error) => {
// Response Interceptor: Calculate duration on error
if (error.config && error.config.metadata) {
const endTime = performance.now();
const rtt = endTime - error.config.metadata.startTime;
error.duration = rtt;
console.error(`[HTTP Error] ${error.config.method?.toUpperCase()} ${error.config.url} - RTT: ${rtt.toFixed(2)} ms`);
}
return Promise.reject(error);
}
);
export default apiClient;Best Practices
- Handle Failed Requests: Always implement the error
callback in
interceptors.response.use. Latency spikes often correlate with timeouts and network failures. - Preserve Config Metadata: Ensure custom fields like
metadatado not overwrite standard Axios configuration options. - Exporting Metrics: Instead of basic console logs,
aggregate the resulting
rttvalues to an Application Performance Monitoring (APM) tool or real-user monitoring (RUM) service to track performance trends over time.