

# Concatenación de mensajes de registro de Amazon ECS de seguimiento de pila o de varias líneas
<a name="firelens-concatanate-multiline"></a>

Empezando por AWS para Fluent Bit versión 2.22.0, se incluye un filtro multilínea. El filtro multilínea ayuda a concatenar mensajes de registro que originalmente pertenecen a un contexto, pero que se dividieron en varios registros o líneas de registro. Para obtener más información acerca del filtro multilínea, consulte la [documentación de Fluent Bit.](https://docs.fluentbit.io/manual/pipeline/filters/multiline-stacktrace) 

Los siguientes son algunos ejemplos comunes de mensajes de registro divididos:
+ Seguimiento de pila. 
+ Aplicaciones que imprimen registros en varias líneas. 
+ Mensajes de registro que se dividieron porque eran más largos que el tamaño máximo de búfer en tiempo de ejecución especificado. Puede concatenar mensajes de registro divididos por el tiempo de ejecución del contenedor siguiendo el ejemplo de GitHub: [Ejemplo de FireLens: Concatenar registros de contenedores parciales/divididos](https://github.com/aws-samples/amazon-ecs-firelens-examples/tree/mainline/examples/fluent-bit/filter-multiline-partial-message-mode).

## Permisos de IAM necesarios
<a name="iam-permissions"></a>

Dispone de los permisos de IAM necesarios para que el agente de contenedor extraiga las imágenes de contenedor de Amazon ECR y para que el contenedor dirija los registros a Registros de CloudWatch.

Para estos permisos, debe tener los siguientes roles: 
+ Un rol de IAM de tareas. 
+ Un rol de IAM de ejecución de tareas. 

También necesita los siguientes permisos:
+ `logs:CreateLogStream`
+ `logs:CreateLogGroup`
+ `logs:PutLogEvents`

## Determine cuándo utilizar la configuración de registro multilínea
<a name="determine-filter"></a>

En los siguientes ejemplos, se muestran fragmentos de registro de ejemplo que se ven en la consola de Registros de CloudWatch con la configuración de registro predeterminada. Puede fijarse en la línea que empieza por `log` para determinar si necesita el filtro multilínea. Cuando el contexto es el mismo, puede utilizar la configuración de registro de varias líneas. En este ejemplo, el contexto es “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"
     }
```

Después de utilizar la configuración del registro multilínea, la salida tendrá un aspecto similar al del ejemplo siguiente. 

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

## Opciones de análisis y concatenación
<a name="parse-multiline-log"></a>

Para analizar registros y concatenar líneas que se dividieron debido a las líneas nuevas, puede utilizar cualquiera de estas dos opciones.
+ Utilice su propio archivo analizador que contenga las reglas para analizar y concatenar líneas que pertenecen al mismo mensaje.
+ Utilizar un analizador integrado de Fluent Bit. Para ver una lista de los idiomas admitidos en los analizadores integrados de Fluent Bit, consulte la [documentación de Fluent Bit.](https://docs.fluentbit.io/manual/pipeline/filters/multiline-stacktrace)

El siguiente tutorial lo guiará por los pasos de cada caso de uso. En los pasos, se muestra cómo concatenar varias líneas y enviar los registros a Amazon CloudWatch. Puede especificar otro destino para los registros.

### Ejemplo: utilizar un analizador que cree
<a name="customer-parser"></a>

En este ejemplo, completará los siguientes pasos: 

1. Cree y cargue la imagen en un contenedor de Fluent Bit. 

1. Cree y cargue la imagen de una aplicación multilínea de demostración que se ejecuta, falla y genera un seguimiento de pila multilínea.

1. Cree la definición de tarea y ejecute la tarea. 

1. Consulte los registros para verificar que los mensajes que abarcan varias líneas aparezcan concatenados. 

**Crear y cargar la imagen en un contenedor de Fluent Bit**

En esta imagen, se incluirá el archivo analizador en el que se especifica la expresión regular y un archivo de configuración que hace referencia al archivo analizador. 

1. Cree una carpeta con el nombre `FluentBitDockerImage`. 

1. Dentro de la carpeta, cree un archivo analizador que contenga las reglas para analizar el registro y concatenar líneas que pertenecen al mismo mensaje.

   1. Pegue los siguientes contenidos en el archivo analizador:

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

      A medida que personaliza el patrón de expresiones regulares, recomendamos utilizar un editor de expresiones regulares para probar la expresión.

   1. Guarde el archivo como `parsers_multiline.conf`. 

1. En la carpeta `FluentBitDockerImage`, cree un archivo de configuración personalizado que haga referencia al archivo analizador que creó en el paso anterior.

   Para obtener más información sobre el archivo de configuración personalizado, consulte [Especificación de un archivo de configuración personalizado](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/firelens-taskdef.html#firelens-taskdef-customconfig) en la *Guía para desarrolladores de Amazon Elastic Container Service* 

   1. Pegue los siguientes contenidos en el archivo:

      ```
      [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**  
Debe utilizar la ruta absoluta del analizador. 

   1. Guarde el archivo como `extra.conf`. 

1. En la carpeta `FluentBitDockerImage`, cree el archivo de Dockerfile con la imagen de Fluent Bit, el analizador y los archivos de configuración que ha creado.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      FROM public.ecr.aws/aws-observability/aws-for-fluent-bit:latest
      
      ADD parsers_multiline.conf /parsers_multiline.conf
      ADD extra.conf /extra.conf
      ```

   1. Guarde el archivo como `Dockerfile`.

1. Con el archivo de Dockerfile, cree una imagen de Fluent Bit personalizada con el analizador y los archivos de configuración personalizados incluidos.
**nota**  
Puede colocar el archivo analizador y el archivo de configuración en cualquier parte de la imagen de Docker, excepto en `/fluent-bit/etc/fluent-bit.conf`, ya que FireLens utiliza esta ruta de archivo.

   1. Cree la imagen: `docker build -t fluent-bit-multiline-image.`

      Donde: `fluent-bit-multiline-image` es el nombre de la imagen de este ejemplo.

   1. Compruebe que la imagen se haya creado correctamente: `docker images —filter reference=fluent-bit-multiline-image` 

      Si la acción se realiza correctamente, el resultado muestra la imagen y la etiqueta `latest`.

1. Cargue la imagen de Fluent Bit personalizada en Amazon Elastic Container Registry.

   1. Cree un repositorio de Amazon ECR para almacenar la imagen: `aws ecr create-repository --repository-name fluent-bit-multiline-repo --region us-east-1`

      Donde: `fluent-bit-multiline-repo` es el nombre del repositorio y `us-east-1` es la región de este ejemplo. 

      El resultado proporciona los detalles del nuevo repositorio. 

   1. Etiquete la imagen con el valor `repositoryUri` del resultado anterior: `docker tag fluent-bit-multiline-image repositoryUri` 

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

   1. Ejecute la imagen de Docker para verificar que se haya ejecutado correctamente: `docker images —filter reference=repositoryUri`

      En el resultado, el nombre del repositorio cambia de fluent-bit-multiline-repo a `repositoryUri`.

   1. Autentíquese en Amazon ECR ejecutando el comando `aws ecr get-login-password` y especifique el ID del registro en el que desea efectuar la autenticación: `aws ecr get-login-password | docker login --username AWS --password-stdin registry ID.dkr.ecr.region.amazonaws.com` 

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

      Aparece un mensaje de inicio de sesión correcto.

   1. Envíe la imagen a Amazon ECR: `docker push registry ID.dkr.ecr.region.amazonaws.com/repository name` 

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

**Crear y cargar la imagen para una aplicación multilínea de demostración**

En esta imagen, se incluirá un archivo de script de Python que ejecuta la aplicación y un archivo de registro de ejemplo. 

Cuando ejecuta la tarea, la aplicación simula las ejecuciones y, a continuación, falla y crea un seguimiento de pila. 

1. Cree una carpeta denominada `multiline-app`: `mkdir multiline-app` 

1. Cree un archivo de script de Python.

   1. En la carpeta `multiline-app`, cree un archivo y asígnele el nombre `main.py`.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      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. Guarde el archivo `main.py`.

1. Cree un archivo de registro de ejemplo. 

   1. En la carpeta `multiline-app`, cree un archivo y asígnele el nombre `test.log`.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      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. Guarde el archivo `test.log`.

1. En la carpeta `multiline-app`, cree el archivo de Dockerfile.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      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. Guarde el archivo `Dockerfile`.

1. Con el archivo de Dockerfile, cree una imagen.

   1. Cree la imagen: `docker build -t multiline-app-image `

      Donde: `multiline-app-image` es el nombre de la imagen de este ejemplo.

   1. Compruebe que la imagen se haya creado correctamente: `docker images —filter reference=multiline-app-image` 

      Si la acción se realiza correctamente, el resultado muestra la imagen y la etiqueta `latest`.

1. Cargue la imagen en Amazon Elastic Container Registry.

   1. Cree un repositorio de Amazon ECR para almacenar la imagen: `aws ecr create-repository --repository-name multiline-app-repo --region us-east-1`

      Donde: `multiline-app-repo` es el nombre del repositorio y `us-east-1` es la región de este ejemplo. 

      El resultado proporciona los detalles del nuevo repositorio. Tome nota del valor `repositoryUri`, ya que lo necesitará en los siguientes pasos. 

   1. Etiquete la imagen con el valor `repositoryUri` del resultado anterior: `docker tag multiline-app-image repositoryUri` 

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

   1. Ejecute la imagen de Docker para verificar que se haya ejecutado correctamente: `docker images —filter reference=repositoryUri`

      En el resultado, el nombre del repositorio cambia de `multiline-app-repo` al valor `repositoryUri`.

   1. Envíe la imagen a Amazon ECR: `docker push aws_account_id.dkr.ecr.region.amazonaws.com/repository name` 

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

**Crear la definición de tarea y ejecutar la tarea**

1. Cree un archivo de definición de tarea con el nombre de archivo `multiline-task-definition.json`. 

1. Pegue los siguientes contenidos en el archivo `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"
   }
   ```

   Sustituya lo siguiente en la definición de tarea `multiline-task-definition.json`:

   1. `task role ARN`

      Para encontrar el ARN del rol de tarea, vaya a la consola de IAM. Elija **Roles** y busque el rol de tarea `ecs-task-role-for-firelens` que ha creado. Elija el rol y copie el **ARN** que aparece en la sección **Summary** (Resumen).

   1. `execution role ARN`

      Para encontrar el ARN del rol de ejecución, vaya a la consola de IAM. Elija **Roles** y busque el rol `ecsTaskExecutionRole`. Elija el rol y copie el **ARN** que aparece en la sección **Summary** (Resumen).

   1. `aws_account_id`

      Para encontrar su `aws_account_id`, inicie sesión en la Consola de administración de AWS. Elija su nombre de usuario en la parte superior derecha y copie su ID de cuenta.

   1. `us-east-1`

      Sustituya la región si es necesario.

1. Registre el archivo de definición de tarea: `aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region region` 

1. Abra la consola en [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2).

1. En el panel de navegación, elija **Task Definitions** (Definiciones de tarea) y, a continuación, seleccione la familia `firelens-example-multiline` porque hemos registrado la definición de tarea en esta familia en la primera línea de la definición de tarea anterior.

1. Elija la versión más reciente. 

1. Elija **Implementar** y **Ejecutar tarea**. 

1. En la página **Ejecutar tarea**, en **Clúster**, elija el clúster y, a continuación, en **Redes**, para **Subredes**, elija las subredes disponibles para la tarea. 

1. Seleccione **Crear**. 

**Verificar que los mensajes de registro multilínea en Amazon CloudWatch aparezcan concatenados**

1. Abra la consola de CloudWatch en [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. En el panel de navegación, amplíe **Logs** (Registros) y elija **Log groups** (Grupos de registros). 

1. Elija el grupo de registros `multiline-test/applicatio`. 

1. Elija el registro. Vea los mensajes. Las líneas que coinciden con las reglas del archivo analizador se concatenan y aparecen como un solo mensaje. 

   En el siguiente fragmento de registro, se muestran las líneas concatenadas en un único evento de seguimiento de pila 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"
   }
   ```

   El siguiente fragmento de registro muestra cómo aparece el mismo mensaje con una sola línea si se ejecuta un contenedor de Amazon ECS que no está configurado para concatenar mensajes de registro de varias líneas. 

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

### Ejemplo: utilizar un analizador integrado de Fluent Bit
<a name="fluent-bit-parser"></a>

En este ejemplo, completará los siguientes pasos: 

1. Cree y cargue la imagen en un contenedor de Fluent Bit. 

1. Cree y cargue la imagen de una aplicación multilínea de demostración que se ejecuta, falla y genera un seguimiento de pila multilínea.

1. Cree la definición de tarea y ejecute la tarea. 

1. Consulte los registros para verificar que los mensajes que abarcan varias líneas aparezcan concatenados. 

**Crear y cargar la imagen en un contenedor de Fluent Bit**

En esta imagen, se incluirá un archivo de configuración que hace referencia al analizador de Fluent Bit. 

1. Cree una carpeta con el nombre `FluentBitDockerImage`. 

1. En la carpeta `FluentBitDockerImage`, cree un archivo de configuración personalizado que haga referencia al archivo analizador integrado de Fluent Bit.

   Para obtener más información sobre el archivo de configuración personalizado, consulte [Especificación de un archivo de configuración personalizado](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/firelens-taskdef.html#firelens-taskdef-customconfig) en la *Guía para desarrolladores de Amazon Elastic Container Service* 

   1. Pegue los siguientes contenidos en el archivo:

      ```
      [FILTER]
          name                  multiline
          match                 *
          multiline.key_content log
          multiline.parser      go
      ```

   1. Guarde el archivo como `extra.conf`. 

1. En la carpeta `FluentBitDockerImage`, cree el archivo de Dockerfile con la imagen de Fluent Bit, el analizador y los archivos de configuración que ha creado.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      FROM public.ecr.aws/aws-observability/aws-for-fluent-bit:latest
      ADD extra.conf /extra.conf
      ```

   1. Guarde el archivo como `Dockerfile`.

1. Con el archivo de Dockerfile, cree una imagen de Fluent Bit personalizada con el archivo de configuración personalizado incluido.
**nota**  
Puede colocar el archivo de configuración en cualquier parte de la imagen de Docker, excepto en `/fluent-bit/etc/fluent-bit.conf`, ya que FireLens utiliza esta ruta de archivo.

   1. Cree la imagen: `docker build -t fluent-bit-multiline-image.`

      Donde: `fluent-bit-multiline-image` es el nombre de la imagen de este ejemplo.

   1. Compruebe que la imagen se haya creado correctamente: `docker images —filter reference=fluent-bit-multiline-image` 

      Si la acción se realiza correctamente, el resultado muestra la imagen y la etiqueta `latest`.

1. Cargue la imagen de Fluent Bit personalizada en Amazon Elastic Container Registry.

   1. Cree un repositorio de Amazon ECR para almacenar la imagen: `aws ecr create-repository --repository-name fluent-bit-multiline-repo --region us-east-1`

      Donde: `fluent-bit-multiline-repo` es el nombre del repositorio y `us-east-1` es la región de este ejemplo. 

      El resultado proporciona los detalles del nuevo repositorio. 

   1. Etiquete la imagen con el valor `repositoryUri` del resultado anterior: `docker tag fluent-bit-multiline-image repositoryUri` 

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

   1. Ejecute la imagen de Docker para verificar que se haya ejecutado correctamente: `docker images —filter reference=repositoryUri`

      En el resultado, el nombre del repositorio cambia de fluent-bit-multiline-repo a `repositoryUri`.

   1. Autentíquese en Amazon ECR ejecutando el comando `aws ecr get-login-password` y especifique el ID del registro en el que desea efectuar la autenticación: `aws ecr get-login-password | docker login --username AWS --password-stdin registry ID.dkr.ecr.region.amazonaws.com` 

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

      Aparece un mensaje de inicio de sesión correcto.

   1. Envíe la imagen a Amazon ECR: `docker push registry ID.dkr.ecr.region.amazonaws.com/repository name` 

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

**Crear y cargar la imagen para una aplicación multilínea de demostración**

En esta imagen, se incluirá un archivo de script de Python que ejecuta la aplicación y un archivo de registro de ejemplo. 

1. Cree una carpeta denominada `multiline-app`: `mkdir multiline-app` 

1. Cree un archivo de script de Python.

   1. En la carpeta `multiline-app`, cree un archivo y asígnele el nombre `main.py`.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      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. Guarde el archivo `main.py`.

1. Cree un archivo de registro de ejemplo. 

   1. En la carpeta `multiline-app`, cree un archivo y asígnele el nombre `test.log`.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      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. Guarde el archivo `test.log`.

1. En la carpeta `multiline-app`, cree el archivo de Dockerfile.

   1. Pegue los siguientes contenidos en el archivo:

      ```
      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. Guarde el archivo `Dockerfile`.

1. Con el archivo de Dockerfile, cree una imagen.

   1. Cree la imagen: `docker build -t multiline-app-image `

      Donde: `multiline-app-image` es el nombre de la imagen de este ejemplo.

   1. Compruebe que la imagen se haya creado correctamente: `docker images —filter reference=multiline-app-image` 

      Si la acción se realiza correctamente, el resultado muestra la imagen y la etiqueta `latest`.

1. Cargue la imagen en Amazon Elastic Container Registry.

   1. Cree un repositorio de Amazon ECR para almacenar la imagen: `aws ecr create-repository --repository-name multiline-app-repo --region us-east-1`

      Donde: `multiline-app-repo` es el nombre del repositorio y `us-east-1` es la región de este ejemplo. 

      El resultado proporciona los detalles del nuevo repositorio. Tome nota del valor `repositoryUri`, ya que lo necesitará en los siguientes pasos. 

   1. Etiquete la imagen con el valor `repositoryUri` del resultado anterior: `docker tag multiline-app-image repositoryUri` 

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

   1. Ejecute la imagen de Docker para verificar que se haya ejecutado correctamente: `docker images —filter reference=repositoryUri`

      En el resultado, el nombre del repositorio cambia de `multiline-app-repo` al valor `repositoryUri`.

   1. Envíe la imagen a Amazon ECR: `docker push aws_account_id.dkr.ecr.region.amazonaws.com/repository name` 

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

**Crear la definición de tarea y ejecutar la tarea**

1. Cree un archivo de definición de tarea con el nombre de archivo `multiline-task-definition.json`. 

1. Pegue los siguientes contenidos en el archivo `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"
   }
   ```

   Sustituya lo siguiente en la definición de tarea `multiline-task-definition.json`:

   1. `task role ARN`

      Para encontrar el ARN del rol de tarea, vaya a la consola de IAM. Elija **Roles** y busque el rol de tarea `ecs-task-role-for-firelens` que ha creado. Elija el rol y copie el **ARN** que aparece en la sección **Summary** (Resumen).

   1. `execution role ARN`

      Para encontrar el ARN del rol de ejecución, vaya a la consola de IAM. Elija **Roles** y busque el rol `ecsTaskExecutionRole`. Elija el rol y copie el **ARN** que aparece en la sección **Summary** (Resumen).

   1. `aws_account_id`

      Para encontrar su `aws_account_id`, inicie sesión en la Consola de administración de AWS. Elija su nombre de usuario en la parte superior derecha y copie su ID de cuenta.

   1. `us-east-1`

      Sustituya la región si es necesario.

1. Registre el archivo de definición de tarea: `aws ecs register-task-definition --cli-input-json file://multiline-task-definition.json --region us-east-1` 

1. Abra la consola en [https://console.aws.amazon.com/ecs/v2](https://console.aws.amazon.com/ecs/v2).

1. En el panel de navegación, elija **Task Definitions** (Definiciones de tarea) y, a continuación, seleccione la familia `firelens-example-multiline` porque hemos registrado la definición de tarea en esta familia en la primera línea de la definición de tarea anterior.

1. Elija la versión más reciente. 

1. Elija **Implementar** y **Ejecutar tarea**. 

1. En la página **Ejecutar tarea**, en **Clúster**, elija el clúster y, a continuación, en **Redes**, para **Subredes**, elija las subredes disponibles para la tarea. 

1. Seleccione **Crear**. 

**Verificar que los mensajes de registro multilínea en Amazon CloudWatch aparezcan concatenados**

1. Abra la consola de CloudWatch en [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. En el panel de navegación, amplíe **Logs** (Registros) y elija **Log groups** (Grupos de registros). 

1. Elija el grupo de registros `multiline-test/applicatio`. 

1. Elija el registro y vea los mensajes. Las líneas que coinciden con las reglas del archivo analizador se concatenan y aparecen como un solo mensaje. 

   En el siguiente fragmento de registro, se muestra un seguimiento de pila Go que está concatenado en un ú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"
   }
   ```

   En el siguiente fragmento de registro, se muestra cómo aparece el mismo evento si ejecuta un contenedor ECS que no está configurado para concatenar mensajes de registro multilínea. El campo de registro contiene una sola línea.

   ```
   {
       "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**  
Si los registros van a los archivos de registro en lugar de al resultado estándar, recomendamos especificar `multiline.parser` y los parámetros de configuración `multiline.key_content` en el [complemento de entrada de cola](https://docs.fluentbit.io/manual/pipeline/inputs/tail#multiline-support) en lugar del filtro.