连接多行或堆栈跟踪 Amazon ECS 日志消息
从 Amazon for Fluent Bit 版本 2.22.0 开始,包含多行筛选条件。多行筛选条件有助于连接原属于一个上下文但被分割为多个记录或日志行的日志消息。有关多行筛选条件的更多信息,请参阅 Fluent Bit 文档
拆分日志消息的常见示例有:
-
堆栈跟踪。
-
在多行上打印日志的应用程序。
-
因为比指定的运行时间最大缓冲区大小长而拆分的日志消息。您可以按照 GitHub 中的以下示例来连接被容器运行时拆分的日志消息:FireLens Example: Concatenate Partial/Split Container Logs
(FireLens 示例:连接部分/拆分的容器日志)。
所需的 IAM 权限
您拥有使用容器代理从 Amazon ECR 中提取容器镜像以及使用容器将日志路由到 CloudWatch Logs 的所需 IAM 权限。
对于这些权限,您还必须具有以下角色:
-
任务 IAM 角色。
-
任务执行 IAM 角色。
使用 JSON 策略编辑器创建策略
登录Amazon Web Services Management Console,然后通过以下网址打开 IAM 控制台:https://console.aws.amazon.com/iam/
。 -
在左侧的导航窗格中,选择策略。
如果这是您首次选择策略,则会显示欢迎访问托管式策略页面。选择开始使用。
-
在页面的顶部,选择创建策略。
-
在策略编辑器部分,选择 JSON 选项。
-
输入以下 JSON 策略文档:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:CreateLogGroup", "logs:PutLogEvents" ], "Resource": "*" }] }
-
选择下一步。
注意
您可以随时在可视化和 JSON 编辑器选项卡之间切换。不过,如果您进行更改或在可视化编辑器中选择下一步,IAM 可能会调整策略结构以针对可视化编辑器进行优化。有关更多信息,请参阅《IAM 用户指南》中的调整策略结构。
-
在查看并创建页面上,为您要创建的策略输入策略名称和描述(可选)。查看此策略中定义的权限以查看策略授予的权限。
-
选择创建策略可保存新策略。
确定何时使用多行日志设置
以下是您将在使用默认日志设置的 CloudWatch Logs 控制台中看到的示例日志片段。您可以查看以 log
开头的行,以确定是否需要多行筛选条件。当上下文相同时,您可以使用多行日志设置,在本例中,上下文为“com.myproject.model.MyProject”。
2022-09-20T15:47:56:595-05-00 {"container_id": "82ba37cada1d44d389b03e78caf74faa-EXAMPLE", "container_name": "example-app", "source=": "stdout", "log": ": " at com.myproject.modele.(MyProject.badMethod.java:22)",
{
"container_id": "82ba37cada1d44d389b03e78caf74faa-EXAMPLE",
"container_name: ": "example-app",
"source": "stdout",
"log": ": " at com.myproject.model.MyProject.badMethod(MyProject.java:22)",
"ecs_cluster": "default",
"ecs_task_arn": "arn:aws:region:123456789012:task/default/b23c940d29ed4714971cba72cEXAMPLE",
"ecs_task_definition": "firelense-example-multiline:3"
}
2022-09-20T15:47:56:595-05-00 {"container_id": "82ba37cada1d44d389b03e78caf74faa-EXAMPLE", "container_name": "example-app", "stdout", "log": ": " at com.myproject.modele.(MyProject.oneMoreMethod.java:18)",
{
"container_id": "82ba37cada1d44d389b03e78caf74faa-EXAMPLE",
"container_name: ": "example-app",
"source": "stdout",
"log": ": " at com.myproject.model.MyProject.oneMoreMethod(MyProject.java:18)",
"ecs_cluster": "default",
"ecs_task_arn": "arn:aws:region:123456789012:task/default/b23c940d29ed4714971cba72cEXAMPLE,
"ecs_task_definition": "firelense-example-multiline:3"
}
使用多行日志设置后,输出将与以下示例类似。
2022-09-20T15:47:56:595-05-00 {"container_id": "82ba37cada1d44d389b03e78caf74faa-EXAMPLE", "container_name": "example-app", "stdout",...
{
"container_id": "82ba37cada1d44d389b03e78caf74faa-EXAMPLE",
"container_name: ": "example-app",
"source": "stdout",
"log: "September 20, 2022 06:41:48 Exception in thread \"main\" java.lang.RuntimeException: Something has gone wrong, aborting!\n
at com.myproject.module.MyProject.badMethod(MyProject.java:22)\n at
at com.myproject.model.MyProject.oneMoreMethod(MyProject.java:18) com.myproject.module.MyProject.main(MyProject.java:6)",
"ecs_cluster": "default",
"ecs_task_arn": "arn:aws:region:123456789012:task/default/b23c940d29ed4714971cba72cEXAMPLE",
"ecs_task_definition": "firelense-example-multiline:2"
}
解析和连接选项
要解析日志并连接因换行符而被拆分的行,您可以使用这两个选项之一。
-
使用自己的解析器文件,该文件中包含用于解析和连接属于同一消息的行的规则。
-
使用 Fluent Bit 内置解析器。有关 Fluent Bit 内置解析器支持的语言的列表,请参阅 Fluent Bit 文档。
以下教程将引导您完成每个使用案例的步骤。这些步骤向您展示了如何连接多行并将日志发送到 Amazon CloudWatch。您可以为日志指定其他目标。
示例:使用您创建的解析器
在本示例中,您将完成以下步骤:
-
为 Fluent Bit 容器生成并上传镜像。
-
为运行、失败和生成多行堆栈跟踪的演示多行应用程序生成并上传镜像。
-
创建任务定义并运行任务。
-
查看日志以验证跨越多行的消息是否连接起来。
为 Fluent Bit 容器生成并上传镜像
此镜像将包括您在其中指定正则表达式的解析器文件和引用解析器文件的配置文件。
-
使用名称
FluentBitDockerImage
创建文件夹。 -
在文件夹内,创建解析器文件,其中包含用于解析日志和连接属于同一消息的行的规则。
-
将以下内容粘贴到解析器文件中:
[MULTILINE_PARSER] name multiline-regex-test type regex flush_timeout 1000 # # Regex rules for multiline parsing # --------------------------------- # # configuration hints: # # - first state always has the name: start_state # - every field in the rule must be inside double quotes # # rules | state name | regex pattern | next state # ------|---------------|-------------------------------------------- rule "start_state" "/(Dec \d+ \d+\:\d+\:\d+)(.*)/" "cont" rule "cont" "/^\s+at.*/" "cont"
自定义正则表达式模式时,我们建议您使用正则表达式编辑器来测试表达式。
-
将该文件保存为
parsers_multiline.conf
。
-
-
在
FluentBitDockerImage
文件夹中,创建引用您在上一步中创建的解析器文件的自定义配置文件。有关自定义配置文件的更多信息,请参阅《Amazon Elastic Container Service 开发人员指南》中的指定自定义配置文件
-
将以下内容粘贴到该文件中:
[SERVICE] flush 1 log_level info parsers_file /parsers_multiline.conf [FILTER] name multiline match * multiline.key_content log multiline.parser multiline-regex-test
注意
您必须使用解析器的绝对路径。
-
将该文件保存为
extra.conf
。
-
-
在
FluentBitDockerImage
文件夹中,使用 Fluent Bit 镜像以及您创建的解析器和配置文件创建 Dockerfile。-
将以下内容粘贴到该文件中:
FROM public.ecr.aws/aws-observability/aws-for-fluent-bit:latest ADD parsers_multiline.conf /parsers_multiline.conf ADD extra.conf /extra.conf
-
将该文件保存为
Dockerfile
。
-
-
使用 Dockerfile,构建一个包含解析器和自定义配置文件的自定义 Fluent Bit 镜像。
注意
您可以将解析器文件和配置文件放置在 Docker 镜像中的任何位置,但
/fluent-bit/etc/fluent-bit.conf
除外,因为 FireLens 使用这个文件路径。-
生成镜像:
docker build -t fluent-bit-multiline-image .
其中:
fluent-bit-multiline-image
是此示例中镜像的名称。 -
验证是否已正确创建镜像:
docker images —filter reference=fluent-bit-multiline-image
如果成功,输出将显示该镜像和
latest
标签。
-
-
将自定义 Fluent Bit 镜像上传到 Amazon Elastic Container Registry。
-
创建用于存储镜像的 Amazon ECR 存储库:
aws ecr create-repository --repository-name fluent-bit-multiline-repo --region us-east-1
其中:
fluent-bit-multiline-repo
是存储库的名称,us-east-1
是此示例中的区域。输出为您提供了新存储库的详细信息。
-
使用上一个输出中的
repositoryUri
值标记您的镜像:docker tag
fluent-bit-multiline-image
repositoryUri
例如:
docker tag fluent-bit-multiline-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo
-
运行 Docker 镜像以验证它是否正确运行:
docker images —filter reference=
repositoryUri
在输出中,存储库名称从 fluent-bit-multiline-repo 更改为
repositoryUri
。 -
通过运行
aws ecr get-login-password
命令并指定您要对其进行身份验证的注册表 ID 对 Amazon ECR 进行身份验证:aws ecr get-login-password | docker login --username AWS --password-stdin
registry ID
.dkr.ecr.region
.amazonaws.com例如:
ecr get-login-password | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com
此时会显示成功登录消息。
-
将镜像推送到 Amazon ECR:
docker push
registry ID
.dkr.ecr.region
.amazonaws.com/repository name
例如:
docker push xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo
-
为演示多行应用程序生成并上传镜像
此镜像将包括运行应用程序的 Python 脚本文件和示例日志文件。
运行任务时,应用程序会模拟运行,然后失败并创建堆栈跟踪。
-
创建名为
multiline-app
的文件夹:mkdir multiline-app
-
创建 Python 脚本文件。
-
在
multiline-app
文件夹中,创建一个文件并将其命名为main.py
。 -
将以下内容粘贴到该文件中:
import os import time file1 = open('/test.log', 'r') Lines = file1.readlines() count = 0 for i in range(10): print("app running normally...") time.sleep(1) # Strips the newline character for line in Lines: count += 1 print(line.rstrip()) print(count) print("app terminated.")
-
保存
main.py
文件。
-
-
创建示例日志文件。
-
在
multiline-app
文件夹中,创建一个文件并将其命名为test.log
。 -
将以下内容粘贴到该文件中:
single line... Dec 14 06:41:08 Exception in thread "main" java.lang.RuntimeException: Something has gone wrong, aborting! at com.myproject.module.MyProject.badMethod(MyProject.java:22) at com.myproject.module.MyProject.oneMoreMethod(MyProject.java:18) at com.myproject.module.MyProject.anotherMethod(MyProject.java:14) at com.myproject.module.MyProject.someMethod(MyProject.java:10) at com.myproject.module.MyProject.main(MyProject.java:6) another line...
-
保存
test.log
文件。
-
-
在
multiline-app
文件夹中,创建 Dockerfile。-
将以下内容粘贴到该文件中:
FROM public.ecr.aws/amazonlinux/amazonlinux:latest ADD test.log /test.log RUN yum upgrade -y && yum install -y python3 WORKDIR /usr/local/bin COPY main.py . CMD ["python3", "main.py"]
-
保存
Dockerfile
文件。
-
-
使用 Dockerfile 生成镜像。
-
生成镜像:
docker build -t multiline-app-image .
其中:
multiline-app-image
是此示例中镜像的名称。 -
验证是否已正确创建镜像:
docker images —filter reference=multiline-app-image
如果成功,输出将显示该镜像和
latest
标签。
-
-
将镜像上载到 Amazon Elastic Container 注册表。
-
创建用于存储镜像的 Amazon ECR 存储库:
aws ecr create-repository --repository-name multiline-app-repo --region us-east-1
其中:
multiline-app-repo
是存储库的名称,us-east-1
是此示例中的区域。输出为您提供了新存储库的详细信息。记下
repositoryUri
值,您将需要在后续步骤中使用该值。 -
使用上一个输出中的
repositoryUri
值标记您的镜像:docker tag
multiline-app-image
repositoryUri
例如:
docker tag multiline-app-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/multiline-app-repo
-
运行 Docker 镜像以验证它是否正确运行:
docker images —filter reference=
repositoryUri
在输出中,存储库名称从
multiline-app-repo
更改为repositoryUri
值。 -
将镜像推送到 Amazon ECR:
docker push
aws_account_id
.dkr.ecr.region
.amazonaws.com/repository name
例如:
docker push
xxxxxxxxxxxx
.dkr.ecr.us-east-1
.amazonaws.com/multiline-app-repo
-
创建任务定义并运行任务
-
使用文件名
multiline-task-definition.json
创建任务定义文件。 -
将以下内容粘贴到
multiline-task-definition.json
文件中:{ "family": "firelens-example-multiline", "taskRoleArn": "
task role ARN
, "executionRoleArn": "execution role ARN
", "containerDefinitions": [ { "essential": true, "image": "aws_account_id
.dkr.ecr.us-east-1
.amazonaws.com/fluent-bit-multiline-image:latest", "name": "log_router", "firelensConfiguration": { "type": "fluentbit", "options": { "config-file-type": "file", "config-file-value": "/extra.conf" } }, "memoryReservation": 50 }, { "essential": true, "image": "aws_account_id
.dkr.ecr.us-east-1
.amazonaws.com/multiline-app-image:latest", "name": "app", "logConfiguration": { "logDriver": "awsfirelens", "options": { "Name": "cloudwatch_logs", "region": "us-east-1
", "log_group_name": "multiline-test/application", "auto_create_group": "true", "log_stream_prefix": "multiline-" } }, "memoryReservation": 100 } ], "requiresCompatibilities": ["FARGATE"], "networkMode": "awsvpc", "cpu": "256", "memory": "512" }替换
multiline-task-definition.json
任务定义中的以下内容:-
task role ARN
要查找任务角色 ARN,请转到 IAM 控制台。选择 Roles(角色),然后查找您创建的
ecs-task-role-for-firelens
任务角色。选择角色,然后复制 Summary(摘要)部分中显示的 ARN。 -
execution role ARN
要查找执行角色 ARN,请转到 IAM 控制台。选择 Roles(角色),然后查找
ecsTaskExecutionRole
角色。选择角色,然后复制 Summary(摘要)部分中显示的 ARN。 -
aws_account_id
要查找您的
aws_account_id
,登录 Amazon Web Services Management Console。在右上角选择您的用户名,然后复制您的账户 ID。 -
us-east-1
如有必要,请更换区域。
-
-
注册任务定义文件:
aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region
region
-
在导航窗格中,选择 Task Definitions(任务定义),然后选择
firelens-example-multiline
系列,因为我们已在上面任务定义的第一行中将任务定义注册到这个系列。 -
选择最新版本。
-
选择部署、运行任务。
-
在运行任务页面上,对于集群,选择集群,然后在联网下的子网中,选择任务的可用子网。
-
选择创建。
验证 Amazon CloudWatch 中的多行日志消息是否已连接
访问 https://console.aws.amazon.com/cloudwatch/
打开 CloudWatch 控制台。 -
从导航窗格中,展开 Logs(日志)并选择 Log groups(日志组)。
-
选择
multiline-test/applicatio
日志组。 -
选择日志。查看消息。与解析器文件中的规则匹配的行将串联起来,并显示为单条消息。
以下日志片段显示了在单个 Java 堆栈跟踪事件中连接的行:
{ "container_id": "xxxxxx", "container_name": "app", "source": "stdout", "log": "Dec 14 06:41:08 Exception in thread \"main\" java.lang.RuntimeException: Something has gone wrong, aborting!\n at com.myproject.module.MyProject.badMethod(MyProject.java:22)\n at com.myproject.module.MyProject.oneMoreMethod(MyProject.java:18)\n at com.myproject.module.MyProject.anotherMethod(MyProject.java:14)\n at com.myproject.module.MyProject.someMethod(MyProject.java:10)\n at com.myproject.module.MyProject.main(MyProject.java:6)", "ecs_cluster": "default", "ecs_task_arn": "arn:aws:ecs:us-east-1:xxxxxxxxxxxx:task/default/xxxxxx", "ecs_task_definition": "firelens-example-multiline:2" }
以下日志代码段显示了如果您运行的是未配置为连接多行日志消息的 Amazon ECS 容器,则如何只用一行显示相同的消息。
{ "log": "Dec 14 06:41:08 Exception in thread \"main\" java.lang.RuntimeException: Something has gone wrong, aborting!", "container_id": "xxxxxx-xxxxxx", "container_name": "app", "source": "stdout", "ecs_cluster": "default", "ecs_task_arn": "arn:aws:ecs:us-east-1:xxxxxxxxxxxx:task/default/xxxxxx", "ecs_task_definition": "firelens-example-multiline:3" }
示例:使用 Fluent Bit 内置解析器
在本示例中,您将完成以下步骤:
-
为 Fluent Bit 容器生成并上传镜像。
-
为运行、失败和生成多行堆栈跟踪的演示多行应用程序生成并上传镜像。
-
创建任务定义并运行任务。
-
查看日志以验证跨越多行的消息是否连接起来。
为 Fluent Bit 容器生成并上传镜像
此镜像将包含一个引用 Fluent Bit 解析器的配置文件。
-
使用名称
FluentBitDockerImage
创建文件夹。 -
在
FluentBitDockerImage
文件夹中,创建引用 Fluent Bit 内置解析器文件的自定义配置文件。有关自定义配置文件的更多信息,请参阅《Amazon Elastic Container Service 开发人员指南》中的指定自定义配置文件
-
将以下内容粘贴到该文件中:
[FILTER] name multiline match * multiline.key_content log multiline.parser go
-
将该文件保存为
extra.conf
。
-
-
在
FluentBitDockerImage
文件夹中,使用 Fluent Bit 镜像以及您创建的解析器和配置文件创建 Dockerfile。-
将以下内容粘贴到该文件中:
FROM public.ecr.aws/aws-observability/aws-for-fluent-bit:latest ADD extra.conf /extra.conf
-
将该文件保存为
Dockerfile
。
-
-
使用 Dockerfile,构建一个包含自定义配置文件的自定义 Fluent Bit 镜像。
注意
您可以将配置文件放置在 Docker 镜像中的任何位置,但
/fluent-bit/etc/fluent-bit.conf
除外,因为 FireLens 使用这个文件路径。-
生成镜像:
docker build -t fluent-bit-multiline-image .
其中:
fluent-bit-multiline-image
是此示例中镜像的名称。 -
验证是否已正确创建镜像:
docker images —filter reference=fluent-bit-multiline-image
如果成功,输出将显示该镜像和
latest
标签。
-
-
将自定义 Fluent Bit 镜像上传到 Amazon Elastic Container Registry。
-
创建用于存储镜像的 Amazon ECR 存储库:
aws ecr create-repository --repository-name fluent-bit-multiline-repo --region us-east-1
其中:
fluent-bit-multiline-repo
是存储库的名称,us-east-1
是此示例中的区域。输出为您提供了新存储库的详细信息。
-
使用上一个输出中的
repositoryUri
值标记您的镜像:docker tag
fluent-bit-multiline-image
repositoryUri
例如:
docker tag fluent-bit-multiline-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo
-
运行 Docker 镜像以验证它是否正确运行:
docker images —filter reference=
repositoryUri
在输出中,存储库名称从 fluent-bit-multiline-repo 更改为
repositoryUri
。 -
通过运行
aws ecr get-login-password
命令并指定您要对其进行身份验证的注册表 ID 对 Amazon ECR 进行身份验证:aws ecr get-login-password | docker login --username AWS --password-stdin
registry ID
.dkr.ecr.region
.amazonaws.com例如:
ecr get-login-password | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com
此时会显示成功登录消息。
-
将镜像推送到 Amazon ECR:
docker push
registry ID
.dkr.ecr.region
.amazonaws.com/repository name
例如:
docker push xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo
-
为演示多行应用程序生成并上传镜像
此镜像将包括运行应用程序的 Python 脚本文件和示例日志文件。
-
创建名为
multiline-app
的文件夹:mkdir multiline-app
-
创建 Python 脚本文件。
-
在
multiline-app
文件夹中,创建一个文件并将其命名为main.py
。 -
将以下内容粘贴到该文件中:
import os import time file1 = open('/test.log', 'r') Lines = file1.readlines() count = 0 for i in range(10): print("app running normally...") time.sleep(1) # Strips the newline character for line in Lines: count += 1 print(line.rstrip()) print(count) print("app terminated.")
-
保存
main.py
文件。
-
-
创建示例日志文件。
-
在
multiline-app
文件夹中,创建一个文件并将其命名为test.log
。 -
将以下内容粘贴到该文件中:
panic: my panic goroutine 4 [running]: panic(0x45cb40, 0x47ad70) /usr/local/go/src/runtime/panic.go:542 +0x46c fp=0xc42003f7b8 sp=0xc42003f710 pc=0x422f7c main.main.func1(0xc420024120) foo.go:6 +0x39 fp=0xc42003f7d8 sp=0xc42003f7b8 pc=0x451339 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003f7e0 sp=0xc42003f7d8 pc=0x44b4d1 created by main.main foo.go:5 +0x58 goroutine 1 [chan receive]: runtime.gopark(0x4739b8, 0xc420024178, 0x46fcd7, 0xc, 0xc420028e17, 0x3) /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc420053e30 sp=0xc420053e00 pc=0x42503c runtime.goparkunlock(0xc420024178, 0x46fcd7, 0xc, 0x1000f010040c217, 0x3) /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc420053e70 sp=0xc420053e30 pc=0x42512e runtime.chanrecv(0xc420024120, 0x0, 0xc420053f01, 0x4512d8) /usr/local/go/src/runtime/chan.go:506 +0x304 fp=0xc420053f20 sp=0xc420053e70 pc=0x4046b4 runtime.chanrecv1(0xc420024120, 0x0) /usr/local/go/src/runtime/chan.go:388 +0x2b fp=0xc420053f50 sp=0xc420053f20 pc=0x40439b main.main() foo.go:9 +0x6f fp=0xc420053f80 sp=0xc420053f50 pc=0x4512ef runtime.main() /usr/local/go/src/runtime/proc.go:185 +0x20d fp=0xc420053fe0 sp=0xc420053f80 pc=0x424bad runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc420053fe8 sp=0xc420053fe0 pc=0x44b4d1 goroutine 2 [force gc (idle)]: runtime.gopark(0x4739b8, 0x4ad720, 0x47001e, 0xf, 0x14, 0x1) /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc42003e768 sp=0xc42003e738 pc=0x42503c runtime.goparkunlock(0x4ad720, 0x47001e, 0xf, 0xc420000114, 0x1) /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc42003e7a8 sp=0xc42003e768 pc=0x42512e runtime.forcegchelper() /usr/local/go/src/runtime/proc.go:238 +0xcc fp=0xc42003e7e0 sp=0xc42003e7a8 pc=0x424e5c runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003e7e8 sp=0xc42003e7e0 pc=0x44b4d1 created by runtime.init.4 /usr/local/go/src/runtime/proc.go:227 +0x35 goroutine 3 [GC sweep wait]: runtime.gopark(0x4739b8, 0x4ad7e0, 0x46fdd2, 0xd, 0x419914, 0x1) /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc42003ef60 sp=0xc42003ef30 pc=0x42503c runtime.goparkunlock(0x4ad7e0, 0x46fdd2, 0xd, 0x14, 0x1) /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc42003efa0 sp=0xc42003ef60 pc=0x42512e runtime.bgsweep(0xc42001e150) /usr/local/go/src/runtime/mgcsweep.go:52 +0xa3 fp=0xc42003efd8 sp=0xc42003efa0 pc=0x419973 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003efe0 sp=0xc42003efd8 pc=0x44b4d1 created by runtime.gcenable /usr/local/go/src/runtime/mgc.go:216 +0x58 one more line, no multiline
-
保存
test.log
文件。
-
-
在
multiline-app
文件夹中,创建 Dockerfile。-
将以下内容粘贴到该文件中:
FROM public.ecr.aws/amazonlinux/amazonlinux:latest ADD test.log /test.log RUN yum upgrade -y && yum install -y python3 WORKDIR /usr/local/bin COPY main.py . CMD ["python3", "main.py"]
-
保存
Dockerfile
文件。
-
-
使用 Dockerfile 生成镜像。
-
生成镜像:
docker build -t multiline-app-image .
其中:
multiline-app-image
是此示例中镜像的名称。 -
验证是否已正确创建镜像:
docker images —filter reference=multiline-app-image
如果成功,输出将显示该镜像和
latest
标签。
-
-
将镜像上载到 Amazon Elastic Container 注册表。
-
创建用于存储镜像的 Amazon ECR 存储库:
aws ecr create-repository --repository-name multiline-app-repo --region us-east-1
其中:
multiline-app-repo
是存储库的名称,us-east-1
是此示例中的区域。输出为您提供了新存储库的详细信息。记下
repositoryUri
值,您将需要在后续步骤中使用该值。 -
使用上一个输出中的
repositoryUri
值标记您的镜像:docker tag
multiline-app-image
repositoryUri
例如:
docker tag multiline-app-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/multiline-app-repo
-
运行 Docker 镜像以验证它是否正确运行:
docker images —filter reference=
repositoryUri
在输出中,存储库名称从
multiline-app-repo
更改为repositoryUri
值。 -
将镜像推送到 Amazon ECR:
docker push
aws_account_id
.dkr.ecr.region
.amazonaws.com/repository name
例如:
docker push
xxxxxxxxxxxx
.dkr.ecr.us-east-1
.amazonaws.com/multiline-app-repo
-
创建任务定义并运行任务
-
使用文件名
multiline-task-definition.json
创建任务定义文件。 -
将以下内容粘贴到
multiline-task-definition.json
文件中:{ "family": "firelens-example-multiline", "taskRoleArn": "
task role ARN
, "executionRoleArn": "execution role ARN
", "containerDefinitions": [ { "essential": true, "image": "aws_account_id
.dkr.ecr.us-east-1
.amazonaws.com/fluent-bit-multiline-image:latest", "name": "log_router", "firelensConfiguration": { "type": "fluentbit", "options": { "config-file-type": "file", "config-file-value": "/extra.conf" } }, "memoryReservation": 50 }, { "essential": true, "image": "aws_account_id
.dkr.ecr.us-east-1
.amazonaws.com/multiline-app-image:latest", "name": "app", "logConfiguration": { "logDriver": "awsfirelens", "options": { "Name": "cloudwatch_logs", "region": "us-east-1
", "log_group_name": "multiline-test/application", "auto_create_group": "true", "log_stream_prefix": "multiline-" } }, "memoryReservation": 100 } ], "requiresCompatibilities": ["FARGATE"], "networkMode": "awsvpc", "cpu": "256", "memory": "512" }替换
multiline-task-definition.json
任务定义中的以下内容:-
task role ARN
要查找任务角色 ARN,请转到 IAM 控制台。选择 Roles(角色),然后查找您创建的
ecs-task-role-for-firelens
任务角色。选择角色,然后复制 Summary(摘要)部分中显示的 ARN。 -
execution role ARN
要查找执行角色 ARN,请转到 IAM 控制台。选择 Roles(角色),然后查找
ecsTaskExecutionRole
角色。选择角色,然后复制 Summary(摘要)部分中显示的 ARN。 -
aws_account_id
要查找您的
aws_account_id
,登录 Amazon Web Services Management Console。在右上角选择您的用户名,然后复制您的账户 ID。 -
us-east-1
如有必要,请更换区域。
-
-
注册任务定义文件:
aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region us-east-1
-
在导航窗格中,选择 Task Definitions(任务定义),然后选择
firelens-example-multiline
系列,因为我们已在上面任务定义的第一行中将任务定义注册到这个系列。 -
选择最新版本。
-
选择部署、运行任务。
-
在运行任务页面上,对于集群,选择集群,然后在联网下的子网中,选择任务的可用子网。
-
选择创建。
验证 Amazon CloudWatch 中的多行日志消息是否已连接
访问 https://console.aws.amazon.com/cloudwatch/
打开 CloudWatch 控制台。 -
从导航窗格中,展开 Logs(日志)并选择 Log groups(日志组)。
-
选择
multiline-test/applicatio
日志组。 -
选择日志并查看消息。与解析器文件中的规则匹配的行将串联起来,并显示为单条消息。
以下日志代码段显示了在单个事件中连接的 Go 堆栈跟踪:
{ "log": "panic: my panic\n\ngoroutine 4 [running]:\npanic(0x45cb40, 0x47ad70)\n /usr/local/go/src/runtime/panic.go:542 +0x46c fp=0xc42003f7b8 sp=0xc42003f710 pc=0x422f7c\nmain.main.func1(0xc420024120)\n foo.go:6 +0x39 fp=0xc42003f7d8 sp=0xc42003f7b8 pc=0x451339\nruntime.goexit()\n /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003f7e0 sp=0xc42003f7d8 pc=0x44b4d1\ncreated by main.main\n foo.go:5 +0x58\n\ngoroutine 1 [chan receive]:\nruntime.gopark(0x4739b8, 0xc420024178, 0x46fcd7, 0xc, 0xc420028e17, 0x3)\n /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc420053e30 sp=0xc420053e00 pc=0x42503c\nruntime.goparkunlock(0xc420024178, 0x46fcd7, 0xc, 0x1000f010040c217, 0x3)\n /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc420053e70 sp=0xc420053e30 pc=0x42512e\nruntime.chanrecv(0xc420024120, 0x0, 0xc420053f01, 0x4512d8)\n /usr/local/go/src/runtime/chan.go:506 +0x304 fp=0xc420053f20 sp=0xc420053e70 pc=0x4046b4\nruntime.chanrecv1(0xc420024120, 0x0)\n /usr/local/go/src/runtime/chan.go:388 +0x2b fp=0xc420053f50 sp=0xc420053f20 pc=0x40439b\nmain.main()\n foo.go:9 +0x6f fp=0xc420053f80 sp=0xc420053f50 pc=0x4512ef\nruntime.main()\n /usr/local/go/src/runtime/proc.go:185 +0x20d fp=0xc420053fe0 sp=0xc420053f80 pc=0x424bad\nruntime.goexit()\n /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc420053fe8 sp=0xc420053fe0 pc=0x44b4d1\n\ngoroutine 2 [force gc (idle)]:\nruntime.gopark(0x4739b8, 0x4ad720, 0x47001e, 0xf, 0x14, 0x1)\n /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc42003e768 sp=0xc42003e738 pc=0x42503c\nruntime.goparkunlock(0x4ad720, 0x47001e, 0xf, 0xc420000114, 0x1)\n /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc42003e7a8 sp=0xc42003e768 pc=0x42512e\nruntime.forcegchelper()\n /usr/local/go/src/runtime/proc.go:238 +0xcc fp=0xc42003e7e0 sp=0xc42003e7a8 pc=0x424e5c\nruntime.goexit()\n /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003e7e8 sp=0xc42003e7e0 pc=0x44b4d1\ncreated by runtime.init.4\n /usr/local/go/src/runtime/proc.go:227 +0x35\n\ngoroutine 3 [GC sweep wait]:\nruntime.gopark(0x4739b8, 0x4ad7e0, 0x46fdd2, 0xd, 0x419914, 0x1)\n /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc42003ef60 sp=0xc42003ef30 pc=0x42503c\nruntime.goparkunlock(0x4ad7e0, 0x46fdd2, 0xd, 0x14, 0x1)\n /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc42003efa0 sp=0xc42003ef60 pc=0x42512e\nruntime.bgsweep(0xc42001e150)\n /usr/local/go/src/runtime/mgcsweep.go:52 +0xa3 fp=0xc42003efd8 sp=0xc42003efa0 pc=0x419973\nruntime.goexit()\n /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003efe0 sp=0xc42003efd8 pc=0x44b4d1\ncreated by runtime.gcenable\n /usr/local/go/src/runtime/mgc.go:216 +0x58", "container_id": "xxxxxx-xxxxxx", "container_name": "app", "source": "stdout", "ecs_cluster": "default", "ecs_task_arn": "arn:aws:ecs:us-east-1:xxxxxxxxxxxx:task/default/xxxxxx", "ecs_task_definition": "firelens-example-multiline:2" }
以下日志代码段显示了如果您运行的是未配置为连接多行日志消息的 ECS 容器,如何显示相同的事件。日志字段包含单行。
{ "log": "panic: my panic", "container_id": "xxxxxx-xxxxxx", "container_name": "app", "source": "stdout", "ecs_cluster": "default", "ecs_task_arn": "arn:aws:ecs:us-east-1:xxxxxxxxxxxx:task/default/xxxxxx", "ecs_task_definition": "firelens-example-multiline:3"
注意
如果您的日志转到日志文件而不是标准输出,我们建议在结尾输入插件multiline.parser
和 multiline.key_content
配置参数,而不是筛选条件。