4

I have a docker container with a python script (Python 3.8), which I execute in AWS Fargate via Airflow (ECSOperator). The script streams several logs to Cloudwatch using the awslog driver defined in the task definition. I'm able to correctly see all the logs in Cloudwatch but the problem is that the logs are always attached to a main log message, that is, my logs are visualized within another log message.

Here is an example of a log, where the first 3 columns are injected automatically, whereas the rest of the message refers to my custom log:

[2021-11-04 17:23:22,026] {{ecs.py:317}} INFO - [2021-11-04T17:22:47.719000] 2021-11-04 17:22:47,718 - myscript - WARNING - testing log message

Thus, no matter which logLevel I set that the first log message is always INFO. It seems like it is something that Fargate adds automatically. I would like my log message to stream directly to Cloudwatch without being delivered into another log message, just:

[2021-11-04T17:22:47.719000] 2021-11-04 17:22:47,718 - myscript - WARNING - testing log message

I assume that I'm not configuring the logger correctly or that I have to get another logger, but I don“t know how to do it properly. These are some of the approaches I followed and the results I obtained.

Prints

If a use prints within my code, the log messages are placed in the stdout so they are streamed to Cloudwatch through the awslog driver.

[2021-11-04 17:23:22,026] {{ecs.py:317}} INFO - testing log message

Logging without configuration

If I use the logger with any ConsoleHandler or StreamHandler configured, the generated log messages are equal to the ones created with prints.

import logging
logger = logging.getLogger(__name__)
logger.warning('testing log message')
[2021-11-04 17:23:22,026] {{ecs.py:317}} INFO - testing log message

Logging with StreamHandler

If I configure a StreamHandler with a formatter, then my log is attached to the main log, as stated before. Thus, it just replaces the string messsage (last column) by the new formatted log message.

import logging
logger = logging.getLogger(__name__)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.warning('testing log message')
[2021-11-04 17:23:22,026] {{ecs.py:317}} INFO - [2021-11-04T17:22:47.719000] 2021-11-04 17:22:47,718 - myscript - WARNING - testing log message

This is the defined log configuration witihn the task definition:

"logConfiguration": {
   "logDriver": "awslogs",
   "secretOptions": [],
   "options": {
      "awslogs-group": "/ecs/my-group",
      "awslogs-region": "eu-west-1",
      "awslogs-stream-prefix": "ecs"
}

EDIT 1

I've been investigating the logs in Cloudwatch and I found out that the logs are streaming to 2 different log groups, since I'm using Airflow to launch fargate.

  • Airflow group: Airflow creates automatically a log group named <airflow_environment>-Task where places the logs generated within the tasks. Here, it seems that Airflow wraps my custom logs within its own log, which are always INFO. When visualizing the logs from the Airflow UI, it shows the logs obtained from this log group.

  • ECS group: this is the log group defined in the TaskDefinition (/ecs/my-group). In this group, the logs are streamed as they are, without being wrapped.

Hence, the problem seems to be with Airflow as it wraps the logs within its own logger and it shows these logs in the Airflow UI. Anyway, logs are correctly delivered and formatted within the log group defined in the TaskDefinition.

mcanizo
  • 115
  • 3
  • 10

1 Answers1

0

Probably a bit late and you already solved, but I think the solution is here. Probably fargate pre-configure a log handler like lambda, given the fact that there is the configuration on awslogs in the task definition.

rok
  • 2,574
  • 3
  • 23
  • 44