Concatenar mensagens de log de várias linhas ou de rastreamento de pilha do Amazon ECS - Amazon Elastic Container Service

Concatenar mensagens de log de várias linhas ou de rastreamento de pilha do Amazon ECS

Começando com AWS para o Fluent Bit versão 2.22.0, um filtro de várias linhas está incluído. O filtro de várias linhas ajuda a concatenar mensagens de log que pertencem originalmente a um contexto, mas foram divididas em vários registros ou linhas de log. Para obter mais informações sobre o filtro multilinha, consulte a documentação do Fluent Bit.

Exemplos comuns de mensagens de log dividido incluem:

  • Rastreamentos de pilhas.

  • Aplicações que imprimem logs em várias linhas.

  • Mensagens de log que foram divididas porque eram maiores que o tamanho máximo do buffer do runtime especificado. É possível concatenar mensagens de log divididas pelo runtime do contêiner seguindo o exemplo no GitHub: Exemplo do FireLens: Concatenar logs de contêiners parciais/divididos.

Permissões obrigatórias do IAM

Você deve primeiro ter as permissões do IAM necessárias para que o agente de contêiner extraia as imagens de contêiner do Amazon ECR e para que o contêiner encaminhe logs ao CloudWatch Logs.

Para essas permissões, você precisa ter as seguintes funções:

  • Uma função do IAM de tarefa.

  • Um perfil do IAM de execução de tarefa.

Você precisa das seguintes permissões:

  • logs:CreateLogStream

  • logs:CreateLogGroup

  • logs:PutLogEvents

Determinar quando usar configuração de logs multilinha

Veja a seguir um exemplo de trechos de log exibidos no console do CloudWatch Logs com a configuração de log padrão. É possível ver a linha que começa com log para determinar se precisa do filtro multilinha. Quando o contexto é o mesmo, você pode usar a configuração de log de várias linhas. Neste exemplo, o contexto é "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" }

Depois de usar a configuração de log multilinha, a saída será semelhante ao exemplo abaixo.

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" }

Opções de análise e concatenação

Para analisar logs e concatenar linhas divididas devido a novas linhas, use qualquer uma destas duas opções.

  • Use seu próprio arquivo do analisador que contém as regras para analisar e concatenar linhas que pertencem à mesma mensagem.

  • Usar um analisador integrado do Fluent Bit. Para obter uma lista de idiomas compatíveis com os analisadores integrados Fluent Bit, consulte a documentação do Fluent Bit.

O tutorial a seguir orientará você sobre as etapas de cada caso de uso. As etapas mostram como concatenar várias linhas e enviar os logs para o Amazon CloudWatch. É possível especificar um destino diferente para os logs.

Exemplo: use um analisador criado por você

Neste exemplo, você concluirá as seguintes etapas:

  1. Criar e carregar a imagem para um contêiner Fluent Bit.

  2. Criar e carregar a imagem para uma aplicação de várias linhas de demonstração que executa, falha e gera um rastreamento de pilha de várias linhas.

  3. Criar a definição de tarefa e executar a tarefa.

  4. Exibir os logs para verificar se as mensagens que abrangem várias linhas aparecem concatenadas.

Criar e carregar a imagem para um contêiner Fluent Bit

