All files / src/common context-logging-middleware.ts

100% Statements 13/13
100% Branches 0/0
100% Functions 4/4
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87                                    2x   2x                 4x                                         17x               17x 17x       17x         17x   17x     14x 14x     2x 2x                
/* 
  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  
  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/
import middy from '@middy/core';
import { APIGatewayProxyEvent, Context } from 'aws-lambda';
import { DependencyContainer } from 'tsyringe';
import { LambdaLoggerFactory, LoggerFactory } from 'shared_types';
 
export function ContextLoggingMiddleware<TEvent, TResponse>(
    applicationName: string,
    rootContainer: DependencyContainer,
    runningLocally?: boolean,
    logLevel?: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly',
    additionalMetadata?: {
        [key: string]: (event: APIGatewayProxyEvent, context: Context) => string;
    }
): middy.MiddlewareObject<TEvent, TResponse> {
    return {
        before: (handler: middy.HandlerLambda, next: middy.NextFunction): void => {
            /* istanbul ignore next */
            const logMetadata: {
                [key: string]: (event: APIGatewayProxyEvent, context: Context) => string;
            } = {
                ...additionalMetadata,
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                applicationName: (_e, _c) => applicationName,
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                resource: (e, _c) => e.resource,
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                httpMethod: (e, _c) => e.httpMethod,
                awsRequestId: (_e, c) => c.awsRequestId,
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                lambdaRequestId: (e, _c) => e.requestContext?.requestId,
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                'X-Amzn-Trace-Id': (event, _) =>
                    event.headers?.['X-Amzn-Trace-Id'] ?? 'n/a',
            };
 
            const loggerFactory = new LambdaLoggerFactory(
                handler.event,
                handler.context,
                runningLocally,
                logMetadata,
                logLevel
            );
 
            const loggingContextContainer = rootContainer.createChildContainer();
            loggingContextContainer.registerInstance<LoggerFactory>(
                'LoggerFactory',
                loggerFactory
            );
            const loggingContext: LoggingContext = {
                ...handler.context,
                loggingContextContainer,
            };
 
            handler.context = loggingContext;
 
            return next();
        },
        after: (handler: middy.HandlerLambda, next: middy.NextFunction): void => {
            (handler.context as LoggingContext).loggingContextContainer.clearInstances();
            return next();
        },
        onError: (handler: middy.HandlerLambda, next: middy.NextFunction): void => {
            (handler.context as LoggingContext).loggingContextContainer.clearInstances();
            return next();
        },
    };
}
 
export interface LoggingContext extends Context {
    loggingContextContainer: DependencyContainer;
}