Documentation forSolarWinds Observability SaaS

Send logs from AWS ECS Fargate using Fluent Bit FireLens Sidecar

You must be using Fluent Bit 3.x or newer.

Values needed for configuration

SolarWinds Observability SaaSfield Source on AWS ECS Fargate How to convert to environmental variable
host.name = ECS service name Not auto-injected by ECS Set explicitly in the task definition's environment block per service
service.name = ECS task ID Part of ECS_CONTAINER_METADATA_URI_V4 Parse with a 2-line shell entrypoint

Step 1: Custom Fluent Bit sidecar image (Dockerfile)

FROM amazon/aws-for-fluent-bit:3.3.2

COPY entrypoint.sh /entrypoint.sh
COPY extra.conf    /fluent-bit/etc/extra.conf
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh derives the task ID from the metadata URI using POSIX shell parameter expansion, then hands off to Fluent Bit:

#!/bin/sh
# ECS_CONTAINER_METADATA_URI_V4 is always set on Fargate platform 1.4+:
#   http://169.254.170.2/v4/<taskId>-<containerId>
# Take the path tail (last '/' segment) and strip the container suffix after the first '-'.
last_segment="${ECS_CONTAINER_METADATA_URI_V4##*/}"
SWO_TASK_ID="${last_segment%%-*}"
export SWO_TASK_ID

exec /fluent-bit/bin/fluent-bit \
  -e /fluent-bit/firehose.so \
  -e /fluent-bit/cloudwatch.so \
  -e /fluent-bit/kinesis.so \
  -c /fluent-bit/etc/fluent-bit.conf

Step 2: Fluent Bit override config (extra.config)

This is the file FireLens layers on top of its auto-generated base config:

[OUTPUT]
    Name                http
    Match               *
    Host                ${SWO_LOGS_HOST}
    Port                443
    URI                 /v1/logs/bulk
    tls                 on
    tls.verify          on
    Format              json_lines
    json_date_key       timestamp
    json_date_format    iso8601
    allow_duplicated_headers false
    Header              Authorization        Bearer ${SWO_INGESTION_TOKEN}
    Header              Content-Type         application/octet-stream
    Header              X-Otel-Resource-Attr host.name=${SWO_HOST_NAME}, service.name=${SWO_TASK_ID}
    Retry_Limit         5

Set SWO_LOGS_HOST per DC: logs.collector.na-01.cloud.solarwinds.com, swap the na-01 prefix to match (na-02, eu-01, ap-01).

Step 3: ECS task definition

{
  "family": "checkout-api",
  "requiresCompatibilities": ["FARGATE"],
  "containerDefinitions": [
    {
      "name": "app",
      "image": "123456789012.dkr.ecr.us-east-2.amazonaws.com/checkout-api:latest",
      "essential": true,
      "logConfiguration": {
        "logDriver": "awsfirelens"
      }
    },
    {
      "name": "log_router",
      "image": "123456789012.dkr.ecr.us-east-2.amazonaws.com/swo-fluent-bit:latest",
      "essential": true,
      "firelensConfiguration": {
        "type": "fluentbit",
        "options": {
          "enable-ecs-log-metadata": "true",
          "config-file-type": "file",
          "config-file-value": "/fluent-bit/etc/extra.conf"
        }
      },
      "environment": [
        { "name": "SWO_HOST_NAME", "value": "checkout-api" },
        { "name": "SWO_LOGS_HOST", "value": "logs.collector.na-01.cloud.solarwinds.com" }
      ],
      "secrets": [
        {
          "name": "SWO_INGESTION_TOKEN",
          "valueFrom": "arn:aws:secretsmanager:us-east-2:123456789012:secret:swo/ingestion-token-XXXXXX"
        }
      ],
      "memoryReservation": 64
    }
  ]
}

Please note the following:

  • SWO_HOST_NAME is set to the ECS service name (checkout-api). You will need to set this per task definition.

  • SWO_TASK_ID is not in this JSON. The entrypoint computes it from ECS_CONTAINER_METADATA_URI_V4 at container start, which ECS always sets on Fargate.

  • SWO_INGESTION_TOKEN is fed in via Secrets Manager. Don't inline the token in plain task-definition JSON in production.

Behavior in SolarWinds Observability SaaS

After the task starts, every log from the app container will land with the following:

  • System (Host) = checkout-api (your ECS service name)

  • program = the task ID (e.g., a1b2c3d4e5f64789abcd1234567890ef)

This is searchable as

host:checkout-api  program:a1b2c3d4e5f64789abcd1234567890ef

Adding the record_modifier filter before OUTPUT will back ECS cluster, container name, and stream into each line:

[FILTER]
    Name   record_modifier
    Match  *
    Record ecs_cluster        ${ECS_CLUSTER}
    Record ecs_service_name   ${SWO_HOST_NAME}
    Record ecs_task_id        ${SWO_TASK_ID}

ecs_cluster, ecs_task_arn, ecs_task_definition, container_name, container_id, and source are already added automatically because enable-ecs-log-metadata: true is on.

The scripts are not supported under any SolarWinds support program or service. The scripts are provided AS IS without warranty of any kind. SolarWinds further disclaims all warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The risk arising out of the use or performance of the scripts and documentation stays with you. In no event shall SolarWinds or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the scripts or documentation.