UNPKG

@energica-city/shared-amplify-utils

Version:

Shared utilities for AWS Amplify projects

119 lines 14.7 kB
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==