

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 에서 관찰 기능 구성 AWS SDK for Java 2.x
<a name="observability"></a>

원격 측정은 시스템의 동작을 모니터링하고 분석할 수 있도록 원격 소스에서 데이터를 자동으로 수집하고 전송하는 기능입니다.

SDK for Java 2.x의 관찰성은 개발자에게 전체 요청 수명 주기를 캡처하는 풍부한 원격 측정 데이터를 AWS 서비스 통해 Java 애플리케이션이 어떻게 상호 작용하는지에 대한 포괄적인 인사이트를 제공합니다. 이러한 기능을 사용하면 지표, 로그 및 추적과 같은 원격 측정 신호를 수집, 분석 및 시각화하여 요청 패턴을 모니터링하고, 병목 현상을 식별하고, 애플리케이션의 AWS 상호 작용을 최적화하여 안정성과 성능을 개선할 수 있습니다.

**Topics**
+ [Metrics](metrics.md)
+ [모니터링](monitoring-overview.md)
+ [로깅](logging-slf4j.md)

# 에서 SDK 지표 게시 AWS SDK for Java 2.x
<a name="metrics"></a>

를 사용하면 애플리케이션의 서비스 클라이언트 및 요청에 대한 지표를 수집하고 Amazon CloudWatch Logs의 출력을 분석한 다음 조치를 취할 AWS SDK for Java 2.x 수 있습니다.

기본적으로 SDK에서 지표 수집은 비활성화되어 있습니다. 이 항목은 활성화하고 구성하는 데 도움이 됩니다.

## SDK 지표 사용 시작하기
<a name="getting-started-with-metrics"></a>

애플리케이션에서 지표 수집을 사용하려면 사용 사례에 따라 `[MetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/MetricPublisher.html)` 인터페이스의 적절한 구현을 선택하고 자세한 설정 안내를 따릅니다.

**장기 실행 애플리케이션의 경우:**
+ `[CloudWatchMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/cloudwatch/CloudWatchMetricPublisher.html)` 사용
+ 전체 설정 안내, 코드 예제 및 구성 옵션은 [장기 실행 애플리케이션의 SDK 지표 게시](metric-pub-impl-cwmp.md)를 참조하세요.

** AWS Lambda 함수의 경우:**
+ `[EmfMetricLoggingPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/emf/EmfMetricLoggingPublisher.html)` 사용
+ 전체 설정 지침, 종속성 및 Lambda별 구성은 [AWS Lambda 함수에 대한 SDK 지표 게시](metric-pub-impl-emf.md)를 참조하세요.

**문제 해결 및 콘솔 출력의 경우:**
+ `[LoggingMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/LoggingMetricPublisher.html)` 사용
+ 설정 안내, 형식 지정 옵션, 로컬 개발 및 문제 해결을 위한 예제는 [개발 및 디버깅용 콘솔에 대한 SDK 지표 출력](metric-pub-impl-logging.md)을 참조하세요.

## 빠른 구현 미리 보기
<a name="quick-implementation-preview"></a>

각 사용 사례에 대한 지표 사용 설정은 다음과 같습니다.

**장기 실행 애플리케이션:**

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

**Lambda 함수:**

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

**개발 및 디버깅:**

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

## AWS CRT 기반 S3 클라이언트의 지표 제한
<a name="metrics-using-s3-crt-based-client"></a>

[AWS CRT 기반 S3 클라이언트](crt-based-s3-client.md)는 현재 SDK 지표 수집을 지원하지 않습니다. AWS CRT 기반 S3 클라이언트 인스턴스의 빌더는 지표 게시자를 구성하는 방법을 제공하지 [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)않습니다.

## 지표는 언제 사용할 수 있나요?
<a name="when-are-metrics-available"></a>

지표는 일반적으로 Java용 SDK가 지표를 생성한 후 5\$110분 이내에 사용할 수 있습니다. 정확한 최신 지표를 확인하려면 Java 애플리케이션에서 지표를 전송한 후 최소 10분 후에 Cloudwatch를 확인하세요.

## 어떤 정보가 수집되나요?
<a name="what-information-is-collected"></a>

지표 수집에는 다음이 포함됩니다.
+ 성공 또는 실패 여부를 포함한 API 요청 수
+ 반환된 예외를 포함하여 API 요청에서 호출 AWS 서비스 하는에 대한 정보
+ 마샬링, 서명, HTTP 요청과 같은 다양한 작업에 소요되는 기간
+ 열린 연결 수, 보류 중인 요청 수, 사용된 HTTP 클라이언트 이름과 같은 HTTP 클라이언트 측정항목

**참고**  
사용 가능한 지표는 HTTP 클라이언트마다 다릅니다.

전체 목록은 [서비스 클라이언트 메트릭](metrics-list.md)을 참조하세요.

## 이 정보를 어떻게 사용할 수 있나요?
<a name="how-can-i-use-this-information"></a>

SDK가 수집하는 측정항목을 사용하여 애플리케이션의 서비스 클라이언트를 모니터링할 수 있습니다. 전반적인 사용 추세를 살펴보고, 이상 현상을 식별하고, 반환된 서비스 클라이언트 예외를 검토하거나, 특정 문제를 이해하기 위해 자세히 알아볼 수 있습니다. Amazon CloudWatch Logs를 사용하면 애플리케이션이 정의한 조건에 도달하는 즉시 알림을 보내는 경보를 만들 수도 있습니다.

자세한 내용은 [Amazon CloudWatch Logs 사용 설명서](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/)에서 [Amazon CloudWatch 지표 사용](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/working_with_metrics.html) 및 [Amazon CloudWatch 경보 사용](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)을 참조하세요.

