I checked the deployment state transition logs with Amazon ECS's new feature "Action Logs"

I checked the deployment state transition logs with Amazon ECS's new feature "Action Logs"

Action Logs are now available in Amazon ECS. Operations performed by ECS during deployments are recorded as structured logs in CloudWatch Logs. I verified the events output in three patterns: successful deployment, OOM failure, and image pull failure.
2026.07.22

This page has been translated by machine translation. View original

Introduction

On July 21, 2026, Action Logs became available in Amazon ECS. Orchestration operations performed by ECS during deployments are now automatically recorded as structured logs in CloudWatch Logs.

https://aws.amazon.com/about-aws/whats-new/2026/07/amazon-ecs-action-logs/

When Action Logs are enabled, the way deployment status is tracked changes as follows:

Aspect Before After enabling Action Logs
Deployment status tracking Check service events (describe-services) each time Automatically recorded as structured logs in CloudWatch Logs
Identifying image digests Difficult to identify with :latest tag Automatically recorded with SERVICE_REVISION_STABLE
Detecting circuit breaker activation Check via service events Recorded as WARN level log, enabling alert integration
Isolating failure causes Manually correlate service events and task status Classifiable by event pattern (presence of SERVICE_REVISION_STABLE)
Log search and analysis Visual inspection of unstructured text Queryable with CloudWatch Logs Insights

In this article, we enabled Action Logs via CLI and observed the events output in three scenarios: successful deployment, OOM failure, and image pull failure. The summary of results for the three scenarios is as follows:

Pattern SERVICE_REVISION_STABLE Rollback observed Result
Successful deployment Present (digest recorded) SERVICE_DEPLOYMENT_SUCCESSFUL
OOM failure Present (digest recorded) Yes (approx. 4 minutes) SERVICE_DEPLOYMENT_ROLLBACK_SUCCESSFUL
Image pull failure Absent No (not reached after 18+ minutes) SERVICE_DEPLOYMENT_IN_PROGRESS only

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/action-logs.html

Verification Details

Verification Environment

Verification was performed targeting a service on Fargate in the ap-northeast-1 region. The deployment circuit breaker was enabled (rollback=true, threshold 50%).

Task definition Purpose Image CPU Memory (task) Memory (container hard limit)
action-logs-test-normal:1 Successful deployment public.ecr.aws/nginx/nginx:latest 256 512 MiB
action-logs-test-oom:1 OOM failure public.ecr.aws/docker/library/alpine:latest 256 512 MiB 6 MiB
action-logs-test-pull-fail:1 Image pull failure public.ecr.aws/does-not-exist/fake-image:v9999 256 512 MiB

Enabling Action Logs (CLI)

Action Logs use the CloudWatch Logs Vended Logs delivery mechanism. It is enabled in 5 steps: create log group → resource policy → delivery source → delivery destination → delivery. Specify ACTION_LOGS for the log-type of the delivery source.

Required IAM permissions:

  • logs:CreateLogGroup
  • logs:PutRetentionPolicy
  • logs:PutResourcePolicy
  • logs:PutDeliverySource
  • logs:PutDeliveryDestination
  • logs:CreateDelivery
  • logs:GetDelivery
  • ecs:AllowVendedLogDeliveryForResource

CLI commands for each step:

# 1. Create log group
aws logs create-log-group \
  --log-group-name /aws/vendedlogs/ecs/action-logs/<cluster-name> \
  --region ap-northeast-1

aws logs put-retention-policy \
  --log-group-name /aws/vendedlogs/ecs/action-logs/<cluster-name> \
  --retention-in-days 7 \
  --region ap-northeast-1

# 2. Resource policy (grant write permission to delivery.logs.amazonaws.com)
aws logs put-resource-policy \
  --policy-name ecs-action-logs-delivery-policy \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Sid": "AllowECSActionLogsDelivery",
      "Effect": "Allow",
      "Principal": {"Service": "delivery.logs.amazonaws.com"},
      "Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
      "Resource": "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/vendedlogs/ecs/action-logs/<cluster-name>:log-stream:*",
      "Condition": {
        "StringEquals": {"aws:SourceAccount": "123456789012"},
        "ArnLike": {"aws:SourceArn": "arn:aws:ecs:ap-northeast-1:123456789012:*"}
      }
    }]
  }' \
  --region ap-northeast-1

# 3. Delivery Source
aws logs put-delivery-source \
  --name <source-name> \
  --resource-arn arn:aws:ecs:ap-northeast-1:123456789012:cluster/<cluster-name> \
  --log-type ACTION_LOGS \
  --region ap-northeast-1

# 4. Delivery Destination
aws logs put-delivery-destination \
  --name <destination-name> \
  --output-format json \
  --delivery-destination-configuration '{"destinationResourceArn":"arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/vendedlogs/ecs/action-logs/<cluster-name>"}' \
  --region ap-northeast-1

# 5. Create Delivery
aws logs create-delivery \
  --delivery-source-name <source-name> \
  --delivery-destination-arn arn:aws:logs:ap-northeast-1:123456789012:delivery-destination:<destination-name> \
  --region ap-northeast-1

Action Logs Schema

