@energica-city/shared-amplify-utils
Version:
Shared utilities for AWS Amplify projects
119 lines • 14.7 kB
JavaScript
import { logger } from '../../log';
import { sanitizeObject } from '../utils/sanitization';
import { extractEventInfo, parseJsonBodyWithFallback, initializeRestMiddleware, } from './utils';
/**
* Builds structured log data for incoming REST requests
* @param input - REST input containing event and context
* @param config - Logger configuration options
* @returns Object containing sanitized request information for logging
*/
function buildEventLog(input, config) {
const { event } = input;
const { logRequestBody = false, excludeEventFields = [], maxDepth = 3, } = config;
const basicInfo = extractEventInfo(event);
if (logRequestBody && event.body) {
const parsedBody = parseJsonBodyWithFallback(event.body, '[Invalid JSON]');
return {
...basicInfo,
body: sanitizeObject(parsedBody, {
excludeFields: excludeEventFields,
maxDepth,
}),
};
}
return basicInfo;
}
/**
* Builds structured log data for outgoing REST responses
* @param response - REST response object
* @param config - Logger configuration options
* @param duration - Request processing duration
* @param requestId - Request identifier for tracking
* @returns Object containing sanitized response information for logging
*/
function buildResponseLog(response, config, duration, requestId) {
const { excludeResponseFields = [], maxDepth = 3 } = config;
let responseBody = null;
if (response.body) {
const parsedBody = parseJsonBodyWithFallback(response.body, '[Invalid JSON]');
responseBody = sanitizeObject(parsedBody, {
excludeFields: excludeResponseFields,
maxDepth,
});
}
return {
statusCode: response.statusCode,
body: responseBody,
headers: response.headers || {},
duration,
requestId,
};
}
/**
* Creates REST request logger middleware for comprehensive request/response logging
*
* Provides structured logging of HTTP requests and responses with configurable detail levels,
* timing information, and data sanitization. Supports different log levels and can exclude
* sensitive fields from logs.
*
* @param config - Configuration options for logging behavior
* @returns Middleware function that logs requests and responses
*
* @example
* ```typescript
* // Basic logging
* const logger = createRestRequestLogger({
* logEvent: true,
* logResponse: true,
* logTiming: true
* });
*
* // Production logging with sensitive data exclusion
* const prodLogger = createRestRequestLogger({
* logRequestBody: false,
* excludeEventFields: ['authorization', 'password'],
* excludeResponseFields: ['token', 'secret'],
* logLevel: 'info'
* });
*
* chain.use('logger', logger);
* ```
*/
export function createRestRequestLogger(config = {}) {
const { logEvent = true, logResponse = true, logTiming = true, defaultContext = {}, logLevel = 'info', forceStructuredLogging = true, } = config;
return async (input, next) => {
const startTime = Date.now();
const { context, requestId } = initializeRestMiddleware(input, {
defaultContext,
forceStructuredLogging,
operation: 'requestLogging',
});
if (logEvent) {
const eventLog = buildEventLog(input, config);
logger[logLevel]('REST request received', {
...context,
}, [eventLog]);
}
try {
const response = await next(input);
const duration = logTiming ? `${Date.now() - startTime}ms` : '0ms';
if (logResponse) {
const responseLog = buildResponseLog(response, config, duration, requestId);
logger[logLevel]('REST response sent', {
...context,
}, [responseLog]);
}
return response;
}
catch (error) {
const duration = logTiming ? `${Date.now() - startTime}ms` : '0ms';
logger.error('REST request failed', {
...context,
duration,
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVzdFJlcXVlc3RMb2dnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9taWRkbGV3YXJlL3Jlc3QvUmVzdFJlcXVlc3RMb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVNuQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDdkQsT0FBTyxFQUNMLGdCQUFnQixFQUNoQix5QkFBeUIsRUFDekIsd0JBQXdCLEdBQ3pCLE1BQU0sU0FBUyxDQUFDO0FBRWpCOzs7OztHQUtHO0FBQ0gsU0FBUyxhQUFhLENBQ3BCLEtBQTBCLEVBQzFCLE1BQStCO0lBRS9CLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDeEIsTUFBTSxFQUNKLGNBQWMsR0FBRyxLQUFLLEVBQ3RCLGtCQUFrQixHQUFHLEVBQUUsRUFDdkIsUUFBUSxHQUFHLENBQUMsR0FDYixHQUFHLE1BQU0sQ0FBQztJQUVYLE1BQU0sU0FBUyxHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTFDLElBQUksY0FBYyxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNqQyxNQUFNLFVBQVUsR0FBRyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDM0UsT0FBTztZQUNMLEdBQUcsU0FBUztZQUNaLElBQUksRUFBRSxjQUFjLENBQUMsVUFBVSxFQUFFO2dCQUMvQixhQUFhLEVBQUUsa0JBQWtCO2dCQUNqQyxRQUFRO2FBQ1QsQ0FBQztTQUNILENBQUM7SUFDSixDQUFDO0lBRUQsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFTLGdCQUFnQixDQUN2QixRQUFzQixFQUN0QixNQUErQixFQUMvQixRQUFnQixFQUNoQixTQUFpQjtJQUVqQixNQUFNLEVB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RUgsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uLy4uL2xvZyc7XG5pbXBvcnQgdHlwZSB7IE1pZGRsZXdhcmUgfSBmcm9tICcuLi9taWRkbGV3YXJlQ2hhaW4nO1xuaW1wb3J0IHR5cGUge1xuICBSZXN0SW5wdXRXaXRoTW9kZWxzLFxuICBSZXN0UmVxdWVzdExvZ2dlckNvbmZpZyxcbiAgUmVzdFJlc3BvbnNlLFxuICBEZWZhdWx0TW9kZWxUeXBlcyxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgdHlwZSB7IEFtcGxpZnlNb2RlbFR5cGUgfSBmcm9tICcuLi8uLi9xdWVyaWVzL3R5cGVzJztcbmltcG9ydCB7IHNhbml0aXplT2JqZWN0IH0gZnJvbSAnLi4vdXRpbHMvc2FuaXRpemF0aW9uJztcbmltcG9ydCB7XG4gIGV4dHJhY3RFdmVudEluZm8sXG4gIHBhcnNlSnNvbkJvZHlXaXRoRmFsbGJhY2ssXG4gIGluaXRpYWxpemVSZXN0TWlkZGxld2FyZSxcbn0gZnJvbSAnLi91dGlscyc7XG5cbi8qKlxuICogQnVpbGRzIHN0cnVjdHVyZWQgbG9nIGRhdGEgZm9yIGluY29taW5nIFJFU1QgcmVxdWVzdHNcbiAqIEBwYXJhbSBpbnB1dCAtIFJFU1QgaW5wdXQgY29udGFpbmluZyBldmVudCBhbmQgY29udGV4dFxuICogQHBhcmFtIGNvbmZpZyAtIExvZ2dlciBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAqIEByZXR1cm5zIE9iamVjdCBjb250YWluaW5nIHNhbml0aXplZCByZXF1ZXN0IGluZm9ybWF0aW9uIGZvciBsb2dnaW5nXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkRXZlbnRMb2coXG4gIGlucHV0OiBSZXN0SW5wdXRXaXRoTW9kZWxzLFxuICBjb25maWc6IFJlc3RSZXF1ZXN0TG9nZ2VyQ29uZmlnLFxuKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICBjb25zdCB7IGV2ZW50IH0gPSBpbnB1dDtcbiAgY29uc3Qge1xuICAgIGxvZ1JlcXVlc3RCb2R5ID0gZmFsc2UsXG4gICAgZXhjbHVkZUV2ZW50RmllbGRzID0gW10sXG4gICAgbWF4RGVwdGggPSAzLFxuICB9ID0gY29uZmlnO1xuXG4gIGNvbnN0IGJhc2ljSW5mbyA9IGV4dHJhY3RFdmVudEluZm8oZXZlbnQpO1xuXG4gIGlmIChsb2dSZXF1ZXN0Qm9keSAmJiBldmVudC5ib2R5KSB7XG4gICAgY29uc3QgcGFyc2VkQm9keSA9IHBhcnNlSnNvbkJvZHlXaXRoRmFsbGJhY2soZXZlbnQuYm9keSwgJ1tJbnZhbGlkIEpTT05dJyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmJhc2ljSW5mbyxcbiAgICAgIGJvZHk6IHNhbml0aXplT2JqZWN0KHBhcnNlZEJvZHksIHtcbiAgICAgICAgZXhjbHVkZUZpZWxkczogZXhjbHVkZUV2ZW50RmllbGRzLFxuICAgICAgICBtYXhEZXB0aCxcbiAgICAgIH0pLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4gYmFzaWNJbmZvO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBzdHJ1Y3R1cmVkIGxvZyBkYXRhIGZvciBvdXRnb2luZyBSRVNUIHJlc3BvbnNlc1xuICogQHBhcmFtIHJlc3BvbnNlIC0gUkVTVCByZXNwb25zZSBvYmplY3RcbiAqIEBwYXJhbSBjb25maWcgLSBMb2dnZXIgY29uZmlndXJhdGlvbiBvcHRpb25zXG4gKiBAcGFyYW0gZHVyYXRpb24gLSBSZXF1ZXN0IHByb2Nlc3NpbmcgZHVyYXRpb25cbiAqIEBwYXJhbSByZXF1ZXN0SWQgLSBSZXF1ZXN0IGlkZW50aWZpZXIgZm9yIHRyYWNraW5nXG4gKiBAcmV0dXJucyBPYmplY3QgY29udGFpbmluZyBzYW5pdGl6ZWQgcmVzcG9uc2UgaW5mb3JtYXRpb24gZm9yIGxvZ2dpbmdcbiAqL1xuZnVuY3Rpb24gYnVpbGRSZXNwb25zZUxvZyhcbiAgcmVzcG9uc2U6IFJlc3RSZXNwb25zZSxcbiAgY29uZmlnOiBSZXN0UmVxdWVzdExvZ2dlckNvbmZpZyxcbiAgZHVyYXRpb246IHN0cmluZyxcbiAgcmVxdWVzdElkOiBzdHJpbmcsXG4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IHsgZXhjbHVkZVJlc3BvbnNlRmllbGRzID0gW10sIG1heERlcHRoID0gMyB9ID0gY29uZmlnO1xuXG4gIGxldCByZXNwb25zZUJvZHkgPSBudWxsO1xuICBpZiAocmVzcG9uc2UuYm9keSkge1xuICAgIGNvbnN0IHBhcnNlZEJvZHkgPSBwYXJzZUpzb25Cb2R5V2l0aEZhbGxiYWNrKFxuICAgICAgcmVzcG9uc2UuYm9keSxcbiAgICAgICdbSW52YWxpZCBKU09OXScsXG4gICAgKTtcbiAgICByZXNwb25zZUJvZHkgPSBzYW5pdGl6ZU9iamVjdChwYXJzZWRCb2R5LCB7XG4gICAgICBleGNsdWRlRmllbGRzOiBleGNsdWRlUmVzcG9uc2VGaWVsZHMsXG4gICAgICBtYXhEZXB0aCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc3RhdHVzQ29kZTogcmVzcG9uc2Uuc3RhdHVzQ29kZSxcbiAgICBib2R5OiByZXNwb25zZUJvZHksXG4gICAgaGVhZGVyczogcmVzcG9uc2UuaGVhZGVycyB8fCB7fSxcbiAgICBkdXJhdGlvbixcbiAgICByZXF1ZXN0SWQsXG4gIH07XG59XG5cbi8qKlxuICogQ3JlYXRlcyBSRVNUIHJlcXVlc3QgbG9nZ2VyIG1pZGRsZXdhcmUgZm9yIGNvbXByZWhlbnNpdmUgcmVxdWVzdC9yZXNwb25zZSBsb2dnaW5nXG4gKlxuICogUHJvdmlkZXMgc3RydWN0dXJlZCBsb2dnaW5nIG9mIEhUVFAgcmVxdWVzdHMgYW5kIHJlc3BvbnNlcyB3aXRoIGNvbmZpZ3VyYWJsZSBkZXRhaWwgbGV2ZWxzLFxuICogdGltaW5nIGluZm9ybWF0aW9uLCBhbmQgZGF0YSBzYW5pdGl6YXRpb24uIFN1cHBvcnRzIGRpZmZlcmVudCBsb2cgbGV2ZWxzIGFuZCBjYW4gZXhjbHVkZVxuICogc2Vuc2l0aXZlIGZpZWxkcyBmcm9tIGxvZ3MuXG4gKlxuICogQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgbG9nZ2luZyBiZWhhdmlvclxuICogQHJldHVybnMgTWlkZGxld2FyZSBmdW5jdGlvbiB0aGF0IGxvZ3MgcmVxdWVzdHMgYW5kIHJlc3BvbnNlc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBCYXNpYyBsb2dnaW5nXG4gKiBjb25zdCBsb2dnZXIgPSBjcmVhdGVSZXN0UmVxdWVzdExvZ2dlcih7XG4gKiAgIGxvZ0V2ZW50OiB0cnVlLFxuICogICBsb2dSZXNwb25zZTogdHJ1ZSxcbiAqICAgbG9nVGltaW5nOiB0cnVlXG4gKiB9KTtcbiAqXG4gKiAvLyBQcm9kdWN0aW9uIGxvZ2dpbmcgd2l0aCBzZW5zaXRpdmUgZGF0YSBleGNsdXNpb25cbiAqIGNvbnN0IHByb2RMb2dnZXIgPSBjcmVhdGVSZXN0UmVxdWVzdExvZ2dlcih7XG4gKiAgIGxvZ1JlcXVlc3RCb2R5OiBmYWxzZSxcbiAqICAgZXhjbHVkZUV2ZW50RmllbGRzOiBbJ2F1dGhvcml6YXRpb24nLCAncGFzc3dvcmQnXSxcbiAqICAgZXhjbHVkZVJlc3BvbnNlRmllbGRzOiBbJ3Rva2VuJywgJ3NlY3JldCddLFxuICogICBsb2dMZXZlbDogJ2luZm8nXG4gKiB9KTtcbiAqXG4gKiBjaGFpbi51c2UoJ2xvZ2dlcicsIGxvZ2dlcik7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlc3RSZXF1ZXN0TG9nZ2VyPFxuICBUVHlwZXMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBBbXBsaWZ5TW9kZWxUeXBlPiA9IERlZmF1bHRNb2RlbFR5cGVzLFxuPihcbiAgY29uZmlnOiBSZXN0UmVxdWVzdExvZ2dlckNvbmZpZyA9IHt9LFxuKTogTWlkZGxld2FyZTxSZXN0SW5wdXRXaXRoTW9kZWxzPFRUeXBlcz4sIFJlc3RSZXNwb25zZT4ge1xuICBjb25zdCB7XG4gICAgbG9nRXZlbnQgPSB0cnVlLFxuICAgIGxvZ1Jlc3BvbnNlID0gdHJ1ZSxcbiAgICBsb2dUaW1pbmcgPSB0cnVlLFxuICAgIGRlZmF1bHRDb250ZXh0ID0ge30sXG4gICAgbG9nTGV2ZWwgPSAnaW5mbycsXG4gICAgZm9yY2VTdHJ1Y3R1cmVkTG9nZ2luZyA9IHRydWUsXG4gIH0gPSBjb25maWc7XG5cbiAgcmV0dXJuIGFzeW5jIChpbnB1dCwgbmV4dCkgPT4ge1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICBjb25zdCB7IGNvbnRleHQsIHJlcXVlc3RJZCB9ID0gaW5pdGlhbGl6ZVJlc3RNaWRkbGV3YXJlKFxuICAgICAgaW5wdXQgYXMgUmVzdElucHV0V2l0aE1vZGVscyxcbiAgICAgIHtcbiAgICAgICAgZGVmYXVsdENvbnRleHQsXG4gICAgICAgIGZvcmNlU3RydWN0dXJlZExvZ2dpbmcsXG4gICAgICAgIG9wZXJhdGlvbjogJ3JlcXVlc3RMb2dnaW5nJyxcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGlmIChsb2dFdmVudCkge1xuICAgICAgY29uc3QgZXZlbnRMb2cgPSBidWlsZEV2ZW50TG9nKGlucHV0IGFzIFJlc3RJbnB1dFdpdGhNb2RlbHMsIGNvbmZpZyk7XG4gICAgICBsb2dnZXJbbG9nTGV2ZWxdKFxuICAgICAgICAnUkVTVCByZXF1ZXN0IHJlY2VpdmVkJyxcbiAgICAgICAge1xuICAgICAgICAgIC4uLmNvbnRleHQsXG4gICAgICAgIH0sXG4gICAgICAgIFtldmVudExvZ10sXG4gICAgICApO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IG5leHQoaW5wdXQpO1xuICAgICAgY29uc3QgZHVyYXRpb24gPSBsb2dUaW1pbmcgPyBgJHtEYXRlLm5vdygpIC0gc3RhcnRUaW1lfW1zYCA6ICcwbXMnO1xuXG4gICAgICBpZiAobG9nUmVzcG9uc2UpIHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2VMb2cgPSBidWlsZFJlc3BvbnNlTG9nKFxuICAgICAgICAgIHJlc3BvbnNlLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBkdXJhdGlvbixcbiAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICk7XG4gICAgICAgIGxvZ2dlcltsb2dMZXZlbF0oXG4gICAgICAgICAgJ1JFU1QgcmVzcG9uc2Ugc2VudCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uY29udGV4dCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIFtyZXNwb25zZUxvZ10sXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3QgZHVyYXRpb24gPSBsb2dUaW1pbmcgPyBgJHtEYXRlLm5vdygpIC0gc3RhcnRUaW1lfW1zYCA6ICcwbXMnO1xuXG4gICAgICBsb2dnZXIuZXJyb3IoJ1JFU1QgcmVxdWVzdCBmYWlsZWQnLCB7XG4gICAgICAgIC4uLmNvbnRleHQsXG4gICAgICAgIGR1cmF0aW9uLFxuICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpLFxuICAgICAgfSk7XG5cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfTtcbn1cbiJdfQ==