# 를 사용하여 장기 실행 애플리케이션의 SDK 지표 게시 AWS SDK for Java 2.x
<a name="metric-pub-impl-cwmp"></a>

`[CloudWatchMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/cloudwatch/CloudWatchMetricPublisher.html)` 구현은 지연과 지표를 집계하고 지연되어 Amazon CloudWatch에 주기적으로 업로드하기 때문에 장기 실행 애플리케이션에 가장 적합합니다.

지표 게시자의 기본 설정은 메모리 사용량과 CloudWatch 비용을 최소화하면서 지표 데이터에 대한 유용한 인사이트를 제공하기 위한 것입니다.

## 설정
<a name="prerequisitesmetrics"></a>

`CloudWatchMetricPublisher`를 통해 지표를 사용 설정하고 사용하려면 먼저 다음 단계를 완료해야 합니다.

### 1단계: 필수 종속성 추가
<a name="cwmp-set-up-deps"></a>

 AWS SDK for Java버전 `2.14.0` 또는 그 이상의 버전을 사용하도록 프로젝트 종속성(예: `pom.xml` 또는 `build.gradle` 파일)을 구성하세요.

프로젝트 종속 항목에 버전 번호 `2.14.0` 이상의 `cloudwatch-metric-publisher` artifactId를 포함해야 합니다.

예제:

```
<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>
```

### 2단계: 필수 권한 구성
<a name="cwmp-set-up-perms"></a>

SDK for Java에서 지표 게시자를 사용하여 IAM ID에 대한 `cloudwatch:PutMetricData` 권한을 사용합니다.

## 특정 요청에 대한 지표 활성화
<a name="enable-metrics-for-a-specific-request"></a>

다음 클래스는 Amazon DynamoDB에 대한 요청에서 CloudWatch 지표 게시자를 사용하는 방법을 보여줍니다. 기본 메트릭 게시자 구성을 사용합니다.

```
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();
    }
}
```

**중요**  
서비스 클라이언트가 더 이상 사용되지 않을 때 애플리케이션이 `[MetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/MetricPublisher.html)` 인스턴스에서 `close`를 직접적으로 호출하는지 확인합니다. 이렇게 하지 않으면 스레드 또는 파일 설명자 누수가 발생할 수 있습니다.

## 특정 서비스 클라이언트에 대한 요약 지표 사용
<a name="enable-metrics-for-a-specific-service-client"></a>

다음 코드 조각은 서비스 클라이언트의 기본 설정으로 CloudWatch 지표 게시자를 사용하는 방법을 보여줍니다.

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

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

## CloudWatch 지표 게시자 사용자 지정
<a name="customize-metrics-publisher"></a>

