

# 创建自定义数据来源连接器。
<a name="CloudWatch_MultiDataSources-Connect-Custom"></a>

 本主题介绍如何将自定义数据来源连接到 CloudWatch。您可以通过两种方式将自定义数据来源连接到 CloudWatch：
+  使用 CloudWatch 提供的示例模板。使用该模板时，您可以使用 JavaScript 或 Python。这些模板包含示例 Lambda 代码，这些代码将有助于您创建 Lambda 函数。然后，您可以修改模板中的 Lambda 函数，以便连接到自定义数据来源。
+  从头开始创建 AWS Lambda 函数，用于实现数据来源连接器、数据查询以及准备供 CloudWatch 使用的时间序列。此函数必须预聚合或合并数据点（如果需要），还必须调整周期和时间戳以与 CloudWatch 兼容。

**Contents**
+ [使用模板](#CloudWatch_MultiDataSources-Connect-Custom-template)
+ [从头开始创建自定义数据来源](#CloudWatch_MultiDataSources-Connect-Custom-Lambda)
  + [步骤 1：创建函数](#MultiDataSources-Connect-Custom-Lambda-Function)
    + [GetMetricData 事件](#MultiDataSources-GetMetricData)
    + [DescribeGetMetricData 事件](#MultiDataSources-DescribeGetMetricData)
    + [CloudWatch 警报的重要注意事项](#MultiDataSources-Connect-Custom-Lambda-Alarms)
    + [（可选）使用 AWS Secrets Manager 存储凭证](#MultiDataSources-Connect-Custom-Lambda-Secrets)
    + [（可选）连接到 VPC 中的数据来源](#MultiDataSources-Connect-Custom-Lambda-VPC)
  + [步骤 2：创建 Lambda 权限策略](#MultiDataSources-Connect-Custom-Lambda-Permissions)
  + [步骤 3：将资源标签附加到 Lambda 函数](#MultiDataSources-Connect-Custom-Lambda-tags)

## 使用模板
<a name="CloudWatch_MultiDataSources-Connect-Custom-template"></a>

使用模板可以创建示例 Lambda 函数，并帮助您更快地构建自定义连接器。这些示例函数提供了示例代码，可用于涉及构建自定义连接器的许多常见场景。在使用模板创建连接器后，您可以检查 Lambda 代码，然后对其进行修改以用于连接数据来源。

此外，如果使用该模板，CloudWatch 会负责创建 Lambda 权限策略并将资源标签附加到 Lambda 函数。

**使用模板创建连接到自定义数据来源的连接器**

1. 通过 [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/) 打开 CloudWatch 控制台。

1. 在导航窗格中，选择**设置**。

1. 选择**指标数据来源**选项卡。

1. 选择**创建数据来源**。

1. 选择**自定义 - 入门模板**单选按钮，然后选择**下一步**。

1. 输入数据来源的名称。

1. 从列出的模板中选择一个。

1. 选择 Node.js 或 Python。

1. 选择**创建数据来源**。

   CloudFormation 堆栈完成创建自定义来源之后，您刚刚添加的新自定义来源才会出现。要查看进度，可以选择**查看我的 CloudFormation 堆栈的状态**。您也可以使用刷新图标来更新此列表。

   新数据来源出现在此列表中时，您就可以在控制台中对其进行测试和修改。

1. （可选）要在控制台中查询来自该来源的测试数据，请按照 [创建源自另一个数据来源的指标图表](graph_a_metric.md#create-metric-graph-multidatasource) 中的说明进行操作。

1. 按需修改 Lambda 函数。

   1. 在导航窗格中，选择**设置**。

   1. 选择**指标数据来源**选项卡。

   1. 针对要修改的来源，选择**在 Lambda 控制台中查看**。

   您现在可以修改函数以访问数据来源。有关更多信息，请参阅 [步骤 1：创建函数](#MultiDataSources-Connect-Custom-Lambda-Function)。
**注意**  
通过使用该模板，您在编写 Lambda 函数时，无需按照 [步骤 2：创建 Lambda 权限策略](#MultiDataSources-Connect-Custom-Lambda-Permissions) 或 [步骤 3：将资源标签附加到 Lambda 函数](#MultiDataSources-Connect-Custom-Lambda-tags) 中的说明进行操作。CloudWatch 会执行这些步骤，因为您使用了该模板。

## 从头开始创建自定义数据来源
<a name="CloudWatch_MultiDataSources-Connect-Custom-Lambda"></a>

按照本节中的步骤创建 Lambda 函数，该函数会将 CloudWatch 连接到数据来源。

### 步骤 1：创建函数
<a name="MultiDataSources-Connect-Custom-Lambda-Function"></a>

自定义数据来源连接器必须支持来自 CloudWatch 的 `GetMetricData` 事件。您也可以实施 `DescribeGetMetricData` 活动，以便在 CloudWatch 控制台中向用户提供有关如何使用连接器的文档。`DescribeGetMetricData` 响应还可用于设置 CloudWatch 自定义查询构建器中使用的默认值。

CloudWatch 提供了代码段示例，以帮助您开始使用。有关更多信息，请参阅 [https://github.com/aws-samples/cloudwatch-data-source-samples](https://github.com/aws-samples/cloudwatch-data-source-samples) 上的示例存储库。

**约束**
+ 来自 Lambda 的响应必须小于 6 Mb。如果响应超过 6 Mb，则 `GetMetricData` 响应会将 Lambda 函数标记为 `InternalError`，并且不会返回任何数据。
+ 如果是用于可视化和控制面板管理，则 Lambda 函数必须在 10 秒内完成执行；如果是用于警报，则 Lambda 函数必须在 4.5 秒内完成执行。如果执行超时，则 `GetMetricData` 响应会将 Lambda 函数标记为 `InternalError`，并且不会返回任何数据。
+ Lambda 函数必须使用以秒为单位的纪元时间戳发送其输出。
+ 如果 Lambda 函数不对数据进行重采样，而是返回与 CloudWatch 用户请求的开始时间和时段长度不一致的数据，则 CloudWatch 将忽略该数据。任何可视化或警报中都将丢弃多余的数据。未介于开始时间和结束时间之间的任何数据也将被丢弃。

  例如，如果用户要求提供 10:00 到 11:00 之间的数据，周期为 5 分钟，则“10:00:00 至 10:04:59”和“10:05:00 至 10:09:59”为返回数据的有效时间范围。必须返回包含 `10:00 value1`、`10:05 value2` 等的时间序列。例如，如果函数返回 `10:03 valueX`，则会被丢弃，因为 10:03 与请求的开始时间和周期不对应。
+ CloudWatch 数据来源连接器不支持多行查询。执行查询，或者使用查询创建警报或控制面板小组件时，每个换行符都会替换为空格。在某些情况下，这可能会导致查询无效。

#### GetMetricData 事件
<a name="MultiDataSources-GetMetricData"></a>

**请求负载**

以下是作为输入发送到 Lambda 函数的 `GetMetricData` 请求负载示例。

```
{
  "EventType": "GetMetricData",
  "GetMetricDataRequest": {
    "StartTime": 1697060700,
    "EndTime": 1697061600,
    "Period": 300,
    "Arguments": ["serviceregistry_external_http_requests{host_cluster!=\"prod\"}"] 
  }
}
```
+ **StartTime**：指定最早返回的数据的时间戳。**类型**为时间戳纪元秒。
+ **EndTime**：指定最新返回的数据的时间戳。**类型**为时间戳纪元秒。
+ **Period**：每个指标数据聚合所代表的秒数。最短时间为 60 秒。**类型**为秒。
+ **Arguments**：要传递给 Lambda 指标数学表达式的参数数组。有关传递参数的更多信息，请参阅 [如何将参数传递给您的 Lambda 函数](CloudWatch_MultiDataSources-Custom-Use.md#MultiDataSources-Connect-Custom-Lambda-arguments)。

**响应负载**

以下是 Lambda 函数返回的 `GetMetricData` 响应负载的示例。

```
{
   "MetricDataResults": [
      {
         "StatusCode": "Complete",
         "Label": "CPUUtilization",
         "Timestamps": [ 1697060700, 1697061000, 1697061300 ],
         "Values": [ 15000, 14000, 16000 ]
      }
   ]
}
```

该响应负载将包含 `MetricDataResults` 字段或 `Error` 字段，但无法同时包含二者。

`MetricDataResults` 字段是 `MetricDataResult` 类型的时间序列字段列表。每个时间序列字段可包括以下字段。
+ **StatusCode**：（可选）`Complete` 表示已返回请求时间范围内的所有数据点。`PartialData` 表示返回的数据点不完整。如果省略，则使用默认值 `Complete`。

  有效值: `Complete` \$1 `InternalError` \$1 `PartialData` \$1 `Forbidden`
+ **Messages**：可选的消息列表，其中包含所返回的数据的其他相关信息。

  类型：包含 `Code` 和 `Value` 字符串的 [MessageData](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MessageData.html) 对象数组。
+ **Label**：与数据关联的人类可读标签。

  类型：字符串
+ **Timestamps**：数据点的时间戳，格式为纪元时间。时间戳的数量始终与值的数量相匹配，`Timestamps[x]` 的值为 `Values[x`]。

  类型：时间戳数组
+ **Values**：与 `Timestamps` 对应的指标数据点值。值的数量始终与时间戳的数量相匹配，`Timestamps[x]` 的值为 `Values[x`]。

  类型：双倍数组

有关 `Error` 对象的更多信息，请参阅以下部分。

**错误响应格式**

您可以选择使用错误响应来提供有关错误的更多信息。当发生验证错误时（例如缺少参数或参数类型错误），我们建议您使用代码验证返回错误。

以下是 Lambda 函数要引发 `GetMetricData` 验证异常时的响应示例。

```
{
   "Error": {
      "Code": "Validation",
      "Value": "Invalid Prometheus cluster"
   }
}
```

以下是 Lambda 函数表示由于访问问题而无法返回数据时的响应示例。响应被转换为单个时间序列，其状态代码为 `Forbidden`。

```
{
   "Error": {
      "Code": "Forbidden",
      "Value": "Unable to access ..."
   }
}
```

以下是 Lambda 函数引发整体 `InternalError` 异常的示例，该异常被转换为单个时间序列，其状态代码为 `InternalError` 并具有一条消息。只要错误代码的值不是 `Validation` 或 `Forbidden`，CloudWatch 都会认为这属于常规内部错误。

```
{
   "Error": {
      "Code": "PrometheusClusterUnreachable",
      "Value": "Unable to communicate with the cluster"
   }
}
```

#### DescribeGetMetricData 事件
<a name="MultiDataSources-DescribeGetMetricData"></a>

**请求负载**

以下是 `DescribeGetMetricData` 请求负载的示例。

```
{
  "EventType": "DescribeGetMetricData"
}
```

**响应负载**

以下是 `DescribeGetMetricData` 响应负载的示例。

```
{
    "Description": "Data source connector",
    "ArgumentDefaults": [{
        Value: "default value"
     }]
}
```
+ **Description**：关于如何使用数据来源连接器的描述。此描述将显示在 CloudWatch 控制台中。支持 Markdown。

  类型：字符串
+ **ArgumentDefaults**：预填充自定义数据来源构建器时使用的参数默认值的可选数组。

  如果返回 `[{ Value: "default value 1"}, { Value: 10}]`，则 CloudWatch 控制台中的查询构建器会显示两个输入，第一个是“default value 1”，第二个是“10”。

  如果未提供 `ArgumentDefaults`，则显示默认类型为 `String` 的一个输入。

  类型：包含值和类型的对象数组。
+ **Error**：（可选）错误字段可包含在任何响应中。您可以在 [GetMetricData 事件](#MultiDataSources-GetMetricData) 中查看示例。

#### CloudWatch 警报的重要注意事项
<a name="MultiDataSources-Connect-Custom-Lambda-Alarms"></a>

 如果要使用数据来源来设置 CloudWatch 警报，则应将其设置为每分钟向 CloudWatch 报告带有时间戳的数据。有关为源自已连接的数据来源的指标创建警报的更多信息和其他注意事项，请参阅 [基于连接的数据来源创建警报](Create_MultiSource_Alarm.md)。

#### （可选）使用 AWS Secrets Manager 存储凭证
<a name="MultiDataSources-Connect-Custom-Lambda-Secrets"></a>

如果您的 Lambda 函数需要使用凭证来访问数据来源，我们建议使用 AWS Secrets Manager 来存储这些凭证，而不是将其硬编码到您的 Lambda 函数中。有关结合使用 AWS Secrets Manager 和 Lambda 函数的更多信息，请参阅[在 AWS Lambda 函数中使用 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html)。

#### （可选）连接到 VPC 中的数据来源
<a name="MultiDataSources-Connect-Custom-Lambda-VPC"></a>

如果数据来源位于由 Amazon Virtual Private Cloud 管理的 VPC 中，则必须配置您的 Lambda 函数才能对其进行访问。有关更多信息，请参阅[将出站联网连接到 VPC 中的资源](https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html)。

您可能还需要配置 VPC 服务端点才能访问 AWS Secrets Manager 等服务。有关更多信息，请参阅[使用接口 VPC 端点访问 AWS 服务](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#access-service-though-endpoint)。

### 步骤 2：创建 Lambda 权限策略
<a name="MultiDataSources-Connect-Custom-Lambda-Permissions"></a>

您必须创建策略语句，授予 CloudWatch 使用您创建的 Lambda 函数的权限。您可以使用 AWS CLI 或 Lambda 控制台创建该策略语句。

**使用 AWS CLI 创建策略语句**
+ 输入如下命令。将 *123456789012* 替换为您的账户 ID，将 *my-data-source-function* 替换为您的 Lambda 函数的名称，然后将 *MyDataSource-DataSourcePermission1234* 替换为任意唯一值。

  ```
  aws lambda add-permission --function-name my-data-source-function --statement-id MyDataSource-DataSourcePermission1234 --action lambda:InvokeFunction --principal lambda.datasource.cloudwatch.amazonaws.com --source-account 123456789012
  ```

### 步骤 3：将资源标签附加到 Lambda 函数
<a name="MultiDataSources-Connect-Custom-Lambda-tags"></a>

CloudWatch 控制台通过使用标签来确定哪些 Lambda 函数是数据来源连接器。使用其中一个向导创建数据来源时，配置该标签的 CloudFormation 堆栈会自动应用该标签。当您自己创建数据来源时，可以将以下标签用于您的 Lambda 函数。这样一来，当您查询指标时，您的连接器就会显示在 CloudWatch 控制台的**数据来源**下拉列表中。
+ 具有键 `cloudwatch:datasource` 和值 `custom` 的标签。