Essa imagem incluirá o arquivo do analisador no qual você especifica a expressão regular e um arquivo de configuração que faz referência ao arquivo do analisador.

  1. Criar uma pasta com o nome FluentBitDockerImage.

  2. Na pasta, crie um arquivo do analisador que contém as regras para analisar o log e concatenar linhas que pertencem à mesma mensagem.

    1. Cole o seguinte conteúdo no arquivo do analisador:

      [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"

      À medida que você personaliza seu padrão de regex, recomendamos que você use um editor de expressões regulares para testar a expressão.

    2. Salve o arquivo como parsers_multiline.conf.

  3. Dentro da pasta FluentBitDockerImage, crie um arquivo de configuração personalizado que faça referência ao arquivo do analisador que você criou na etapa anterior.

    Para obter mais informações sobre o arquivo de configuração personalizado, consulte Especificar um arquivo de configuração personalizado no Guia do desenvolvedor do Amazon Elastic Container Service

    1. Cole o seguinte conteúdo no arquivo:

      [SERVICE] flush 1 log_level info parsers_file /parsers_multiline.conf [FILTER] name multiline match * multiline.key_content log multiline.parser multiline-regex-test
      nota

      Você deve usar o caminho absoluto do analisador.

    2. Salve o arquivo como extra.conf.

  4. Dentro da pasta FluentBitDockerImage, crie o Dockerfile com a imagem Fluent Bit e os arquivos do analisador e de configuração que você criou.

    1. Cole o seguinte conteúdo no arquivo:

      FROM public.ecr.aws/aws-observability/aws-for-fluent-bit:latest ADD parsers_multiline.conf /parsers_multiline.conf ADD extra.conf /extra.conf
    2. Salve o arquivo como Dockerfile.

  5. Usando o Dockerfile, crie uma imagem Fluent Bit personalizada com os arquivos de configuração personalizados e do analisador incluídos.

    nota

    É possível colocar o arquivo do analisador e o arquivo de configuração em qualquer lugar da imagem do Docker, exceto em /fluent-bit/etc/fluent-bit.conf, pois esse caminho de arquivo é usado pelo FireLens.

    1. Crie a imagem: docker build -t fluent-bit-multiline-image.

      Onde: fluent-bit-multiline-image é o nome da imagem neste exemplo.

    2. Verifique se a imagem foi criada corretamente: docker images —filter reference=fluent-bit-multiline-image

      Se tiver êxito, a saída mostrará a imagem e a etiqueta latest.

  6. Carregue a imagem personalizada do Fluent Bit no Amazon Elastic Container Registry.

    1. Crie um repositório do Amazon ECR para armazenar a imagem: aws ecr create-repository --repository-name fluent-bit-multiline-repo --region us-east-1

      Onde: fluent-bit-multiline-repo é o nome do repositório e us-east-1 é a região neste exemplo.

      A saída fornece os detalhes do novo repositório.

    2. Marque sua imagem com o valor repositoryUri da saída anterior: docker tag fluent-bit-multiline-image repositoryUri

      Exemplo: docker tag fluent-bit-multiline-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo

    3. Execute a imagem do Docker para verificar se ela é executada corretamente: docker images —filter reference=repositoryUri

      Na saída, o nome do repositório muda de fluent-bit-multiline-repo para o repositoryUri.

    4. Autentique-se no Amazon ECR executando o comando aws ecr get-login-password e especificando o ID de registro para o qual deseja fazer a autenticação: aws ecr get-login-password | docker login --username AWS --password-stdin registry ID.dkr.ecr.region.amazonaws.com

      Exemplo: ecr get-login-password | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com

      Uma mensagem de login com êxito é exibida.

    5. Envie a imagem para o Amazon ECR: docker push registry ID.dkr.ecr.region.amazonaws.com/repository name

      Exemplo: docker push xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo

Crie e carregue a imagem para uma aplicação de várias linhas de demonstração

Essa imagem incluirá um arquivo de script Python que executa a aplicação e um arquivo de log de amostra.

Quando você executa a tarefa, a aplicação simula execuções, depois falha e cria um rastreamento de pilha.

  1. Crie uma pasta denominada multiline-app: mkdir multiline-app

  2. Crie um arquivo de script do Python.

    1. Na pasta multiline-app, crie um arquivo de texto e denomine-o main.py.

    2. Cole o seguinte conteúdo no arquivo:

      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.")
    3. Salve o arquivo main.py.

  3. Crie um arquivo de log de exemplo.

    1. Na pasta multiline-app, crie um arquivo de texto e denomine-o test.log.

    2. Cole o seguinte conteúdo no arquivo:

      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...
    3. Salve o arquivo test.log.

  4. Dentro da pasta multiline-app, crie o Dockerfile.

    1. Cole o seguinte conteúdo no arquivo:

      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"]
    2. Salve o arquivo Dockerfile.

  5. Usando o Dockerfile, crie uma imagem.

    1. Crie a imagem: docker build -t multiline-app-image

      Onde: multiline-app-image é o nome da imagem neste exemplo.

    2. Verifique se a imagem foi criada corretamente: docker images —filter reference=multiline-app-image

      Se tiver êxito, a saída mostrará a imagem e a etiqueta latest.

  6. Carregue a imagem no Amazon Elastic Container Registry.

    1. Crie um repositório do Amazon ECR para armazenar a imagem: aws ecr create-repository --repository-name multiline-app-repo --region us-east-1

      Onde: multiline-app-repo é o nome do repositório e us-east-1 é a região neste exemplo.

      A saída fornece os detalhes do novo repositório. Anote o valor do repositoryUri, pois ele será necessário na próxima etapa.

    2. Marque sua imagem com o valor repositoryUri da saída anterior: docker tag multiline-app-image repositoryUri

      Exemplo: docker tag multiline-app-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/multiline-app-repo

    3. Execute a imagem do Docker para verificar se ela é executada corretamente: docker images —filter reference=repositoryUri

      Na saída, o nome do repositório muda de multiline-app-repo para o valor repositoryUri.

    4. Envie a imagem para o Amazon ECR: docker push aws_account_id.dkr.ecr.region.amazonaws.com/repository name

      Exemplo: docker push xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/multiline-app-repo

Crie a definição da tarefa e execute a tarefa
  1. Crie um arquivo de definição de tarefa com o nome de arquivo multiline-task-definition.json.

  2. Cole o seguinte conteúdo no arquivo 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" }

    Substitua o seguinte na definição de tarefa multiline-task-definition.json:

    1. task role ARN

      Para encontrar o ARN da função de tarefa, acesse o console do IAM. Escolha Roles (Funções) e encontre a função de tarefa ecs-task-role-for-firelens que você criou. Escolha a função e copie o ARN que consta na seção Summary (Resumo).

    2. execution role ARN

      Para encontrar o ARN da função de execução, acesse o console do IAM. Selecione Roles (Funções) e localize a função ecsTaskExecutionRole. Escolha a função e copie o ARN que consta na seção Summary (Resumo).

    3. aws_account_id

      Para encontrar seu aws_account_id, faça login no Console de gerenciamento da AWS. Escolha seu nome de usuário no canto superior direito e copie o ID da conta.

    4. us-east-1

      Substitua a região, se necessário.

  3. Registre o arquivo de definição de tarefa: aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region region

  4. Abra o console em https://console.aws.amazon.com/ecs/v2.

  5. No painel de navegação, selecione Task Definitions (Definições de tarefa) e, em seguida, escolha a família firelens-example-multiline, pois registramos a definição de tarefa para essa família na primeira linha da definição de tarefa acima.

  6. Escolha a versão mais recente.

  7. Escolha Implantar, Executar tarefa.

  8. Na página Executar tarefa, para Cluster, escolha o cluster e, em seguida, em Rede, para Sub-redes, escolha as sub-redes disponíveis para sua tarefa.

  9. Escolha Criar.

Verifique se as mensagens de log de várias linhas no Amazon CloudWatch parecem concatenadas
  1. Abra o console do CloudWatch, em https://console.aws.amazon.com/cloudwatch/.

  2. No painel de navegação, expanda Logs e escolha Log groups (Grupos de log).

  3. Escolha o grupo de logs multiline-test/applicatio.

  4. Escolha o log. Vejas as mensagens. As linhas que correspondem às regras no arquivo do analisador são concatenadas e aparecem como uma única mensagem.

    O trecho de log a seguir mostra linhas concatenadas em um único evento de rastreamento de pilha 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" }

    O trecho de log a seguir mostra como a mesma mensagem é exibida com apenas uma única linha se você executar um contêiner do Amazon ECS que não esteja configurado para concatenar mensagens de log multinha.

    { "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" }

Exemplo: use um analisador integrado Fluent Bit

Neste exemplo, você concluirá as seguintes etapas:

  1. Criar e carregar a imagem para um contêiner Fluent Bit.

  2. Criar e carregar a imagem para uma aplicação de várias linhas de demonstração que executa, falha e gera um rastreamento de pilha de várias linhas.

  3. Criar a definição de tarefa e executar a tarefa.

  4. Exibir os logs para verificar se as mensagens que abrangem várias linhas aparecem concatenadas.

Criar e carregar a imagem para um contêiner Fluent Bit

Essa imagem incluirá um arquivo de configuração que faz referência ao analisador Fluent Bit.

  1. Criar uma pasta com o nome FluentBitDockerImage.

  2. Dentro da pasta FluentBitDockerImage, crie um arquivo de configuração personalizado que faça referência ao arquivo do analisador integrado Fluent Bit.

    Para obter mais informações sobre o arquivo de configuração personalizado, consulte Especificar um arquivo de configuração personalizado no Guia do desenvolvedor do Amazon Elastic Container Service

    1. Cole o seguinte conteúdo no arquivo:

      [FILTER] name multiline match * multiline.key_content log multiline.parser go
    2. Salve o arquivo como extra.conf.

  3. Dentro da pasta FluentBitDockerImage, crie o Dockerfile com a imagem Fluent Bit e os arquivos do analisador e de configuração que você criou.

    1. Cole o seguinte conteúdo no arquivo:

      FROM public.ecr.aws/aws-observability/aws-for-fluent-bit:latest ADD extra.conf /extra.conf
    2. Salve o arquivo como Dockerfile.

  4. Usando o Dockerfile, crie uma imagem Fluent Bit personalizada com o arquivo de configuração personalizado incluído.

    nota

    É possível colocar o arquivo de configuração em qualquer lugar da imagem do Docker, exceto em /fluent-bit/etc/fluent-bit.conf, pois esse caminho de arquivo é usado pelo FireLens.

    1. Crie a imagem: docker build -t fluent-bit-multiline-image.

      Onde: fluent-bit-multiline-image é o nome da imagem neste exemplo.

    2. Verifique se a imagem foi criada corretamente: docker images —filter reference=fluent-bit-multiline-image

      Se tiver êxito, a saída mostrará a imagem e a etiqueta latest.

  5. Carregue a imagem personalizada do Fluent Bit no Amazon Elastic Container Registry.

    1. Crie um repositório do Amazon ECR para armazenar a imagem: aws ecr create-repository --repository-name fluent-bit-multiline-repo --region us-east-1

      Onde: fluent-bit-multiline-repo é o nome do repositório e us-east-1 é a região neste exemplo.

      A saída fornece os detalhes do novo repositório.

    2. Marque sua imagem com o valor repositoryUri da saída anterior: docker tag fluent-bit-multiline-image repositoryUri

      Exemplo: docker tag fluent-bit-multiline-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo

    3. Execute a imagem do Docker para verificar se ela é executada corretamente: docker images —filter reference=repositoryUri

      Na saída, o nome do repositório muda de fluent-bit-multiline-repo para o repositoryUri.

    4. Autentique-se no Amazon ECR executando o comando aws ecr get-login-password e especificando o ID de registro para o qual deseja fazer a autenticação: aws ecr get-login-password | docker login --username AWS --password-stdin registry ID.dkr.ecr.region.amazonaws.com

      Exemplo: ecr get-login-password | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com

      Uma mensagem de login com êxito é exibida.

    5. Envie a imagem para o Amazon ECR: docker push registry ID.dkr.ecr.region.amazonaws.com/repository name

      Exemplo: docker push xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/fluent-bit-multiline-repo

Crie e carregue a imagem para uma aplicação de várias linhas de demonstração

Essa imagem incluirá um arquivo de script Python que executa a aplicação e um arquivo de log de amostra.

  1. Crie uma pasta denominada multiline-app: mkdir multiline-app

  2. Crie um arquivo de script do Python.

    1. Na pasta multiline-app, crie um arquivo de texto e denomine-o main.py.

    2. Cole o seguinte conteúdo no arquivo:

      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.")
    3. Salve o arquivo main.py.

  3. Crie um arquivo de log de exemplo.

    1. Na pasta multiline-app, crie um arquivo de texto e denomine-o test.log.

    2. Cole o seguinte conteúdo no arquivo:

      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
    3. Salve o arquivo test.log.

  4. Dentro da pasta multiline-app, crie o Dockerfile.

    1. Cole o seguinte conteúdo no arquivo:

      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"]
    2. Salve o arquivo Dockerfile.

  5. Usando o Dockerfile, crie uma imagem.

    1. Crie a imagem: docker build -t multiline-app-image

      Onde: multiline-app-image é o nome da imagem neste exemplo.

    2. Verifique se a imagem foi criada corretamente: docker images —filter reference=multiline-app-image

      Se tiver êxito, a saída mostrará a imagem e a etiqueta latest.

  6. Carregue a imagem no Amazon Elastic Container Registry.

    1. Crie um repositório do Amazon ECR para armazenar a imagem: aws ecr create-repository --repository-name multiline-app-repo --region us-east-1

      Onde: multiline-app-repo é o nome do repositório e us-east-1 é a região neste exemplo.

      A saída fornece os detalhes do novo repositório. Anote o valor do repositoryUri, pois ele será necessário na próxima etapa.

    2. Marque sua imagem com o valor repositoryUri da saída anterior: docker tag multiline-app-image repositoryUri

      Exemplo: docker tag multiline-app-image xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/multiline-app-repo

    3. Execute a imagem do Docker para verificar se ela é executada corretamente: docker images —filter reference=repositoryUri

      Na saída, o nome do repositório muda de multiline-app-repo para o valor repositoryUri.

    4. Envie a imagem para o Amazon ECR: docker push aws_account_id.dkr.ecr.region.amazonaws.com/repository name

      Exemplo: docker push xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/multiline-app-repo

Crie a definição da tarefa e execute a tarefa
  1. Crie um arquivo de definição de tarefa com o nome de arquivo multiline-task-definition.json.

  2. Cole o seguinte conteúdo no arquivo 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" }

    Substitua o seguinte na definição de tarefa multiline-task-definition.json:

    1. task role ARN

      Para encontrar o ARN da função de tarefa, acesse o console do IAM. Escolha Roles (Funções) e encontre a função de tarefa ecs-task-role-for-firelens que você criou. Escolha a função e copie o ARN que consta na seção Summary (Resumo).

    2. execution role ARN

      Para encontrar o ARN da função de execução, acesse o console do IAM. Selecione Roles (Funções) e localize a função ecsTaskExecutionRole. Escolha a função e copie o ARN que consta na seção Summary (Resumo).

    3. aws_account_id

      Para encontrar seu aws_account_id, faça login no Console de gerenciamento da AWS. Escolha seu nome de usuário no canto superior direito e copie o ID da conta.

    4. us-east-1

      Substitua a região, se necessário.

  3. Registre o arquivo de definição de tarefa: aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region us-east-1

  4. Abra o console em https://console.aws.amazon.com/ecs/v2.

  5. No painel de navegação, selecione Task Definitions (Definições de tarefa) e, em seguida, escolha a família firelens-example-multiline, pois registramos a definição de tarefa para essa família na primeira linha da definição de tarefa acima.

  6. Escolha a versão mais recente.

  7. Escolha Implantar, Executar tarefa.

  8. Na página Executar tarefa, para Cluster, escolha o cluster e, em seguida, em Rede, para Sub-redes, escolha as sub-redes disponíveis para sua tarefa.

  9. Escolha Criar.

Verifique se as mensagens de log de várias linhas no Amazon CloudWatch parecem concatenadas
  1. Abra o console do CloudWatch, em https://console.aws.amazon.com/cloudwatch/.

  2. No painel de navegação, expanda Logs e escolha Log groups (Grupos de log).

  3. Escolha o grupo de logs multiline-test/applicatio.

  4. Escolha o log e veja as mensagens. As linhas que correspondem às regras no arquivo do analisador são concatenadas e aparecem como uma única mensagem.

    O trecho de log a seguir mostra um rastreamento de pilha Go concatenado em um único evento:

    { "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" }

    O trecho de log a seguir mostra como o mesmo evento aparece se você executar um contêiner ECS que não esteja configurado para concatenar mensagens de log de várias linhas. O campo de log contém uma única linha.

    { "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"
nota

Se seus registros forem para arquivos de log em vez da saída padrão, recomendamos especificar os parâmetros de configuração multiline.parser e multiline.key_content no Plug-in de entrada final em vez do Filtro.