다음 클래스는 특정 서비스 클라이언트의 지표 게시자에 대한 사용자 지정 구성을 사용하는 방법을 보여줍니다. 사용자 지정에는 특정 프로필 로드, 지표 게시자가 요청을 보내는 AWS 리전 지정, 게시자가 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();
    }
}
```

이전 코드 조각에 표시된 사용자 지정은 다음과 같은 효과가 있습니다.
+ `cloudWatchClient` 메서드를 사용하면 지표를 전송하는 데 사용되는 CloudWatch 클라이언트를 사용자 지정할 수 있습니다. 이 예제에서는 클라이언트가 지표를 보내는 *us-east-1* 기본값과 다른 리전을 사용합니다. 또한 CloudWatch에 대한 요청을 인증하는 데 사용되는 자격 증명인 *cloudwatch*라는 다른 이름의 프로필을 사용합니다. 이러한 자격 증명에는 `cloudwatch:PutMetricData` 작업에 대한 권한이 있어야 합니다.
+ `uploadFrequency` 메서드를 사용하면 지표 게시자가 CloudWatch에 지표를 업로드하는 빈도를 지정할 수 있습니다. 기본값은 분당 1회입니다.
+ `maximumCallsPerUpload` 메서드는 업로드당 발생하는 직접 호출 수를 제한합니다. 기본값은 무제한입니다.
+ 기본적으로 SDK for Java 2.x는 네임스페이스(`AwsSdk/JavaSdk2`) 아래에 지표를 게시합니다. `namespace` 메서드를 사용하여 다른 값을 지정할 수 있습니다.
+ 기본적으로 SDK는 요약 지표를 게시합니다. 요약 지표는 평균, 최소, 최대, 합계 및 샘플 수로 구성됩니다. SDK는 `detailedMetrics` 메서드에 하나 이상의 SDK 지표를 지정하여 각 지표에 대한 추가 데이터를 게시합니다. 이 추가 데이터는 CloudWatch에서 쿼리할 수 있는 p90 및 p99와 같은 백분위수 통계를 사용합니다. 세부 지표는 SDK 클라이언트 요청의 종단간 지연 시간을 측정하는 `APICallDuration`과 같은 지연 시간 지표에 특히 유용합니다. `[CoreMetric](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/metrics/CoreMetric.html)` 클래스의 필드를 사용하여 다른 일반적인 SDK 지표를 지정할 수 있습니다.

**다음 단계:** Lambda 함수로도 작업하는 경우 EMF 기반 [지표 게시를 위한 AWS Lambda 함수에 대한 SDK](metric-pub-impl-emf.md) 지표 게시를 참조하세요.

# 를 사용하여 AWS Lambda 함수에 대한 SDK 지표 게시 AWS SDK for Java 2.x
<a name="metric-pub-impl-emf"></a>

Lambda 함수는 일반적으로 밀리초에서 분 단위 동안 실행되므로 `CloudWatchMetricPublisher`에서 발생하는 지표 전송 지연으로 인해 데이터가 손실될 위험이 있습니다.

`[EmfMetricLoggingPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/emf/EmfMetricLoggingPublisher.html)`는 지표를 [CloudWatch Embedded Metric Format(EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html)의 정형화된 로그 항목으로 즉시 작성하여 보다 적합한 접근 방식을 제공합니다. `EmfMetricLoggingPublisher`는 AWS Lambda 및 Amazon Elastic Container Service등 Amazon CloudWatch Logs와의 통합이 내장된 실행 환경에서 작동합니다.

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

`EmfMetricLoggingPublisher`를 통해 지표를 사용 설정하고 사용하려면 먼저 다음 단계를 완료해야 합니다.

### 1단계: 필수 종속성 추가
<a name="metric-pub-impl-emf-set-up-deps"></a>

 AWS SDK for Java버전 `2.30.3` 또는 그 이상의 버전을 사용하도록 프로젝트 종속성(예: `pom.xml` 또는 `build.gradle` 파일)을 구성하세요.

프로젝트 종속 항목에 버전 번호 `2.30.3` 이상의 `emf-metric-logging-publisher` artifactId를 포함해야 합니다.

예제:

```
<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>
```

### 2단계: 필수 권한 구성
<a name="metric-pub-impl-emf-set-up-perm"></a>

SDK for Java에서 지표 게시자를 사용하여 IAM ID에 대한 `logs:PutLogEvents` 권한을 사용 설정해 EMF 형식 로그를 작성합니다.

### 3단계: 로깅 설정
<a name="metric-pub-impl-emf-set-up-logger"></a>

적절한 지표 수집을 확보하려면 `INFO` 수준 이하(예: `DEBUG`)에서 콘솔에 출력하도록 로깅을 구성합니다. `log4j2.xml` 파일의 경우:

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

`log4j2.xml` 파일 설정 방법에 대한 자세한 내용은 이 가이드의 [로깅 주제](logging-slf4j.md)를 참조하세요.

## `EmfMetricLoggingPublisher` 구성 및 사용
<a name="metric-pub-impl-emf-use"></a>

다음 Lambda 함수 클래스는 먼저 `EmfMetricLoggingPublisher` 인스턴스를 만들고 구성한 다음 Amazon DynamoDB 서비스 클라이언트와 함께 사용합니다.

```
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";
    }
}
```

DynamoDB 클라이언트는 `putItem` 메서드를 실행할 경우 지표를 EMF 형식의 CloudWatch 로그 스트림에 자동으로 게시합니다.

### EMF 로그 이벤트의 예제
<a name="emf-logged-output"></a>

예를 들어 다음과 같이 구성된 로깅을 사용하여 GameHandler Lambda 함수에 다음 이벤트를 전송하는 경우입니다.

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

함수에서 이벤트를 처리한 후 다음 예제와 유사한 2개의 로그 이벤트를 찾습니다. 두 번째 이벤트의 JSON 객체에는 DynamoDB에 대한 `PutItem` 작업의 Java SDK 지표 데이터가 포함됩니다.

CloudWatch는 EMF 형식의 로그 이벤트를 수신하면 정형화된 JSON을 자동으로 구문 분석하여 지표 데이터를 추출합니다. 그런 다음 CloudWatch는 원본 로그 항목을 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
}
```

`EmfMetricLoggingPublisher.Builder`의 [API 설명서](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/publishers/emf/EmfMetricLoggingPublisher.Builder.html)에는 사용할 수 있는 구성 옵션이 나와 있습니다.

