84 lines
2.6 KiB
JavaScript
84 lines
2.6 KiB
JavaScript
const logger = require('../utils/logger');
|
|
|
|
const apiLogger = (req, res, next) => {
|
|
const startTime = Date.now();
|
|
const reqLogger = logger.withRequestId(req.id);
|
|
|
|
const requestData = {
|
|
method: req.method,
|
|
url: req.url,
|
|
userAgent: req.get('User-Agent'),
|
|
ip: req.ip,
|
|
userId: req.user?.id || 'anonymous',
|
|
body: logger.sanitize(req.body),
|
|
params: req.params,
|
|
query: req.query,
|
|
headers: {
|
|
'content-type': req.get('Content-Type'),
|
|
'content-length': req.get('Content-Length'),
|
|
'referer': req.get('Referer'),
|
|
}
|
|
};
|
|
|
|
reqLogger.info('API Request', requestData);
|
|
|
|
const originalSend = res.send;
|
|
res.send = function(body) {
|
|
const endTime = Date.now();
|
|
const responseTime = endTime - startTime;
|
|
|
|
const responseData = {
|
|
statusCode: res.statusCode,
|
|
responseTime: `${responseTime}ms`,
|
|
contentLength: res.get('Content-Length') || (body ? body.length : 0),
|
|
method: req.method,
|
|
url: req.url,
|
|
userId: req.user?.id || 'anonymous'
|
|
};
|
|
|
|
// Parse response body for error responses to include error details
|
|
if (res.statusCode >= 400) {
|
|
let errorDetails = null;
|
|
if (body) {
|
|
try {
|
|
const parsed = typeof body === 'string' ? JSON.parse(body) : body;
|
|
// Extract error message, validation errors, or full response
|
|
errorDetails = {
|
|
error: parsed.error || parsed.message || null,
|
|
errors: parsed.errors || null, // validation errors array
|
|
details: parsed.details || null
|
|
};
|
|
// Remove null values
|
|
Object.keys(errorDetails).forEach(key => {
|
|
if (errorDetails[key] === null) delete errorDetails[key];
|
|
});
|
|
if (Object.keys(errorDetails).length > 0) {
|
|
responseData.errorDetails = errorDetails;
|
|
}
|
|
} catch (e) {
|
|
// Body is not JSON, include as string (truncated)
|
|
if (typeof body === 'string' && body.length > 0) {
|
|
responseData.errorDetails = { raw: body.substring(0, 500) };
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (res.statusCode >= 400 && res.statusCode < 500) {
|
|
// Don't log 401s for /users/profile - these are expected auth checks
|
|
if (!(res.statusCode === 401 && req.url === '/profile')) {
|
|
reqLogger.warn('API Response - Client Error', responseData);
|
|
}
|
|
} else if (res.statusCode >= 500) {
|
|
reqLogger.error('API Response - Server Error', responseData);
|
|
} else {
|
|
reqLogger.info('API Response - Success', responseData);
|
|
}
|
|
|
|
return originalSend.call(this, body);
|
|
};
|
|
|
|
next();
|
|
};
|
|
|
|
module.exports = apiLogger; |