

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 可观测性
<a name="observability"></a>

可观测性是指可以根据系统发出的数据推断出其当前状态的程度。发出的数据通常称为遥测。

 适用于 Kotlin 的 AWS SDK 可以提供所有三种常见的遥测信号：指标、跟踪和日志。您可以连接[https://docs.aws.amazon.com/smithy-kotlin/api/latest/telemetry-api/aws.smithy.kotlin.runtime.telemetry/-telemetry-provider/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/telemetry-api/aws.smithy.kotlin.runtime.telemetry/-telemetry-provider/index.html)以将遥测数据发送到可观测性后端（例如或 [AWS X-Ray](https://docs.aws.amazon.com/xray/?icmpid=docs_homepage_devtools)A [ma](https://docs.aws.amazon.com/cloudwatch/?icmpid=docs_homepage_mgmtgov) zon CloudWatch），然后对其进行操作。

默认情况下，SDK 中仅启用日志功能，禁用其他遥测信号。本主题介绍如何启用和配置遥测输出。

**重要**  
`TelemetryProvider`目前是一个实验性 API，必须选择加入才能使用。

## 配置 `TelemetryProvider`
<a name="observability-conf-telemetry-provider"></a>

您可以在应用程序`TelemetryProvider`中为所有服务客户端或单个客户端全局配置。以下示例使用假设`getConfiguredProvider()`函数来演示 `TelemetryProvider` API 操作。本[遥测提供程序](observability-telemetry-providers.md)节介绍了 SDK 提供的实现信息。如果不支持提供商，则可以实现自己的支持或[在上打开功能请求 GitHub](https://github.com/awslabs/aws-sdk-kotlin/issues/new/choose)。

### 配置默认的全局遥测提供程序
<a name="observability-conf-telemetry-provider-global"></a>

默认情况下，每个服务客户端都尝试使用全局可用的遥测提供程序。这样，您只需设置一次提供程序，所有客户端都会使用它。在实例化任何服务客户端之前，只能执行一次。

要使用全局遥测提供程序，请先更新您的项目依赖项以添加遥测默认模块，如以下 Gradle 代码段所示。

（您可以导航到该*X.Y.Z*链接以查看可用的最新版本。）

```
dependencies {
    implementation(platform("aws.smithy.kotlin:bom:[https://github.com/smithy-lang/smithy-kotlin/releases/latest](https://github.com/smithy-lang/smithy-kotlin/releases/latest)"))
    implementation("aws.smithy.kotlin:telemetry-defaults")
    ...
}
```

然后在创建服务客户端之前设置全局遥测提供商，如以下代码所示。

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.smithy.kotlin.runtime.telemetry.GlobalTelemetryProvider
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val myTelemetryProvider = getConfiguredProvider()
    GlobalTelemetryProvider.set(myTelemetryProvider)

    S3Client.fromEnvironment().use { s3 ->
        …
    }     
}

fun getConfiguredProvider(): TelemetryProvider {
    TODO("TODO - configure a provider")
}
```

### 为特定服务客户端配置遥测提供程序
<a name="observability-conf-telemetry-provider-client"></a>

您可以为单个服务客户端配置特定的遥测提供程序（而不是全局遥测提供程序）。如以下示例所示。

```
import aws.sdk.kotlin.services.s3.S3Client
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    S3Client.fromEnvironment{
        telemetryProvider = getConfiguredProvider()
    }.use { s3 ->
        ...
    }
}

