Send logs from AWS ECS Fargate using Fluent Bit FireLens Sidecar
You must be using Fluent Bit 3.x or newer.
AWS ECS tasks running on Fargate can forward container logs to SolarWinds Observability SaaS using Fluent Bit FireLens Sidecar. SolarWinds Observability SaaS supports two configurations:
- A simple configuration (recommended for most users) allows you to use the AWS-provided Fluent Bit init image and to configure log ingestion entirely in the ECS task definition.
- An advanced configuration allows users needing additional filtering, transformation, or routing control to use a custom Fluent Bit image and configuration.
Start with the simple configuration unless you have a specific requirement that it cannot meet.
Simple configuration
A simple configuration is the preferred option for most users. This configuration will use the AWS-provided Fluent Bit init image and will configure log ingestion entirely in the ECS task definition. No custom image or external Fluent Bit configuration file is required.
Prerequisites
To configure ECS Fargate logging with Fluent Bit FireLens Sidecar, you will need the following:
- An ECS Fargate task definition.
- A SolarWinds Observability SaaS ingestion token.
- The collector hostname for your SolarWinds Observability SaaS data center:
logs.collector.na-01.cloud.solarwinds.comlogs.collector.na-02.cloud.solarwinds.comlogs.collector.eu-01.cloud.solarwinds.comlogs.collector.ap-01.cloud.solarwinds.com
Step 1: Configure the task definition
Add the following configuration to your task definition. Replace the application image, collector hostname, ingestion token, and ECS service name with your values.
{
"family": "checkout-api",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"cpu": "512",
"memory": "1024",
"containerDefinitions": [
{
"name": "app",
"image": "123456789012.dkr.ecr.us-east-2.amazonaws.com/checkout-api:latest",
"essential": true,
"logConfiguration": {
"logDriver": "awsfirelens",
"options": {
"Name": "http",
"Host": "logs.collector.na-01.cloud.solarwinds.com",
"Port": "443",
"URI": "/v1/logs/bulk/YOUR_INGESTION_TOKEN",
"tls": "on",
"tls.verify": "on",
"Format": "json_lines",
"json_date_key": "timestamp",
"json_date_format": "iso8601",
"Header": "X-Otel-Resource-Attr host.name=checkout-api, service.name=${ECS_TASK_ID}",
"Retry_Limit": "5"
}
}
},
{
"name": "log_router",
"image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:init-3.4.13",
"essential": true,
"firelensConfiguration": {
"type": "fluentbit",
"options": {
"enable-ecs-log-metadata": "true"
}
},
"memoryReservation": 64
}
]
}
When adapting this example, use the following values:
- Set
Hostto the collector hostname for your SolarWinds Observability SaaS data center. - Replace
YOUR_INGESTION_TOKENwith your SolarWinds Observability SaaS ingestion token. - Set
host.nameto the ECS service name. - Keep
service.name=${ECS_TASK_ID}exactly as shown. - Use an
init-*image tag. Theinit-3.4.13tag is the validated example. - Keep
enable-ecs-log-metadataset to true to include ECS metadata with each record.
Step 2: Deploy the task definition
Take the following steps to deploy the task definition:
-
Register a new revision of the task definition.
-
Deploy the revision to your ECS Fargate service.
-
Generate log output from the application container.
Step 3: Verify the logs
In SolarWinds Observability SaaS, confirm that the logs are searchable with the ECS service name as the hostname and the ECS task ID as the program value: host:checkout-api program:<ECS_TASK_ID>.
Records arrive as JSON objects, not bare log lines. The application message is stored in the log field, with ECS metadata in the same object. A record has the following structure:
{
"timestamp": "2026-08-20T07:59:04.249644Z",
"container_id": "<container-id>",
"container_name": "app",
"source": "stdout",
"log": "Example application log message",
"ecs_cluster": "<ecs-cluster>",
"ecs_task_arn": "arn:aws:ecs:<region>:<account-id>:task/<cluster>/<task-id>",
"ecs_task_definition": "<family>:<revision>"
}
The ECS task ID is available in the program field from the X-Otel-Resource-Attr header.
Advanced configuration
Users who need additional filtering, transformation, or routing control can use a custom Fluent Bit image and configuration to configure log ingestion.
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_NAMEis set to the ECS service name (checkout-api). You will need to set this per task definition. -
SWO_TASK_IDis not in this JSON. The entrypoint computes it fromECS_CONTAINER_METADATA_URI_V4at container start, which ECS always sets on Fargate. -
SWO_INGESTION_TOKENis 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.