Kevin W. McConnell

How to enable API Gateway access logs with the CDK

Access logs can be invaluable when debugging API issues and understanding usage patterns. If you’re using API Gateway in your applications, it’s usually a good idea to enable logging on your APIs so the logs will be there when you need them.

But if you’re building an HTTP API with the CDK, you’ll notice that the CDK constructs for HTTP APIs don’t provide access to the log settings (at least, not yet).

Luckily the CDK provides an escape hatch for cases like this. Whenever the higher-level constructs are missing a property you need, you can reach inside them to access the low-level CFN Resource constructs that they’re built around. These autogenerated CFN resources correspond exactly to the CloudFormation resources that they represent, which means they have all the same properties.

In other words, if something is possible in CloudFormation, it’s also possible by using the CFN resources.

You can access the CFN resource for a construct through the node.defaultChild property. So to enable logging for a stage of your HTTP API, reach in to its CfnStage resource, and use the accessLogSettings property to specify the format and log group for your logs.

You’ll also need to make sure the log group’s permissions allow API Gateway to write to it.

Here’s an example of setting up logging in this way for the default stage of an HTTP API:

typescript
function enableLogging(api: apigw.HttpApi) {
const stage = api.defaultStage!.node.defaultChild as apigw.CfnStage;
const logGroup = new logs.LogGroup(api, 'AccessLogs', {
retention: 90, // Keep logs for 90 days
});
stage.accessLogSettings = {
destinationArn: logGroup.logGroupArn,
format: JSON.stringify({
requestId: '$context.requestId',
userAgent: '$context.identity.userAgent',
sourceIp: '$context.identity.sourceIp',
requestTime: '$context.requestTime',
httpMethod: '$context.httpMethod',
path: '$context.path',
status: '$context.status',
responseLength: '$context.responseLength',
}),
};
logGroup.grantWrite(new iam.ServicePrincipal('apigateway.amazonaws.com'));
}

Posted November 15, 2021.

← A fast(er) de-referer service with CloudFront Functions
How I wrote my book →