The events obtained in this verification had the following structure (field placement may differ from the schema definition in the official documentation).

{
  "resourceArn": "arn:aws:ecs:<region>:<account>:cluster/<cluster-name>",
  "actionSourceId": "service/<cluster-name>/<service-name>",
  "logLevel": "INFO | WARN | ERROR",
  "eventTimestamp": 1784663292399,
  "detail": {
    "eventName": "<event-name>",
    "status": "IN_PROGRESS | SUCCEEDED",
    "statusReason": "<human-readable reason>",
    "serviceDeploymentArn": "arn:aws:ecs:...:service-deployment/...",
    "serviceRevisionArn": "arn:aws:ecs:...:service-revision/..."
  }
}
Field Meaning
resourceArn ARN of the target cluster
actionSourceId Event source (in service/<cluster-name>/<service-name> format; also used as the log stream name)
logLevel Log level (INFO / WARN / ERROR)
eventTimestamp Event occurrence time (epoch milliseconds)
detail.eventName Event type
detail.statusReason Human-readable status reason

Log streams are created with the naming convention service/<cluster-name>/<service-name>, making it easy to filter by service.

The eventName values confirmed in this verification are as follows:

eventName logLevel Meaning
SERVICE_DEPLOYMENT_IN_PROGRESS INFO Deployment started
SERVICE_REVISION_STABLE INFO Service revision stable, locked to image digest
SERVICE_DEPLOYMENT_SUCCESSFUL INFO Deployment completed successfully
SERVICE_DEPLOYMENT_ROLLBACK WARN Circuit breaker activated, rollback in progress
SERVICE_DEPLOYMENT_ROLLBACK_SUCCESSFUL INFO Rollback completed

Verifying Logs for Successful Deployment

A service was created with the nginx image (action-logs-test-normal:1) and the events output during a successful deployment were verified.

Elapsed eventName logLevel
0 sec SERVICE_DEPLOYMENT_IN_PROGRESS INFO
+34 sec SERVICE_REVISION_STABLE INFO
+approx. 3 min SERVICE_DEPLOYMENT_SUCCESSFUL INFO

Full structure of each event:

{
  "resourceArn": "arn:aws:ecs:ap-northeast-1:123456789012:cluster/action-logs-test-cluster",
  "actionSourceId": "service/action-logs-test-cluster/action-logs-test-service",
  "logLevel": "INFO",
  "eventTimestamp": 1784663292399,
  "detail": {
    "statusReason": "Service deployment in progress.",
    "serviceDeploymentArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-deployment/action-logs-test-cluster/action-logs-test-service/xQiDJv98PtZRdF7HNahyb",
    "status": "IN_PROGRESS",
    "eventName": "SERVICE_DEPLOYMENT_IN_PROGRESS"
  }
}
{
  "resourceArn": "arn:aws:ecs:ap-northeast-1:123456789012:cluster/action-logs-test-cluster",
  "actionSourceId": "service/action-logs-test-cluster/action-logs-test-service",
  "logLevel": "INFO",
  "eventTimestamp": 1784663326125,
  "detail": {
    "statusReason": "Service revision marked stable. Locked to container image(s): public.ecr.aws/nginx/nginx:latest@sha256:709204fab25be0425d55090c79f3e84161cf99f50278543d7f6bf372e326ad1f.",
    "serviceRevisionArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-revision/action-logs-test-cluster/action-logs-test-service/7911470091089632318",
    "status": "SUCCEEDED",
    "eventName": "SERVICE_REVISION_STABLE"
  }
}
{
  "resourceArn": "arn:aws:ecs:ap-northeast-1:123456789012:cluster/action-logs-test-cluster",
  "actionSourceId": "service/action-logs-test-cluster/action-logs-test-service",
  "logLevel": "INFO",
  "eventTimestamp": 1784663469912,
  "detail": {
    "statusReason": "Service deployment completed successfully.",
    "serviceDeploymentArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-deployment/action-logs-test-cluster/action-logs-test-service/xQiDJv98PtZRdF7HNahyb",
    "status": "SUCCEEDED",
    "eventName": "SERVICE_DEPLOYMENT_SUCCESSFUL"
  }
}

Worth noting is the SERVICE_REVISION_STABLE event. The statusReason records Locked to container image(s): ...@sha256:709204... with the image digest included. Even when deploying with the :latest tag, you can later identify the digest of the image that was actually running.

Verifying Logs for Deployment Failure (OOM → Circuit Breaker)

Next, we verified the logs when OOM is intentionally triggered and the circuit breaker activates. The alpine image container memory limit was restricted to 6 MiB, and memory was consumed using dd if=/dev/zero, resulting in an OOM immediately after startup.

Elapsed eventName logLevel
0 sec SERVICE_DEPLOYMENT_IN_PROGRESS INFO
+53 sec SERVICE_REVISION_STABLE INFO
+approx. 3 min 45 sec SERVICE_DEPLOYMENT_ROLLBACK WARN
+approx. 4 min SERVICE_DEPLOYMENT_ROLLBACK_SUCCESSFUL INFO

Full structure of each event:

