

# 自定义指标与 Application Signals
<a name="AppSignals-CustomMetrics"></a>

为了监控应用程序性能和可用性，Application Signals 会在启用后从发现的应用程序中收集标准指标（故障数量、错误数量和延迟）和运行时指标。

自定义指标可为应用程序监控增添宝贵的背景信息，有助于加快问题排查。您可以使用这些指标执行以下操作：
+ 自定义遥测数据分析
+  确定问题的根本原因
+ 快速做出精确的业务和运营决策

Application Signals 让您可以查看从服务生成的自定义指标并将这些指标与标准指标和运行时指标相关联。例如，应用程序可以发出请求大小指标和缓存未命中计数指标。这些自定义指标可以提供更精细的性能问题信息，帮助您更快地诊断和解决可用性下降和延迟峰值的问题。

**Topics**
+ [为 Application Signals 配置自定义指标](#AppSignals-CustomMetrics-Adding)
+ [在 Application Signals 中查看自定义指标](#AppSignals-CustomMetrics-Viewing)
+ [常见问题（FAQ）](#AppSignals-CustomMetrics-FAQ)

## 为 Application Signals 配置自定义指标
<a name="AppSignals-CustomMetrics-Adding"></a>

您可以使用两种方法从应用程序生成自定义指标：*OpenTelemetry 指标*和*跨度指标*。

**Topics**
+ [OpenTelemetry 指标](#AppSignals-CustomMetrics-OpenTelemetry)
+ [跨度指标](#AppSignals-CustomMetrics-SpanMetrics)

### OpenTelemetry 指标
<a name="AppSignals-CustomMetrics-OpenTelemetry"></a>

要将自定义 OpenTelemetry 指标与 Application Signals 配合使用，必须使用 CloudWatch 代理或 OpenTelemetry 收集器。自定义 OpenTelemetry 指标允许您使用 OpenTelemetry Metrics SDK 直接从应用程序代码创建和导出指标。

1. 将服务载入 Application Signals。

1. 配置代理或收集器。
   + 使用 CloudWatch 代理时，必须使用 `otlp` [配置](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-OpenTelemetry-metrics.html) `metrics_collected`。例如，`cloudwatch-config.json`

     ```
     {
       "traces": {
         "traces_collected": {
           "application_signals": {}
         }
       },
       "logs": {
         "metrics_collected": {
           "application_signals": {},
           "otlp": {
             "grpc_endpoint": "0.0.0.0:4317",
             "http_endpoint": "0.0.0.0:4318"
           }
         }
       }
     }
     ```
   + 使用 OpenTelemetry 收集器时，请配置指标管道。您必须使用[适用于 OpenTelemetry 收集器的 CloudWatch EMF 导出器](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/awsemfexporter)，并启用[指标标签的资源属性](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/awsemfexporter#resource-attributes-to-metric-labels)。建议配置 ` dimension_rollup_option: NoDimensionRollup` 以避免发出许多指标聚合。例如 `config.yaml`：

     ```
     receivers:
       otlp:
         protocols:
           grpc:
             endpoint: 0.0.0.0:4317
           http:
             endpoint: 0.0.0.0:4318
     
     exporters:
       awsemf:
         region: $REGION
         namespace: $NAMESPACE
         log_group_name:$LOG_GROUP_NAME
         resource_to_telemetry_conversion:
           enabled: true
         dimension_rollup_option: "NoDimensionRollup"
         
       otlphttp/traces:
         compression: gzip
         traces_endpoint: https://xray.$REGION.amazonaws.com/v1/traces
         auth:
           authenticator: sigv4auth/traces
     
     extensions:
       sigv4auth/logs:
         region: "$REGION"
         service: "logs"
       sigv4auth/traces:
         region: "$REGION"
         service: "xray"
     
     processors:
       batch:
     
     service:
       telemetry:
       extensions: [sigv4auth/logs, sigv4auth/traces]
       pipelines:
         metrics:
           receivers: [otlp]
           processors: [batch]
           exporters: [awsemf]
         traces:
           receivers: [otlp]
           processors: [batch]
           exporters: [otlphttp/traces]
     ```

1. 配置环境。如果有多项服务具有相同的服务名称，为了准确地将 Application Signals 指标与正确的服务名称相关联，建议配置资源属性 `deployment.environment.name`。通常使用环境变量来配置此资源属性。

   ```
   OTEL_RESOURCE_ATTRIBUTES="service.name=$YOUR_SVC_NAME,deployment.environment.name=$YOUR_ENV_NAME"
   ```

1. 配置将指标导出到 CloudWatch 代理或 OpenTelemetry 收集器。您可以使用以下方法之一：
   + （推荐）自定义导出管道：在应用程序代码中，创建一个专用 [MeterProvider](https://opentelemetry.io/docs/specs/otel/metrics/sdk/#meterprovider)，导出到已配置的代理或收集器端点。例如：

     ```
     Resource resource = Resource.getDefault().toBuilder()
             .put(AttributeKey.stringKey("service.name"), serviceName)
             .put(AttributeKey.stringKey("deployment.environment.name"), environment)
             .build();
     
     MetricExporter metricExporter = OtlpHttpMetricExporter.builder()
             .setEndpoint("http://localhost:4318/v1/metrics")
             .build();
     
     MetricReader metricReader = PeriodicMetricReader.builder(metricExporter)
             .setInterval(Duration.ofSeconds(10))
             .build()
     
     SdkMeterProvider meterProvider = SdkMeterProvider.builder()
         .setResource(resource)
         .registerMetricReader()
         .build();
         
     Meter meter = meterProvider.get("myMeter");
     ```
   + [基于代理的导出：配置代理环境变量 [OTEL\$1METRICS\$1EXPORTER](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection) 和 OTEL\$1EXPORTER\$1OTLP\$1METRICS\$1ENDPOINT](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/#otel_exporter_otlp_metrics_endpoint)。例如：

     ```
     OTEL_METRICS_EXPORTER=otlp
     OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics
     ```

     在应用程序代码中，依赖代理创建的全局 MeterProvider。例如：

     ```
     Meter meter = GlobalOpenTelemetry.getMeter("myMeter");
     ```

1. 在应用程序代码中使用 [OTEL 指标 SDK](https://opentelemetry.io/docs/specs/otel/metrics/sdk/)，添加 OTEL 指标。例如，要在 Python 中添加 OTEL 指标，请执行以下操作：

   ```
   counter = meter.counterBuilder("myCounter").build();
   counter.add(value);
   counter.add(value, Attributes.of(AttributeKey.stringKey("Operation"), "myOperation"));
   ```

   不需要添加“操作”属性，但添加该属性对于将 Application Signals 服务操作与自定义 OpenTelemetry 指标相关联很有用。

### 跨度指标
<a name="AppSignals-CustomMetrics-SpanMetrics"></a>

自定义跨度指标目前仅适用于事务搜索功能。使用自定义跨度指标，您可以：
+ 使用指标筛选条件创建指标
+ 处理应用程序代码中添加的跨度属性
+ 使用 OpenTelemetry 追踪 SDK 进行实现

1. 启用 Application Signals 监控的事务搜索功能。有关更多信息，请参阅 [Transaction Search](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Transaction-Search-getting-started.html)。

   为确保 100% 的指标采样，建议将 100% 的跨度发送到端点。

1. 使用 [OTEL 追踪 SDK](https://opentelemetry.io/docs/specs/otel/trace/sdk/) 添加跨度属性。有两种方式：
   + [推荐] 向自动生成的跨度添加属性。例如：

     ```
     Span.current().setAttribute("myattribute", value);
     ```
   + 向手动生成的跨度添加属性。例如：

     ```
     Span span = tracer.spanBuilder("myspan").startSpan();
     try (Scope scope = span.makeCurrent()) {
        span.setAttribute("myattribute",  value);
     }
     ```

1. 使用以下值创建指标筛选条件。有关如何创建指标筛选条件的信息，请参阅 [Create a metric filter for a log group](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CreateMetricFilterProcedure.html)。
   + 日志组：aws/spans
   + 筛选模式：\$1 \$1.attributes.['myattribute'] = \$1 \$1
   + 指标名称：myattribute（值必须完全匹配，否则跨度关联将不起作用）
   + 指标值：\$1.attributes.['myattribute']
   + 维度：字段名称：服务，字段值：\$1.attributes.['aws.local.service']，字段名称：环境，字段值：\$1.attributes.['aws.local.environment']，以及字段名称：操作，字段值：\$1.attributes.['aws.local.operation']
**注意**  
向手动生成的跨度添加属性时，无法设置 `Operation`，因为 `aws.local.operation` 不会出现在跨度数据中。

## 在 Application Signals 中查看自定义指标
<a name="AppSignals-CustomMetrics-Viewing"></a>

现在，您可以在 Application Signals 控制台中查看服务和操作的自定义指标：
+ 从**服务**列表中选择一项服务，查看新的**相关指标**选项卡
+  查看所选服务的标准指标、运行时指标和相关指标
+ 从列表中筛选并选择多个指标
+ 绘制所选指标的图表，确定相关性和问题的根本原因

有关相关指标的更多信息，请参阅[查看相关指标](ServiceDetail.md#ServiceDetail-relatedmetrics)。

## 常见问题（FAQ）
<a name="AppSignals-CustomMetrics-FAQ"></a>

### 不为自定义指标添加环境配置会有什么影响？
<a name="AppSignals-CustomMetrics-FAQ-Environment"></a>

Application Signals 会配置 `deployment.environment.name` 资源属性以消除应用程序的歧义。如果不消除歧义，Application Signals 就无法将两个同名的不同服务生成的自定义指标与正确的服务相关联。

要向应用程序添加环境配置，请参阅 [OpenTelemetry 指标](#AppSignals-CustomMetrics-OpenTelemetry)。

### 指标筛选条件数量有限额吗？
<a name="AppSignals-CustomMetrics-FAQ-Limits"></a>

每个 CloudWatch Logs 日志组最多只能创建 100 个指标筛选条件。每个指标最多可定义 3 个维度。您可以在此处查看指标筛选条件数量的限额：[OpenTelemetry 指标](#AppSignals-CustomMetrics-OpenTelemetry)。

### 为什么指标图表没有出现在指标表中？
<a name="AppSignals-CustomMetrics-FAQ-Graph"></a>

解决方案取决于您的指标类型：
+ 自定义指标：请参阅[为 Application Signals 配置自定义指标](#AppSignals-CustomMetrics-Adding)，验证指标配置
+ 标准或运行时指标：请参阅[对Application Signals 安装进行问题排查](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Signals-Enable-Troubleshoot.html)