

# Configuring observability features in the AWS SDK for Java 2.x
<a name="observability"></a>

Telemetry is the automated collection and transmission of data from remote sources that enable you to monitor and analyze your system's behavior. 

Observability in the SDK for Java 2.x provides developers with comprehensive insight into how their Java applications interact with AWS services through rich telemetry data that captures the complete request lifecycle. These capabilities enable you to collect, analyze, and visualize telemetry signals such as metrics, logs, and traces, allowing you to monitor request patterns, identify bottlenecks, and optimize your application's AWS interactions for improved reliability and performance.

**Topics**
+ [Metrics](metrics.md)
+ [Monitoring](monitoring-overview.md)
+ [Logging](logging-slf4j.md)

# Publish SDK metrics from the AWS SDK for Java 2.x
<a name="metrics"></a>

With the AWS SDK for Java 2.x you can collect metrics about the service clients and requests in your application, analyze the output in Amazon CloudWatch Logs, and then act on it.

By default, metrics collection is disabled in the SDK. This topic helps you to enable and configure it.

## Getting started with SDK metrics
<a name="getting-started-with-metrics"></a>

To enable metrics collection in your application, choose the appropriate implementation of the `[MetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/MetricPublisher.html)` interface based on your use case and follow the detailed setup instructions:

**For long-running applications:**
+ Use `[CloudWatchMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/cloudwatch/CloudWatchMetricPublisher.html)`
+ See [Publish SDK metrics from long-running applications](metric-pub-impl-cwmp.md) for complete setup instructions, code examples, and configuration options.

**For AWS Lambda functions:**
+ Use `[EmfMetricLoggingPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/emf/EmfMetricLoggingPublisher.html)`
+ See [Publish SDK metrics for AWS Lambda functions](metric-pub-impl-emf.md) for complete setup instructions, dependencies, and Lambda-specific configuration.

**For troubleshooting and console output:**
+ Use `[LoggingMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/LoggingMetricPublisher.html)`
+ See [Output SDK metrics to console for development and debugging](metric-pub-impl-logging.md) for setup instructions, formatting options, and examples for local development and troubleshooting.

## Quick implementation preview
<a name="quick-implementation-preview"></a>

Here's what enabling metrics looks like for each use case:

**Long-running applications:**

```
MetricPublisher metricsPub = CloudWatchMetricPublisher.create();
DynamoDbClient ddb = DynamoDbClient.builder()
    .overrideConfiguration(c -> c.addMetricPublisher(metricsPub))
    .build();
```

**Lambda functions:**

```
EmfMetricLoggingPublisher emfPublisher = EmfMetricLoggingPublisher.builder()
    .namespace("MyApp")
    .build();
DynamoDbClient dynamoDb = DynamoDbClient.builder()
    .overrideConfiguration(c -> c.addMetricPublisher(emfPublisher))
    .build();
```

**Development and debugging:**

```
MetricPublisher loggingPublisher = LoggingMetricPublisher.create();
S3Client s3 = S3Client.builder()
    .overrideConfiguration(c -> c.addMetricPublisher(loggingPublisher))
    .build();
```

## Metrics limitation of the AWS CRT-based S3 client
<a name="metrics-using-s3-crt-based-client"></a>

The [AWS CRT-based S3 client](crt-based-s3-client.md) does not currently support SDK metrics collection. The builder for an AWS CRT-based S3 client instance, [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.html), does not provide methods to configure metrics publishers.

## When are metrics available?
<a name="when-are-metrics-available"></a>

Metrics are generally available within 5-10 minutes after the SDK for Java emits them. For accurate and up-to-date metrics, check Cloudwatch at least 10 minutes after emitting the metrics from your Java applications. 

## What information is collected?
<a name="what-information-is-collected"></a>

Metrics collection includes the following:
+ Number of API requests, including whether they succeed or fail
+ Information about the AWS services you call in your API requests, including exceptions returned
+ The duration for various operations such as Marshalling, Signing, and HTTP requests
+ HTTP client metrics, such as the number of open connections, the number of pending requests, and the name of the HTTP client used

**Note**  
The metrics available vary by HTTP client.

For a complete list, see [Service client metrics](metrics-list.md).

## How can I use this information?
<a name="how-can-i-use-this-information"></a>

You can use the metrics the SDK collects to monitor the service clients in your application. You can look at overall usage trends, identify anomalies, review service client exceptions returned, or to dig in to understand a particular issue. Using Amazon CloudWatch Logs, you can also create alarms to notify you as soon as your application reaches a condition that you define.

For more information, see [Using Amazon CloudWatch Logs Metrics](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/working_with_metrics.html) and [Using Amazon CloudWatch Logs Alarms](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html) in the [ Amazon CloudWatch Logs User Guide](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/).

# Publish SDK metrics from long-running applications using the AWS SDK for Java 2.x
<a name="metric-pub-impl-cwmp"></a>

Because the `[CloudWatchMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/cloudwatch/CloudWatchMetricPublisher.html)` implementation aggregates and periodically uploads metrics to Amazon CloudWatch with a delay, its use is best suited for long-running applications. 

The default settings of the metrics publisher are meant to minimize memory usage and CloudWatch cost, while still providing a useful amount of insight into the metric data.

## Set-up
<a name="prerequisitesmetrics"></a>

Before you can enable and use metrics by using `CloudWatchMetricPublisher`, complete the following steps.

### Step 1: Add required dependency
<a name="cwmp-set-up-deps"></a>

Configure your project dependencies (for example, in your `pom.xml` or `build.gradle` file) to use version `2.14.0` or later of the AWS SDK for Java.

Include the artifactId `cloudwatch-metric-publisher` with the version number `2.14.0` or later in your project's dependencies.

For example:

```
<project>
  <dependencyManagement>
   <dependencies>
      <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>bom</artifactId>
        <version>[2.30.11](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)</version>  <!-- Navigate the link to see the latest version. -->
        <type>pom</type>
        <scope>import</scope>
      </dependency>
   </dependencies>
  </dependencyManagement>
  <dependencies>
   <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>cloudwatch-metric-publisher</artifactId>
   </dependency>
  </dependencies>
</project>
```

### Step 2: Configure required permissions
<a name="cwmp-set-up-perms"></a>

Enable `cloudwatch:PutMetricData` permissions for the IAM identity used by the metrics publisher to allow the SDK for Java to write metrics.

## Enable metrics for a specific request
<a name="enable-metrics-for-a-specific-request"></a>

The following class shows how to enable the CloudWatch metrics publisher for a request to Amazon DynamoDB. It uses the default metrics publisher configuration.

```
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest;

public class DefaultConfigForRequest {
    // Use one MetricPublisher for your application. It can be used with requests or service clients.
    static MetricPublisher metricsPub = CloudWatchMetricPublisher.create();

    public static void main(String[] args) {
        DynamoDbClient ddb = DynamoDbClient.create();
        // Publish metrics the for ListTables operation.
        ddb.listTables(ListTablesRequest.builder()
            .overrideConfiguration(c -> c.addMetricPublisher(metricsPub))
            .build());

        // Perform more work in your application.

        // A MetricsPublisher has its own lifecycle independent of any service client or request that uses it.
        // If you no longer need the publisher, close it to free up resources.
        metricsPub.close();  // All metrics stored in memory are flushed to CloudWatch.

        // Perform more work with the DynamoDbClient instance without publishing metrics.
        // Close the service client when you no longer need it.
        ddb.close();
    }
}
```

**Important**  
Make sure your application calls `close` on the `[MetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/MetricPublisher.html)` instance when the service client is no longer in use. Failure to do so results in possible thread or file descriptor leaks.

## Enable summary metrics for a specific service client
<a name="enable-metrics-for-a-specific-service-client"></a>

The following code snippet shows how to enable a CloudWatch metrics publisher with default settings for a service client.

