Java 中的 Amazon Lambda 函数日志记录 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Java 中的 Amazon Lambda 函数日志记录

Amazon Lambda自动监控 Lambda 函数并将日志条目发送到亚马逊。 CloudWatch您的 Lambda 函数带有 CloudWatch 日志日志组和每个函数实例的日志流。Lambda 运行时系统环境会将每次调用的详细信息以及函数代码的其他输出发送到该日志流。有关 CloudWatch 日志的更多信息,请参阅将 Amazon CloudWatch 日志与 Amazon Lambda

要从函数代码输出日志,您可以使用 java.lang.System 的方法,或使用写入到 stdout 或 stderr 的任何日志记录模块。

创建返回日志的函数

要从函数代码输出日志,您可以使用 java.lang.System 的方法,或使用写入到 stdoutstderr 的任何日志记录模块。该aws-lambda-java-core库提供了一个名为的记录器类LambdaLogger,您可以从上下文对象访问该类。记录器类支持多行日志。

以下示例使用上下文对象提供的 LambdaLogger 记录器。

例 Handler.java
// Handler value: example.Handler public class Handler implements RequestHandler<Object, String>{ Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Override public String handleRequest(Object event, Context context) { LambdaLogger logger = context.getLogger(); String response = new String("SUCCESS"); // log execution details logger.log("ENVIRONMENT VARIABLES: " + gson.toJson(System.getenv())); logger.log("CONTEXT: " + gson.toJson(context)); // process event logger.log("EVENT: " + gson.toJson(event)); return response; } }
例 日志格式
START RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0 Version: $LATEST ENVIRONMENT VARIABLES: { "_HANDLER": "example.Handler", "AWS_EXECUTION_ENV": "AWS_Lambda_java8", "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "512", ... } CONTEXT: { "memoryLimit": 512, "awsRequestId": "6bc28136-xmpl-4365-b021-0ce6b2e64ab0", "functionName": "java-console", ... } EVENT: { "records": [ { "messageId": "19dd0b57-xmpl-4ac1-bd88-01bbb068cb78", "receiptHandle": "MessageReceiptHandle", "body": "Hello from SQS!", ... } ] } END RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0 REPORT RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0 Duration: 198.50 ms Billed Duration: 200 ms Memory Size: 512 MB Max Memory Used: 90 MB Init Duration: 524.75 ms

Java 运行时记录每次调用的 STARTENDREPORT 行。报告行提供了以下详细信息:

REPORT 行数据字段
  • RequestId— 调用的唯一请求 ID。

  • Duration(持续时间)– 函数的处理程序方法处理事件所花费的时间。

  • Billed Duration(计费持续时间)– 针对调用计费的时间量。

  • Memory Size(内存大小)– 分配给函数的内存量。

  • Max Memory Used(最大内存使用量)– 函数使用的内存量。

  • Init Duration(初始持续时间)– 对于提供的第一个请求,为运行时在处理程序方法外部加载函数和运行代码所花费的时间。

  • XRAY TraceId — 对于已跟踪的请求,为Amazon X-Ray跟踪 ID。

  • SegmentId— 对于已跟踪的请求,使用 X-Ray 分段 ID。

  • Sampled(采样)– 对于追踪的请求,为采样结果。

在 Java 中使用 Lambda 高级日志记录控件

为了更好地控制捕获、处理和使用函数日志的方式,您可以为支持的 Java 运行时系统配置以下日志记录选项:

  • 日志格式 - 为函数日志选择纯文本或结构化的 JSON 格式

  • 日志级别-对于 JSON 格式的日志,选择 Lambda 发送到的日志的详细级别 CloudWatch,例如错误、调试或信息

  • 日志组-选择您的函数将 CloudWatch 日志发送到的日志组

有关这些日志记录选项的更多信息以及如何通过配置来使用函数的说明,请参阅 为您的 Lambda 函数配置高级日志记录控件

要在 Java Lambda 函数中使用日志格式和日志级别选项,请参阅以下各节中的指南。

在 Java 中使用结构化的 JSON 日志格式

如果您为函数的日志格式选择 JSON,Lambda 将使用 LambdaLogger 类将日志输出作为结构化的 JSON 发送到 CloudWatch。每个 JSON 日志对象包含至少四个键值对和以下键:

  • "timestamp" - 生成日志消息的时间

  • "level" - 分配给消息的日志级别

  • "message" - 日志消息的内容

  • "AWSrequestId" - 函数调用的唯一请求 ID

根据您使用的日志记录方法,以 JSON 格式捕获的函数日志输出还可能包含其他键值对。

要为使用 LambdaLogger 记录器创建的日志分配级别,您需要在日志记录命令中提供 LogLevel 参数,如以下示例所示。

例 Java 日志记录代码
LambdaLogger logger = context.getLogger(); logger.log("This is a debug log", LogLevel.DEBUG);

此示例代码输出的日志将在 CloudWatch 日志中捕获,如下所示:

例 JSON 日志记录
{ "timestamp":"2023-11-01T00:21:51.358Z", "level":"DEBUG", "message":"This is a debug log", "AWSrequestId":"93f25699-2cbf-4976-8f94-336a0aa98c6f" }

如果您没有为日志输出分配级别,Lambda 将自动为其分配 INFO 级别。

如果您的代码已经使用其他日志记录库来生成 JSON 结构化日志,则无需进行任何更改。Lambda 不会对任何已采用 JSON 编码的日志进行双重编码。即使您将函数配置为使用 JSON 日志格式,您的日志输出也会显示 CloudWatch 在您定义的 JSON 结构中。

在 Java 中使用日志级别筛选

为了让 Amazon Lambda 根据日志级别筛选应用程序日志,您的函数必须使用 JSON 格式的日志。您可以通过两种方式实现这一点:

将函数配置为使用日志级别筛选时,您必须从以下选项中选择希望 Lambda 发送 CloudWatch 到日志的日志级别:

日志级别 标准使用情况
TRACE(最详细) 用于跟踪代码执行路径的最精细信息
调试 系统调试的详细信息
信息 记录函数正常运行情况的消息
警告 有关潜在错误的消息,如果不加以解决,这些错误可能会导致意外行为
ERROR 有关会阻碍代码按预期执行的问题的消息
FATAL(最简略) 有关导致应用程序停止运行的严重错误的消息

要让 Lambda 筛选函数的日志,还必须在 JSON 日志输出中包含一个 "timestamp" 键值对。必须以有效的 RFC 3339 时间戳格式指定时间。如果您未提供有效的时间戳,Lambda 将为日志分配 INFO 级别并为您添加时间戳。

Lambda 将选定级别及更低级别的日志发送到。 CloudWatch例如,如果您将日志级别配置为 WARN,Lambda 将发送与 WARN、ERROR 和 FATAL 级别相对应的日志。

使用 Log4j2 和 SLF4J 进行高级日志记录

注意

Amazon Lambda 的托管式运行时或基本容器映像中不包括 Log4j2。因此,这些不受 CVE-2021-44228、CVE-2021-45046 和 CVE-2021-45105 中描述的问题影响。

对于客户的函数包含受影响的 Log4j2 版本的情况,我们对 Lambda Java 托管式运行时基本容器映像应用了更改,以帮助缓解 CVE-2021-44228、CVE-2021-45046 和 CVE-2021-45105 中描述的问题。由于这一更改,使用 Log4J2 的客户可能会看到额外的日志条目,类似于“Transforming org/apache/logging/log4j/core/lookup/JndiLookup (java.net.URLClassLoader@...)”。Log4J2 输出中引用 jndi 映射器的任何日志字符串都将替换为“Patched JndiLookup::lookup()”。

无论是否有这一更改,我们强烈建议其函数中包括 Log4j2 的所有客户更新到最新版本。具体而言,在函数中使用 aws-lambda-java-log 4j2 库的客户应更新到 1.5.0(或更高版本),然后重新部署其函数。此版本将底层 Log4j2 实用程序依赖项更新为版本 2.17.0(或更高版本)。更新后的 aws-lambda-java-log 4j2 二进制文件可在 Maven 存储库中找到,其源代码可在 Github 中找到。

最后,请注意,在任何情况下都不应使用任何与 aws-lambda-java-log4j(v1.0.0 或 1.0.1)相关的库。这些库与 log4j 的 1.x 版本相关,该版本已于 2015 年终止使用。这些库不受支持、未维护、未修补,并且存在已知的安全漏洞。

要自定义日志输出、在单元测试期间支持日志记录以及记录 Amazon 开发工具包调用,请将 Apache Log4j2 与 SLF4J 结合使用。Log4j 是 Java 程序的日志库,这些程序使您能够配置日志级别和使用 Appender 库。SLF4J 是一个 Facade 库,可让您更改您使用的库,而不更改函数代码。

要将请求 ID 添加到函数的日志中,请使用 aws-lambda-java-log4j 2 库中的附加程序。

src/main/resources/log4j2.xml – Appender 配置
<Configuration> <Appenders> <Lambda name="Lambda" format="${env:AWS_LAMBDA_LOG_FORMAT:-TEXT}"> <LambdaTextFormat> <PatternLayout> <pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1} - %m%n </pattern> </PatternLayout> </LambdaTextFormat> <LambdaJSONFormat> <JsonTemplateLayout eventTemplateUri="classpath:LambdaLayout.json" /> </LambdaJSONFormat> </Lambda> </Appenders> <Loggers> <Root level="${env:AWS_LAMBDA_LOG_LEVEL:-INFO}"> <AppenderRef ref="Lambda"/> </Root> <Logger name="software.amazon.awssdk" level="WARN" /> <Logger name="software.amazon.awssdk.request" level="DEBUG" /> </Loggers> </Configuration>

