Skip to content

Commit

Permalink
logging
Browse files Browse the repository at this point in the history
Signed-off-by: Francis <colifran@amazon.com>
  • Loading branch information
colifran committed Apr 4, 2024
1 parent b82320b commit 33c7ac8
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ function installLatestSdk(packageName: string): void {
}

interface AwsSdk {
[key: string]: any
[key: string]: any;
}

async function loadAwsSdk(
packageName: string,
logErrors: boolean,
installLatestAwsSdk?: 'true' | 'false',
) {
let awsSdk: AwsSdk;
Expand All @@ -49,7 +51,9 @@ async function loadAwsSdk(
// esbuild-disable unsupported-require-call -- not esbuildable but that's fine
awsSdk = require(`/tmp/node_modules/${packageName}`);
} catch (e) {
console.log(`Failed to install latest AWS SDK v3. Falling back to pre-installed version. Error: ${e}`);
if (logErrors) {
console.log(`Failed to install latest AWS SDK v3. Falling back to pre-installed version. Error: ${e}`);
}
// MUST use require as dynamic import() does not support importing from directories
// esbuild-disable unsupported-require-call -- not esbuildable but that's fine
return require(packageName); // Fallback to pre-installed version
Expand All @@ -71,6 +75,11 @@ async function loadAwsSdk(

/* eslint-disable @typescript-eslint/no-require-imports, import/no-extraneous-dependencies */
export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context) {
let logHandlerEvent = event.ResourceProperties.LogHandlerEvent === 'true';
let logApiResponse = event.ResourceProperties.LogApiResponse === 'true';
let logResponseObject = event.ResourceProperties.LogResponseObject === 'true';
let logErrors = event.ResourceProperties.LogErrors === 'true';

try {
event.ResourceProperties.Create = decodeCall(event.ResourceProperties.Create);
event.ResourceProperties.Update = decodeCall(event.ResourceProperties.Update);
Expand All @@ -95,9 +104,11 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
if (call) {
const apiCall = new ApiCall(call.service, call.action);

let awsSdk: AwsSdk | Promise<AwsSdk> = loadAwsSdk(apiCall.v3PackageName, event.ResourceProperties.InstallLatestAwsSdk);
let awsSdk: AwsSdk | Promise<AwsSdk> = loadAwsSdk(apiCall.v3PackageName, logErrors, event.ResourceProperties.InstallLatestAwsSdk);

console.log(JSON.stringify({ ...event, ResponseURL: '...' }));
if (logHandlerEvent) {
console.log(JSON.stringify({ ...event, ResponseURL: '...' }));
}

let credentials;
if (call.assumedRoleArn) {
Expand Down Expand Up @@ -128,7 +139,9 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
flattenResponse: true,
});

console.log('API response', response);
if (logApiResponse) {
console.log('API response', response);
}

flatData.apiVersion = apiCall.client.config.apiVersion; // For test purposes: check if apiVersion was correctly passed.
flatData.region = await apiCall.client.config.region().catch(() => undefined); // For test purposes: check if region was correctly passed.
Expand Down Expand Up @@ -159,9 +172,9 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
}
}

await respond(event, 'SUCCESS', 'OK', physicalResourceId, data);
await respond(event, 'SUCCESS', 'OK', physicalResourceId, data, logResponseObject);
} catch (e: any) {
console.log(e);
await respond(event, 'FAILED', e.message || 'Internal Error', context.logStreamName, {});
await respond(event, 'FAILED', e.message || 'Internal Error', context.logStreamName, {}, logResponseObject);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function filterKeys(object: object, pred: (key: string) => boolean) {

type Event = AWSLambda.CloudFormationCustomResourceEvent

export function respond(event: Event, responseStatus: string, reason: string, physicalResourceId: string, data: any) {
export function respond(event: Event, responseStatus: string, reason: string, physicalResourceId: string, data: any, logResponseObject: boolean) {
const responseBody = JSON.stringify({
Status: responseStatus,
Reason: reason,
Expand All @@ -55,8 +55,10 @@ export function respond(event: Event, responseStatus: string, reason: string, ph
Data: data,
});

// eslint-disable-next-line no-console
console.log('Responding', responseBody);
if (logResponseObject) {
// eslint-disable-next-line no-console
console.log('Responding', responseBody);
}

// eslint-disable-next-line @typescript-eslint/no-require-imports
const parsedUrl = require('url').parse(event.ResponseURL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Annotations } from '../../../core';
import { AwsCustomResourceSingletonFunction } from '../../../custom-resource-handlers/dist/custom-resources/aws-custom-resource-provider.generated';
import * as cxapi from '../../../cx-api';
import { awsSdkToIamAction } from '../helpers-internal/sdk-info';
import { Logging } from './logging';

// Shared definition with packages/@aws-cdk/custom-resource-handlers/lib/custom-resources/aws-custom-resource-handler/shared.ts
const PHYSICAL_RESOURCE_ID_REFERENCE = 'PHYSICAL:RESOURCEID:';
Expand Down Expand Up @@ -394,6 +395,13 @@ export interface AwsCustomResourceProps {
* @default - the Vpc default strategy if not specified
*/
readonly vpcSubnets?: ec2.SubnetSelection;

/**
* Enables logging
*
* @default Logging.on()
*/
readonly logging?: Logging;
}

/**
Expand Down Expand Up @@ -497,6 +505,10 @@ export class AwsCustomResource extends Construct implements iam.IGrantable {
update: props.onUpdate && this.encodeJson(props.onUpdate),
delete: props.onDelete && this.encodeJson(props.onDelete),
installLatestAwsSdk,
logHandlerEvent: props.logging?.logHandlerEvent ?? true,
logApiResponse: props.logging?.logApiResponse ?? true,
logRespondeObject: props.logging?.logResponseObject ?? true,
logErrors: props.logging?.logErrors ?? true,
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* Properties used to initialize Logging.
*/
export interface LoggingProps {
/**
* Whether or not to log the event object received by the lambda handler.
*
* @default true
*/
readonly logHandlerEvent?: boolean;

/**
* Whether or not to log the response returned from the API call.
*
* @default true
*/
readonly logApiResponse?: boolean;

/**
* Whether or not to log the response object that will be returned by the lambda.
*
* @default true
*/
readonly logResponseObject?: boolean;

/**
* Whether or not to log errors that were encountered during lambda execution.
*
* @default true
*/
readonly logErrors?: boolean;
}

/**
* A class that represents Logging that will take place during lambda execution.
*/
export class Logging {
/**
* Enables logging of all logged data in the lambda handler.
*
* This includes the event object, the API call response, all fields in the response object
* returned by the lambda, and any errors encountered.
*/
public static on() {
return new Logging();
}

/**
* Enables selective logging of logged data in the lambda handler.
*/
public static selective(props: LoggingProps) {
return new Logging({ ...props });
}

/**
* Turns off all logging in the lambda handler.
*/
public static off() {
return new Logging({
logHandlerEvent: false,
logApiResponse: false,
logResponseObject: false,
logErrors: false,
});
}

/**
* Whether or not to log the event object received by the lambda handler.
*/
public readonly logHandlerEvent: boolean;

/**
* Whether or not to log the API call response.
*/
public readonly logApiResponse: boolean;

/**
* Whether or not to log the response object that will be returned by the lambda.
*/
public readonly logResponseObject: boolean;

/**
* Whether or not to log errors that were encountered during lambda execution.
*/
public readonly logErrors: boolean;

private constructor(props: LoggingProps = {}) {
this.logHandlerEvent = props.logHandlerEvent ?? true;
this.logApiResponse = props.logApiResponse ?? true;
this.logResponseObject = props.logResponseObject ?? true;
this.logErrors = props.logErrors ?? true;
}
}

0 comments on commit 33c7ac8

Please sign in to comment.