fun getConfiguredProvider(): TelemetryProvider {
    TODO("TODO - configure a provider")
}
```

# 指标
<a name="observability-telemetry-metrics"></a>

下表列出了 SDK 发出的遥测指标。[配置遥测提供程序](observability.md#observability-conf-telemetry-provider)以使指标可观测。


**发出哪些指标？**  

| 指标名称 | 单位 | Type | 属性 | 说明 | 
| --- | --- | --- | --- | --- | 
| smithy.client.call.durati | s | 直方图 | rpc.service, rpc.method | 总通话时长（包括重试次数） | 
| smithy.client.call.tept | \$1attempt\$1 | MonotonicCounter | rpc.service, rpc.method | 单个操作的尝试次数 | 
| smithy.client.call.errors | \$1error\$1 | MonotonicCounter | rpc.service, rpc.method, exception.type | 操作的错误数 | 
| smithy.client.call.tempt\$1duration | s | 直方图 | rpc.service, rpc.method | 连接到服务、发送请求以及获取 HTTP 状态代码和标头所用的时间（包括等待发送的排队时间） | 
| smithy.client.call.resolve\$1endpoint\$1持续时间 | s | 直方图 | rpc.service, rpc.method | 解析请求的端点（端点解析器，不是 DNS）所用的时间 | 
| smithy.client.call.serialization\$1dur | s | 直方图 | rpc.service, rpc.method | 序列化消息正文所用的时间 | 
| smithy.client.call.derization\$1duration | s | 直方图 | rpc.service, rpc.method | 反序列化消息正文所用的时间 | 
| smithy.client.call.auth.signing\$1durati | s | 直方图 | rpc.service、rpc.method、auth.scheme\$1 | 签署请求所用的时间 | 
| smithy.client.call.auth.resolve\$1identity\$1持续时间 | s | 直方图 | rpc.service、rpc.method、auth.scheme\$1 | 从身份提供商处获取身份（例如 AWS 凭证或持有者令牌）所花费的时间 | 
| smithy.client.http.connections.acquire\$1 | s | 直方图 |  | 请求获取连接所花费的时间 | 
| smithy.client.http.connections. | \$1连接\$1 | [异步] UpDownCounter |  | HTTP 客户端的最大打开连接数 allowed/configured  | 
| smithy.client.http.connections. | \$1连接\$1 | [异步] UpDownCounter | 状态：闲置 \$1 已获得 | 连接池的当前状态 | 
| smithy.client.http.connections. | s | 直方图 |  | 连接打开的时间 | 
| smithy.client.http.requests. | \$1请求\$1 | [异步] UpDownCounter | 状态：已排队 \$1 飞行中 | HTTP 客户端请求并发的当前状态 | 
| smithy.client.http.requead\$1duration | s | 直方图 |  | 请求排队等待 HTTP 客户端执行所花费的时间 | 
| smithy.client.http.bytes\$1sent | 方式 | MonotonicCounter | server.address | HTTP 客户端发送的字节总数 | 
| smithy.client.http.bytes\$1receiv | 方式 | MonotonicCounter | server.address | HTTP 客户端接收的字节总数 | 

以下是列说明：
+ **指标名称** – 发出的指标的名称。
+ **单位** - 指标的度量单位。单位以 [UCUM](https://unitsofmeasure.org/ucum) 区分大小写（“c/s”）表示法给出。
+ **类型** - 用于捕获指标的工具类型。
+ **描述** - 对指标所衡量内容的描述。
+ **属性** - 与指标一起发出的一组属性（维度）。

# 日志记录
<a name="logging"></a>

将兼容 [SLF4J](https://www.slf4j.org/manual.html) 的记录器 适用于 Kotlin 的 AWS SDK 配置为遥测提供商`LoggerProvider`的默认记录器。使用 SLF4 J（抽象层），您可以在运行时使用多个日志系统中的任何一个。[支持的日志系统包括 [Java Logging APIs](https://docs.oracle.com/javase/8/docs/technotes/guides/logging/)、[Log4j 2](https://logging.apache.org/log4j/2.x/) 和 Logback。](https://logback.qos.ch/)

**警告**  
我们建议您仅将线路日志用于调试目的。（下文将讨论线路记录。） 在生产环境中将其关闭，因为它可以记录敏感数据，例如电子邮件地址、安全令牌、API 密钥、密码和 AWS Secrets Manager 机密。即使是 HTTPS 呼叫，电线日志记录也无需加密即可记录完整的请求或响应。  
对于大型请求（例如将文件上传到 Amazon S3）或响应，冗长的电汇记录也会显著影响应用程序的性能。

## Log4j 2 日志配置示例
<a name="log4j2-example"></a>

 虽然可以使用任何`SLF4J`兼容的日志库，但此示例使用 Log4j 2 在 JVM 程序中启用 SDK 的日志输出：

**Gradle 依赖关系**

（您可以导航到该*X.Y.Z*链接以查看可用的最新版本。）

```
implementation("org.apache.logging.log4j:log4j-slf4j2-impl:[https://search.maven.org/#search|gav|1|g:org.apache.logging.log4j%20AND%20a:log4j-slf4j2-impl](https://search.maven.org/#search|gav|1|g:org.apache.logging.log4j%20AND%20a:log4j-slf4j2-impl)")
```

**Log4j 2 配置文件**

`log4j2.xml`在您的`resources`目录中创建一个名为的文件（例如，`<project-dir>/src/main/resources`）。将以下 XML 配置添加到文件中：

```
<Configuration status="ERROR">
    <Appenders>
        <Console name="Out">
            <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} %-5p %c:%L %X - %encode{%m}{CRLF}%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Out"/>
        </Root>
    </Loggers>
</Configuration>
```

此配置在`pattern`属性中包含启用 MDC（映射的诊断上下文）日志记录的`%X`说明符。

SDK 为每个操作添加以下 MDC 元素。

**rpc**  
例如`S3.GetObject`，被调用的 RPC 的名称。

**sdkInvocationId**  
服务客户端为操作分配的唯一 ID。该 ID 关联与调用单个操作相关的所有日志事件。

## 为线级消息指定日志模式
<a name="sdk-log-mode"></a>

默认情况下， 适用于 Kotlin 的 AWS SDK 不记录线级消息，因为它们可能包含来自 API 请求和响应的敏感数据。但是，有时出于调试目的，你需要这种详细程度。

使用 Kotlin SDK，您可以在代码中设置日志模式，也可以使用环境设置为以下内容启用调试消息：
+ HTTP 请求
+ HTTP 响应

日志模式由一个位域支持，其中每个位都是一个标志（模式），值是累加的。您可以将一种请求模式和一种响应模式结合使用。

### 在代码中设置日志模式
<a name="set-log-mode-programmatically"></a>

要选择使用其他日志记录，请在构建服务客户端时设置该`logMode`属性。

以下示例说明如何启用请求（使用正文）和响应（不带正文）的日志记录。

```
import aws.smithy.kotlin.runtime.client.LogMode