또한 [CloudWatchMetricPublisher에 표시된 대로](metric-pub-impl-cwmp.md#enable-metrics-for-a-specific-request) 단일 요청에 대해 EMF 지표 로깅을 사용할 수 있습니다.

**다음 단계:** 장기 실행 애플리케이션의 경우 CloudWatch 기반 지표 게시를 위해 [장기 실행 애플리케이션의 SDK 지표 게시](metric-pub-impl-cwmp.md)를 참조하세요.

# 를 사용하여 SDK 지표를 콘솔로 출력 AWS SDK for Java 2.x
<a name="metric-pub-impl-logging"></a>

`[LoggingMetricPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/metrics/LoggingMetricPublisher.html)` 구현은 지표를 애플리케이션의 콘솔 또는 로그 파일에 직접 출력합니다. 이 접근 방식은 Amazon CloudWatch와 같은 외부 서비스 없이 SDK가 수집하는 지표를 개발, 디버깅 및 이해하는 데 적합합니다.

`CloudWatchMetricPublisher` 및 `EmfMetricLoggingPublisher`와 달리 `LoggingMetricPublisher`는 지연이나 외부 종속성 없이 즉각적인 출력을 제공합니다. 따라서 로컬 개발 및 문제 해결 시나리오에 적합합니다.

## LoggingMetricPublisher를 사용해야 하는 경우
<a name="logging-metric-publisher-when-to-use"></a>

다음 작업 시 `LoggingMetricPublisher`를 사용합니다.
+ 개발 중 지표 수집 디버그
+ SDK가 작업에 대해 수집하는 지표 이해
+ 로컬 방식으로 성능 문제 해결
+ 외부 서비스 종속성 없이 지표 수집 테스트
+ 콘솔 또는 로그 파일에서 지표 즉시 보기

**참고**  
`LoggingMetricPublisher`는 영구 지표 스토리지 및 분석 기능이 필요한 프로덕션 환경에는 권장되지 않습니다.

## 지표용 콘솔 로깅 설정
<a name="logging-metric-publisher-setup"></a>

`LoggingMetricPublisher` 출력을 보려면 `INFO` 레벨 메시지를 표시하도록 로깅 프레임워크를 구성합니다. 다음 `log4j2.xml` 구성을 사용하면 지표가 콘솔에 표시됩니다.

```
<?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>
```

이 구성은 SDK가 `INFO` 레벨의 콘솔에 지표를 출력하도록 지시합니다. `LoggingMetricPublisher` 로거 구성을 사용하면 루트 로거가 `WARN` 또는 `ERROR` 등의 상위 수준을 사용하더라도 지표 출력이 나타납니다.

## 서비스 클라이언트에 대한 콘솔 지표 사용
<a name="logging-metric-publisher-basic-usage"></a>

다음 예제에서는 `LoggingMetricPublisher`를 만들고 Amazon Simple Storage Service 클라이언트와 함께 사용하는 방법을 보여줍니다.

```
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();
```

## 지표 출력 형식 선택
<a name="logging-metric-publisher-formatting-options"></a>

`LoggingMetricPublisher`에서 지원되는 2가지 출력 형식:
+ **PLAIN 형식(기본값):** 지표를 압축된 한 줄 항목으로 출력합니다.
+ **PRETTY 형식:** 사람이 읽을 수 있는 여러 줄 형식으로 지표를 출력합니다.

다음 예제에서는 개발 중에 읽기 쉽도록 PRETTY 형식을 사용하는 방법을 보여줍니다.

```
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();
```

## 전체 예제
<a name="logging-metric-publisher-complete-example"></a>

다음의 예제는 2가지 방식으로 `LoggingMetricPublisher`를 사용하는 쿼리를 보여줍니다.
+ 서비스 클라이언트 수준인 경우
+ 단일 요청인 경우

```
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();
    }
}
```

코드는 콘솔에 다음을 로그합니다.

```
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.
```

### 예제용 추가 아티팩트
<a name="logging-metric-publisher-complete-example-artifacts"></a>

Maven `pom.xml` 파일

```
<?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` 구성 파일

```
<?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>
```

지표에는 애플리케이션의 AWS API 사용 패턴을 이해하는 데 도움이 되는 타이밍 정보, 서비스 세부 정보, 작업 이름 및 HTTP 상태 코드가 포함됩니다.

## 다음 단계
<a name="logging-metric-publisher-next-steps"></a>

개발 및 디버깅에 `LoggingMetricPublisher`를 사용한 후 프로덕션 환경에 대해 다음 옵션을 고려합니다.
+ 장기 실행 애플리케이션의 경우 [CloudWatchMetricPublisher](metric-pub-impl-cwmp.md)를 사용하여 분석 및 알림용으로 Amazon CloudWatch에 지표를 전송합니다.
+  AWS Lambda 함수의 경우 [EmfMetricLoggingPublisher](metric-pub-impl-emf.md)를 사용하여 CloudWatch 임베디드 지표 형식으로 지표 게시

# AWS SDK for Java 2.x: 포괄적인 지표 참조
<a name="metrics-list"></a>

를 사용하면 애플리케이션의 서비스 클라이언트에서 지표를 수집한 다음 해당 지표를 [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html)에 게시(출력)할 AWS SDK for Java 2.x수 있습니다.

다음 표에는 수집할 수 있는 지표와 HTTP 클라이언트 사용 요구 사항이 나열되어 있습니다.

SDK 지표를 활성화 및 구성하는 자세한 내용은 [SDK 지표 활성화](metrics.md)를 참조하세요.

## 각 요청에서 수집된 지표
<a name="metrics-perrequest"></a>


| 지표 이름 | 설명 | 형식 | 
| --- | --- | --- | 
|  ApiCallDuration  |  API 직접 호출 지속 시간입니다. 여기에는 모든 직접 호출 시도가 포함됩니다.  |  지속 시간\$1  | 
|  ApiCallSuccessful  |  API 직접 호출이 성공하면 true이고, 그렇지 않으면 false입니다.  |  부울  | 
|  CredentialsFetchDuration  |  API 직접 호출용 서명 자격 증명을 가져오는 지속 시간입니다.  |  지속 시간\$1  | 
| EndpointResolveDuration | API 직접 호출에 사용되는 엔드포인트를 해결하는 데 걸리는 시간입니다. | 지속 시간\$1 | 
|  MarshallingDuration  |  SDK 요청을 HTTP 요청으로 마샬하는 데 걸리는 시간입니다.  |  지속 시간\$1  | 
|  OperationName  |  간접 호출 중인 서비스 작업의 이름입니다.  |  문자열  | 
|  RetryCount  |  SDK가 요청 실행 시 수행한 재시도 횟수입니다. 0은 요청이 처음 작동했고 재시도가 시도되지 않았음을 의미합니다. 재시도 동작 구성에 대한 자세한 내용은 [재시도 전략](retry-strategy.md#retry-strategies) 섹션을 참조하세요.  |  Integer  | 
|  ServiceId  |  서비스의 고유 ID입니다.  |  문자열  | 
|  ServiceEndpoint  |  서비스의 엔드포인트입니다.  |  URI  | 
|  TokenFetchDuration  | API 직접 호출용 서명 자격 증명을 가져오는 지속 시간입니다. | 지속 시간\$1 | 

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

## 각 요청 시도에 대해 수집된 지표
<a name="metrics-perattempt"></a>

응답을 수신하려면 각 API 호출에 여러 번 시도해야 할 수 있습니다. 이 지표는 각 요청 시도에 대해 수집됩니다.

### 주요 지표
<a name="metrics-perattempt-core"></a>


| 지표 이름 | 설명 | 형식 | 
| --- | --- | --- | 
|  AwsExtendedRequestId  |  서비스 요청의 확장 요청 ID입니다.  |  문자열  | 
|  AwsRequestId  |  서비스 요청의 요청 ID입니다.  |  문자열  | 
|  BackoffDelayDuration  |  이 API 직접 호출을 시도하기 전에 SDK가 대기한 지속 시간입니다. 값은 클라이언트에 설정된 `[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)`를 기반으로 합니다. 자세한 내용은 이 가이드의 [재시도 전략](retry-strategy.md#retry-strategies) 섹션을 참조하세요.  |  지속 시간\$1  | 
| ErrorType |  직접 호출 시도에서 발생한 오류 유형입니다. 유효한 값은 다음과 같습니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/metrics-list.html)  | 문자열 | 
| ReadThroughput |  `NumberOfResponseBytesRead / (TTLB - TTFB)`로 정의된 클라이언트의 읽기 처리량입니다. 이 값은 초당 바이트 단위입니다. 이 지표는 `ResponseTransformer` 또는 `AsyncResponseTransformer` 내에서 읽은 바이트만 측정합니다. 응답 스트림이 변환기의 결과로 반환되는 경우와 같이 변환기 외부에서 읽는 데이터는 계산에 포함되지 않습니다.  | 배정밀도 실수 | 
| WriteThroughput |  로 정의된 클라이언트의 쓰기 처리량입니다`RequestBytesWritten / (LastByteWrittenTime - FirstByteWrittenTime)`. 이 값은 초당 바이트 단위입니다. 이 지표는 SDK가 HTTP 클라이언트에 요청 본문을 제공하는 속도를 측정합니다. 연결 설정, TLS 핸드셰이크 시간 및 서버 처리 시간은 제외됩니다. 이 지표는 S3 PutObject와 같은 스트리밍 본문이 있는 요청에 대해서만 보고됩니다. 이 지표는 HTTP 클라이언트 계층의 버퍼링을 고려하지 않습니다. HTTP 클라이언트가 전송하기 전에 데이터를 버퍼링하면 실제 네트워크 전송 속도가 낮아질 수 있습니다. 이 지표는 네트워크 처리량의 상한을 나타냅니다.  | 배정밀도 실수 | 
|  ServiceCallDuration  |  서비스에 연결하고(또는 연결 풀에서 연결을 획득하고), 직렬화된 요청을 보내고, 초기 응답(예: HTTP 상태 코드 및 헤더)을 수신하는 지속 시간입니다. 여기에는 서비스의 전체 응답을 읽는 시간은 포함되지 않습니다.  |  지속 시간\$1  | 
|  SigningDuration  |  HTTP 요청에 서명하는 지속 시간입니다.  |  지속 시간\$1  | 
| TimeToFirstByte | 서비스에 HTTP 요청(연결 획득 포함)을 보내고 응답에서 헤더의 첫 번째 바이트를 수신하는 지속 시간입니다. | 지속 시간\$1 | 
| TimeToLastByte |  서비스에 HTTP 요청(연결 획득 포함)을 보내고 응답에서 마지막 바이트를 수신하는 지속 시간입니다. 스트리밍 응답을 반환하는 API의 경우 이 지표는 `ResponseTransformer` 또는 `AsyncResponseTransformer`가 완료될 때까지의 시간에 걸쳐 있습니다.  | 지속 시간\$1 | 
|  UnmarshallingDuration  |  SDK 응답에 대한 HTTP 응답을 언마샬하는 데 걸리는 지속 시간입니다. 참고: 스트리밍 작업의 경우 응답 페이로드를 읽는 데 걸리는 시간은 포함되지 않습니다.  |  지속 시간\$1  | 

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

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


| 지표 이름 | 설명 | 형식 | HTTP 클라이언트 필요\$1 | 
| --- | --- | --- | --- | 
|  AvailableConcurrency  |  대상 서버에 대한 새 연결을 설정하지 않고 HTTP 클라이언트가 지원하는 추가 동시 요청 수입니다. HTTP/1 작업의 경우 서비스에 설정된 유휴 TCP 연결 수와 같습니다. HTTP/2 작업의 경우 유휴 스트림 수와 같습니다. 참고: 이 값은 HTTP 클라이언트 구현에 따라 다릅니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/metrics-list.html) 값은 개별 HTTP 클라이언트 인스턴스로 범위가 지정되며 동일한 JVM의 다른 HTTP 클라이언트에서 동시성을 제외합니다.  |  Integer  | Apache, Netty, CRT | 
|  ConcurrencyAcquireDuration  |  연결 풀에서 채널을 획득하는 데 걸린 지속 시간입니다. HTTP/1 작업의 경우 채널은 TCP 연결과 같습니다. HTTP/2 작업의 경우 채널은 HTTP/2 스트림 채널과 같습니다. 새 채널을 획득하는 데 다음과 같은 시간이 포함될 수 있습니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/metrics-list.html)  |  지속 시간\$1  |  Apache, Netty, CRT  | 
|  HttpClientName  |  요청에 사용 중인 HTTP의 이름입니다.  |  문자열  |  Apache, Netty, CRT  | 
|  HttpStatusCode  |  HTTP 응답의 상태 코드입니다.  |  Integer  |  임의  | 
|  LeasedConcurrency  |  HTTP 클라이언트에서 실행하는 요청 수입니다. HTTP/1 작업의 경우 서비스와의 활성 TCP 연결 수와 같습니다(유휴 연결 제외). HTTP/2 작업의 경우 서비스가 포함된 활성 HTTP 스트림 수와 같습니다(유휴 스트림 용량 제외). 참고: 이 값은 HTTP 클라이언트 구현에 따라 다릅니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/metrics-list.html) 값은 개별 HTTP 클라이언트 인스턴스로 범위가 지정되며 동일한 JVM의 다른 HTTP 클라이언트에서 동시성을 제외합니다.  |  Integer  |  Apache, Netty, CRT  | 
|  LocalStreamWindowSize  |  이 요청이 실행되는 스트림의 로컬 HTTP/2 창 크기(바이트)입니다.  |  Integer  |  Netty  | 
|  MaxConcurrency  |  HTTP 클라이언트가 지원하는 최대 동시 요청 수입니다. HTTP/1 작업의 경우 HTTP 클라이언트가 풀링할 수 있는 최대 TCP 연결 수와 같습니다. HTTP/2 작업의 경우 HTTP 클라이언트가 풀링할 수 있는 최대 스트림 수와 같습니다. 참고: 이 값은 HTTP 클라이언트 구현에 따라 다릅니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/metrics-list.html) 값은 개별 HTTP 클라이언트 인스턴스로 범위가 지정되며 동일한 JVM의 다른 HTTP 클라이언트에서 동시성을 제외합니다.  |  Integer  |  Apache, Netty, CRT  | 
|  PendingConcurrencyAcquires  |  HTTP 클라이언트의 동시성을 기다리는 요청 수입니다. HTTP/1 작업의 경우 TCP 연결이 연결 풀에서 설정되거나 반환될 때까지 대기하는 요청 수와 같습니다. HTTP/2 작업의 경우 연결 풀에서 새 스트림(및 가능한 경우 새 HTTP/2 연결)을 기다리는 요청 수와 같습니다. 참고: 이 값은 HTTP 클라이언트 구현에 따라 다릅니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/metrics-list.html) 값은 개별 HTTP 클라이언트 인스턴스로 범위가 지정되며 동일한 JVM의 다른 HTTP 클라이언트에서 동시성을 제외합니다.  |  Integer  |  Apache, Netty, CRT  | 
|  RemoteStreamWindowSize  |  이 요청이 실행되는 스트림의 원격 HTTP/2 창 크기(바이트)입니다.  |  Integer  |  Netty  | 

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