```
MetricPublisher metricsPub = CloudWatchMetricPublisher.create();

DynamoDbClient ddb = DynamoDbClient.builder()
          .overrideConfiguration(c -> c.addMetricPublisher(metricsPub))
          .build();
```

## Customize a CloudWatch metrics publisher
<a name="customize-metrics-publisher"></a>

The following class demonstrates how to set up a custom configuration for the metrics publisher for a specific service client. The customizations include loading a specific profile, specifying a AWS Region where the metrics publisher sends requests, and customizing how often the publisher sends metrics to CloudWatch.

```
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.core.metrics.CoreMetric;
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;

import java.time.Duration;

public class CustomConfigForDDBClient {
    // Use one MetricPublisher for your application. It can be used with requests or service clients.
    static MetricPublisher metricsPub = CloudWatchMetricPublisher.builder()
        .cloudWatchClient(CloudWatchAsyncClient.builder()
            .region(Region.US_WEST_2)
            .credentialsProvider(ProfileCredentialsProvider.create("cloudwatch"))
            .build())
        .uploadFrequency(Duration.ofMinutes(5))
        .maximumCallsPerUpload(100)
        .namespace("ExampleSDKV2Metrics")
        .detailedMetrics(CoreMetric.API_CALL_DURATION)
        .build();

    public static void main(String[] args) {
        DynamoDbClient ddb = DynamoDbClient.builder()
            .overrideConfiguration(c -> c.addMetricPublisher(metricsPub))
            .build();
        // Publish metrics for DynamoDB operations.
        ddb.listTables();
        ddb.describeEndpoints();
        ddb.describeLimits();
        // Perform more work in your application.

        // A MetricsPublisher has its own lifecycle independent of any service client or request that uses it.
        // If you no longer need the publisher, close it to free up resources.
        metricsPub.close();  // All metrics stored in memory are flushed to CloudWatch.


        // Perform more work with the DynamoDbClient instance without publishing metrics.
        // Close the service client when you no longer need it.
        ddb.close();
    }
}
```

The customizations shown in the previous snippet have the following effects.
+ The `cloudWatchClient` method lets you customize the CloudWatch client used to send metrics. In this example, we use a different region from the default of *us-east-1* where the client sends metrics. We also use a different named profile, *cloudwatch*, whose credentials will be used to authenticate requests to CloudWatch. Those credentials must have permissions to `cloudwatch:PutMetricData`.
+ The `uploadFrequency` method allows you to specify how frequently the metrics publisher uploads metrics to CloudWatch. The default is once a minute.
+ The `maximumCallsPerUpload` method limits the number of calls made per upload. The default is unlimited.
+ By default, the SDK for Java 2.x publishes metrics under the namespace `AwsSdk/JavaSdk2`. You can use the `namespace` method to specify a different value.
+ By default, the SDK publishes summary metrics. Summary metrics consist of average, minimum, maximum, sum, and sample count. By specifying one or more SDK metrics in the `detailedMetrics` method, the SDK publishes additional data for each metric. This additional data enables percentile statistics like p90 and p99 that you can query in CloudWatch. The detailed metrics are especially useful for latency metrics like `APICallDuration`, which measures the end-to-end latency for SDK client requests. You can use fields of the `[CoreMetric](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/metrics/CoreMetric.html)` class to specify other common SDK metrics. 

**Next steps:** If you're also working with Lambda functions, see [Publish SDK metrics for AWS Lambda functions](metric-pub-impl-emf.md) for EMF-based metrics publishing.

# Publish SDK metrics for AWS Lambda functions using the AWS SDK for Java 2.x
<a name="metric-pub-impl-emf"></a>

Because Lambda functions typically execute for milliseconds to minutes, any delay in sending the metrics, which happens with the `CloudWatchMetricPublisher`, risks the loss of data. 