{
  "logLevel": "INFO",
  "eventTimestamp": 1784663519017,
  "detail": {
    "statusReason": "Service deployment in progress.",
    "serviceDeploymentArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-deployment/action-logs-test-cluster/action-logs-test-service/Z6HSP7lksB3wTV0bOxmpF",
    "status": "IN_PROGRESS",
    "eventName": "SERVICE_DEPLOYMENT_IN_PROGRESS"
  }
}
{
  "logLevel": "INFO",
  "eventTimestamp": 1784663571619,
  "detail": {
    "statusReason": "Service revision marked stable. Locked to container image(s): public.ecr.aws/docker/library/alpine:latest@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b.",
    "serviceRevisionArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-revision/action-logs-test-cluster/action-logs-test-service/2005995910462199077",
    "status": "SUCCEEDED",
    "eventName": "SERVICE_REVISION_STABLE"
  }
}
{
  "logLevel": "WARN",
  "eventTimestamp": 1784663746287,
  "detail": {
    "statusReason": "Service deployment rolled back because the circuit breaker threshold was exceeded.",
    "serviceDeploymentArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-deployment/action-logs-test-cluster/action-logs-test-service/Z6HSP7lksB3wTV0bOxmpF",
    "status": "IN_PROGRESS",
    "eventName": "SERVICE_DEPLOYMENT_ROLLBACK"
  }
}
{
  "logLevel": "INFO",
  "eventTimestamp": 1784663762604,
  "detail": {
    "statusReason": "Service deployment rolled back because the circuit breaker threshold was exceeded.",
    "serviceDeploymentArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-deployment/action-logs-test-cluster/action-logs-test-service/Z6HSP7lksB3wTV0bOxmpF",
    "status": "SUCCEEDED",
    "eventName": "SERVICE_DEPLOYMENT_ROLLBACK_SUCCESSFUL"
  }
}

In this pattern, since the image itself could be resolved, SERVICE_REVISION_STABLE was output. After that, as the task continued to fail to start due to OOM, SERVICE_DEPLOYMENT_ROLLBACK was recorded at WARN level. Since the statusReason explicitly states the reason for exceeding the threshold, it can be used to detect rollbacks in conjunction with CloudWatch Alarms.

Verifying Logs for Image Pull Failure

Finally, the service was updated to use the non-existent image public.ecr.aws/does-not-exist/fake-image:v9999.

Only the event indicating the start of the deployment was output to Action Logs (within the range observable during the verification period).

{
  "logLevel": "INFO",
  "eventTimestamp": 1784663869100,
  "detail": {
    "statusReason": "Service deployment in progress.",
    "serviceDeploymentArn": "arn:aws:ecs:ap-northeast-1:123456789012:service-deployment/action-logs-test-cluster/action-logs-test-service/IB_8BjTwukTyDzQ4uW4Ca",
    "status": "IN_PROGRESS",
    "eventName": "SERVICE_DEPLOYMENT_IN_PROGRESS"
  }
}

SERVICE_REVISION_STABLE was not output. This is because the image could not be resolved and the digest could not be locked. In other words, the presence or absence of SERVICE_REVISION_STABLE allows you to distinguish whether the failure occurred before or after image resolution.

The traditional service events recorded per-container failure reasons.

CannotPullContainerError: pull image manifest has been retried 7 time(s):
failed to resolve ref public.ecr.aws/does-not-exist/fake-image:v9999:
public.ecr.aws/does-not-exist/fake-image:v9999: not found.

Since Action Logs record at the deployment-wide state transition level, they can be used in a complementary manner with traditional service events that contain per-container details.

Note that the time for the circuit breaker to activate was approximately 4 minutes in the OOM case. In the image pull failure case, the circuit breaker had not activated even after more than 18 minutes had elapsed, so the SERVICE_DEPLOYMENT_ROLLBACK log was not obtained.

CloudWatch Logs Insights Query Examples

Here are some query examples useful for operations.

-- Extract WARN/ERROR events (for deployment failure investigation)
fields @timestamp, detail.eventName, logLevel, detail.statusReason
| filter logLevel in ["WARN", "ERROR"]
| sort @timestamp asc
| limit 50
-- All events in chronological order (service level)
fields @timestamp, detail.eventName, logLevel, detail.status, detail.statusReason
| filter @logStream like /^service\//
| sort @timestamp asc
| limit 50
-- Tracking a specific deployment
fields @timestamp, detail.eventName, logLevel, detail.statusReason
| filter detail.serviceDeploymentArn like /<deployment-id>/
| sort @timestamp asc
-- Detecting circuit breaker activation
fields @timestamp, detail.eventName, detail.statusReason
| filter detail.eventName = "SERVICE_DEPLOYMENT_ROLLBACK"
| sort @timestamp desc
| limit 20

Summary

With ECS Action Logs, we were able to track deployment progress, completion, and rollbacks on CloudWatch Logs. In this verification, combining the presence or absence of SERVICE_REVISION_STABLE output with subsequent events made it easier to investigate failures before and after image resolution. The rollback start event can also be used as an alert condition for detecting deployment failures.

Share this article

AWSのお困り事はクラスメソッドへ