

# Concatenar mensagens de log de várias linhas ou de rastreamento de pilha do Amazon ECS
<a name="firelens-concatanate-multiline"></a>

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.](https://docs.fluentbit.io/manual/pipeline/filters/multiline-stacktrace) 

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](https://github.com/aws-samples/amazon-ecs-firelens-examples/tree/mainline/examples/fluent-bit/filter-multiline-partial-message-mode).

## Permissões obrigatórias do IAM
<a name="iam-permissions"></a>

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
<a name="determine-filter"></a>

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
<a name="parse-multiline-log"></a>

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.](https://docs.fluentbit.io/manual/pipeline/filters/multiline-stacktrace)

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ê
<a name="customer-parser"></a>

Neste exemplo, você concluirá as seguintes etapas: 

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

1. 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.

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

1. 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`. 

1. 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.

   1. Salve o arquivo como `parsers_multiline.conf`. 

1. 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](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/firelens-taskdef.html#firelens-taskdef-customconfig) 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. 

   1. Salve o arquivo como `extra.conf`. 

1. 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
      ```

   1. Salve o arquivo como `Dockerfile`.

1. 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.

   1. 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`.

1. 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. 

   1. 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` 

   1. 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`.

   1. 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.

   1. 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` 

1. Crie um arquivo de script do Python.

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

   1. 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.")
      ```

   1. Salve o arquivo `main.py`.

1. Crie um arquivo de log de exemplo. 

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

   1. 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...
      ```

   1. Salve o arquivo `test.log`.

1. 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"]
      ```

   1. Salve o arquivo `Dockerfile`.

1. 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.

   1. 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`.

1. 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. 

   1. 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` 

   1. 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`.

   1. 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`. 

1. 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).

   1. `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).

   1. `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.

   1. `us-east-1`

      Substitua a região, se necessário.

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

1. Abra o console em [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2).

1. 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.

1. Escolha a versão mais recente. 

1. Escolha **Implantar**, **Executar tarefa**. 

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

1. 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/](https://console.aws.amazon.com/cloudwatch/).

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

1. Escolha o grupo de logs `multiline-test/applicatio`. 

1. 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
<a name="fluent-bit-parser"></a>

Neste exemplo, você concluirá as seguintes etapas: 

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

1. 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.

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

1. 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`. 

1. 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](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/firelens-taskdef.html#firelens-taskdef-customconfig) 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
      ```

   1. Salve o arquivo como `extra.conf`. 

1. 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
      ```

   1. Salve o arquivo como `Dockerfile`.

1. 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.

   1. 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`.

1. 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. 

   1. 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` 

   1. 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`.

   1. 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.

   1. 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` 

1. Crie um arquivo de script do Python.

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

   1. 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.")
      ```

   1. Salve o arquivo `main.py`.

1. Crie um arquivo de log de exemplo. 

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

   1. 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
      ```

   1. Salve o arquivo `test.log`.

1. 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"]
      ```

   1. Salve o arquivo `Dockerfile`.

1. 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.

   1. 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`.

1. 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. 

   1. 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` 

   1. 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`.

   1. 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`. 

1. 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).

   1. `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).

   1. `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.

   1. `us-east-1`

      Substitua a região, se necessário.

1. 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` 

1. Abra o console em [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2).

1. 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.

1. Escolha a versão mais recente. 

1. Escolha **Implantar**, **Executar tarefa**. 

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

1. 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/](https://console.aws.amazon.com/cloudwatch/).

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

1. Escolha o grupo de logs `multiline-test/applicatio`. 

1. 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](https://docs.fluentbit.io/manual/pipeline/inputs/tail#multiline-support) em vez do Filtro.