`[EmfMetricLoggingPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/emf/EmfMetricLoggingPublisher.html)` provides a more suitable approach by immediately writing metrics as structured log entries in [CloudWatch Embedded Metric Format (EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html). `EmfMetricLoggingPublisher` works in execution environments that have built-in integration with Amazon CloudWatch Logs such as AWS Lambda and Amazon Elastic Container Service.

## Set-up
<a name="metric-pub-impl-emf-set-up"></a>

Before you can enable and use metrics by using `EmfMetricLoggingPublisher`, complete the following steps.

### Step 1: Add required dependency
<a name="metric-pub-impl-emf-set-up-deps"></a>

Configure your project dependencies (for example, in your `pom.xml` or `build.gradle` file) to use version `2.30.3` or later of the AWS SDK for Java.

Include the artifactId `emf-metric-logging-publisher` with the version number `2.30.3` or later in your project's dependencies.

For example:

```
<project>
  <dependencyManagement>
   <dependencies>
      <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>bom</artifactId>
        <version>[2.30.11](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)</version>  <!-- Navigate the link to see the latest version. -->
        <type>pom</type>
        <scope>import</scope>
      </dependency>
   </dependencies>
  </dependencyManagement>
  <dependencies>
   <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>emf-metric-logging-publisher</artifactId>
   </dependency>
  </dependencies>
</project>
```

### Step 2: Configure required permissions
<a name="metric-pub-impl-emf-set-up-perm"></a>

Enable `logs:PutLogEvents` permissions for the IAM identity used by the metrics publisher to allow the SDK for Java to write EMF-formatted logs.

### Step 3: Setup logging
<a name="metric-pub-impl-emf-set-up-logger"></a>

To ensure proper metric collection, configure your logging to output to the console at the `INFO` level or lower (such as `DEBUG`). In your `log4j2.xml` file:

```
<Loggers>
  <Root level="WARN">
   <AppenderRef ref="ConsoleAppender"/>
  </Root>
  <Logger name="software.amazon.awssdk.metrics.publishers.emf.EmfMetricLoggingPublisher" level="INFO" />
</Loggers>
```

See the [logging topic](logging-slf4j.md) in this guide for more information on how to set up a `log4j2.xml` file. 

## Configure and use `EmfMetricLoggingPublisher`
<a name="metric-pub-impl-emf-use"></a>

The following Lambda function class first creates and configures an `EmfMetricLoggingPublisher` instance and then uses it with a Amazon DynamoDB service client:

```
public class GameIdHandler implements RequestHandler<Map<String, String>, String> {
    private final EmfMetricLoggingPublisher emfPublisher;
    private final DynamoDbClient dynamoDb;

    public GameIdHandler() {
        // Build the publisher. 
        this.emfPublisher = EmfMetricLoggingPublisher.builder()
                .namespace("namespace")
                .dimensions(CoreMetric.SERVICE_ID,
                        CoreMetric.OPERATION_NAME)
                .build();
        // Add the publisher to the client.
        this.dynamoDb = DynamoDbClient.builder()
                .overrideConfiguration(c -> c.addMetricPublisher(emfPublisher))
                .region(Region.of(System.getenv("AWS_REGION")))
                .build();
    }

    @Override
    public String handleRequest(Map<String, String> event, Context context) {
        Map<String, AttributeValue> gameItem = new HashMap<>();

        gameItem.put("gameId", AttributeValue.builder().s(event.get("id")).build());

        PutItemRequest putItemRequest = PutItemRequest.builder()
                .tableName("games")
                .item(gameItem)
                .build();

        dynamoDb.putItem(putItemRequest);

        return "Request handled";
    }
}
```

When the DynamoDB client executes the `putItem` method, it automatically publishes metrics to a CloudWatch log stream in EMF format. 

### Example of an EMF log event
<a name="emf-logged-output"></a>

For example, if you send the following event to the GameHandler Lambda function with logging configured as shown previously:

```
{
  "id": "23456"
}
```

After the function processes the event, you find two log events that look similar to the following example. The JSON object in the second event contains the Java SDK metric data for the `PutItem` operation to DynamoDB.

When CloudWatch receives a log event in EMF format, it automatically parses the structured JSON to extract metric data. CloudWatch then creates corresponding metrics while storing the original log entry in CloudWatch Logs.

```
2025-07-11 15:58:30 [main] INFO  org.example.GameIdHandler:39 - Received map: {id=23456}

2025-07-11 15:58:34 [main] INFO  software.amazon.awssdk.metrics.publishers.emf.EmfMetricLoggingPublisher:43 - 
{
    "_aws": {
        "Timestamp": 1752249513975,
        "LogGroupName": "/aws/lambda/GameId",
        "CloudWatchMetrics": [
            {
                "Namespace": "namespace",
                "Dimensions": [
                    [
                        "OperationName",
                        "ServiceId"
                    ]
                ],
                "Metrics": [
                    {
                        "Name": "AvailableConcurrency"
                    },
                    {
                        "Name": "PendingConcurrencyAcquires"
                    },
                    {
                        "Name": "ServiceCallDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "EndpointResolveDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "MaxConcurrency"
                    },
                    {
                        "Name": "BackoffDelayDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "MarshallingDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "LeasedConcurrency"
                    },
                    {
                        "Name": "SigningDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "ConcurrencyAcquireDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "ApiCallSuccessful"
                    },
                    {
                        "Name": "RetryCount"
                    },
                    {
                        "Name": "UnmarshallingDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "ApiCallDuration",
                        "Unit": "Milliseconds"
                    },
                    {
                        "Name": "CredentialsFetchDuration",
                        "Unit": "Milliseconds"
                    }
                ]
            }
        ]
    },
    "AvailableConcurrency": 0,
    "PendingConcurrencyAcquires": 0,
    "OperationName": "PutItem",
    "ServiceCallDuration": 1339,
    "EndpointResolveDuration": 81,
    "MaxConcurrency": 50,
    "BackoffDelayDuration": 0,
    "ServiceId": "DynamoDB",
    "MarshallingDuration": 181,
    "LeasedConcurrency": 1,
    "SigningDuration": 184,
    "ConcurrencyAcquireDuration": 83,
    "ApiCallSuccessful": 1,
    "RetryCount": 0,
    "UnmarshallingDuration": 85,
    "ApiCallDuration": 1880,
    "CredentialsFetchDuration": 138
}
```

The [API documentation](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/emf/EmfMetricLoggingPublisher.Builder.html) for `EmfMetricLoggingPublisher.Builder` shows the configuration options that you can use.

You can also enable EMF metric logging for a single request as [shown for the CloudWatchMetricPublisher](metric-pub-impl-cwmp.md#enable-metrics-for-a-specific-request).

**Next steps:** For long-running applications, see [Publish SDK metrics from long-running applications](metric-pub-impl-cwmp.md) for CloudWatch-based metrics publishing.

# Output SDK metrics to the console using the AWS SDK for Java 2.x
<a name="metric-pub-impl-logging"></a>

The `[LoggingMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/LoggingMetricPublisher.html)` implementation outputs metrics directly to your application's console or log files. This approach is ideal for development, debugging, and understanding what metrics the SDK collects without requiring external services like Amazon CloudWatch.

Unlike `CloudWatchMetricPublisher` and `EmfMetricLoggingPublisher`, `LoggingMetricPublisher` provides immediate output with no delays or external dependencies. This makes it perfect for local development and troubleshooting scenarios.

## When to use LoggingMetricPublisher
<a name="logging-metric-publisher-when-to-use"></a>

Use `LoggingMetricPublisher` when you need to:
+ Debug metric collection during development
+ Understand what metrics the SDK collects for your operations
+ Troubleshoot performance issues locally
+ Test metric collection without external service dependencies
+ View metrics immediately in your console or log files

**Note**  
`LoggingMetricPublisher` is not recommended for production environments where you need persistent metric storage and analysis capabilities.

## Set up console logging for metrics
<a name="logging-metric-publisher-setup"></a>

To see `LoggingMetricPublisher` output, configure your logging framework to display `INFO` level messages. The following `log4j2.xml` configuration ensures metrics appear in your console:

```
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="ConsoleAppender"/>
        </Root>
        <!-- Ensure LoggingMetricPublisher output appears. -->
        <Logger name="software.amazon.awssdk.metrics.LoggingMetricPublisher" level="INFO" />
    </Loggers>
</Configuration>
```

This configuration directs the SDK to output metrics to your console at the `INFO` level. The `LoggingMetricPublisher` logger configuration ensures that metric output appears even if your root logger uses a higher level like `WARN` or `ERROR`.

## Enable console metrics for a service client
<a name="logging-metric-publisher-basic-usage"></a>

The following example shows how to create a `LoggingMetricPublisher` and use it with an Amazon Simple Storage Service client:

```
import software.amazon.awssdk.metrics.LoggingMetricPublisher;
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;

// Create a LoggingMetricPublisher with default settings.
MetricPublisher metricPublisher = LoggingMetricPublisher.create();

// Add the publisher to your service client.
S3Client s3Client = S3Client.builder()
    .region(Region.US_EAST_1)
    .overrideConfiguration(config -> config.addMetricPublisher(metricPublisher))
    .build();

// Make requests - metrics will appear in your console.
s3Client.listBuckets();

// Clean up resources.
metricPublisher.close();
s3Client.close();
```

## Choose metric output format
<a name="logging-metric-publisher-formatting-options"></a>

`LoggingMetricPublisher` supports two output formats:
+ **PLAIN format (default):** Outputs metrics as compact, single-line entries
+ **PRETTY format:** Outputs metrics in a multi-line, human-readable format

The following example shows how to use the PRETTY format for easier reading during development:

```
import org.slf4j.event.Level;
import software.amazon.awssdk.metrics.LoggingMetricPublisher;

// Create a LoggingMetricPublisher with PRETTY format.
MetricPublisher prettyMetricPublisher = LoggingMetricPublisher.create(
    Level.INFO, 
    LoggingMetricPublisher.Format.PRETTY
);

// Use with your service client.
S3Client s3Client = S3Client.builder()
    .region(Region.US_EAST_1)
    .overrideConfiguration(config -> config.addMetricPublisher(prettyMetricPublisher))
    .build();
```

## Complete example
<a name="logging-metric-publisher-complete-example"></a>

The following example demonstrates using `LoggingMetricPublisher` in two ways:
+ At the service client level
+ For a single request

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
import software.amazon.awssdk.metrics.LoggingMetricPublisher;
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.ListBucketsRequest;
import software.amazon.awssdk.services.s3.model.ListBucketsResponse;

/**
 * Demonstrates how to use LoggingMetricPublisher with AWS S3 SDK for Java 2.x.
 * <p>
 * This demo focuses on the S3 listBuckets operation to show how metrics are collected
 * and logged to the console for development and debugging purposes.
 * <p>
 * LoggingMetricPublisher is ideal for:
 * - Development and debugging
 * - Console output for troubleshooting
 * - Understanding what metrics are being collected
 * - Testing metric collection without external dependencies
 */
public class S3LoggingMetricPublisherDemo {

    private static final Logger logger = LoggerFactory.getLogger(S3LoggingMetricPublisherDemo.class);

    public static void main(String[] args) {
        S3LoggingMetricPublisherDemo demo = new S3LoggingMetricPublisherDemo();
        demo.demonstrateUsage();
    }

    /**
     * Demonstrates basic usage with S3Client and metrics enabled at the client level.
     */
    private void demonstrateUsage() {

        // Create a LoggingMetricPublisher with default settings. The SDK logs metrics as text in a single line.
        // The default settings are equivalent to using `LoggingMetricPublisher.Format.PLAIN`.

        MetricPublisher metricPublisher = LoggingMetricPublisher.create();

        // Create an S3 client with metrics enabled.
        try (S3Client s3Client = S3Client.builder()
                .region(Region.US_EAST_1)
                .overrideConfiguration(config -> config.addMetricPublisher(metricPublisher))
                .build()) {

            // Make the listBuckets request - metrics will be logged to console.
            ListBucketsResponse response = s3Client.listBuckets(ListBucketsRequest.builder().build());

            // The next block shows the using a different LoggingMetricPublisher with a `PRETTY` format.
            // Since the metric publisher is added to the request using the `overrideConfiguration`, this formatting
            // applies only to the one request.
            try {
                s3Client.listBuckets(ListBucketsRequest.builder()
                        .overrideConfiguration(config -> config
                                .addMetricPublisher(LoggingMetricPublisher.create(
                                        Level.INFO, LoggingMetricPublisher.Format.PRETTY)))
                        .build());
            } catch (Exception e) {
                logger.info("Request failed with metrics logged: {}", e.getMessage());
            }
            logger.info("Found {} buckets in your AWS account.", response.buckets().size());

        } catch (Exception e) {
            logger.error("Error during S3 operation: {}", e.getMessage());
            logger.info("Note: This is expected if AWS credentials are not configured.");
        }

        // Close the metric publisher to flush any remaining metrics.
        metricPublisher.close();
    }
}
```

The code logs the following to the console:

```
INFO  LoggingMetricPublisher - Metrics published: MetricCollection(name=ApiCall, metrics=[MetricRecord(metric=MarshallingDuration, value=PT0.005409792S), MetricRecord(metric=RetryCount, value=0), MetricRecord(metric=ApiCallSuccessful, value=true), MetricRecord(metric=OperationName, value=ListBuckets), MetricRecord(metric=EndpointResolveDuration, value=PT0.000068S), MetricRecord(metric=ApiCallDuration, value=PT0.163802958S), MetricRecord(metric=CredentialsFetchDuration, value=PT0.145686542S), MetricRecord(metric=ServiceEndpoint, value=https://s3.amazonaws.com), MetricRecord(metric=ServiceId, value=S3)], children=[MetricCollection(name=ApiCallAttempt, metrics=[MetricRecord(metric=TimeToFirstByte, value=PT0.138816S), MetricRecord(metric=SigningDuration, value=PT0.007803459S), MetricRecord(metric=ReadThroughput, value=165153.96002660287), MetricRecord(metric=ServiceCallDuration, value=PT0.138816S), MetricRecord(metric=AwsExtendedRequestId, value=e13Swj3uwn0qP1Oz+m7II5OGq7jf8xxT8H18iDfRBCQmDg+gU4ek91Xrsl8XxRLROlIzCAPQtsQF0DAAWOb8ntuKCzX2AJdj), MetricRecord(metric=HttpStatusCode, value=200), MetricRecord(metric=BackoffDelayDuration, value=PT0S), MetricRecord(metric=TimeToLastByte, value=PT0.148915667S), MetricRecord(metric=AwsRequestId, value=78AW9BM7SWR6YMGB)], children=[MetricCollection(name=HttpClient, metrics=[MetricRecord(metric=MaxConcurrency, value=50), MetricRecord(metric=AvailableConcurrency, value=0), MetricRecord(metric=LeasedConcurrency, value=1), MetricRecord(metric=ConcurrencyAcquireDuration, value=PT0.002623S), MetricRecord(metric=PendingConcurrencyAcquires, value=0), MetricRecord(metric=HttpClientName, value=Apache)], children=[])])])
INFO  LoggingMetricPublisher - [4e6f2bb5] ApiCall
INFO  LoggingMetricPublisher - [4e6f2bb5] ┌──────────────────────────────────────────┐
INFO  LoggingMetricPublisher - [4e6f2bb5] │ MarshallingDuration=PT0.000063S          │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ RetryCount=0                             │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ ApiCallSuccessful=true                   │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ OperationName=ListBuckets                │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ EndpointResolveDuration=PT0.000024375S   │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ ApiCallDuration=PT0.018463083S           │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ CredentialsFetchDuration=PT0.000022334S  │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ ServiceEndpoint=https://s3.amazonaws.com │
INFO  LoggingMetricPublisher - [4e6f2bb5] │ ServiceId=S3                             │
INFO  LoggingMetricPublisher - [4e6f2bb5] └──────────────────────────────────────────┘
INFO  LoggingMetricPublisher - [4e6f2bb5]     ApiCallAttempt
INFO  LoggingMetricPublisher - [4e6f2bb5]     ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ TimeToFirstByte=PT0.0165575S                                                                                          │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ SigningDuration=PT0.000301125S                                                                                        │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ ReadThroughput=1195591.792850103                                                                                      │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ ServiceCallDuration=PT0.0165575S                                                                                      │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ AwsExtendedRequestId=3QI1eenRuokdszWqZBmBMDUmko6FlSmHkM+CUMNMeLor7gJml4D4lv6QXUZ1zWoTgG+tHbr6yo2vHdz4h1P8PDovvtMFRCeB │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ HttpStatusCode=200                                                                                                    │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ BackoffDelayDuration=PT0S                                                                                             │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ TimeToLastByte=PT0.017952625S                                                                                         │
INFO  LoggingMetricPublisher - [4e6f2bb5]     │ AwsRequestId=78AVFAF795AAWAXH                                                                                         │
INFO  LoggingMetricPublisher - [4e6f2bb5]     └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
INFO  LoggingMetricPublisher - [4e6f2bb5]         HttpClient
INFO  LoggingMetricPublisher - [4e6f2bb5]         ┌───────────────────────────────────────┐
INFO  LoggingMetricPublisher - [4e6f2bb5]         │ MaxConcurrency=50                     │
INFO  LoggingMetricPublisher - [4e6f2bb5]         │ AvailableConcurrency=0                │
INFO  LoggingMetricPublisher - [4e6f2bb5]         │ LeasedConcurrency=1                   │
INFO  LoggingMetricPublisher - [4e6f2bb5]         │ ConcurrencyAcquireDuration=PT0.00004S │
INFO  LoggingMetricPublisher - [4e6f2bb5]         │ PendingConcurrencyAcquires=0          │
INFO  LoggingMetricPublisher - [4e6f2bb5]         │ HttpClientName=Apache                 │
INFO  LoggingMetricPublisher - [4e6f2bb5]         └───────────────────────────────────────┘
INFO  S3LoggingMetricPublisherDemo - Found 6 buckets in your AWS account.
```

### Additional artifacts for the example
<a name="logging-metric-publisher-complete-example-artifacts"></a>

Maven `pom.xml` file

```
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>s3-logging-metric-publisher-demo</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>AWS S3 LoggingMetricPublisher Demo</name>
    <description>Demonstrates how to use LoggingMetricPublisher with AWS S3 SDK for Java 2.x</description>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <aws.java.sdk.version>2.31.66</aws.java.sdk.version>
        <log4j.version>2.24.3</log4j.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- AWS SDK BOM for dependency management -->
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>${aws.java.sdk.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Log4j BOM for logging dependency management -->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-bom</artifactId>
                <version>${log4j.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- AWS S3 SDK for demonstration -->
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
        </dependency>

        <!-- Log4j2 SLF4J implementation -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
        </dependency>

        <!-- Log4j2 Core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
```

`Log4j2.xml` configuration file

```
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="ConsoleAppender"/>
        </Root>
        <!-- Ensure LoggingMetricPublisher output appears. -->
        <Logger name="software.amazon.awssdk.metrics.LoggingMetricPublisher" level="INFO"/>
    </Loggers>
</Configuration>
```

The metrics include timing information, service details, operation names, and HTTP status codes that help you understand your application's AWS API usage patterns.

## Next steps
<a name="logging-metric-publisher-next-steps"></a>

After using `LoggingMetricPublisher` for development and debugging, consider these options for production environments:
+ For long-running applications, use [CloudWatchMetricPublisher](metric-pub-impl-cwmp.md) to send metrics to Amazon CloudWatch for analysis and alerting
+ For AWS Lambda functions, use [EmfMetricLoggingPublisher](metric-pub-impl-emf.md) to publish metrics in CloudWatch Embedded Metric Format

# AWS SDK for Java 2.x: Comprehensive Metrics Reference
<a name="metrics-list"></a>

With the AWS SDK for Java 2.x, you can collect metrics from the service clients in your application and then publish (output) those metrics to [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html).

These tables list the metrics that you can collect and any HTTP client usage requirement.

For more information about enabling and configuring metrics for the SDK, see [Enabling SDK metrics](metrics.md).

## Metrics collected with each request
<a name="metrics-perrequest"></a>


| Metric name | Description | Type | 
| --- | --- | --- | 
|  ApiCallDuration  |  The duration of the API call. This includes all call attempts made.  |  Duration\$1  | 
|  ApiCallSuccessful  |  True if the API call succeeded, false otherwise.  |  Boolean  | 
|  CredentialsFetchDuration  |  The duration of time to fetch signing credentials for the API call.  |  Duration\$1  | 
| EndpointResolveDuration | The duration of time to resolve the endpoint used for the API call. | Duration\$1 | 
|  MarshallingDuration  |  The duration of time to marshall the SDK request to an HTTP request.  |  Duration\$1  | 
|  OperationName  |  The name of the service operation being invoked.  |  String  | 
|  RetryCount  |  The number of retries that the SDK performed in the execution of the request. 0 implies that the request worked the first time and that no retries were attempted. For more information about configuring retry behavior, see [Retry strategies](retry-strategy.md#retry-strategies).  |  Integer  | 
|  ServiceId  |  The unique ID for the service.  |  String  | 
|  ServiceEndpoint  |  The endpoint for the service.  |  URI  | 
|  TokenFetchDuration  | The duration of time to fetch signing credentials for the API call. | Duration\$1 | 

\$1[java.time.Duration](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html).

## Metrics collected for each request attempt
<a name="metrics-perattempt"></a>

Each API call might require multiple attempts before a response is received. These metrics are collected for each attempt.

### Core metrics
<a name="metrics-perattempt-core"></a>


| Metric name | Description | Type | 
| --- | --- | --- | 
|  AwsExtendedRequestId  |  The extended request ID of the service request.  |  String  | 
|  AwsRequestId  |  The request ID of the service request.  |  String  | 
|  BackoffDelayDuration  |  The duration of time that the SDK has waited before this API call attempt. The value is based on the `[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/retries/api/BackoffStrategy.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/retries/api/BackoffStrategy.html)` set on the client. See the [Retry strategies](retry-strategy.md#retry-strategies) section in this guide for more information.  |  Duration\$1  | 
| ErrorType |  The type of error that occurred for a call attempt. The following are possible values: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics-list.html)  | String | 
| ReadThroughput |  The read throughput of the client, defined as `NumberOfResponseBytesRead / (TTLB - TTFB)`. This value is in bytes per second. Note that this metric only measures the bytes read from within the `ResponseTransformer` or `AsyncResponseTransformer`. Data that is read outside the transformer—for example when the response stream is returned as the result of the transformer—is not included in the calculation.  | Double | 
| WriteThroughput |  The write throughput of the client, defined as `RequestBytesWritten / (LastByteWrittenTime - FirstByteWrittenTime)`. This value is in bytes per second. This metric measures the rate at which the SDK provides the request body to the HTTP client. It excludes connection setup, TLS handshake time, and server processing time. This metric is only reported for requests that have a streaming body such as S3 PutObject. Note that this metric does not account for buffering in the HTTP client layer. The actual network transmission rate may be lower if the HTTP client buffers data before sending. This metric represents an upper bound of the network throughput.  | Double | 
|  ServiceCallDuration  |  The duration of time to connect to the service (or acquire a connection from the connection pool), send the serialized request and receive the initial response (for example HTTP status code and headers). This DOES NOT include the time to read the entire response from the service.  |  Duration\$1  | 
|  SigningDuration  |  The duration of time to sign the HTTP request.  |  Duration\$1  | 
| TimeToFirstByte | The duration of time from sending the HTTP request (including acquiring a connection) to the service, and receiving the first byte of the headers in the response. | Duration\$1 | 
| TimeToLastByte |  The duration of time from sending the HTTP request (including acquiring a connection) to the service, and receiving the last byte of the response. Note that for APIs that return streaming responses, this metric spans the time until the `ResponseTransformer` or `AsyncResponseTransformer` completes.  | Duration\$1 | 
|  UnmarshallingDuration  |  The duration of time to unmarshall the HTTP response to an SDK response. Note: For streaming operations, this does not include the time to read the response payload.  |  Duration\$1  | 

\$1[java.time.Duration](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html).

### HTTP Metrics
<a name="metrics-perattempt-http"></a>


| Metric name | Description | Type | HTTP client required\$1 | 
| --- | --- | --- | --- | 
|  AvailableConcurrency  |  The number of additional concurrent requests that the HTTP client supports without establishing new connections to the target server. For HTTP/1 operations, this equals the number of idle TCP connections established with the service. For HTTP/2 operations, this equals the number of idle streams. Note: This value varies by HTTP client implementation: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics-list.html) The value is scoped to an individual HTTP client instance and excludes concurrency from other HTTP clients in the same JVM.  |  Integer  | Apache, Netty, CRT | 
|  ConcurrencyAcquireDuration  |  The duration of time to acquire a channel from the connection pool. For HTTP/1 operations, a channel equals a TCP connection. For HTTP/2 operations, a channel equals an HTTP/2 stream channel. Acquiring a new channel may include time for: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics-list.html)  |  Duration\$1  |  Apache, Netty, CRT  | 
|  HttpClientName  |  The name of the HTTP used for the request.  |  String  |  Apache, Netty, CRT  | 
|  HttpStatusCode  |  The status code of the HTTP response.  |  Integer  |  Any  | 
|  LeasedConcurrency  |  The number of requests that the HTTP client currently executes.  For HTTP/1 operations, this equals the number of active TCP connections with the service (excluding idle connections). For HTTP/2 operations, this equals the number of active HTTP streams with the service (excluding idle stream capacity).  Note: This value varies by HTTP client implementation: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics-list.html) The value is scoped to an individual HTTP client instance and excludes concurrency from other HTTP clients in the same JVM.  |  Integer  |  Apache, Netty, CRT  | 
|  LocalStreamWindowSize  |  The local HTTP/2 window size in bytes for the stream that executes this request.  |  Integer  |  Netty  | 
|  MaxConcurrency  |  The maximum number of concurrent requests that the HTTP client supports. For HTTP/1 operations, this equals the maximum number of TCP connections that the HTTP client can pool. For HTTP/2 operations, this equals the maximum number of streams that the HTTP client can pool. Note: This value varies by HTTP client implementation: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics-list.html) The value is scoped to an individual HTTP client instance and excludes concurrency from other HTTP clients in the same JVM.  |  Integer  |  Apache, Netty, CRT  | 
|  PendingConcurrencyAcquires  |  The number of requests that wait for concurrency from the HTTP client. For HTTP/1 operations, this equals the number of requests waiting for a TCP connection to establish or return from the connection pool. For HTTP/2 operations, this equals the number of requests waiting for a new stream (and possibly a new HTTP/2 connection) from the connection pool. Note: This value varies by HTTP client implementation: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics-list.html) The value is scoped to an individual HTTP client instance and excludes concurrency from other HTTP clients in the same JVM.  |  Integer  |  Apache, Netty, CRT  | 
|  RemoteStreamWindowSize  |  The remote HTTP/2 window size in bytes for the stream that executes this request.  |  Integer  |  Netty  | 

\$1[java.time.Duration](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html).

The terms used in the column mean:
+ Apache: the Apache-based HTTP client (`[ApacheHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache/ApacheHttpClient.html)`)
+ Netty: the Netty-based HTTP client (`[NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)`)
+ CRT: the AWS CRT-based HTTP client (`[AwsCrtAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.html)`)
+ Any: the collection of metric data does not depend on the HTTP client; this includes the URLConnection-based HTTP client (`[UrlConnectionHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html)`)

# Monitoring AWS SDK for Java 2.x applications
<a name="monitoring-overview"></a>

Monitoring is an important part of maintaining the reliability, availability, and performance of applications using the AWS SDK for Java 2.x. AWS provides the following monitoring tools to watch SDK for Java 2.x, report when something is wrong, and take automatic actions when appropriate:
+ *Amazon CloudWatch* monitors your AWS resources and and the applications you run on AWS in real time. You can collect and track metrics, create customized dashboards, and set alarms that notify you or take actions when a specified metric reaches a threshold that you specify. For example, you can have CloudWatch track CPU usage or other metrics of your Amazon EC2 instances and automatically launch new instances when needed. For more information, see the [Amazon CloudWatch User Guide](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/).
+ *Amazon CloudWatch Logs* enables you to monitor, store, and access your log files from Amazon EC2 instances, CloudTrail, and other sources. CloudWatch Logs can monitor information in the log files and notify you when certain thresholds are met. You can also archive your log data in highly durable storage. For more information, see the [Amazon CloudWatch Logs User Guide](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/).
+ *AWS CloudTrail* captures API calls and related events made by or on behalf of your AWS account and delivers the log files to an Amazon S3 bucket that you specify. You can identify which users and accounts called AWS, the source IP address from which the calls were made, and when the calls occurred. For more information, see the [AWS CloudTrail User Guide](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/).

# Logging with the SDK for Java 2.x
<a name="logging-slf4j"></a>

The AWS SDK for Java 2.x uses [SLF4J](https://www.slf4j.org/manual.html), which is an abstraction layer that enables the use of any one of several logging systems at runtime.

Supported logging systems include the Java Logging Framework and Apache[ Log4j 2](https://logging.apache.org/log4j/2.x/), among others. This topic shows you how to use Log4j 2 as the logging system for working with the SDK.

## Log4j 2 configuration file
<a name="log4j-configuration-file"></a>

You typically use a configuration file, named`log4j2.xml` with Log4j 2. Example configuration files are shown below. To learn more about the values used in the configuration file, see the [manual for Log4j configuration](https://logging.apache.org/log4j/2.x/manual/configuration.html).

The `log4j2.xml` file needs to be on the classpath when your application starts up. For a Maven project, put the file in the `<project-dir>/src/main/resources` directory.

The `log4j2.xml` configuration file specifies properties such as [logging level](https://logging.apache.org/log4j/2.x/manual/configuration.html#Loggers), where logging output is sent (for example, [to a file or to the console](https://logging.apache.org/log4j/2.x/manual/appenders.html)), and the [format of the output](https://logging.apache.org/log4j/2.x/manual/layouts.html). The logging level specifies the level of detail that Log4j 2 outputs. Log4j 2 supports the concept of multiple logging [https://logging.apache.org/log4j/2.x/manual/architecture.html#](https://logging.apache.org/log4j/2.x/manual/architecture.html#). The logging level is set independently for each hierarchy. The main logging hierarchy that you use with the AWS SDK for Java 2.x is `software.amazon.awssdk`.

## Add logging dependency
<a name="sdk-java-logging-classpath"></a>

To configure the Log4j 2 binding for SLF4J in your build file, use the following.

------
#### [ Maven ]

Add the following elements to your `pom.xml` file.

```
...
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-slf4j2-impl</artifactId>
   <version>VERSION</version>
</dependency>
...
```

------
#### [ Gradle–Kotlin DSL ]

Add the following to your `build.gradle.kts` file.

```
...
dependencies {
    ...
    implementation("org.apache.logging.log4j:log4j-slf4j2-impl:VERSION")
    ...
}
...
```

------

Use `2.20.0` for the minimum version of the `log4j-slf4j2-impl` artifact. For the latest version, use the version published to [Maven central](https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-slf4j2-impl). Replace *VERSION* with version you'll use.

## SDK-specific errors and warnings
<a name="sdk-java-logging-service"></a>

We recommend that you always leave the "software.amazon.awssdk" logger hierarchy set to "WARN" to catch any important messages from the SDK's client libraries. For example, if the Amazon S3 client detects that your application hasn’t properly closed an `InputStream` and could be leaking resources, the S3 client reports it through a warning message to the logs. This also ensures that messages are logged if the client has any problems handling requests or responses.

The following `log4j2.xml` file sets the `rootLogger` to "WARN", which causes warning and error-level messages from all loggers in the application to be output, *including* those in the "software.amazon.awssdk" hierarchy. Alternatively, you can explicitly set the "software.amazon.awssdk" logger hierarchy to "WARN" if `<Root level="ERROR">` is used.

**Example Log4j2.xml configuration file**

This configuration will log messages at the "ERROR" and "WARN" levels to the console for all logger hierarchies.

```
<Configuration status="WARN">
 <Appenders>
  <Console name="ConsoleAppender" target="SYSTEM_OUT">
   <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
  </Console>
 </Appenders>

 <Loggers>
  <Root level="WARN">
   <AppenderRef ref="ConsoleAppender"/>
  </Root>
 </Loggers>
</Configuration>
```

## Request/response summary logging
<a name="sdk-java-logging-request-response"></a>

Every request to an AWS service generates a unique AWS request ID that is useful if you run into an issue with how an AWS service is handling a request. AWS request IDs are accessible programmatically through [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html#requestId()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html#requestId()) objects in the SDK for any failed service call, and can also be reported through the "DEBUG" log level of the "software.amazon.awssdk.request" logger.

The following `log4j2.xml` file enables a summary of requests and responses.

```
<Configuration status="WARN">
 <Appenders>
  <Console name="ConsoleAppender" target="SYSTEM_OUT">
   <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
  </Console>
 </Appenders>

 <Loggers>
  <Root level="ERROR">
   <AppenderRef ref="ConsoleAppender"/>
  </Root>
  <Logger name="software.amazon.awssdk" level="WARN" />
  <Logger name="software.amazon.awssdk.request" level="DEBUG" />
 </Loggers>
</Configuration>
```

Here is an example of the log output:

```
2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Sending Request: DefaultSdkHttpFullRequest(httpMethod=POST, protocol=https, host=dynamodb.us-east-1.amazonaws.com, encodedPath=/, headers=[amz-sdk-invocation-id, Content-Length, Content-Type, User-Agent, X-Amz-Target], queryParameters=[])
2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Received successful response: 200, Request ID: QS9DUMME2NHEDH8TGT9N5V53OJVV4KQNSO5AEMVJF66Q9ASUAAJG, Extended Request ID: not available
```

If you are interested in only the request ID use `<Logger name="software.amazon.awssdk.requestId" level="DEBUG" />`.

## Debug-level SDK logging
<a name="sdk-debug-level-logging"></a>

If you need more detail about what the SDK is doing, you can set the logging level of the `software.amazon.awssdk` logger to `DEBUG`. At this level, the SDK outputs a large amount of detail, so we recommend that you set this level to resolve errors using integration tests. 

At this logging level, the SDK logs information about configuration, credentials resolution, execution interceptors, high-level TLS activity, request signing, and much more.

The following is a sampling of statements that are output by the SDK at `DEBUG` level for a `S3Client#listBuckets()` call.

```
DEBUG s.a.a.r.p.AwsRegionProviderChain:57 - Unable to load region from software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@324dcd31:Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region).
DEBUG s.a.a.c.i.h.l.ClasspathSdkHttpServiceProvider:85 - The HTTP implementation loaded is software.amazon.awssdk.http.apache.ApacheSdkHttpService@a23a01d
DEBUG s.a.a.c.i.ExecutionInterceptorChain:85 - Creating an interceptor chain that will apply interceptors in the following order: [software.amazon.awssdk.core.internal.interceptor.HttpChecksumValidationInterceptor@69b2f8e5, software.amazon.awssdk.awscore.interceptor.HelpfulUnknownHostExceptionInterceptor@6331250e, software.amazon.awssdk.awscore.eventstream.EventStreamInitialRequestInterceptor@a10c1b5, software.amazon.awssdk.awscore.interceptor.TraceIdExecutionInterceptor@644abb8f, software.amazon.awssdk.services.s3.auth.scheme.internal.S3AuthSchemeInterceptor@1a411233, software.amazon.awssdk.services.s3.endpoints.internal.S3ResolveEndpointInterceptor@70325d20, software.amazon.awssdk.services.s3.endpoints.internal.S3RequestSetEndpointInterceptor@7c2327fa, software.amazon.awssdk.services.s3.internal.handlers.StreamingRequestInterceptor@4d847d32, software.amazon.awssdk.services.s3.internal.handlers.CreateBucketInterceptor@5f462e3b, software.amazon.awssdk.services.s3.internal.handlers.CreateMultipartUploadRequestInterceptor@3d7fa3ae, software.amazon.awssdk.services.s3.internal.handlers.DecodeUrlEncodedResponseInterceptor@58065f0c, software.amazon.awssdk.services.s3.internal.handlers.GetBucketPolicyInterceptor@3605c4d3, software.amazon.awssdk.services.s3.internal.handlers.S3ExpressChecksumInterceptor@585c13de, software.amazon.awssdk.services.s3.internal.handlers.AsyncChecksumValidationInterceptor@187eb9a8, software.amazon.awssdk.services.s3.internal.handlers.SyncChecksumValidationInterceptor@726a6b94, software.amazon.awssdk.services.s3.internal.handlers.EnableTrailingChecksumInterceptor@6ad11a56, software.amazon.awssdk.services.s3.internal.handlers.ExceptionTranslationInterceptor@522b2631, software.amazon.awssdk.services.s3.internal.handlers.GetObjectInterceptor@3ff57625, software.amazon.awssdk.services.s3.internal.handlers.CopySourceInterceptor@1ee29c84, software.amazon.awssdk.services.s3.internal.handlers.ObjectMetadataInterceptor@7c8326a4]
DEBUG s.a.a.u.c.CachedSupplier:85 - (SsoOidcTokenProvider()) Cached value is stale and will be refreshed.
...
DEBUG s.a.a.c.i.ExecutionInterceptorChain:85 - Creating an interceptor chain that will apply interceptors in the following order: [software.amazon.awssdk.core.internal.interceptor.HttpChecksumValidationInterceptor@51351f28, software.amazon.awssdk.awscore.interceptor.HelpfulUnknownHostExceptionInterceptor@21618fa7, software.amazon.awssdk.awscore.eventstream.EventStreamInitialRequestInterceptor@15f2eda3, software.amazon.awssdk.awscore.interceptor.TraceIdExecutionInterceptor@34cf294c, software.amazon.awssdk.services.sso.auth.scheme.internal.SsoAuthSchemeInterceptor@4d7aaca2, software.amazon.awssdk.services.sso.endpoints.internal.SsoResolveEndpointInterceptor@604b1e1d, software.amazon.awssdk.services.sso.endpoints.internal.SsoRequestSetEndpointInterceptor@62566842]
...
DEBUG s.a.a.request:85 - Sending Request: DefaultSdkHttpFullRequest(httpMethod=GET, protocol=https, host=portal.sso.us-east-1.amazonaws.com, encodedPath=/federation/credentials, headers=[amz-sdk-invocation-id, User-Agent, x-amz-sso_bearer_token], queryParameters=[role_name, account_id])
DEBUG s.a.a.c.i.h.p.s.SigningStage:85 - Using SelectedAuthScheme: smithy.api#noAuth
DEBUG s.a.a.h.a.i.c.SdkTlsSocketFactory:366 - Connecting socket to portal.sso.us-east-1.amazonaws.com/18.235.195.183:443 with timeout 2000
...
DEBUG s.a.a.requestId:85 - Received successful response: 200, Request ID: bb4f40f4-e920-4b5c-8648-58f26e7e08cd, Extended Request ID: not available
DEBUG s.a.a.request:85 - Received successful response: 200, Request ID: bb4f40f4-e920-4b5c-8648-58f26e7e08cd, Extended Request ID: not available
DEBUG s.a.a.u.c.CachedSupplier:85 - (software.amazon.awssdk.services.sso.auth.SsoCredentialsProvider@b965857) Successfully refreshed cached value. Next Prefetch Time: 2024-04-25T22:03:10.097Z. Next Stale Time: 2024-04-25T22:05:30Z
DEBUG s.a.a.c.i.ExecutionInterceptorChain:85 - Interceptor 'software.amazon.awssdk.services.s3.endpoints.internal.S3RequestSetEndpointInterceptor@7c2327fa' modified the message with its modifyHttpRequest method.
...
DEBUG s.a.a.c.i.h.p.s.SigningStage:85 - Using SelectedAuthScheme: aws.auth#sigv4
...
DEBUG s.a.a.a.s.Aws4Signer:85 - AWS4 Canonical Request: GET
...
DEBUG s.a.a.h.a.a.i.s.DefaultV4RequestSigner:85 - AWS4 String to sign: AWS4-HMAC-SHA256
20240425T210631Z
20240425/us-east-1/s3/aws4_request
aafb7784627fa7a49584256cb746279751c48c2076f813259ef767ecce304d64
DEBUG s.a.a.h.a.i.c.SdkTlsSocketFactory:366 - Connecting socket to s3.us-east-1.amazonaws.com/52.217.41.86:443 with timeout 2000
...
```

The following `log4j2.xml` file configures the previous output.

```
<Configuration status="WARN">
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%-5p %c{1.}:%L - %m%n" />
        </Console>
    </Appenders>

    <Loggers>
        <Root level="WARN">
            <AppenderRef ref="ConsoleAppender"/>
        </Root>
        <Logger name="software.amazon.awssdk" level="DEBUG" />
    </Loggers>
</Configuration>
```

## Enable wire logging
<a name="sdk-java-logging-verbose"></a>

It can be useful to see the exact requests and responses that the SDK for Java 2.x sends and receives. If you need access to this information, you can temporarily enable it by adding the necessary configuration depending on the HTTP client the service client uses.

By default, synchronous service clients, such as the [S3Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html), use an underlying Apache HttpClient, and asynchronous service clients, such as the [S3AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html), use a Netty non-blocking HTTP client.

Here is a breakdown of HTTP clients you can use for the two categories of service clients:


| Synchronous HTTP Clients | Asynchronous HTTP Clients | 
| --- | --- | 
| [ApacheHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache/ApacheHttpClient.html) (default) | [NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html) (default) | 
| [UrlConnectionHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html) | [AwsCrtAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.html) | 
| [AwsCrtHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtHttpClient.html) |  | 
| [Apache5HttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache5/Apache5HttpClient.html)  | 

Consult the appropriate tab below for configuration settings you need to add depending on the underlying HTTP client.

**Warning**  
We recommend you only use wire logging for debugging purposes. Disable it in your production environments because it can log sensitive data. It logs the full request or response without encryption, even for an HTTPS call. For large requests (e.g., to upload a file to Amazon S3) or responses, verbose wire logging can also significantly impact your application’s performance.

------
#### [ ApacheHttpClient ]

Add the "org.apache.http.wire" logger to the `log4j2.xml` configuration file and set the level to "DEBUG".

The following `log4j2.xml` file turns on full wire logging for the Apache HttpClient.

```
<Configuration status="WARN">
 <Appenders>
  <Console name="ConsoleAppender" target="SYSTEM_OUT">
   <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
  </Console>
 </Appenders>

 <Loggers>
  <Root level="WARN">
   <AppenderRef ref="ConsoleAppender"/>
  </Root>
  <Logger name="software.amazon.awssdk" level="WARN" />
  <Logger name="software.amazon.awssdk.request" level="DEBUG" />
  <Logger name="org.apache.http.wire" level="DEBUG" />
 </Loggers>
</Configuration>
```

An additional Maven dependency on the `log4j-1.2-api` artifact is required for wire logging with Apache since it uses 1.2 under the hood. 

The full set of Maven dependencies for log4j 2, including wire logging for the Apache HTTP client are shown in the following build file snippets.

**Maven**

```
...
<dependencyManagement>
    ...
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-bom</artifactId>
            <version>VERSION</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
     </dependencies>
</dependencyManagement>
...
<!-- The following is needed for Log4j2 with SLF4J -->
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-slf4j2-impl</artifactId>
</dependency>

<!-- The following is needed for Apache HttpClient wire logging -->
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-1.2-api</artifactId>
</dependency>
...
```

**Gradle–Kotlin DSL**

```
...
dependencies {
    ...
    implementation(platform("org.apache.logging.log4j:log4j-bom:VERSION"))
    implementation("org.apache.logging.log4j:log4j-slf4j2-impl")
    implementation("org.apache.logging.log4j:log4j-1.2-api")
}
...
```

Use `2.20.0` for the minimum version of the `log4j-bom` artifact. For the latest version, use the version published to [Maven central](https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-bom). Replace *VERSION* with version you'll use.

------
#### [ Apache5HttpClient ]

Add the "org.apache.hc.client5.http.wire" logger to the `log4j2.xml` configuration file and set the level to "DEBUG".

The following `log4j2.xml` file turns on full wire logging for the Apache5 HttpClient.

```
<Configuration status="WARN">
 <Appenders>
  <Console name="ConsoleAppender" target="SYSTEM_OUT">
   <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
  </Console>
 </Appenders>

 <Loggers>
  <Root level="WARN">
   <AppenderRef ref="ConsoleAppender"/>
  </Root>
  <Logger name="software.amazon.awssdk" level="WARN" />
  <Logger name="software.amazon.awssdk.request" level="DEBUG" />
  <Logger name="org.apache.hc.client5.http.wire" level="DEBUG" />
 </Loggers>
</Configuration>
```

------
#### [ UrlConnectionHttpClient ]

To log details for service clients that use the `UrlConnectionHttpClient`, first create a `logging.properties` file with the following contents:

```
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=FINEST
sun.net.www.protocol.http.HttpURLConnection.level=ALL
```

Set the following JVM system property with the full path of the `logging.properties`:

```
-Djava.util.logging.config.file=/full/path/to/logging.properties
```

This configuration will log the only the headers of the request and response, for example:

```
<Request>  FINE: sun.net.www.MessageHeader@35a9782c11 pairs: {GET /fileuploadtest HTTP/1.1: null}{amz-sdk-invocation-id: 5f7e707e-4ac5-bef5-ba62-00d71034ffdc}{amz-sdk-request: attempt=1; max=4}{Authorization: AWS4-HMAC-SHA256 Credential=<deleted>/20220927/us-east-1/s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;host;x-amz-content-sha256;x-amz-date;x-amz-te, Signature=e367fa0bc217a6a65675bb743e1280cf12fbe8d566196a816d948fdf0b42ca1a}{User-Agent: aws-sdk-java/2.17.230 Mac_OS_X/12.5 OpenJDK_64-Bit_Server_VM/25.332-b08 Java/1.8.0_332 vendor/Amazon.com_Inc. io/sync http/UrlConnection cfg/retry-mode/legacy}{x-amz-content-sha256: UNSIGNED-PAYLOAD}{X-Amz-Date: 20220927T133955Z}{x-amz-te: append-md5}{Host: tkhill-test1.s3.amazonaws.com}{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}{Connection: keep-alive}
<Response> FINE: sun.net.www.MessageHeader@70a36a6611 pairs: {null: HTTP/1.1 200 OK}{x-amz-id-2: sAFeZDOKdUMsBbkdjyDZw7P0oocb4C9KbiuzfJ6TWKQsGXHM/dFuOvr2tUb7Y1wEHGdJ3DSIxq0=}{x-amz-request-id: P9QW9SMZ97FKZ9X7}{Date: Tue, 27 Sep 2022 13:39:57 GMT}{Last-Modified: Tue, 13 Sep 2022 14:38:12 GMT}{ETag: "2cbe5ad4a064cedec33b452bebf48032"}{x-amz-transfer-encoding: append-md5}{Accept-Ranges: bytes}{Content-Type: text/plain}{Server: AmazonS3}{Content-Length: 67}
```

To see the request/response bodies, add `-Djavax.net.debug=all` to the JVM properties. This additional property logs a great deal of information, including all SSL information. 

Within the log console or log file, search for `"GET"` or `"POST"` to quickly go to the section of the log containing actual requests and responses. Search for `"Plaintext before ENCRYPTION"` for requests and `"Plaintext after DECRYPTION"` for responses to see the full text of the headers and bodies.

------
#### [ NettyNioAsyncHttpClient ]

If your asynchronous service client uses the default `NettyNioAsyncHttpClient`, add two additional loggers to your `log4j2.xml` file to log HTTP headers and request/response bodies.

```
<Logger name="io.netty.handler.logging" level="DEBUG" />
<Logger name="io.netty.handler.codec.http2.Http2FrameLogger" level="DEBUG" />
```

Here is a complete `log4j2.xml` example:

```
<Configuration status="WARN">
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
        </Console>
    </Appenders>

    <Loggers>
        <Root level="WARN">
            <AppenderRef ref="ConsoleAppender"/>
        </Root>
        <Logger name="software.amazon.awssdk" level="WARN" />
        <Logger name="software.amazon.awssdk.request" level="DEBUG" />
        <Logger name="io.netty.handler.logging" level="DEBUG" />
        <Logger name="io.netty.handler.codec.http2.Http2FrameLogger" level="DEBUG" />
    </Loggers>
</Configuration>
```

These settings log all header details and request/response bodies.

------
#### [ AwsCrtAsyncHttpClient/AwsCrtHttpClient ]

If you have configured your service client to use an instance of an AWS CRT-based HTTP client, you can log details by setting JVM system properties or programmatically.


|  | 
| --- |
|  Log to a file at "Debug" level  | 
|  Using system properties: <pre>-Daws.crt.log.level=Trace <br />-Daws.crt.log.destination=File <br />-Daws.crt.log.filename=<path to file></pre>  |  Programmatically: <pre>import software.amazon.awssdk.crt.Log;<br /><br />// Execute this statement before constructing the SDK service client.<br />Log.initLoggingToFile(Log.LogLevel.Trace, "<path to file>");</pre>  | 
|  Log to the console at "Debug" level  | 
|  Using system properties: <pre>-Daws.crt.log.level=Trace <br />-Daws.crt.log.destination=Stdout</pre>  |  Programmatically: <pre>import software.amazon.awssdk.crt.Log;<br /><br />// Execute this statement before constructing the SDK service client.<br />Log.initLoggingToStdout(Log.LogLevel.Trace);</pre>  | 

For security reasons, at the "Trace" level the AWS CRT-based HTTP clients log only response headers. Request headers, request bodies, and response bodies are not logged.

------