您可以通过在 <LambdaTextFormat><LambdaJSONFormat> 标签下指定布局来决定如何为纯文本或 JSON 输出配置 Log4j2 日志。

在此示例中,使用文本模式,每行都会在前面加上日期、时间、请求 ID、日志级别和类名。在 JSON 模式下,<JsonTemplateLayout> 要结合与 aws-lambda-java-log4j2 库一起提供的配置使用。

SLF4J 是一个用于在 Java 代码中进行日志记录的 Facade 库。在函数代码中,您可以使用 SLF4J 记录器工厂,通过适用于日志级别(如 info()warn())的方法来检索记录器。在构建配置中,您可以在类路径中包含日志记录库和 SLF4J 适配器。通过更改构建配置中的库,您可以在不更改函数代码的情况下更改记录器类型。从适用于 Java 的开发工具包中捕获日志需要使用 SLF4J。

在以下示例代码中,处理程序类使用 SLF4J 检索记录器。

src/main/java/example/HandlerS3.java:使用 SLF4J 进行日志记录
package example; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.S3Event; import static org.apache.logging.log4j.CloseableThreadContext.put; public class HandlerS3 implements RequestHandler<S3Event, String>{ private static final Logger logger = LoggerFactory.getLogger(HandlerS3.class); @Override public String handleRequest(S3Event event, Context context) { for(var record : event.getRecords()) { try (var loggingCtx = put("awsRegion", record.getAwsRegion())) { loggingCtx.put("eventName", record.getEventName()); loggingCtx.put("bucket", record.getS3().getBucket().getName()); loggingCtx.put("key", record.getS3().getObject().getKey()); logger.info("Handling s3 event"); } } return "Ok"; } }