열에 사용된 용어의 의미는 다음과 같습니다.
+ Apache: Apache 기반 HTTP 클라이언트(`[ApacheHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache/ApacheHttpClient.html)`)
+ Netty: Netty 기반 HTTP 클라이언트(`[NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)`)
+ CRT: AWS CRT 기반 HTTP 클라이언트(`[AwsCrtAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.html)`)
+ 임의: 지표 데이터 수집은 HTTP 클라이언트에 종속되지 않습니다. 여기에는 URLConnection 기반 HTTP 클라이언트(`[UrlConnectionHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html)`)가 포함됨

# AWS SDK for Java 2.x 애플리케이션 모니터링
<a name="monitoring-overview"></a>

AWS SDK for Java 2.x를 사용하는 애플리케이션의 신뢰성, 가용성 및 성능을 유지하려면 모니터링이 중요합니다. AWS는 SDK for Java 2.x를 모니터링하고, 이상이 있을 때 이를 보고하고, 필요한 경우 자동 조치를 취할 수 있도록 다음과 같은 모니터링 도구를 제공합니다.
+ *Amazon CloudWatch*는 AWS에서 실행하는 AWS 리소스와 애플리케이션을 실시간으로 모니터링합니다. 지표를 수집 및 추적하고, 사용자 지정 대시보드를 생성할 수 있으며, 지정된 지표가 지정한 임곗값에 도달하면 사용자에게 알리거나 조치를 취하도록 경보를 설정할 수 있습니다. 예를 들어 CloudWatch에서 Amazon EC2 인스턴스의 CPU 사용량 또는 기타 지표를 추적하고 필요할 때 자동으로 새 인스턴스를 시작할 수 있습니다. 자세한 내용은 [CloudWatch 사용 설명서](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/)를 참조하세요.
+ *Amazon CloudWatch Logs*로 Amazon EC2 인스턴스, CloudTrail, 기타 소스의 로그 파일을 모니터링, 저장 및 액세스할 수 있습니다. CloudWatch Logs는 로그 파일의 정보를 모니터링하고 특정 임곗값에 도달하면 사용자에게 알릴 수 있습니다. 또한 매우 내구력 있는 스토리지에 로그 데이터를 저장할 수 있습니다. 자세한 내용은 [Amazon CloudWatch Logs 사용 설명서](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/)를 참조하세요.
+ AWS CloudTrail은 직접 수행하거나 AWS 계정을 대신하여 수행한 API 직접 호출 및 관련 이벤트를 캡처하고 지정한 Amazon S3 버킷에 로그 파일을 전송합니다.** 어떤 사용자 및 계정이 AWS를 직접적으로 호출했는지, 어떤 소스 IP 주소에 직접 호출이 이루어졌는지, 언제 직접 호출이 발생했는지 확인할 수 있습니다. 자세한 내용은 [AWS CloudTrail 사용 설명서](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/)를 참조하세요.