// ...

val client = DynamoDbClient {
    // ...
    logMode = LogMode.LogRequestWithBody + LogMode.LogResponse
}
```

在服务客户端构建期间设置的日志模式值会覆盖环境中设置的任何日志模式值。

### 从环境中设置日志模式
<a name="set-log-mode-from-enviironment"></a>

要为所有未在代码中明确配置的服务客户机设置全局日志模式，请使用以下方法之一：
+ JVM 系统属性：`sdk.logMode`
+ 环境变量：`SDK_LOG_MODE`

以下不区分大小写的值可用：
+ `LogRequest`
+ `LogRequestWithBody`
+ `LogResponse`
+ `LogResponseWithBody`

要使用环境中的设置创建组合日志模式，请使用竖线 (`|`) 符号分隔值。

例如，以下示例设置的日志模式与前面的示例相同。

```
# Environment variable.
export SDK_LOG_MODE=LogRequestWithBody|LogResponse
```

```
# JVM system property.
java -Dsdk.logMode=LogRequestWithBody|LogResponse ...
```

**注意**  
您还必须配置兼容的 SLF4 J Logger 并将日志级别设置为 DEBUG 才能启用线级日志记录。

# 遥测提供程序
<a name="observability-telemetry-providers"></a>

SDK 目前支持 [OpenTelemetry](https://opentelemetry.io/)(OTel) 作为提供者。SDK 将来可能会提供其他遥测提供商。

**Topics**
+ [配置 OpenTelemetry基于遥测的提供商](observability-telemetry-providers-otel.md)

# 配置 OpenTelemetry基于遥测的提供商
<a name="observability-telemetry-providers-otel"></a>

适用于 Kotlin 的 SDK 提供了由 OpenTelemetry支持的`TelemetryProvider`接口的实现。

## 先决条件
<a name="observability-telemetry-providers-otel-prereqs"></a>

更新您的项目依赖项以添加 OpenTelemetry 提供者，如以下 Gradle 代码段所示。您可以导航到该*X.Y.Z*链接以查看可用的最新版本。

```
dependencies {
    implementation(platform("aws.smithy.kotlin:bom:[https://github.com/smithy-lang/smithy-kotlin/releases/latest](https://github.com/smithy-lang/smithy-kotlin/releases/latest)"))
    implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:[https://search.maven.org/#search|gav|1|g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-instrumentation-bom](https://search.maven.org/#search|gav|1|g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-instrumentation-bom)"))
    implementation("aws.smithy.kotlin:telemetry-provider-otel")

    // OPTIONAL: If you use log4j, the following entry enables the ability to export logs through OTel.
    runtimeOnly("io.opentelemetry.instrumentation:opentelemetry-log4j-appender-2.17")
}
```

## 配置 SDK
<a name="observability-telemetry-providers-otel-conf"></a>

以下代码使用 OpenTelemetry遥测提供程序配置服务客户端。

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.smithy.kotlin.runtime.telemetry.otel.OpenTelemetryProvider
import io.opentelemetry.api.GlobalOpenTelemetry
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val otelProvider = OpenTelemetryProvider(GlobalOpenTelemetry.get())

    S3Client.fromEnvironment().use { s3 ->
        telemetryProvider = otelProvider
        …
    }
}
```

**注意**  
关于如何配置 OpenTelemetry SDK 的讨论不在本指南的讨论范围之内。[OpenTelemetryJava 文档](https://opentelemetry.io/docs/instrumentation/java/)包含有关各种方法的配置信息：[手动](https://opentelemetry.io/docs/instrumentation/java/manual/)、通过 [Java 代理](https://opentelemetry.io/docs/instrumentation/java/automatic/)自动或（可选）[收集器](https://opentelemetry.io/docs/collector/)。

## 资源
<a name="observability-telemetry-providers-otel-res"></a>

以下资源可帮助您入门 OpenTelemetry。
+ [AWS 发行版 for OpenTelemetry](https://aws-otel.github.io/docs/introduction)- AWS OTe L Distro 主页
+ [aws-otel-java-instrumentation](https://github.com/aws-observability/aws-otel-java-instrumentation)- OpenTelemetry Java 工具库 AWS 发行版
+ [aws-otel-lambda](https://github.com/aws-observability/aws-otel-lambda)- AWS 托管 OpenTelemetry Lambda 层
+ [aws-otel-collector](https://github.com/aws-observability/aws-otel-collector)- AWS 收藏家发行 OpenTelemetry版
+ [AWS 可观测性最佳实践](https://aws-observability.github.io/observability-best-practices/)-特定于可观测性的一般最佳实践 AWS