JAVASCRIPT
Centralized API Error Handling and Logging in Node.js
Implement a robust, centralized error handling and logging mechanism for external API calls in a Node.js application to improve debugging and reliability.
const axios = require('axios');
class ApiError extends Error {
constructor(message, statusCode = 500, details = {}) {
super(message);
this.name = 'ApiError';
this.statusCode = statusCode;
this.details = details;
Error.captureStackTrace(this, this.constructor);
}
}
// A simple logger for demonstration
const logger = {
error: (message, context) => console.error(`[ERROR] ${message}`, context),
warn: (message, context) => console.warn(`[WARN] ${message}`, context),
info: (message, context) => console.log(`[INFO] ${message}`, context)
};
async function makeApiCall(config) {
try {
const response = await axios(config);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
const { response } = error;
const statusCode = response ? response.status : 500;
const errorMessage = response ? (response.data.message || response.statusText) : error.message;
const errorDetails = response ? response.data : null;
logger.error(`API Call Failed: [${statusCode}] ${errorMessage}`, {
url: config.url,
method: config.method,
errorDetails
});
throw new ApiError(errorMessage, statusCode, errorDetails);
} else {
// Non-Axios errors (e.g., network issues before request sent)
logger.error(`General API Call Error: ${error.message}`, { url: config.url, method: config.method, originalError: error });
throw new ApiError('An unexpected error occurred during the API call.', 500, { originalError: error });
}
}
}
// Example Usage:
// (async () => {
// try {
// const data = await makeApiCall({
// method: 'GET',
// url: 'https://jsonplaceholder.typicode.com/posts/1'
// });
// logger.info('Successfully fetched data:', data);
// // Example of an API call that will fail
// await makeApiCall({
// method: 'GET',
// url: 'https://jsonplaceholder.typicode.com/nonexistent-endpoint'
// });
// } catch (e) {
// if (e instanceof ApiError) {
// logger.warn(`Caught custom ApiError: ${e.message} (Status: ${e.statusCode})`);
// } else {
// logger.error(`Caught unexpected error: ${e.message}`);
// }
// }
// })();
How it works: This Node.js snippet establishes a centralized mechanism for handling and logging errors from external API calls using Axios. It introduces a custom `ApiError` class to encapsulate relevant error details like status code and original API response. The `makeApiCall` wrapper intelligently distinguishes between Axios-specific errors (HTTP responses) and general network issues. All errors are logged with contextual information (URL, method, error details) before being re-thrown as instances of `ApiError`. This pattern makes error identification, debugging, and consistent error messaging throughout your application much easier.