# SDK를 사용하여 Java 2.x로 로깅하기
<a name="logging-slf4j"></a>

 AWS SDK for Java 2.x 는 런타임에 여러 로깅 시스템 중 하나를 사용할 수 있는 추상화 계층인 [SLF4J](https://www.slf4j.org/manual.html)를 사용합니다.

지원되는 로깅 시스템에는 Java Logging Framework와 Apache [Log4j 2](https://logging.apache.org/log4j/2.x/) 등이 있습니다. 이 항목에서는 Log4j 2를 SDK 작업을 위한 로깅 시스템으로 사용하는 방법을 보여줍니다.

## Log4j 구성 파일
<a name="log4j-configuration-file"></a>

일반적으로 Log4j 2을 포함하고 이름이 `log4j2.xml`로 지정된 구성 파일을 사용합니다. 아래에는 예제 구성 파일이 나와 있습니다. 구성 파일에 사용된 값에 대한 자세한 내용은 [Log4j 구성에 대한 설명서](https://logging.apache.org/log4j/2.x/manual/configuration.html)를 참조하세요.

애플리케이션을 시작할 때 `log4j2.xml` 파일이 클래스 경로에 있어야 합니다. Maven 프로젝트의 경우 파일을 `<project-dir>/src/main/resources` 디렉터리에 넣으세요.

`log4j2.xml` 구성 파일은 로깅 출력이 전송될 대상인 [로깅 수준](https://logging.apache.org/log4j/2.x/manual/configuration.html#Loggers)(예를 들면, [파일 또는 콘솔](https://logging.apache.org/log4j/2.x/manual/appenders.html)), [출력 형식](https://logging.apache.org/log4j/2.x/manual/layouts.html) 같은 속성을 지정합니다. 로깅 수준은 Log4j 2가 출력하는 세부 수준을 지정합니다. Log4j는 여러 로깅 [https://logging.apache.org/log4j/2.x/manual/architecture.html#](https://logging.apache.org/log4j/2.x/manual/architecture.html#)의 개념을 지원합니다. 로깅 수준은 각 계층마다 독립적으로 설정됩니다. 에서 사용하는 기본 로깅 계층 구조는 AWS SDK for Java 2.x 입니다`software.amazon.awssdk`.

## 로깅 종속성 추가
<a name="sdk-java-logging-classpath"></a>

빌드 파일에서 SLF4J Log4j 2 바인딩을 구성하려면 다음을 사용하세요.

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

다음 요소를 `pom.xml` 파일에 추가합니다.

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

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

다음을 `build.gradle.kts` 파일에 추가합니다.

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

------

`log4j-slf4j2-impl` 아티팩트의 최소 버전에 `2.20.0`를 사용 최신 버전의 경우 [Maven Central](https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-slf4j2-impl)에 게시된 버전을 사용하세요. *VERSION*을 사용할 버전으로 교체하세요.

## 서비스 관련 오류 및 경고
<a name="sdk-java-logging-service"></a>

SDK 클라이언트 라이브러리에서 중요한 메시지를 포착하려면 항상 "software.amazon.awssdk" 로거 계층 구조를 "WARN"으로 설정해 두는 것이 좋습니다. 예를 들어 Amazon S3 클라이언트가 애플리케이션이 `InputStream`를 제대로 닫지 않았고 리소스가 누출될 수 있음을 감지하면 S3 클라이언트는 경고 메시지를 통해 이를 로그에 보고합니다. 또한 클라이언트에 요청 또는 응답 처리 문제가 발생하는 경우에도 메시지가 기록됩니다.

다음 `log4j2.xml` 파일은 `rootLogger`를 “WARN”으로 설정합니다. 그러면 “software.amazon.awssdk” 계층 구조에 있는 로거를 *포함하여* 애플리케이션에 있는 모든 로거에서 경고 및 오류 수준 메시지가 출력됩니다. 또는 `<Root level="ERROR">`를 사용하는 경우 “software.amazon.awssdk” 로거 계층을 명시적으로 “WARN”으로 설정할 수도 있습니다.

**예제 Log4j2.xml 구성 파일**

이 구성은 모든 로거 계층에 대해 “ERROR” 및 “WARN” 수준의 메시지를 콘솔에 기록합니다.

```
<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>
```

## 요청 및 응답 요약 로깅
<a name="sdk-java-logging-request-response"></a>

에 대한 모든 요청은가 요청을 AWS 서비스 처리하는 방식에 문제가 발생할 경우 유용한 고유한 AWS 요청 ID를 AWS 서비스 생성합니다. AWS 요청 IDs는 실패한 서비스 호출에 대해 SDK의 [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()) 객체를 통해 프로그래밍 방식으로 액세스할 수 있으며 "software.amazon.awssdk.request" 로거의 "DEBUG" 로그 수준을 통해 보고할 수도 있습니다.

다음 `log4j2.xml` 파일은 요청 및 응답의 요약을 제공합니다.

```
<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>
```

다음은 로그 출력의 예입니다:

```
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
```

요청 ID에만 관심이 있는 경우 `<Logger name="software.amazon.awssdk.requestId" level="DEBUG" />`를 사용하세요.

## 디버그 수준 SDK 로깅
<a name="sdk-debug-level-logging"></a>

SDK가 수행하는 작업에 대한 자세한 정보가 필요한 경우 `software.amazon.awssdk` 로거의 로깅 수준을 `DEBUG`로 설정할 수 있습니다. 이 수준에서 SDK는 많은 세부 정보를 출력하므로 통합 테스트를 사용하여 오류를 해결하려면 이 수준을 설정하는 것이 좋습니다.

이 로깅 수준에서 SDK는 구성, 자격 증명 해결, 실행 인터셉터, 개괄적인 TLS 활동, 요청 서명 등에 대한 정보를 로깅합니다.

다음은 `S3Client#listBuckets()` 직접 호출에 대해 SDK가 `DEBUG` 수준에서 출력하는 문의 샘플입니다.

```
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
...
```

다음 `log4j2.xml` 파일은 이전 출력을 구성합니다.

```
<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>
```

## 유선 로깅 사용
<a name="sdk-java-logging-verbose"></a>

Java 2.x용 SDK가 보내고 받는 정확한 요청과 응답을 확인하는 것이 유용할 수 있습니다. 이 정보에 액세스해야 하는 경우 서비스 클라이언트가 사용하는 HTTP 클라이언트에 따라 필요한 구성을 추가하여 일시적으로 활성화할 수 있습니다.

기본적으로 [S3Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html)와 같은 동기 서비스 클라이언트는 기본 Apache HTTPClient를 사용하고 [S3AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html)와 같은 비동기 서비스 클라이언트는 Netty 비차단 HTTP 클라이언트를 사용합니다.

다음은 두 가지 범주의 서비스 클라이언트에 사용할 수 있는 HTTP 클라이언트의 분석입니다.


| 동기식 HTTP 클라이언트 | 동기식 HTTP 클라이언트 | 
| --- | --- | 
| [ApacheHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache/ApacheHttpClient.html)(기본값) | [NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)(기본값) | 
| [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)  | 

기본 HTTP 클라이언트에 따라 추가해야 하는 구성 설정은 아래 해당 탭을 참조하세요.

**주의**  
유선 로깅은 디버깅 목적에만 사용하는 것이 좋습니다. 로그에 민감한 데이터가 될 수 있기 때문에 프로덕션 환경에서는 비활성화합니다. HTTPS 호출을 포함, 암호화 없는 전체 요청이나 응답을 로그로 기록합니다. 대규모 요청(예:에 파일 업로드 Amazon S3) 또는 응답의 경우 자세한 유선 로깅도 애플리케이션 성능에 상당한 영향을 미칠 수 있습니다.

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

`log4j2.xml` 구성 파일에 “org.apache.http.wire” 로거를 추가하고 레벨을 “DEBUG”로 설정합니다.

다음 `log4j2.xml` 파일은 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>
```

Apache는 내부적으로 1.2를 사용하기 때문에 Apache를 통한 유선 로깅에는 `log4j-1.2-api` 아티팩트에 대한 추가 Maven 종속성이 필요합니다.

Apache HTTP 클라이언트의 유선 로깅을 포함하여 log4j 2의 전체 Maven 종속성 집합은 다음 빌드 파일 코드 조각에 나와 있습니다.

**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")
}
...
```

`log4j-bom` 아티팩트의 최소 버전에 `2.20.0`를 사용 최신 버전의 경우 [Maven Central](https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-bom)에 게시된 버전을 사용하세요. *VERSION*을 사용할 버전으로 교체하세요.

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

"org.apache.hc.client5.http.wire" 로거를 `log4j2.xml` 구성 파일에 추가하고 레벨을 "DEBUG"로 설정합니다.

다음 `log4j2.xml` 파일은 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 ]

`UrlConnectionHttpClient`를 사용하는 서비스 클라이언트의 세부 정보를 기록하려면 먼저 다음 내용이 포함된 `logging.properties` 파일을 만드세요.

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

`logging.properties`의 전체 경로를 사용하여 다음 JVM 시스템 속성을 설정합니다.

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

이 구성은 요청 및 응답의 헤더만 기록합니다. 예를 들면 다음과 같습니다.

```
<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}
```

요청 alc 응답 본문을 보려면 JVM 속성에 `-Djavax.net.debug=all`를 추가하세요. 이 추가 속성은 모든 SSL 정보를 포함하여 많은 양의 정보를 기록합니다.

로그 콘솔 또는 로그 파일 내에서 실제 요청 및 응답이 포함된 로그 단원으로 빠르게 이동하려면 `"GET"`나 `"POST"`를 검색하세요. 요청으로는 `"Plaintext before ENCRYPTION"`을 검색하고 응답으로는 `"Plaintext after DECRYPTION"` 검색하면 헤더와 본문의 전체 텍스트를 볼 수 있습니다.

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

비동기 서비스 클라이언트가 기본값 `NettyNioAsyncHttpClient`을 사용하는 경우 HTTP 헤더와 요청 및 응답 본문에 대한 `log4j2.xml` 파일에 로거 2개를 추가하세요.

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

다음은 전체 `log4j2.xml` 예제입니다.

```
<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>
```

이러한 설정은 모든 헤더 세부 정보와 요청 및 응답 본문을 기록합니다.

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

 AWS CRT 기반 HTTP 클라이언트의 인스턴스를 사용하는 서비스 클라이언트를 구성한 경우 JVM 시스템 속성을 설정하거나 프로그래밍 방식으로 세부 정보를 로그할 수 있습니다.


|  | 
| --- |
|  Log to a file at "Debug" level  | 
|  시스템 속성 사용: <pre>-Daws.crt.log.level=Trace <br />-Daws.crt.log.destination=File <br />-Daws.crt.log.filename=<path to file></pre>  |  프로그래밍 방식으로 <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  | 
|  시스템 속성 사용: <pre>-Daws.crt.log.level=Trace <br />-Daws.crt.log.destination=Stdout</pre>  |  프로그래밍 방식으로 <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>  | 

보안상의 이유로 "추적" 수준에서 AWS CRT 기반 HTTP 클라이언트는 응답 헤더만 로깅합니다. 요청 헤더, 요청 본문 및 응답 본문은 로깅되지 않습니다.

------