跳转到内容

TypeScript Lambda 函数

TypeScript Lambda 函数生成器能够为现有的 TypeScript 项目添加 Lambda 函数。

该生成器会创建一个新的 TypeScript Lambda 处理程序,并配置 AWS CDK 或 Terraform 基础设施。生成的处理器使用 AWS Lambda Powertools for TypeScript 实现可观测性功能,包括日志记录、AWS X-Ray 追踪和 CloudWatch 指标,同时通过 AWS Lambda Powertools 的 Parser 工具 提供可选的事件类型安全验证。

您可以通过两种方式生成 Lambda 函数:

  1. 安装 Nx Console VSCode Plugin 如果您尚未安装
  2. 在VSCode中打开Nx控制台
  3. 点击 Generate (UI) 在"Common Nx Commands"部分
  4. 搜索 @aws/nx-plugin - ts#lambda-function
  5. 填写必需参数
    • 点击 Generate
    参数 类型 默认值 描述
    project 必需 string - The project to add the lambda function to
    functionName 必需 string - The name of the function to add
    functionPath string - Optional subdirectory within the project source directory to add the function to
    eventSource string Any Optional event source schema to use for the lambda function
    iacProvider string Inherit The preferred IaC provider. By default this is inherited from your initial selection.

    生成器将在项目中添加以下文件:

    • 文件夹<project-name>
      • 文件夹src/
        • <lambda-function>.ts 函数实现

    若提供了 functionPath 选项,生成器会将处理程序添加到项目源码目录的指定路径下:

    • 文件夹<project-name>
      • 文件夹src/
        • 文件夹<custom-path>/
          • <function-name>.ts 函数实现

    由于该生成器会根据您选择的 iacProvider 以基础设施即代码的形式输出,它将在 packages/common 目录下创建一个包含相关 CDK 构造体或 Terraform 模块的项目。

    通用的基础设施即代码项目结构如下:

    • 文件夹packages/common/constructs
      • 文件夹src
        • 文件夹app/ 针对特定项目/生成器的基础设施构造体
        • 文件夹core/ app 目录构造体重用的通用构造体
        • index.ts 导出 app 目录构造体的入口文件
      • project.json 项目构建目标与配置

    生成器会根据选定的 iacProvider 创建用于部署函数的基础设施即代码:

    生成器会创建一个 CDK 构造,用于部署您的函数,该构造位于 packages/common/constructs/src/app/lambda-functions 目录。

    主函数实现位于 <function-name>.ts 文件中。示例如下:

    import { parser } from '@aws-lambda-powertools/parser/middleware';
    import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas';
    import middy from '@middy/core';
    import { Tracer } from '@aws-lambda-powertools/tracer';
    import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
    import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware';
    import { Logger } from '@aws-lambda-powertools/logger';
    import { Metrics } from '@aws-lambda-powertools/metrics';
    import { logMetrics } from '@aws-lambda-powertools/metrics/middleware';
    import { z } from 'zod';
    process.env.POWERTOOLS_METRICS_NAMESPACE = 'MyFunction';
    process.env.POWERTOOLS_SERVICE_NAME = 'MyFunction';
    const tracer = new Tracer();
    const logger = new Logger();
    const metrics = new Metrics();
    export const myFunction = async (
    event: z.infer<typeof EventBridgeSchema>,
    ): Promise<void> => {
    logger.info('Received event', event);
    // TODO: 实现具体逻辑
    };
    export const handler = middy()
    .use(captureLambdaHandler(tracer))
    .use(injectLambdaContext(logger))
    .use(logMetrics(metrics))
    .use(parser({ schema: EventBridgeSchema }))
    .handler(myFunction);

    生成器自动配置了以下功能:

    1. Middy 中间件栈 用于增强 Lambda 功能
    2. AWS Lambda Powertools 集成 实现可观测性
    3. CloudWatch 指标收集
    4. 类型安全 通过解析器中间件实现
    5. 使用 Rolldown 打包 优化部署包

    使用 AWS Lambda Powertools 实现可观测性

    Section titled “使用 AWS Lambda Powertools 实现可观测性”

    生成器通过 Middy 中间件自动配置了带有上下文注入的结构化日志记录:

    export const handler = middy()
    .use(injectLambdaContext(logger))
    .handler(myFunction);

    通过 captureLambdaHandler 中间件自动配置 AWS X-Ray 追踪。您可以添加自定义追踪子段:

    const tracer = new Tracer();
    export const myFunction = async (
    event: z.infer<typeof EventBridgeSchema>,
    ): Promise<void> => {
    // 创建新的追踪子段
    const subsegment = tracer.getSegment()?.addNewSubsegment('custom-operation');
    try {
    // 业务逻辑实现
    } catch (error) {
    subsegment?.addError(error as Error);
    throw error;
    } finally {
    subsegment?.close();
    }
    };
    export const handler = middy()
    .use(captureLambdaHandler(tracer))
    .handler(myFunction);

    通过 logMetrics 中间件自动收集 CloudWatch 指标。您可以添加自定义指标:

    const metrics = new Metrics();
    export const myFunction = async (
    event: z.infer<typeof EventBridgeSchema>,
    ): Promise<void> => {
    metrics.addMetric("CustomMetric", MetricUnit.Count, 1);
    metrics.addMetric("ProcessingTime", MetricUnit.Milliseconds, processingTime);
    };
    export const handler = middy()
    .use(logMetrics(metrics))
    .handler(myFunction);

    如果在生成 Lambda 函数时选择了 eventSource,您的函数将通过 AWS Lambda Powertools 的解析器中间件 实现类型安全。例如:

    export const myFunction = async (
    event: z.infer<typeof EventBridgeSchema>,
    ): Promise<void> => {
    event.detail // <- 类型安全,支持 IDE 自动补全
    };
    export const handler = middy()
    .use(parser({ schema: EventBridgeSchema }))
    .handler(myFunction);

    这为 Lambda 事件提供了编译时类型安全和运行时验证。

    如果不需要对事件进行类型约束,可以选择 eventSourceAny,此时事件参数将保持 any 类型。

    生成器会自动配置一个使用 Rolldown 创建部署包的 bundle 目标:

    Terminal window
    pnpm nx run <project-name>:bundle

    Rolldown 配置位于 rolldown.config.ts 文件中,每个要生成的包都有对应的入口配置。如果定义了多个包,Rolldown 会并行管理这些包的创建过程。

    该生成器会根据您选择的 iacProvider 创建 CDK 或 Terraform 基础设施即代码。您可以用它来部署函数。

    该生成器会在 common/constructs 目录下创建用于部署函数的 CDK 构造体。您可以在 CDK 应用中使用:

    import { MyProjectMyFunction } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    // 将函数添加到堆栈
    const fn = new MyProjectMyFunction(this, 'MyFunction');
    }
    }

    这会配置:

    1. AWS Lambda 函数
    2. CloudWatch 日志组
    3. X-Ray 追踪配置
    4. CloudWatch 指标命名空间

    该函数可作为任何 Lambda 事件源的目标:

    以下示例演示了使用 EventBridge 定时调用 Lambda 函数的 CDK 代码:

    import { Rule, Schedule } from 'aws-cdk-lib/aws-events';
    import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets';
    import { MyProjectMyFunction } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    // 将函数添加到堆栈
    const fn = new MyProjectMyFunction(this, 'MyFunction');
    // 将函数添加到 EventBridge 定时规则
    const eventRule = new Rule(this, 'MyFunctionScheduleRule', {
    schedule: Schedule.cron({ minute: '15' }),
    targets: [new LambdaFunction(fn)],
    });
    }
    }