此代码产生类似下面的日志输出:

例 日志格式
{ "timestamp": "2023-11-15T16:56:00.815Z", "level": "INFO", "message": "Handling s3 event", "logger": "example.HandlerS3", "AWSRequestId": "0bced576-3936-4e5a-9dcd-db9477b77f97", "awsRegion": "eu-south-1", "bucket": "java-logging-test-input-bucket", "eventName": "ObjectCreated:Put", "key": "test-folder/" }

构建配置使用 Lambda Appender 和 SLF4J 适配器上的运行时系统依赖项以及 Log4j2 上的实现依赖项。

build.gradle – 日志记录依赖项
dependencies { ... 'com.amazonaws:aws-lambda-java-log4j2:[1.6.0,)', 'com.amazonaws:aws-lambda-java-events:[3.11.3,)', 'org.apache.logging.log4j:log4j-layout-template-json:[2.17.1,)', 'org.apache.logging.log4j:log4j-slf4j2-impl:[2.19.0,)', ... }

在本地运行代码进行测试时,带有 Lambda 记录器的上下文对象不可用,并且没有供 Lambda Appender 使用的请求 ID 。有关测试配置示例,请参阅下一节中的示例应用程序。

其他工具和库

Powertools for Amazon Lambda(Java)是一个开发人员工具包,用于实施无服务器最佳实践并提高开发人员速度。日志记录实用程序提供经优化的 Lambda 日志记录程序,其中包含有关所有函数的函数上下文的附加信息,输出结构为 JSON。请使用该实用程序执行以下操作:

  • 从 Lambda 上下文中捕获关键字段,冷启动并将日志记录输出结构化为 JSON

  • 根据指示记录 Lambda 调用事件(默认情况下禁用)

  • 通过日志采样仅针对一定百分比的调用输出所有日志(默认情况下禁用)

  • 在任何时间点将其他键附加到结构化日志

  • 使用自定义日志格式设置程序(自带格式设置程序),从而在与组织的日志记录 RFC 兼容的结构中输出日志

