複数行またはスタックトレースの Amazon ECS ログメッセージの連結
Fluent Bit バージョン 2.22.0 以降の AWS では、複数行フィルターが含まれています。複数行フィルターは、もともと 1 つのコンテキストに属していても、複数のレコードまたはログ行に分割されたログメッセージを連結するのに役立ちます。複数行フィルターの詳細については、「Fluent Bit documentation
以下は、分割されたログメッセージの一般的な例です。
-
スタックトレース
-
複数の行にログを出力するアプリケーション。
-
指定されたランタイムの最大バッファサイズを超過した場合に、ログメッセージが分割されます GitHub の例、「FireLens Example: Concatenate Partial/Split Container Logs
」(FireLens の例:部分/分割コンテナログの連結) に従い、コンテナランタイムによって分割されたログメッセージを連結することができます。
必要な IAM 許可
コンテナエージェントが Amazon ECR からコンテナイメージをプルし、コンテナがログを CloudWatch Logs にルーティングするために必要なIAM 許可を持っていることを確認する必要があります。
これらの許可には、次のロールが必要です。
-
タスク IAM ロール
-
タスク実行 IAM ロールです。
JSON ポリシーエディタでポリシーを作成するには
AWS 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": "*" }] }
-
[次へ] をクリックします。
注記
いつでも [Visual] と [JSON] エディタオプションを切り替えることができます。ただし、[Visual] エディタで [次] に変更または選択した場合、IAM はポリシーを再構成して visual エディタに合わせて最適化することがあります。詳細については、「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"
}
オプションを解析して連結する
ログを解析し、改行によって分割された行を連結するには、以下の 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 イメージをビルドします。
注記
このファイルパスが FireLens によって使用される
/fluent-bit/etc/fluent-bit.conf
の場合を除いて、Dockerイメージの任意の場所にパーサーファイルと構成ファイルを配置できます。-
イメージを構築します:
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
はこの例のリージョンです。出力には、新しいリポジトリの詳細が表示されます。
-
前のステップの
docker tag
の値でfluent-bit-multiline-image
repositoryUri
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 コンテナレジストリにアップロードします。
-
イメージを保存する Amazon ECR リポジトリを作成します:
aws ecr create-repository --repository-name multiline-app-repo --region us-east-1
どこ:
multiline-app-repo
は、リポジトリの名前です。us-east-1
はこの例のリージョンです。出力には、新しいリポジトリの詳細が表示されます。次のステップで必要になるため、
repositoryUri
の値を書きとめておきます。 -
前のステップの
docker tag
の値でmultiline-app-image
repositoryUri
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 コンソールに移動します。ロールを選択し、作成した
ecs-task-role-for-firelens
タスクロールを検索します。ロールを選択し、概要セクションに表示される ARN をコピーします。 -
execution role ARN
実行ロールの ARN を検索するには、IAM コンソールに移動します。ロールを選択し、
ecsTaskExecutionRole
ロールを検索します。ロールを選択し、概要セクションに表示される ARN をコピーします。 -
aws_account_id
aws_account_id
を検索するには、AWS Management Console にログインします。右上のユーザー名を選択し、アカウント ID をコピーします。 -
us-east-1
必要に応じてリージョンを置換します。
-
-
タスク定義ファイルを登録します:
aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region
region
コンソール (https://console.aws.amazon.com/ecs/v2
) を開きます。 -
ナビゲーションペインで、[タスク定義] を選択し、上記のタスク定義の最初の行でタスク定義をこのファミリに登録したため、
firelens-example-multiline
ファミリを選択します。 -
最新バージョンを選択します。
-
[デプロイ]、[タスクを実行] を選択します。
-
[タスクを実行] ページの [クラスター] でクラスターを選択し、[ネットワーク] の [サブネット] で、タスクに使用できるサブネットを選択します。
-
[Create] (作成) を選択します。
Amazon CloudWatch の複数行のログメッセージが連結されて表示されることを確認する
CloudWatch コンソール (https://console.aws.amazon.com/cloudwatch/
) を開きます。 -
ナビゲーションペインで、[Logs (ログ)] を展開して、[Log groups (ロググループ)] を選択します。
-
multiline-test/applicatio
ロググループを選択します。 -
ログを選択します。メッセージを表示します。パーサーファイル内のルールに一致する行は連結され、1 つのメッセージとして表示されます。
次のログスニペットは、単一の 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 コンテナを実行する場合に、同じメッセージが 1 行でどのように表示されるかを示しています。
{ "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 イメージをビルドします。
注記
このファイルパスが FireLens によって使用される
/fluent-bit/etc/fluent-bit.conf
の場合を除いて、Docker イメージの任意の場所に設定ファイルを配置できます。-
イメージを構築します:
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
はこの例のリージョンです。出力には、新しいリポジトリの詳細が表示されます。
-
前のステップの
docker tag
の値でfluent-bit-multiline-image
repositoryUri
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 コンテナレジストリにアップロードします。
-
イメージを保存する Amazon ECR リポジトリを作成します:
aws ecr create-repository --repository-name multiline-app-repo --region us-east-1
どこ:
multiline-app-repo
は、リポジトリの名前です。us-east-1
はこの例のリージョンです。出力には、新しいリポジトリの詳細が表示されます。次のステップで必要になるため、
repositoryUri
の値を書きとめておきます。 -
前のステップの
docker tag
の値でmultiline-app-image
repositoryUri
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 コンソールに移動します。ロールを選択し、作成した
ecs-task-role-for-firelens
タスクロールを検索します。ロールを選択し、概要セクションに表示される ARN をコピーします。 -
execution role ARN
実行ロールの ARN を検索するには、IAM コンソールに移動します。ロールを選択し、
ecsTaskExecutionRole
ロールを検索します。ロールを選択し、概要セクションに表示される ARN をコピーします。 -
aws_account_id
aws_account_id
を検索するには、AWS Management Console にログインします。右上のユーザー名を選択し、アカウント ID をコピーします。 -
us-east-1
必要に応じてリージョンを置換します。
-
-
タスク定義ファイルを登録します:
aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region us-east-1
コンソール (https://console.aws.amazon.com/ecs/v2
) を開きます。 -
ナビゲーションペインで、[タスク定義] を選択し、上記のタスク定義の最初の行でタスク定義をこのファミリに登録したため、
firelens-example-multiline
ファミリを選択します。 -
最新バージョンを選択します。
-
[デプロイ]、[タスクを実行] を選択します。
-
[タスクを実行] ページの [クラスター] でクラスターを選択し、[ネットワーク] の [サブネット] で、タスクに使用できるサブネットを選択します。
-
[Create] (作成) を選択します。
Amazon CloudWatch の複数行のログメッセージが連結されて表示されることを確認する
CloudWatch コンソール (https://console.aws.amazon.com/cloudwatch/
) を開きます。 -
ナビゲーションペインで、[Logs (ログ)] を展開して、[Log groups (ロググループ)] を選択します。
-
multiline-test/applicatio
ロググループを選択します。 -
ログを選択し、メッセージを表示します。パーサーファイル内のルールに一致する行は連結され、1 つのメッセージとして表示されます。
次のログスニペットは、単一の 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 コンテナを実行する場合に、同じイベントがどのように表示されるかを示しています。ログフィールドには 1 行が含まれます。
{ "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"
注記
ログが標準出力ではなくログファイルに移動する場合は、フィルターではなく Tail 入力プラグインmultiline.parser
および multiline.key_content
構成パラメーターを指定することをお勧めします。