From 042e9e9a46231c7761369108df00955b076b2ae2 Mon Sep 17 00:00:00 2001 From: Marco Jahn Date: Fri, 23 Jan 2026 10:01:59 +0100 Subject: [PATCH 1/8] added lambda-s3-athena-cdk-ts pattern --- lambda-s3-athena-cdk-ts/.gitignore | 13 + lambda-s3-athena-cdk-ts/README.md | 267 ++++++++++++++++++ .../bin/lambda-s3-athena-cdk-ts.ts | 12 + lambda-s3-athena-cdk-ts/cdk.json | 22 ++ lambda-s3-athena-cdk-ts/example-pattern.json | 74 +++++ .../lambda-s3-athena-cdk-ts.png | Bin 0 -> 34251 bytes lambda-s3-athena-cdk-ts/lambda/processor.js | 58 ++++ lambda-s3-athena-cdk-ts/lib/pattern-stack.ts | 133 +++++++++ lambda-s3-athena-cdk-ts/package.json | 22 ++ lambda-s3-athena-cdk-ts/tsconfig.json | 23 ++ 10 files changed, 624 insertions(+) create mode 100644 lambda-s3-athena-cdk-ts/.gitignore create mode 100644 lambda-s3-athena-cdk-ts/README.md create mode 100644 lambda-s3-athena-cdk-ts/bin/lambda-s3-athena-cdk-ts.ts create mode 100644 lambda-s3-athena-cdk-ts/cdk.json create mode 100644 lambda-s3-athena-cdk-ts/example-pattern.json create mode 100644 lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.png create mode 100644 lambda-s3-athena-cdk-ts/lambda/processor.js create mode 100644 lambda-s3-athena-cdk-ts/lib/pattern-stack.ts create mode 100644 lambda-s3-athena-cdk-ts/package.json create mode 100644 lambda-s3-athena-cdk-ts/tsconfig.json diff --git a/lambda-s3-athena-cdk-ts/.gitignore b/lambda-s3-athena-cdk-ts/.gitignore new file mode 100644 index 000000000..cec1a33a0 --- /dev/null +++ b/lambda-s3-athena-cdk-ts/.gitignore @@ -0,0 +1,13 @@ +!jest.config.js +*.d.ts +node_modules + +# CDK asset staging directory +.cdk.staging +cdk.out + +# Parcel default cache directory +.parcel-cache + +# Mac files +.DS_Store diff --git a/lambda-s3-athena-cdk-ts/README.md b/lambda-s3-athena-cdk-ts/README.md new file mode 100644 index 000000000..32b0e9a04 --- /dev/null +++ b/lambda-s3-athena-cdk-ts/README.md @@ -0,0 +1,267 @@ +# AWS Lambda with Amazon S3 Failed-Event Destination and Amazon Athena Analytics + +This pattern demonstrates how to use Amazon S3 as a failed-event destination for AWS Lambda asynchronous invocations, with Amazon Athena for analytics on failed events. The pattern includes an AWS Lambda function with business logic that can succeed or fail, automatically capturing failed events to Amazon S3 for analysis. + +Learn more about this pattern at Serverless Land Patterns: [https://serverlessland.com/patterns/lambda-s3-athena-cdk-ts](https://serverlessland.com/patterns/lambda-s3-athena-cdk-ts) + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Requirements + +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [Node.js and npm](https://nodejs.org/) installed +* [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html) installed + +## Deployment Instructions + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + + ```bash + git clone https://github.com/aws-samples/serverless-patterns + ``` + +2. Change directory to the pattern directory: + + ```bash + cd lambda-s3-athena-cdk-ts + ``` + +3. Install dependencies: + + ```bash + npm install + ``` + +4. Deploy the CDK stack to your default AWS account and region: + + ```bash + cdk deploy + ``` + +5. Note the outputs from the CDK deployment process. These contain the resource names and URLs which are used for testing. + +## Deployment Outputs + +After deployment, CDK will display the following outputs. Save these values for configuration and testing: + +| Output Key | Description | Usage | +|------------|-------------|-------| +| `LambdaFunctionName` | AWS Lambda function name | Use this name to invoke the AWS Lambda function via AWS CLI | +| `FailedEventsBucketName` | Amazon S3 bucket storing failed AWS Lambda events | Check this bucket to verify failed events are being captured | +| `AthenaResultsBucketName` | Amazon S3 bucket for Amazon Athena query results | Amazon Athena stores query results here automatically | +| `GlueDatabaseName` | AWS Glue database name (typically `failed_events_db`) | Use in Amazon Athena queries: `FROM .` | +| `GlueTableName` | AWS Glue table name (`failed_events`) | Use in Amazon Athena queries: `FROM .
` | +| `AthenaWorkgroupName` | Amazon Athena workgroup name | Specify this workgroup when running Amazon Athena queries | + +**Example output:** +``` +Outputs: +LambdaS3AthenaCdkStack.LambdaFunctionName = processor-function-abc123 +LambdaS3AthenaCdkStack.FailedEventsBucketName = lambdas3athenac-failedeventsbucket12345-abcdef +LambdaS3AthenaCdkStack.AthenaResultsBucketName = lambdas3athenac-athenaresultsbucket67890-ghijkl +LambdaS3AthenaCdkStack.GlueDatabaseName = failed_events_db +LambdaS3AthenaCdkStack.GlueTableName = failed_events +LambdaS3AthenaCdkStack.AthenaWorkgroupName = failed-events-workgroup +``` + +## How it works + +![Architecture Diagram](./lambda-s3-athena-cdk-ts.png) + +This pattern creates an AWS Lambda function that implements simple business logic with three actions: `process`, `validate`, and `calculate`. When the AWS Lambda function fails (throws an error) during asynchronous invocation, the failed event is automatically sent to an Amazon S3 bucket configured as the failed-event destination. + +The pattern also sets up AWS Glue and Amazon Athena to enable SQL-based analytics on the failed events stored in Amazon S3. This allows you to query and analyze error patterns, identify common failure scenarios, and gain insights into your application's error behavior. + +Architecture flow: +1. Client invokes AWS Lambda function asynchronously via AWS CLI +2. AWS Lambda processes the request based on the action type +3. On success: AWS Lambda returns successful response +4. On failure: AWS Lambda throws error, and AWS automatically sends the failed event to Amazon S3 +5. Failed events are stored in Amazon S3 as JSON files +6. Amazon Athena queries the failed events using AWS Glue Data Catalog for analytics + +### AWS Lambda Destinations and Invocation Types + +**Important**: AWS Lambda destinations only work with **asynchronous invocations** and **stream-based invocations** (on-failure only). They do not trigger for synchronous invocations. + +| Invocation Type | Examples | Destinations Supported? | +|----------------|----------|------------------------| +| **Synchronous** | Amazon API Gateway, Application Load Balancer, SDK RequestResponse | ❌ No | +| **Asynchronous** | Amazon S3, Amazon SNS, Amazon EventBridge, SDK Event | ✅ Yes | +| **Stream/Poll-based** | Amazon Kinesis, Amazon DynamoDB Streams, Amazon SQS | ✅ On-failure only | + +This pattern uses **asynchronous invocation via AWS CLI** (`--invocation-type Event`) to demonstrate the Amazon S3 failed-event destination feature. + +The AWS Glue Data Catalog is required for Amazon Athena to query Amazon S3 data, providing the schema definition, data location, and SerDe configuration needed to parse the JSON files. This pattern uses a simplified configuration without a predefined schema, allowing Amazon Athena to perform full scans of all failed event files for learning and low-volume workloads. + +## Testing + +### Test Successful Requests + +1. Get the AWS Lambda function name from the stack outputs: + + ```bash + FUNCTION_NAME=$(aws cloudformation describe-stacks --stack-name LambdaS3AthenaCdkStack --query 'Stacks[0].Outputs[?OutputKey==`LambdaFunctionName`].OutputValue' --output text) + ``` + +2. Test the `process` action (success) with asynchronous invocation: + + ```bash + aws lambda invoke \ + --function-name $FUNCTION_NAME \ + --invocation-type Event \ + --cli-binary-format raw-in-base64-out \ + --payload '{"action": "process", "value": 10}' \ + response.json + ``` + + Expected response: `{"StatusCode": 202}` (request accepted) + +3. Test the `validate` action (success): + + ```bash + aws lambda invoke \ + --function-name $FUNCTION_NAME \ + --invocation-type Event \ + --cli-binary-format raw-in-base64-out \ + --payload '{"action": "validate", "value": "hello"}' \ + response.json + ``` + +4. Test the `calculate` action (success): + + ```bash + aws lambda invoke \ + --function-name $FUNCTION_NAME \ + --invocation-type Event \ + --cli-binary-format raw-in-base64-out \ + --payload '{"action": "calculate", "value": [1, 2, 3, 4, 5]}' \ + response.json + ``` + +### Test Failed Requests + +1. Test with invalid value for `process` (negative number): + + ```bash + aws lambda invoke \ + --function-name $FUNCTION_NAME \ + --invocation-type Event \ + --cli-binary-format raw-in-base64-out \ + --payload '{"action": "process", "value": -5}' \ + response.json + ``` + +2. Test with invalid value for `validate` (empty string): + + ```bash + aws lambda invoke \ + --function-name $FUNCTION_NAME \ + --invocation-type Event \ + --cli-binary-format raw-in-base64-out \ + --payload '{"action": "validate", "value": ""}' \ + response.json + ``` + +3. Test with invalid value for `calculate` (empty array): + + ```bash + aws lambda invoke \ + --function-name $FUNCTION_NAME \ + --invocation-type Event \ + --cli-binary-format raw-in-base64-out \ + --payload '{"action": "calculate", "value": []}' \ + response.json + ``` + +4. Test with unknown action: + + ```bash + aws lambda invoke \ + --function-name $FUNCTION_NAME \ + --invocation-type Event \ + --cli-binary-format raw-in-base64-out \ + --payload '{"action": "unknown", "value": "test"}' \ + response.json + ``` + +5. Wait a few minutes for the failed events to be written to Amazon S3, then verify they exist: + + ```bash + BUCKET_NAME=$(aws cloudformation describe-stacks --stack-name LambdaS3AthenaCdkStack --query 'Stacks[0].Outputs[?OutputKey==`FailedEventsBucketName`].OutputValue' --output text) + aws s3 ls s3://$BUCKET_NAME/ --recursive + ``` + + Note: Failed events typically appear in Amazon S3 within 1-2 minutes after the AWS Lambda invocation fails. + +### Query Failed Events with Amazon Athena + +1. Open the Amazon Athena console to run queries. + +2. Query to count failed events by error type: + + ```sql + SELECT + responsepayload.errortype as error_type, + COUNT(*) as error_count + FROM failed_events + GROUP BY responsepayload.errortype + ORDER BY error_count DESC; + ``` + +3. Query to see detailed error messages: + + ```sql + SELECT + timestamp, + responsepayload.errortype as error_type, + responsepayload.errormessage as error_message, + requestpayload.body as request_body + FROM failed_events + ORDER BY timestamp DESC + LIMIT 10; + ``` + +4. Query to analyze errors by action type: + + ```sql + SELECT + json_extract_scalar(requestpayload.body, '$.action') as action, + responsepayload.errortype as error_type, + COUNT(*) as count + FROM failed_events + GROUP BY + json_extract_scalar(requestpayload.body, '$.action'), + responsepayload.errortype + ORDER BY count DESC; + ``` + +5. Query to find errors within a specific time range: + + ```sql + SELECT + timestamp, + responsepayload.errormessage as error_message, + requestpayload.body as request_body + FROM failed_events + WHERE timestamp >= '2025-01-01T00:00:00Z' + ORDER BY timestamp DESC; + ``` + +## Cleanup + +1. Delete the stack: + + ```bash + cdk destroy + ``` + +2. Confirm the deletion when prompted. + +--- + +Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 diff --git a/lambda-s3-athena-cdk-ts/bin/lambda-s3-athena-cdk-ts.ts b/lambda-s3-athena-cdk-ts/bin/lambda-s3-athena-cdk-ts.ts new file mode 100644 index 000000000..2f59a8491 --- /dev/null +++ b/lambda-s3-athena-cdk-ts/bin/lambda-s3-athena-cdk-ts.ts @@ -0,0 +1,12 @@ +#!/usr/bin/env node +import 'source-map-support/register'; +import * as cdk from 'aws-cdk-lib'; +import { PatternStack } from '../lib/pattern-stack'; + +const app = new cdk.App(); +new PatternStack(app, 'LambdaS3AthenaCdkStack', { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + } +}); diff --git a/lambda-s3-athena-cdk-ts/cdk.json b/lambda-s3-athena-cdk-ts/cdk.json new file mode 100644 index 000000000..8eb3ac511 --- /dev/null +++ b/lambda-s3-athena-cdk-ts/cdk.json @@ -0,0 +1,22 @@ +{ + "app": "npx ts-node --prefer-ts-exts bin/lambda-s3-athena-cdk-ts.ts", + "watch": { + "include": ["**"], + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + "cdk.out" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": ["aws", "aws-cn"] + } +} diff --git a/lambda-s3-athena-cdk-ts/example-pattern.json b/lambda-s3-athena-cdk-ts/example-pattern.json new file mode 100644 index 000000000..e2cd539a9 --- /dev/null +++ b/lambda-s3-athena-cdk-ts/example-pattern.json @@ -0,0 +1,74 @@ +{ + "title": "Lambda with S3 Failed-Event Destination and Athena Analytics", + "description": "Capture Lambda failed events to S3 and analyze them with Athena for error insights and patterns using asynchronous invocations.", + "language": "TypeScript", + "level": "200", + "framework": "AWS CDK", + "introBox": { + "headline": "How it works", + "text": [ + "This pattern demonstrates how to use Amazon S3 as a failed-event destination for AWS Lambda asynchronous invocations.", + "A Lambda function implements business logic with success and failure scenarios.", + "When Lambda fails during asynchronous invocation, AWS automatically captures the failed event to S3 for analysis.", + "Amazon Athena with AWS Glue enables SQL-based analytics on failed events to identify error patterns and gain insights.", + "The pattern uses AWS CLI with --invocation-type Event to demonstrate asynchronous invocation.", + "Important: Lambda destinations only work with asynchronous invocations (S3, SNS, EventBridge) and stream-based sources (Kinesis, DynamoDB Streams, SQS). They do not trigger for synchronous invocations." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/lambda-s3-athena-cdk-ts", + "templateURL": "serverless-patterns/lambda-s3-athena-cdk-ts", + "projectFolder": "lambda-s3-athena-cdk-ts", + "templateFile": "lib/pattern-stack.ts" + } + }, + "resources": { + "bullets": [ + { + "text": "AWS Lambda S3 Failed-Event Destination Announcement", + "link": "https://aws.amazon.com/about-aws/whats-new/2024/11/aws-lambda-s3-failed-event-destination-stream-event-sources/" + }, + { + "text": "AWS Lambda Destinations Documentation", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations" + }, + { + "text": "Amazon Athena Documentation", + "link": "https://docs.aws.amazon.com/athena/latest/ug/what-is.html" + }, + { + "text": "AWS Glue Data Catalog", + "link": "https://docs.aws.amazon.com/glue/latest/dg/catalog-and-crawler.html" + } + ] + }, + "deploy": { + "text": [ + "Clone the repository: git clone https://github.com/aws-samples/serverless-patterns", + "Change directory: cd lambda-s3-athena-cdk-ts", + "Install dependencies: npm install", + "Deploy the CDK stack: cdk deploy" + ] + }, + "testing": { + "text": [ + "Get Lambda function name: FUNCTION_NAME=$(aws cloudformation describe-stacks --stack-name LambdaS3AthenaCdkStack --query 'Stacks[0].Outputs[?OutputKey==`LambdaFunctionName`].OutputValue' --output text)", + "Test successful request: aws lambda invoke --function-name $FUNCTION_NAME --invocation-type Event --payload '{\"action\": \"process\", \"value\": 10}' response.json", + "Test failed request: aws lambda invoke --function-name $FUNCTION_NAME --invocation-type Event --payload '{\"action\": \"process\", \"value\": -5}' response.json", + "Verify failed events in S3: aws s3 ls s3://$(aws cloudformation describe-stacks --stack-name LambdaS3AthenaCdkStack --query 'Stacks[0].Outputs[?OutputKey==`FailedEventsBucketName`].OutputValue' --output text)/ --recursive", + "Query errors with Athena: SELECT responsepayload.errortype, COUNT(*) FROM failed_events GROUP BY responsepayload.errortype;" + ] + }, + "cleanup": { + "text": ["Delete the stack: cdk destroy"] + }, + "authors": [ + { + "name": "Marco Jahn", + "image": "https://sessionize.com/image/e99b-400o400o2-pqR4BacUSzHrq4fgZ4wwEQ.png", + "bio": "Senior Solutions Architect, Amazon Web Services", + "linkedin": "marcojahn" + } + ] +} diff --git a/lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.png b/lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.png new file mode 100644 index 0000000000000000000000000000000000000000..77e6d0dc895196237ab244f8832e574be8bbb070 GIT binary patch literal 34251 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 literal 0 HcmV?d00001 diff --git a/lambda-s3-athena-cdk-ts/lambda/processor.js b/lambda-s3-athena-cdk-ts/lambda/processor.js new file mode 100644 index 000000000..806a7bf47 --- /dev/null +++ b/lambda-s3-athena-cdk-ts/lambda/processor.js @@ -0,0 +1,58 @@ +exports.handler = async (event) => { + console.log('Event received:', JSON.stringify(event, null, 2)); + + try { + const action = event.action; + const value = event.value; + + // Simple business logic simulation + switch (action) { + case 'process': + if (!value || value < 0) { + throw new Error('Invalid value: must be a positive number'); + } + return { + statusCode: 200, + body: JSON.stringify({ + message: 'Processing successful', + result: value * 2, + action: action + }) + }; + + case 'validate': + if (typeof value !== 'string' || value.length === 0) { + throw new Error('Invalid value: must be a non-empty string'); + } + return { + statusCode: 200, + body: JSON.stringify({ + message: 'Validation successful', + result: value.toUpperCase(), + action: action + }) + }; + + case 'calculate': + if (!Array.isArray(value) || value.length === 0) { + throw new Error('Invalid value: must be a non-empty array'); + } + const sum = value.reduce((acc, curr) => acc + curr, 0); + return { + statusCode: 200, + body: JSON.stringify({ + message: 'Calculation successful', + result: sum, + action: action + }) + }; + + default: + throw new Error(`Unknown action: ${action}`); + } + } catch (error) { + console.error('Error processing request:', error); + // Lambda will automatically send this to the failed-event destination + throw error; + } +}; diff --git a/lambda-s3-athena-cdk-ts/lib/pattern-stack.ts b/lambda-s3-athena-cdk-ts/lib/pattern-stack.ts new file mode 100644 index 000000000..1391d2eeb --- /dev/null +++ b/lambda-s3-athena-cdk-ts/lib/pattern-stack.ts @@ -0,0 +1,133 @@ +import * as cdk from 'aws-cdk-lib'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as glue from 'aws-cdk-lib/aws-glue'; +import * as athena from 'aws-cdk-lib/aws-athena'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { Construct } from 'constructs'; +import * as path from 'path'; + +export class PatternStack extends cdk.Stack { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + // S3 bucket for failed Lambda events + const failedEventsBucket = new s3.Bucket(this, 'FailedEventsBucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true, + encryption: s3.BucketEncryption.S3_MANAGED, + }); + + // S3 bucket for Athena query results + const athenaResultsBucket = new s3.Bucket(this, 'AthenaResultsBucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + autoDeleteObjects: true, + encryption: s3.BucketEncryption.S3_MANAGED, + }); + + // Lambda function with S3 failed-event destination + // Note: S3Destination automatically grants only necessary write permissions (PutObject) + // to the Lambda function for failed event delivery + const processorFunction = new lambda.Function(this, 'ProcessorFunction', { + runtime: lambda.Runtime.NODEJS_20_X, + handler: 'processor.handler', + code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')), + timeout: cdk.Duration.seconds(30), + onFailure: new cdk.aws_lambda_destinations.S3Destination(failedEventsBucket), + }); + + // Glue Database for Athena + const glueDatabase = new glue.CfnDatabase(this, 'FailedEventsDatabase', { + catalogId: cdk.Aws.ACCOUNT_ID, + databaseInput: { + name: 'failed_events_db', + description: 'Database for failed Lambda events', + }, + }); + + // Glue Table for failed events (simplified without partitioning) + const glueTable = new glue.CfnTable(this, 'FailedEventsTable', { + catalogId: cdk.Aws.ACCOUNT_ID, + databaseName: glueDatabase.ref, + tableInput: { + name: 'failed_events', + description: 'Table for failed Lambda events stored in S3', + tableType: 'EXTERNAL_TABLE', + storageDescriptor: { + columns: [ + { name: 'version', type: 'string' }, + { name: 'timestamp', type: 'string' }, + { name: 'requestcontext', type: 'struct' }, + { name: 'requestpayload', type: 'struct,queryparam:map>' }, + { name: 'responsepayload', type: 'struct>' }, + ], + location: `s3://${failedEventsBucket.bucketName}/`, + inputFormat: 'org.apache.hadoop.mapred.TextInputFormat', + outputFormat: 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat', + serdeInfo: { + serializationLibrary: 'org.openx.data.jsonserde.JsonSerDe', + parameters: { + 'case.insensitive': 'true', + }, + }, + }, + }, + }); + + glueTable.addDependency(glueDatabase); + + // Athena Workgroup + const athenaWorkgroup = new athena.CfnWorkGroup(this, 'FailedEventsWorkgroup', { + name: 'failed-events-workgroup', + workGroupConfiguration: { + resultConfiguration: { + outputLocation: `s3://${athenaResultsBucket.bucketName}/`, + }, + }, + }); + + // IAM role for Athena queries + const athenaRole = new iam.Role(this, 'AthenaQueryRole', { + assumedBy: new iam.ServicePrincipal('athena.amazonaws.com'), + }); + + failedEventsBucket.grantRead(athenaRole); + athenaResultsBucket.grantReadWrite(athenaRole); + + // Outputs + new cdk.CfnOutput(this, 'LambdaFunctionName', { + value: processorFunction.functionName, + description: 'Lambda function name for CLI invocation', + }); + + new cdk.CfnOutput(this, 'LambdaFunctionArn', { + value: processorFunction.functionArn, + description: 'Lambda function ARN', + }); + + new cdk.CfnOutput(this, 'FailedEventsBucketName', { + value: failedEventsBucket.bucketName, + description: 'S3 bucket for failed Lambda events', + }); + + new cdk.CfnOutput(this, 'AthenaResultsBucketName', { + value: athenaResultsBucket.bucketName, + description: 'S3 bucket for Athena query results', + }); + + new cdk.CfnOutput(this, 'GlueDatabaseName', { + value: glueDatabase.ref, + description: 'Glue database name', + }); + + new cdk.CfnOutput(this, 'GlueTableName', { + value: 'failed_events', + description: 'Glue table name', + }); + + new cdk.CfnOutput(this, 'AthenaWorkgroupName', { + value: athenaWorkgroup.name!, + description: 'Athena workgroup name', + }); + } +} diff --git a/lambda-s3-athena-cdk-ts/package.json b/lambda-s3-athena-cdk-ts/package.json new file mode 100644 index 000000000..40c2c71de --- /dev/null +++ b/lambda-s3-athena-cdk-ts/package.json @@ -0,0 +1,22 @@ +{ + "name": "lambda-s3-athena-cdk-ts", + "version": "0.1.0", + "bin": { + "lambda-s3-athena-cdk-ts": "bin/lambda-s3-athena-cdk-ts.js" + }, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "cdk": "cdk" + }, + "devDependencies": { + "@types/node": "22.7.9", + "aws-cdk": "2.1003.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" + }, + "dependencies": { + "aws-cdk-lib": "2.189.1", + "constructs": "^10.0.0" + } +} diff --git a/lambda-s3-athena-cdk-ts/tsconfig.json b/lambda-s3-athena-cdk-ts/tsconfig.json new file mode 100644 index 000000000..507608a99 --- /dev/null +++ b/lambda-s3-athena-cdk-ts/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["es2020"], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": ["./node_modules/@types"] + }, + "exclude": ["node_modules", "cdk.out"] +} From 89d8e75fe11e3ded51d695edc9531af2108b696a Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 2 Feb 2026 10:21:40 +0100 Subject: [PATCH 2/8] Update lambda-s3-athena-cdk-ts/example-pattern.json Co-authored-by: Ben <9841563+bfreiberg@users.noreply.github.com> --- lambda-s3-athena-cdk-ts/example-pattern.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambda-s3-athena-cdk-ts/example-pattern.json b/lambda-s3-athena-cdk-ts/example-pattern.json index e2cd539a9..7a13ec730 100644 --- a/lambda-s3-athena-cdk-ts/example-pattern.json +++ b/lambda-s3-athena-cdk-ts/example-pattern.json @@ -1,5 +1,5 @@ { - "title": "Lambda with S3 Failed-Event Destination and Athena Analytics", + "title": "AWS Lambda with Amazon S3 Failed-Event Destination and Amazon Athena Analytics", "description": "Capture Lambda failed events to S3 and analyze them with Athena for error insights and patterns using asynchronous invocations.", "language": "TypeScript", "level": "200", From 06e320e67ab261659a905de9a57ee01e156a138c Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 2 Feb 2026 10:23:37 +0100 Subject: [PATCH 3/8] Update lambda-s3-athena-cdk-ts/example-pattern.json Co-authored-by: Ben <9841563+bfreiberg@users.noreply.github.com> --- lambda-s3-athena-cdk-ts/example-pattern.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambda-s3-athena-cdk-ts/example-pattern.json b/lambda-s3-athena-cdk-ts/example-pattern.json index 7a13ec730..c588d4b7f 100644 --- a/lambda-s3-athena-cdk-ts/example-pattern.json +++ b/lambda-s3-athena-cdk-ts/example-pattern.json @@ -1,6 +1,6 @@ { "title": "AWS Lambda with Amazon S3 Failed-Event Destination and Amazon Athena Analytics", - "description": "Capture Lambda failed events to S3 and analyze them with Athena for error insights and patterns using asynchronous invocations.", + "description": "Capture AWS Lambda failed events to Amazon S3 and analyze them with Amazon Athena for error insights and patterns using asynchronous invocations.", "language": "TypeScript", "level": "200", "framework": "AWS CDK", From 96215749474cccdfc113848e3bb63cea1471e5d8 Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 2 Feb 2026 10:23:44 +0100 Subject: [PATCH 4/8] Update lambda-s3-athena-cdk-ts/example-pattern.json Co-authored-by: Ben <9841563+bfreiberg@users.noreply.github.com> --- lambda-s3-athena-cdk-ts/example-pattern.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambda-s3-athena-cdk-ts/example-pattern.json b/lambda-s3-athena-cdk-ts/example-pattern.json index c588d4b7f..7c5755490 100644 --- a/lambda-s3-athena-cdk-ts/example-pattern.json +++ b/lambda-s3-athena-cdk-ts/example-pattern.json @@ -9,7 +9,7 @@ "text": [ "This pattern demonstrates how to use Amazon S3 as a failed-event destination for AWS Lambda asynchronous invocations.", "A Lambda function implements business logic with success and failure scenarios.", - "When Lambda fails during asynchronous invocation, AWS automatically captures the failed event to S3 for analysis.", + "When the Lambda function fails during asynchronous invocation, AWS automatically captures the failed event to S3 for analysis.", "Amazon Athena with AWS Glue enables SQL-based analytics on failed events to identify error patterns and gain insights.", "The pattern uses AWS CLI with --invocation-type Event to demonstrate asynchronous invocation.", "Important: Lambda destinations only work with asynchronous invocations (S3, SNS, EventBridge) and stream-based sources (Kinesis, DynamoDB Streams, SQS). They do not trigger for synchronous invocations." From 085545434fcb7dea2ce832583b2e09e03210f4a1 Mon Sep 17 00:00:00 2001 From: Marco Jahn Date: Mon, 2 Feb 2026 10:26:10 +0100 Subject: [PATCH 5/8] added athena service label --- .../lambda-s3-athena-cdk-ts.png | Bin 34251 -> 35695 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.png b/lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.png index 77e6d0dc895196237ab244f8832e574be8bbb070..31dc85083f13a108d1cb7f96411abc990384621d 100644 GIT binary patch literal 35695 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

    2_jc{9O2gX60;{;2to z_300EbQJQ$;gLHZkHo&pisHAEZxUbRCCMLJm{5AhV3E?VSnha#u!WaXzmR#JZDj9vny~L#xaxH_syWGMF53K6F8_2##|DWpLbpCS6OBp zlUVhE*M172pv^&!{VZJzYZJ)pk(OB;2Ue@88~!IgraW;1h#7i|Z#)7@hHlC9O((vrMvOs!&py)`aG>Z9-^` zF{HFt1dOqCgG)9~*VEkw4Vq$UdYKl>DFsTGRn`ZlR}+279qKlo4NEon9ebH1uzmTs z2$EDYRcdbeLe6Mal7Qk^XS#M;9o;@Bwf z>9J{3B8?v-MsLHsNim&8wjm8Ed$H2Qz91VL-RZj0ciDn;3Ma`mDtb-+(u*s}FF?70 zF#(0yPDU3_Xp!c;8^u1E0AkS0M5L5{CoX ztoTv;+OFk0u1iMVEAOmqqPix=q}FkKD~xFljmMS4lA`!fJR;o-Bc)~=$sj5sdJ7c} zN4?!A6BXh2sAYj~43y0v-7kL!{=4A%yO6`O>YDpwQoS85Zi&>dn9_tPUOUX+upRnZ zcM??pEP_Ud%w12^xX(I{3_=AfaGaj5ylk^cyIS_3)fk1LJhQ>UT_^BCwC|~Lbr4#| zgGIQ74(qtzc0tnc)`RYJo(Jhp&pa1{!v#AW_*WcFEnl6~|C+c)D>u02nRltLNit#i z@$g*p+19Xn$8XHm!;y}s7evSI3)o9pHc=ALUK7~f-b%Q?W1wmwdnPTb25Q!Nd`AAV zX$h2KmC^GGk?#-#iYcve*rI#seDxD&S}hh6Q8nwj0aFGkfA-h)sFs$ssO!;*D7q zHUADhMvpP#`{DUA_C)g?Hv-WxwGU(4P;s+26n6Y1&PJw!Oj=WNyP`jwU~%t1}0a8so|ZWxz-_sZU4RV05HdITsI^|I=}I_ z^9-+E(o$mUw4AiSSt6>?fLhXscUl1a5qISgy#x`A4Znx`@&cw1O$S4@Cv`GrW4q)f zR2Hvbg&whf4z>O)sbVHzXjsGT7+_j)9Y&d1o^!!;T8Ne|M^GxXWxCQP9U2@dEvF6MbsgzAfe!p_ey_dFIY}R+Xj)-&Dqxfh~5E2H{L6F$h58W{Z2eh(-BV zy?h)a-Y?lQH-cn#+2>rH#8z*K4wu!XE^SpmUZUZd+mNxbn%b*eB2l$VW1gT~#;(t> z#Op^OW-gH-@4!c$a5GhTY%X@^X}@he9&cUn0AIxNDy8)B04$&7)@u zqLL!4O7V2+VG4;p?PL}OUY`<)Y~;BLi8dBjE5;J1uzA{S#%)Cl$%|U9L1@M2avOA4 z1oLrCpT-f{$H@2D{R$7^=eAAHH_%Efj>o3Rcn4J9vkJvxu(d3*%$V9JDTMn`Y?b`5 z@e%2yi)p3ZiO%*)#@kw^5+X1s?VCD}l5KyQUu*q1-ZT5jN$%M#&yy;(>YLT86{*S;gy}0#2w;CfqVj;HF9=Hny&(IvAA_bH{JwhWo1}%kNAU zvpA^PcgpGoNz0BA<6NcqtIA@e3f-LtWq)~BC`V|Y2fU7DiVm9~9(wKMTi>%-5Ptzo zglH2_;OZh@P)6Klxuzl)@*SiWmD0Hh$xt@?fhk0x*~^#I9;0DsY;A^=n;uv=6y8h1 z*j;U0$o(j<#Nskd>gI;|yZkQr$K+afM!sP1PR*I*lay)lmAiQT9IMt_*bJgeRX*|n znOs7VIK!{K#i5Wr()BPM2yReBg!X38N0Np??E)qSwK1ByOq)Sao77YgO8f;LT16h1lSsbu%BiT zLr%|@0&Q1@`;$tCyngh@X57q?9DG(waRME+(p8Ix>sEFbRCbxj7RMP#crL&fBqz*q z5qwgdlz=z8_`A5vJYDJ0tash;mdj*1O@l^C;)?Tadqwm0EI?0Wuq=NXd=)WlkeF*y z%HDAh4(LWG();jhs3bJc+$}g7S{h$)!Q~M?B`or|#P~VjHN6_|w5@KBA5C0QGqO6ip!~DaK-^dyl!yDFj2TWW(yr&V`ob?aM6>t4GfS zLLXev=2GR)cJoN=!7vA(DPFzY;W%_5q#h~q_zRyTm%i;UaSKgXCiCT=KiBpuXmLvK z?(IL4c^Spk`FNB6T3N! zxqxW5|Ka#c&5czZ(`YHK_5`kef`%R!SYi2Ff|+etRc>J@*$ZkFqWWgqTK7H?a^@A+ zDkQ%Q*|2%<7@=kdiu}N#MdZ#_<`Ao_SPp@dVW%p&{xM5`&*Eu^;jXB5f#dz9H*R6b zx6mhali~4cU(zYrZ9l)<6X>V`5SLI7VMK&~{?Y(J(Z$|C3vCL*ZRHo%;bEu`DyYyt z)4+JmsG}9Zau-#bkv7|1PD=v;>{t84JvD@eYVr{x*R3pyfYz)9of=0j45QDK=}@(8 zE+}5gP~NLD8|9(O2poe$xq`fO_}-d!P%`RCRtFEXtI+X+l8yMak^2W;~L8pQlUqE ztDH~!Ki7gxjiu5}_zh^TtEU`XnrC<{NJAC_hL9%i*!OZuWb5w-stF*VHD^z4KwL}2 zBHj7houUbuSas(S@#8DFqKd$aII`@nJ8=2IXj#^?!<#F)mWps~7#`2k6p+h-0(c~$ z=1>mNO^7Gtw%Ac~Y-A~A{;Kra`eDlo^#g;h*j(xmI>h8TLLj>{4ZI#a`esCzc#4n^ zeBr{?be5A5d|1XWDKXUBSRo1wGJTAQr#vv~U5G{%GPZ^ez7UBjlf@!k zkiCEr{wh!K7UzS_r9xc3T+$ANBkT#_Z2a$Pmdvj7?CCHH&oR?(-QWLeROpHC8&4o| z`fx5Nz0QxCoKHIGY1K$Cxa@X7b9JypbEQ-B$Hu>70r%4O0^kUo@A3UJwf(tIO{%m; zY;;2%h+VfspFZJmv(HHqt00$(!-i7k5jjtakgCX!xs|1YMvh9btk!3G6Qu@&h!Q16 zAg$qI0T9yW&l<^eB))J_`|OL^Oaat#KG4nneKNl?x%zt)S?)e>N$44l0W|-y(gy*P z;hB=hnQA%F((F0JDw`ZM*o*9$Pt58XV(^_8Q^+%~PZMCvM&KDh5Mzcz%gcAg5P8b6 z1oR^T9g5CJs_@aI>unKHfTzO^3~apz3) zr{qsUEm%yf14zdaEX<3n0uUC7!y%OQjX_#u0eJU>sF0 z#)LlwTFqthZ4@>#NGy1m=W@*Th|57LH>eFO8F;2BAQ?Vf_NX03Oqw0RQ(lx&FH+Wg zDopi&pvx(k0QWhTQdB4)9cmfak4!DmpHg@jEV5lPs@QYQn&)DJhMZaR8q_eINs&vTS4A_PvO>v-u$06) z=Ix}%2x%<9ax$ttZ)1C#9rBe#n3$*Ol1Nd7ytJq5f||^=>_#REzj%JjXL|9Y{YEdQ5)|Oe+7b)(Og@ZMSMNetNFZLlm$a z%W+_OH&^xfbINE)vzjYsCdQCG>gl!#uWX{{L5ESsc~t2BK{r(sx?a`#e=DPT>0f0u zBL#`!(%Ax^UKz#9D2sR$&TRwZh8FR1xn4=s#A^24%LQQUElQn<=dV3IE zR*gTP=6Z?C3}+zmsGmK$>vqdg9qS|Q*e#~(H*hTRj zcHc?*5qS7)Snayk7aj3JPmKx^o@(QdHf15C_!3u+fNaAIgFNHkVCJaBwS0TLA*RJt z!Ad}cjV=->CpPt3UW_DCL8Ly_d`tWfW5nkl#)w~NY#Lp4E?;}#%`i~+N3j(il83v~uuYy{wqCinIF<{XS#bLO{pjJxtN^wYe z4s9sf4aS)x=57q7#ZVE&00Hf@F|l429dx`b*ucz(-zWblV|F~52BE}73Jo7vXhgHB zHuT0>aGd9P{X)m$7Y|2EcB|6T!3{o?rSR`cEk$vL$^^pAR8ByqA|>zpnnIHVxReM8 z+eoz;F=RoOc>ITtk=*~li=^OS?4mL_aQ<5_+h7h0=O}(Tvs)&70DBTgHC7+MW-;*311;1~{X?%rjv~VFW?8oX#~! zyaqz*q`5M#uSZqbG%>D*Suy^)bL_8oKr{#ZD?9xAtlzGROc*^PGx2M!y zyRLJ252v=-|5bD*Bbu|rlh!Q(B(?UfNdy2AC*a0gMUcS{L?H+88bT`KC{|Vbaq97} z%fSkyd9-1&Bv@HDBZiD8@-9{x)L6r+gV&9(K z(jEZ?&i<(Z3MR)k0U~7>hX;=RGuO*lBd(1RLB&wBnDzQfRwt7E?WBC%#Zt`q9TGh+$Uq!Qa=x^Mh_kVTITt}wT{v-{hnjkZg_qQ48 z&qku#d$`%|W=$+R>YN|eHtX+kb|Bj)SXHM?hi2dG zhz?)GYQcMHpxkdfOQ*tJx=81h)lHF`O)P%xTyg8}4{2guxNIr>t*S z7u~8!J@2_Nj?MJ?#Ny|x&gB}@=vKfQ%XFUd-~+_W`6Z<|@zL=x^wkpA$NSJ42adW# zfM#2NfAdjj)E{KgcHwYf%A+0ncb2n9w>M`>Of34U!kG-rSXDo6zmxb+#oym%Ln5F) zjX~aMx7Fj!eEr0xgFP?iQ@PwS=-`=61*5}bQ__C@p8h`g42n*3eyy}{RmM*pH@_(zt+8wdK z-SWFUQI^$TB2K&r7ltojin_01oZGb+AEy_|+t$1g-gL=;H5Om9Ro1gtV>xB*N26>R z7hU^sksY2Z^9T1re>-RUQ~KGy?UE>E-wcm2N%XV2y#wu?yRfYP)n2p_ihitgJl5d= zw671^S@=%RM}Oot7=HJts$au~D}ByB$=_~>9k|#RU%mAABH8yCb$2iTIE5U<)x(gQ zSw`mL-o5J7krzT)s;wQblOB2P#8}x$wnx^lCCPqgoQVGKWS2{KT*$3T0oVQGd9)kl zng3P}_Gpp7m=KA#AbE!dM5HLTv4G;cu^T4pG3VU0VtN`5BycA+!=`=xDR{4}uv?3* zikc)Sk>|Wa?|Ga-;p}3)cn^l*C7PDik`3YVOQ65qDDG6b_Z=(=!IQ#Mp9?Mes$*g$ zoZiNZ19q&xMXAtXZ*`C5wlY=TqeAk$Ek!0=??=J*CX>YEO4L3E6e}AS_Q))(e1G$G z-J~WSxAQSoHuVdWTk)1)lIFO5e7o+06fc?A)vN9Td`j{DmE@;oU?sLbBi6;dai9R(9VS_`u@5*fS< z5x0wP#qxY>6yi;*I%1=c-Yq#QGkZ67+^DR<#A2eEB0%d}uQ}pcC(j8W>8(NFbK-%? zkdd+9u~C3n*p`XaG~~KTVcLlKGJO-*@9_T%FB2_QCK5wy;(d?cAiT^$ZRIXk$2Gx=q6$7M zUA>!K9l|uH9b0c2c)lC<8mLkW+HZe4$Zl~CBKUu^$#uj` z6E8{uRzu&$Sj7ym*njzvRz>FF>F%YLPEJGHsm!vxG`5hC*x@zCdt3A6{1~AO&yQm< zEi0eHr`o$TyB0Txl^s;WziGvBW%_>ZHyK&*x$O9ZN$H{9n?*x@57psmwKU7J z=oViD-dNAlD5~z4UW=UYS!4V503c^JODYWgl;1p>$@X5uQpoPBFYjAZ3(JTc*AMqs z+4mYsh|%`-2(RWv^JyE}*KW{@mrarOtwp5?zg28V6;^xgA4otz)~te(yJeI~_xO$L zl5>ngUZ&6vU@^spWT~Edhkpu@K@@#!OaSi2cE6&6W|DA{lLLL)8y%kMX{5_m3x%on|S% zm2ZELbN4$G*}T1|{;frM%~(2biGvn>aily^z?EAp@mH4C-z*os&*n;y7ok zJ0>liT*xD6p!jxT7VW9kVsW}_&UO2ncOEN9#Ec}JljS!|CoS@**^`bu{3%D3KiN{?o0j-&@44O z{y4pEQu;k---c7Td5w3jBP;?fY^SH1Af?F}<*86zsqUWG8*1^+jkR{HRG+D@N;xv2 zHUr`wO!Y;jEJyK$DqSeAHm}j57{KIbiQ3w0k5xG|GMc>1;{imXw9b^Oo2lsoy|yPu z9*6D-3zhke)syHiHm?MQH`|-vSac-5DxhH5dH9_bD8wl*1}yyW5d_80;_n^Gu+xgG zS;&gTFeT9PtYzTx)9lds=;G!iBjU2#T2KCyl&y2 zd2b#t7U6g^ZoZD-nQ>|{`GC;&-d&Ent+^d04c#5%O0Ap8@{eF<322EK_F2G-$jJ%2 z(^4w@=$Wk zi-O)6X{4?tb^l`g6iqR{_Ey!vKbRNNGCwS&XS&={Ro61eB{_{scYU8*_kH~K``5J* z4AO>H8q9oG(%W_cEz2k9^mN>}xHD@f_^Lg_t6d?gs?VS16-~*w#A)xMV-A0QSP8pb zoPT#9E`5DMj%UfxXJ5F$M?y#QQUQUjZy7elN*oGL|@8h_$yXt$G>N_wX%hH)_O`QN3&Jzdr7w3Rw7~OfjF9f zd#f$&>4TJY5s;Gk$y|}u%5?k7H0!m1S&8{}+Ps%kgqhMaR4MBpA;2J-?8035sOQwP z>^#$MWu4e#Y$!zc-cy&y-zHs>-_vOJztDcVy(LDMwVdTl#e)7;@3Bi6$jp#V^IYba zEGqy=1=v*NxER+CT3znB#onfTE3^;LMc8&0`>6-b3?$Ef+Q`yMY!o@U@-7|AIwNpr zhZ1w^GZ|Mh6t~MHsZI z`|7w&LDROt$*FF4-Yu75cz@heQONEP!nZIbl4|}b+o3R(bHc{o%gzrp!>m>ZYi>R3KdJP z{Yh(3yDB&*bqT+NUHF3^D!QGU`kh+MgP2Qf?gjhE+XrjLMaJ)hKR*wW{*>jLz-voZ z#ia9~JFzL4j8tutLzSA=nBqfC#G4*24Vt#t0gWJhI`PBMDZ$o^FQ~cx{;QNK+Q{aC z!9{oPl?0=iF}2q*_TPUXslo=KVC&*Cwb= z!YmI!5cTNaiJ3eUu`#!J>4LERUYUQi0;SKqJ`;LvQ)+msr@?_qn>Vvr@{R8jTPlY4 zjz>=Gvd~mux2}ljgwrWZq9ORvd$&aSZp9kQkk`(Go=NR*z_!My%5bgN9VK3|&z$|@ zEFMj^zRf{lnEvhkXISP?ZEL~O-|(WIV!^ny!|f!s_djs_)4uR!H`bAB-K4BX?@Z&Q z*5|Ly9?eK8k=&DVbkcZJ8(jFg7Vwf*opR**N%-cf9N6YEzTE``u1R0kgx@Tq>!Ol? zW%PBd)5)*Wxm&CIxSQ4;GU#JCub9DIcJXju*`YmtW37EC=1r>Qlf(zYOmbX29=c$Bk#%ecl&kxTBT~{s(u5o<~x~6hu#G_@_p0ev2M+5OIw2ZzpY!W)|w_zc=nX zdO>(0&Le;BMpDO-Lj%@wtDwEFMz_Anh)-lgdNv~|xUg%&e@jt(kaWjUNCOuf3-Q!_pMImwXO`Z%LHZQS$=vo0ny& z&%w#kW_Rg>;0;E==irSU#;>NX{U9Tz3R%BO-0F@;AFa1>+H}|IKD;G6B_?p|#dCg> zs|uSlYW`PA`!;4fo@$sdJMVoFcQEnaP`SK&WNwwRlJI~f=25N5!vlV|j8Eycu2XgC z*USU=yV5siLgd-Q4~)N?*krnLL^~>Mf(rBP%pA5Zcns2PXunhLvyQ^tkTk9b+9lfc zVV!$Z3ZAE3*_%5-+MAo#qA}94Hd@4?658d@ov@A`HXW-dJXO>0` zU&mI4dmd>i!o{IKm4eBIDrV%Dy*CObu7GHe)J}`8$m)UP3^;mvTq`C)qv=TMZbm|8 zt#tqX`@@G|gewwPfBgCDTU1v@m0N>NFRNl6K!SFCb84{rn7GkFRg~A@JEZr?nVF%< zca$K?PDK7+^o*^JOJ(Wwdav~rgIEUZQo*|Iq Xed+T`?Zg%QLZG6kiFz%6Kk)wm;s8Bi literal 34251 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 From 27edda7b297d933697b10ea78294780e2da5213a Mon Sep 17 00:00:00 2001 From: Marco Jahn Date: Mon, 2 Feb 2026 10:28:30 +0100 Subject: [PATCH 6/8] changed lambda runtime to NODEJS_LATEST --- lambda-s3-athena-cdk-ts/lib/pattern-stack.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambda-s3-athena-cdk-ts/lib/pattern-stack.ts b/lambda-s3-athena-cdk-ts/lib/pattern-stack.ts index 1391d2eeb..4264c335c 100644 --- a/lambda-s3-athena-cdk-ts/lib/pattern-stack.ts +++ b/lambda-s3-athena-cdk-ts/lib/pattern-stack.ts @@ -29,7 +29,7 @@ export class PatternStack extends cdk.Stack { // Note: S3Destination automatically grants only necessary write permissions (PutObject) // to the Lambda function for failed event delivery const processorFunction = new lambda.Function(this, 'ProcessorFunction', { - runtime: lambda.Runtime.NODEJS_20_X, + runtime: lambda.Runtime.NODEJS_LATEST, handler: 'processor.handler', code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')), timeout: cdk.Duration.seconds(30), From b03e3133e82fed210c1c1eee7d95e14a54b9dce2 Mon Sep 17 00:00:00 2001 From: Marco Jahn Date: Thu, 5 Feb 2026 12:19:45 +0100 Subject: [PATCH 7/8] fixed review comments, title length and additional informations on Athena setup --- lambda-s3-athena-cdk-ts/README.md | 2 ++ lambda-s3-athena-cdk-ts/example-pattern.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lambda-s3-athena-cdk-ts/README.md b/lambda-s3-athena-cdk-ts/README.md index 32b0e9a04..33322fbd5 100644 --- a/lambda-s3-athena-cdk-ts/README.md +++ b/lambda-s3-athena-cdk-ts/README.md @@ -199,6 +199,8 @@ The AWS Glue Data Catalog is required for Amazon Athena to query Amazon S3 data, ### Query Failed Events with Amazon Athena 1. Open the Amazon Athena console to run queries. + * You will need to setup a query result location in Amazon S3 if you've never run a query before + * This can be changed later in the settings 2. Query to count failed events by error type: diff --git a/lambda-s3-athena-cdk-ts/example-pattern.json b/lambda-s3-athena-cdk-ts/example-pattern.json index 7c5755490..2043d32ed 100644 --- a/lambda-s3-athena-cdk-ts/example-pattern.json +++ b/lambda-s3-athena-cdk-ts/example-pattern.json @@ -1,5 +1,5 @@ { - "title": "AWS Lambda with Amazon S3 Failed-Event Destination and Amazon Athena Analytics", + "title": "AWS Lambda Failed-Event Destination and Amazon Athena Analytics", "description": "Capture AWS Lambda failed events to Amazon S3 and analyze them with Amazon Athena for error insights and patterns using asynchronous invocations.", "language": "TypeScript", "level": "200", From 704b1dab1da390730f6f5e99a6a146b0e694453d Mon Sep 17 00:00:00 2001 From: Ben <9841563+bfreiberg@users.noreply.github.com> Date: Fri, 6 Feb 2026 12:23:34 +0100 Subject: [PATCH 8/8] Add final pattern file --- .../lambda-s3-athena-cdk-ts.json | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.json diff --git a/lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.json b/lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.json new file mode 100644 index 000000000..a9ffef05b --- /dev/null +++ b/lambda-s3-athena-cdk-ts/lambda-s3-athena-cdk-ts.json @@ -0,0 +1,106 @@ +{ + "title": "AWS Lambda Failed-Event Destination and Amazon Athena Analytics", + "description": "Capture AWS Lambda failed events to Amazon S3 and analyze them with Amazon Athena for error insights and patterns using asynchronous invocations.", + "language": "TypeScript", + "level": "200", + "framework": "AWS CDK", + "introBox": { + "headline": "How it works", + "text": [ + "This pattern demonstrates how to use Amazon S3 as a failed-event destination for AWS Lambda asynchronous invocations.", + "A Lambda function implements business logic with success and failure scenarios.", + "When the Lambda function fails during asynchronous invocation, AWS automatically captures the failed event to S3 for analysis.", + "Amazon Athena with AWS Glue enables SQL-based analytics on failed events to identify error patterns and gain insights.", + "The pattern uses AWS CLI with --invocation-type Event to demonstrate asynchronous invocation.", + "Important: Lambda destinations only work with asynchronous invocations (S3, SNS, EventBridge) and stream-based sources (Kinesis, DynamoDB Streams, SQS). They do not trigger for synchronous invocations." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/lambda-s3-athena-cdk-ts", + "templateURL": "serverless-patterns/lambda-s3-athena-cdk-ts", + "projectFolder": "lambda-s3-athena-cdk-ts", + "templateFile": "lib/pattern-stack.ts" + } + }, + "resources": { + "bullets": [ + { + "text": "AWS Lambda S3 Failed-Event Destination Announcement", + "link": "https://aws.amazon.com/about-aws/whats-new/2024/11/aws-lambda-s3-failed-event-destination-stream-event-sources/" + }, + { + "text": "AWS Lambda Destinations Documentation", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations" + }, + { + "text": "Amazon Athena Documentation", + "link": "https://docs.aws.amazon.com/athena/latest/ug/what-is.html" + }, + { + "text": "AWS Glue Data Catalog", + "link": "https://docs.aws.amazon.com/glue/latest/dg/catalog-and-crawler.html" + } + ] + }, + "deploy": { + "text": [ + "Clone the repository: git clone https://github.com/aws-samples/serverless-patterns", + "Change directory: cd lambda-s3-athena-cdk-ts", + "Install dependencies: npm install", + "Deploy the CDK stack: cdk deploy" + ] + }, + "testing": { + "text": [ + "Get Lambda function name: FUNCTION_NAME=$(aws cloudformation describe-stacks --stack-name LambdaS3AthenaCdkStack --query 'Stacks[0].Outputs[?OutputKey==`LambdaFunctionName`].OutputValue' --output text)", + "Test successful request: aws lambda invoke --function-name $FUNCTION_NAME --invocation-type Event --payload '{\"action\": \"process\", \"value\": 10}' response.json", + "Test failed request: aws lambda invoke --function-name $FUNCTION_NAME --invocation-type Event --payload '{\"action\": \"process\", \"value\": -5}' response.json", + "Verify failed events in S3: aws s3 ls s3://$(aws cloudformation describe-stacks --stack-name LambdaS3AthenaCdkStack --query 'Stacks[0].Outputs[?OutputKey==`FailedEventsBucketName`].OutputValue' --output text)/ --recursive", + "Query errors with Athena: SELECT responsepayload.errortype, COUNT(*) FROM failed_events GROUP BY responsepayload.errortype;" + ] + }, + "cleanup": { + "text": [ + "Delete the stack: cdk destroy" + ] + }, + "authors": [ + { + "name": "Marco Jahn", + "image": "https://sessionize.com/image/e99b-400o400o2-pqR4BacUSzHrq4fgZ4wwEQ.png", + "bio": "Senior Solutions Architect, Amazon Web Services", + "linkedin": "marcojahn" + } + ], + "patternArch": { + "icon1": { + "x": 20, + "y": 50, + "service": "lambda", + "label": "AWS Lambda" + }, + "icon2": { + "x": 55, + "y": 50, + "service": "s3", + "label": "Amazon S3" + }, + "icon3": { + "x": 80, + "y": 50, + "service": "athena", + "label": "Amazon Athena" + }, + "line1": { + "from": "icon1", + "to": "icon2", + "label": "Failed-event destination" + }, + "line2": { + "from": "icon2", + "to": "icon3", + "label": "analyze" + } + } +}