将 Powertools for Amazon Lambda(Java)和 Amazon SAM 用于结构化日志记录

请按照以下步骤使用 Amazon SAM,通过集成的 Powertools for Amazon Lambda(Java)~ 模块来下载、构建和部署示例 Hello World Java 应用程序。此应用程序实现了基本的 API 后端,并使用 Powertools 发送日志、指标和跟踪。它由 Amazon API Gateway 端点和 Lambda 函数组成。当您向 API Gateway 终端节点发送 GET 请求时,Lambda 函数会调用、使用嵌入式指标格式向其发送日志和指标 CloudWatch,并将跟踪发送到。Amazon X-Ray该函数将返回一条 hello world 消息。

先决条件

要完成本节中的步骤,您必须满足以下条件:

部署示例 Amazon SAM 应用程序
  1. 使用 Hello World Java 模板初始化该应用程序。

    sam init --app-template hello-world-powertools-java --name sam-app --package-type Zip --runtime java11 --no-tracing
  2. 构建应用程序。

    cd sam-app && sam build
  3. 部署应用程序。

    sam deploy --guided
  4. 按照屏幕上的提示操作。要在交互式体验中接受提供的默认选项,请按 Enter

    注意

    因为HelloWorldFunction 可能没有定义授权,这样可以吗? ,请务必输入y

  5. 获取已部署应用程序的 URL:

    aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
  6. 调用 API 端点:

    curl -X GET <URL_FROM_PREVIOUS_STEP>

    如果成功,您将会看到如下响应:

    {"message":"hello world"}
  7. 要获取该函数的日志,请运行 sam logs。有关更多信息,请参阅《Amazon Serverless Application Model 开发人员指南》中的 使用日志

    sam logs --stack-name sam-app

    该日志输出类似于以下示例:

    2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.095000 INIT_START Runtime Version: java:11.v15 Runtime Version ARN: arn:aws:lambda:eu-central-1::runtime:0a25e3e7a1cc9ce404bc435eeb2ad358d8fa64338e618d0c224fe509403583ca 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.114000 Picked up JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.793000 Transforming org/apache/logging/log4j/core/lookup/JndiLookup (lambdainternal.CustomerClassLoader@1a6c5a9e) 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:35.252000 START RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765 Version: $LATEST 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.531000 { "_aws": { "Timestamp": 1675416276051, "CloudWatchMetrics": [ { "Namespace": "sam-app-powerools-java", "Metrics": [ { "Name": "ColdStart", "Unit": "Count" } ], "Dimensions": [ [ "Service", "FunctionName" ] ] } ] }, "function_request_id": "7fcf1548-d2d4-41cd-a9a8-6ae47c51f765", "traceId": "Root=1-63dcd2d1-25f90b9d1c753a783547f4dd;Parent=e29684c1be352ce4;Sampled=1", "FunctionName": "sam-app-HelloWorldFunction-y9Iu1FLJJBGD", "functionVersion": "$LATEST", "ColdStart": 1.0, "Service": "service_undefined", "logStreamId": "2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81", "executionEnvironment": "AWS_Lambda_java11" } 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.974000 Feb 03, 2023 9:24:36 AM com.amazonaws.xray.AWSXRayRecorder <init> 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.993000 Feb 03, 2023 9:24:36 AM com.amazonaws.xray.config.DaemonConfiguration <init> 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.993000 INFO: Environment variable AWS_XRAY_DAEMON_ADDRESS is set. Emitting to daemon on address XXXX.XXXX.XXXX.XXXX:2000. 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:37.331000 09:24:37.294 [main] INFO helloworld.App - {"version":null,"resource":"/hello","path":"/hello/","httpMethod":"GET","headers":{"Accept":"*/*","CloudFront-Forwarded-Proto":"https","CloudFront-Is-Desktop-Viewer":"true","CloudFront-Is-Mobile-Viewer":"false","CloudFront-Is-SmartTV-Viewer":"false","CloudFront-Is-Tablet-Viewer":"false","CloudFront-Viewer-ASN":"16509","CloudFront-Viewer-Country":"IE","Host":"XXXX.execute-api.eu-central-1.amazonaws.com","User-Agent":"curl/7.86.0","Via":"2.0 f0300a9921a99446a44423d996042050.cloudfront.net (CloudFront)","X-Amz-Cf-Id":"t9W5ByT11HaY33NM8YioKECn_4eMpNsOMPfEVRczD7T1RdhbtiwV1Q==","X-Amzn-Trace-Id":"Root=1-63dcd2d1-25f90b9d1c753a783547f4dd","X-Forwarded-For":"XX.XXX.XXX.XX, XX.XXX.XXX.XX","X-Forwarded-Port":"443","X-Forwarded-Proto":"https"},"multiValueHeaders":{"Accept":["*/*"],"CloudFront-Forwarded-Proto":["https"],"CloudFront-Is-Desktop-Viewer":["true"],"CloudFront-Is-Mobile-Viewer":["false"],"CloudFront-Is-SmartTV-Viewer":["false"],"CloudFront-Is-Tablet-Viewer":["false"],"CloudFront-Viewer-ASN":["16509"],"CloudFront-Viewer-Country":["IE"],"Host":["XXXX.execute-api.eu-central-1.amazonaws.com"],"User-Agent":["curl/7.86.0"],"Via":["2.0 f0300a9921a99446a44423d996042050.cloudfront.net (CloudFront)"],"X-Amz-Cf-Id":["t9W5ByT11HaY33NM8YioKECn_4eMpNsOMPfEVRczD7T1RdhbtiwV1Q=="],"X-Amzn-Trace-Id":["Root=1-63dcd2d1-25f90b9d1c753a783547f4dd"],"X-Forwarded-For":["XXX, XXX"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"queryStringParameters":null,"multiValueQueryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"accountId":"XXX","stage":"Prod","resourceId":"at73a1","requestId":"ba09ecd2-acf3-40f6-89af-fad32df67597","operationName":null,"identity":{"cognitoIdentityPoolId":null,"accountId":null,"cognitoIdentityId":null,"caller":null,"apiKey":null,"principalOrgId":null,"sourceIp":"54.240.197.236","cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":null,"userAgent":"curl/7.86.0","user":null,"accessKey":null},"resourcePath":"/hello","httpMethod":"GET","apiId":"XXX","path":"/Prod/hello/","authorizer":null},"body":null,"isBase64Encoded":false} 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:37.351000 09:24:37.351 [main] INFO helloworld.App - Retrieving https://checkip.amazonaws.com 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.313000 { "function_request_id": "7fcf1548-d2d4-41cd-a9a8-6ae47c51f765", "traceId": "Root=1-63dcd2d1-25f90b9d1c753a783547f4dd;Parent=e29684c1be352ce4;Sampled=1", "xray_trace_id": "1-63dcd2d1-25f90b9d1c753a783547f4dd", "functionVersion": "$LATEST", "Service": "service_undefined", "logStreamId": "2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81", "executionEnvironment": "AWS_Lambda_java11" } 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.371000 END RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.371000 REPORT RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765 Duration: 4118.98 ms Billed Duration: 4119 ms Memory Size: 512 MB Max Memory Used: 152 MB Init Duration: 1155.47 ms XRAY TraceId: 1-63dcd2d1-25f90b9d1c753a783547f4dd SegmentId: 3a028fee19b895cb Sampled: true
  8. 这是一个可以通过互联网访问的公有 API 端点。我们建议您在测试后删除该端点。

    sam delete

管理日志保留日期

删除函数时,日志组不会自动删除。为避免无限期存储日志,请删除该日志组,或配置保留期,之后 CloudWatch 自动删除日志。要设置日志保留日期,请将以下内容添加到您的 Amazon SAM 模板中:

Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: # Omitting other properties LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub "/aws/lambda/${HelloWorldFunction}" RetentionInDays: 7

使用 Lambda 控制台

调用 Lambda 函数后,您可以使用 Lambda 控制台查看日志输出。

如果可以在嵌入式代码编辑器中测试代码,则可以在执行结果中找到日志。使用控制台测试功能调用函数时,可以在详细信息部分找到日志输出

使用控制 CloudWatch 台

您可以使用亚马逊 CloudWatch 控制台查看所有 Lambda 函数调用的日志。

在 CloudWatch 控制台上查看日志
  1. 在 CloudWatch 控制台上打开日志组页面

  2. 为您的函数选择日志组 (/aws/lambda/ your-function-name)。

  3. 创建日志流。

每个日志流对应一个函数实例。日志流会在您更新 Lambda 函数以及创建更多实例来处理多个并发调用时显示。要查找特定调用的日志,建议您使用 Amazon X-Ray 检测函数。X-Ray 会在追踪中记录有关请求和日志流的详细信息。

如需使用将日志和跟踪与 X-Ray 相关联的示例应用程序,请参阅 Amazon Lambda 错误处理器示例应用程序

使用 Amazon Command Line Interface (Amazon CLI)

Amazon CLI 是一种开源工具,让您能够在命令行 Shell 中使用命令与 Amazon 服务进行交互。要完成本节中的步骤,您必须满足以下条件:

您可以通过 Amazon CLI,使用 --log-type 命令选项检索调用的日志。响应包含一个 LogResult 字段,其中包含多达 4KB 来自调用的 base64 编码日志。

例 检索日志 ID

以下示例说明如何从 LogResult 字段中检索名为 my-function 的函数的日志 ID

aws lambda invoke --function-name my-function out --log-type Tail

您应看到以下输出:

{ "StatusCode": 200, "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...", "ExecutedVersion": "$LATEST" }
例 解码日志

在同一命令提示符下,使用 base64 实用程序解码日志。以下示例说明如何为 my-function 检索 base64 编码的日志。

aws lambda invoke --function-name my-function out --log-type Tail \ --query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode

如果使用 cli-binary-format 版本 2,则 Amazon CLI 选项是必需的。要将其设为默认设置,请运行 aws configure set cli-binary-format raw-in-base64-out。有关更多信息,请参阅版本 2 的 Amazon Command Line Interface 用户指南中的 Amazon CLI 支持的全局命令行选项

您应看到以下输出:

START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST "AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib", END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Duration: 79.67 ms Billed Duration: 80 ms Memory Size: 128 MB Max Memory Used: 73 MB

base64 实用程序在 Linux、macOS 和 Ubuntu on Windows 上可用。macOS 用户可能需要使用 base64 -D

例 get-logs.sh 脚本

在同一命令提示符下,使用以下脚本下载最后五个日志事件。此脚本使用 sed 从输出文件中删除引号,并休眠 15 秒以等待日志可用。输出包括来自 Lambda 的响应,以及来自 get-log-events 命令的输出。

复制以下代码示例的内容并将其作为 get-logs.sh 保存在 Lambda 项目目录中。

如果使用 cli-binary-format 版本 2,则 Amazon CLI 选项是必需的。要将其设为默认设置,请运行 aws configure set cli-binary-format raw-in-base64-out。有关更多信息,请参阅版本 2 的 Amazon Command Line Interface 用户指南中的 Amazon CLI 支持的全局命令行选项

#!/bin/bash aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out sed -i'' -e 's/"//g' out sleep 15 aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
例 macOS 和 Linux(仅限)

在同一命令提示符下,macOS 和 Linux 用户可能需要运行以下命令以确保脚本可执行。

chmod -R 755 get-logs.sh
例 检索最后五个日志事件

在同一命令提示符下,运行以下脚本以获取最后五个日志事件。

./get-logs.sh

您应看到以下输出:

{ "StatusCode": 200, "ExecutedVersion": "$LATEST" } { "events": [ { "timestamp": 1559763003171, "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n", "ingestionTime": 1559763003309 }, { "timestamp": 1559763003173, "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...", "ingestionTime": 1559763018353 }, { "timestamp": 1559763003173, "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r \"key\": \"value\"\r}\n", "ingestionTime": 1559763018353 }, { "timestamp": 1559763003218, "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n", "ingestionTime": 1559763018353 }, { "timestamp": 1559763003218, "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n", "ingestionTime": 1559763018353 } ], "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795", "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080" }

删除日志

删除函数时,日志组不会自动删除。要避免无限期存储日志,请删除日志组,或配置一个保留期,在该保留期之后,日志将自动删除。

日志记录代码示例

本指南的 GitHub 存储库包括演示各种日志配置用法的示例应用程序。每个示例应用程序都包含用于轻松部署和清理的脚本、一个 Amazon SAM 模板和支持资源。

Java 中的 Lambda 应用程序示例
  • java17-examples:这是一种 Java 函数,演示如何使用 Java 记录来表示输入事件数据对象。

  • java-basic – 具有单元测试和变量日志记录配置的最小 Java 函数的集合。

  • java-events – Java 函数的集合,其中包含用于处理来自 Amazon API Gateway、Amazon SQS 和 Amazon Kinesis 等各种服务的事件的框架代码。这些函数使用最新版本的aws-lambda-java-events库(3.0.0 及更高版本)。这些示例不需要 Amazon 开发工具包作为依赖项。

  • s3-java – 此 Java 函数可处理来自 Amazon S3 的通知事件,并使用 Java 类库(JCL)从上传的图像文件创建缩略图。

  • 使用 API Gateway 调用 Lambda 函数 – Java 函数,用于扫描包含员工信息的 Amazon DynamoDB 表。然后,该函数使用 Amazon Simple Notification Service 向员工发送短信,祝贺他们工作周年纪念日快乐。此示例使用 API Gateway 调用函数。

java-basic 示例应用程序显示支持日志记录测试的最小日志记录配置。处理程序代码使用上下文对象提供的 LambdaLogger 记录器。对于测试,应用程序使用一个自定义 TestLogger 类,此类实现带有 Log4j2 记录器的 LambdaLogger 接口。它使用 SLF4J 作为 Facade 以与Amazon开发工具包兼容。从构建输出中排除日志记录库,以使部署程序包保持较小。