diff --git a/manifest.json b/manifest.json index 5115392e3..73bda49ea 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "variables": { - "${LATEST}": "3.327.1" + "${LATEST}": "3.328.0" }, "endpoints": "https://raw.githubusercontent.com/aws/aws-sdk-php/${LATEST}/src/data/endpoints.json", "services": { diff --git a/src/Service/CloudWatch/CHANGELOG.md b/src/Service/CloudWatch/CHANGELOG.md index dc216f016..c30a49244 100644 --- a/src/Service/CloudWatch/CHANGELOG.md +++ b/src/Service/CloudWatch/CHANGELOG.md @@ -2,6 +2,10 @@ ## NOT RELEASED +### Added + +- AWS api-change: Adds support for adding related Entity information to metrics ingested through PutMetricData. + ### Changed - use strict comparison `null !==` instead of `!` diff --git a/src/Service/CloudWatch/composer.json b/src/Service/CloudWatch/composer.json index de5f8899e..9afc4a76d 100644 --- a/src/Service/CloudWatch/composer.json +++ b/src/Service/CloudWatch/composer.json @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } } } diff --git a/src/Service/CloudWatch/src/CloudWatchClient.php b/src/Service/CloudWatch/src/CloudWatchClient.php index 22313863f..459066a0c 100644 --- a/src/Service/CloudWatch/src/CloudWatchClient.php +++ b/src/Service/CloudWatch/src/CloudWatchClient.php @@ -20,6 +20,7 @@ use AsyncAws\CloudWatch\Result\ListMetricsOutput; use AsyncAws\CloudWatch\ValueObject\Dimension; use AsyncAws\CloudWatch\ValueObject\DimensionFilter; +use AsyncAws\CloudWatch\ValueObject\EntityMetricData; use AsyncAws\CloudWatch\ValueObject\LabelOptions; use AsyncAws\CloudWatch\ValueObject\MetricDataQuery; use AsyncAws\CloudWatch\ValueObject\MetricDatum; @@ -235,17 +236,23 @@ public function listMetrics($input = []): ListMetricsOutput } /** - * Publishes metric data points to Amazon CloudWatch. CloudWatch associates the data points with the specified metric. - * If the specified metric does not exist, CloudWatch creates the metric. When CloudWatch creates a metric, it can take - * up to fifteen minutes for the metric to appear in calls to ListMetrics [^1]. + * Publishes metric data to Amazon CloudWatch. CloudWatch associates the data with the specified metric. If the + * specified metric does not exist, CloudWatch creates the metric. When CloudWatch creates a metric, it can take up to + * fifteen minutes for the metric to appear in calls to ListMetrics [^1]. * - * You can publish either individual data points in the `Value` field, or arrays of values and the number of times each - * value occurred during the period by using the `Values` and `Counts` fields in the `MetricData` structure. Using the + * You can publish metrics with associated entity data (so that related telemetry can be found and viewed together), or + * publish metric data by itself. To send entity data with your metrics, use the `EntityMetricData` parameter. To send + * metrics without entity data, use the `MetricData` parameter. The `EntityMetricData` structure includes `MetricData` + * structures for the metric data. + * + * You can publish either individual values in the `Value` field, or arrays of values and the number of times each value + * occurred during the period by using the `Values` and `Counts` fields in the `MetricData` structure. Using the * `Values` and `Counts` method enables you to publish up to 150 values per metric with one `PutMetricData` request, and * supports retrieving percentile statistics on this data. * * Each `PutMetricData` request is limited to 1 MB in size for HTTP POST requests. You can send a payload compressed by - * gzip. Each request is also limited to no more than 1000 different metrics. + * gzip. Each request is also limited to no more than 1000 different metrics (across both the `MetricData` and + * `EntityMetricData` properties). * * Although the `Value` parameter accepts numbers of type `Double`, CloudWatch rejects values that are either too small * or too large. Values must be in the range of -2^360 to 2^360. In addition, special values (for example, NaN, @@ -260,7 +267,7 @@ public function listMetrics($input = []): ListMetricsOutput * * Data points with time stamps from 24 hours ago or longer can take at least 48 hours to become available for * GetMetricData [^3] or GetMetricStatistics [^4] from the time they are submitted. Data points with time stamps between - * 3 and 24 hours ago can take as much as 2 hours to become available for for GetMetricData [^5] or GetMetricStatistics + * 3 and 24 hours ago can take as much as 2 hours to become available for GetMetricData [^5] or GetMetricStatistics * [^6]. * * CloudWatch needs raw data points to calculate percentile statistics. If you publish data using a statistic set @@ -281,7 +288,9 @@ public function listMetrics($input = []): ListMetricsOutput * * @param array{ * Namespace: string, - * MetricData: array, + * MetricData?: null|array, + * EntityMetricData?: null|array, + * StrictEntityValidation?: null|bool, * '@region'?: string|null, * }|PutMetricDataInput $input * diff --git a/src/Service/CloudWatch/src/Input/ListMetricsInput.php b/src/Service/CloudWatch/src/Input/ListMetricsInput.php index d9778b523..1422c80f5 100644 --- a/src/Service/CloudWatch/src/Input/ListMetricsInput.php +++ b/src/Service/CloudWatch/src/Input/ListMetricsInput.php @@ -44,7 +44,7 @@ final class ListMetricsInput extends Input * parameter with a value of `PT3H`. This is the only valid value for this parameter. * * The results that are returned are an approximation of the value you specify. There is a low probability that the - * returned results include metrics with last published data as much as 40 minutes more than the specified time + * returned results include metrics with last published data as much as 50 minutes more than the specified time * interval. * * @var RecentlyActive::*|null diff --git a/src/Service/CloudWatch/src/Input/PutMetricDataInput.php b/src/Service/CloudWatch/src/Input/PutMetricDataInput.php index 0d56c5ce6..2d81c1057 100644 --- a/src/Service/CloudWatch/src/Input/PutMetricDataInput.php +++ b/src/Service/CloudWatch/src/Input/PutMetricDataInput.php @@ -2,6 +2,8 @@ namespace AsyncAws\CloudWatch\Input; +use AsyncAws\CloudWatch\ValueObject\Entity; +use AsyncAws\CloudWatch\ValueObject\EntityMetricData; use AsyncAws\CloudWatch\ValueObject\MetricDatum; use AsyncAws\Core\Exception\InvalidArgument; use AsyncAws\Core\Input; @@ -24,18 +26,62 @@ final class PutMetricDataInput extends Input private $namespace; /** - * The data for the metric. The array can include no more than 1000 metrics per call. + * The data for the metrics. Use this parameter if your metrics do not contain associated entities. The array can + * include no more than 1000 metrics per call. * - * @required + * The limit of metrics allowed, 1000, is the sum of both `EntityMetricData` and `MetricData` metrics. * * @var MetricDatum[]|null */ private $metricData; + /** + * Data for metrics that contain associated entity information. You can include up to two `EntityMetricData` objects, + * each of which can contain a single `Entity` and associated metrics. + * + * The limit of metrics allowed, 1000, is the sum of both `EntityMetricData` and `MetricData` metrics. + * + * @var EntityMetricData[]|null + */ + private $entityMetricData; + + /** + * Whether to accept valid metric data when an invalid entity is sent. + * + * - When set to `true`: Any validation error (for entity or metric data) will fail the entire request, and no data will + * be ingested. The failed operation will return a 400 result with the error. + * - When set to `false`: Validation errors in the entity will not associate the metric with the entity, but the metric + * data will still be accepted and ingested. Validation errors in the metric data will fail the entire request, and no + * data will be ingested. + * + * In the case of an invalid entity, the operation will return a `200` status, but an additional response header will + * contain information about the validation errors. The new header, `X-Amzn-Failure-Message` is an enumeration of the + * following values: + * + * - `InvalidEntity` - The provided entity is invalid. + * - `InvalidKeyAttributes` - The provided `KeyAttributes` of an entity is invalid. + * - `InvalidAttributes` - The provided `Attributes` of an entity is invalid. + * - `InvalidTypeValue` - The provided `Type` in the `KeyAttributes` of an entity is invalid. + * - `EntitySizeTooLarge` - The number of `EntityMetricData` objects allowed is 2. + * - `MissingRequiredFields` - There are missing required fields in the `KeyAttributes` for the provided `Type`. + * + * For details of the requirements for specifying an entity, see How to add related information to telemetry [^1] in + * the *CloudWatch User Guide*. + * + * This parameter is *required* when `EntityMetricData` is included. + * + * [^1]: https://docs.aws.amazon.com/adding-your-own-related-telemetry.html + * + * @var bool|null + */ + private $strictEntityValidation; + /** * @param array{ * Namespace?: string, - * MetricData?: array, + * MetricData?: null|array, + * EntityMetricData?: null|array, + * StrictEntityValidation?: null|bool, * '@region'?: string|null, * } $input */ @@ -43,13 +89,17 @@ public function __construct(array $input = []) { $this->namespace = $input['Namespace'] ?? null; $this->metricData = isset($input['MetricData']) ? array_map([MetricDatum::class, 'create'], $input['MetricData']) : null; + $this->entityMetricData = isset($input['EntityMetricData']) ? array_map([EntityMetricData::class, 'create'], $input['EntityMetricData']) : null; + $this->strictEntityValidation = $input['StrictEntityValidation'] ?? null; parent::__construct($input); } /** * @param array{ * Namespace?: string, - * MetricData?: array, + * MetricData?: null|array, + * EntityMetricData?: null|array, + * StrictEntityValidation?: null|bool, * '@region'?: string|null, * }|PutMetricDataInput $input */ @@ -58,6 +108,14 @@ public static function create($input): self return $input instanceof self ? $input : new self($input); } + /** + * @return EntityMetricData[] + */ + public function getEntityMetricData(): array + { + return $this->entityMetricData ?? []; + } + /** * @return MetricDatum[] */ @@ -71,6 +129,11 @@ public function getNamespace(): ?string return $this->namespace; } + public function getStrictEntityValidation(): ?bool + { + return $this->strictEntityValidation; + } + /** * @internal */ @@ -92,6 +155,16 @@ public function request(): Request return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body)); } + /** + * @param EntityMetricData[] $value + */ + public function setEntityMetricData(array $value): self + { + $this->entityMetricData = $value; + + return $this; + } + /** * @param MetricDatum[] $value */ @@ -109,6 +182,13 @@ public function setNamespace(?string $value): self return $this; } + public function setStrictEntityValidation(?bool $value): self + { + $this->strictEntityValidation = $value; + + return $this; + } + private function requestBody(): array { $payload = []; @@ -116,17 +196,27 @@ private function requestBody(): array throw new InvalidArgument(\sprintf('Missing parameter "Namespace" for "%s". The value cannot be null.', __CLASS__)); } $payload['Namespace'] = $v; - if (null === $v = $this->metricData) { - throw new InvalidArgument(\sprintf('Missing parameter "MetricData" for "%s". The value cannot be null.', __CLASS__)); + if (null !== $v = $this->metricData) { + $index = 0; + foreach ($v as $mapValue) { + ++$index; + foreach ($mapValue->requestBody() as $bodyKey => $bodyValue) { + $payload["MetricData.member.$index.$bodyKey"] = $bodyValue; + } + } } - - $index = 0; - foreach ($v as $mapValue) { - ++$index; - foreach ($mapValue->requestBody() as $bodyKey => $bodyValue) { - $payload["MetricData.member.$index.$bodyKey"] = $bodyValue; + if (null !== $v = $this->entityMetricData) { + $index = 0; + foreach ($v as $mapValue) { + ++$index; + foreach ($mapValue->requestBody() as $bodyKey => $bodyValue) { + $payload["EntityMetricData.member.$index.$bodyKey"] = $bodyValue; + } } } + if (null !== $v = $this->strictEntityValidation) { + $payload['StrictEntityValidation'] = $v ? 'true' : 'false'; + } return $payload; } diff --git a/src/Service/CloudWatch/src/ValueObject/Entity.php b/src/Service/CloudWatch/src/ValueObject/Entity.php new file mode 100644 index 000000000..e448c74bf --- /dev/null +++ b/src/Service/CloudWatch/src/ValueObject/Entity.php @@ -0,0 +1,105 @@ +|null + */ + private $keyAttributes; + + /** + * Additional attributes of the entity that are not used to specify the identity of the entity. A list of key-value + * pairs. + * + * For details about how to use the attributes, see How to add related information to telemetry [^1] in the *CloudWatch + * User Guide*. + * + * [^1]: https://docs.aws.amazon.com/adding-your-own-related-telemetry.html + * + * @var array|null + */ + private $attributes; + + /** + * @param array{ + * KeyAttributes?: null|array, + * Attributes?: null|array, + * } $input + */ + public function __construct(array $input) + { + $this->keyAttributes = $input['KeyAttributes'] ?? null; + $this->attributes = $input['Attributes'] ?? null; + } + + /** + * @param array{ + * KeyAttributes?: null|array, + * Attributes?: null|array, + * }|Entity $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return array + */ + public function getAttributes(): array + { + return $this->attributes ?? []; + } + + /** + * @return array + */ + public function getKeyAttributes(): array + { + return $this->keyAttributes ?? []; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->keyAttributes) { + $index = 0; + foreach ($v as $mapKey => $mapValue) { + ++$index; + $payload["KeyAttributes.entry.$index.key"] = $mapKey; + $payload["KeyAttributes.entry.$index.value"] = $mapValue; + } + } + if (null !== $v = $this->attributes) { + $index = 0; + foreach ($v as $mapKey => $mapValue) { + ++$index; + $payload["Attributes.entry.$index.key"] = $mapKey; + $payload["Attributes.entry.$index.value"] = $mapValue; + } + } + + return $payload; + } +} diff --git a/src/Service/CloudWatch/src/ValueObject/EntityMetricData.php b/src/Service/CloudWatch/src/ValueObject/EntityMetricData.php new file mode 100644 index 000000000..13e0c3ba5 --- /dev/null +++ b/src/Service/CloudWatch/src/ValueObject/EntityMetricData.php @@ -0,0 +1,84 @@ +, + * } $input + */ + public function __construct(array $input) + { + $this->entity = isset($input['Entity']) ? Entity::create($input['Entity']) : null; + $this->metricData = isset($input['MetricData']) ? array_map([MetricDatum::class, 'create'], $input['MetricData']) : null; + } + + /** + * @param array{ + * Entity?: null|Entity|array, + * MetricData?: null|array, + * }|EntityMetricData $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getEntity(): ?Entity + { + return $this->entity; + } + + /** + * @return MetricDatum[] + */ + public function getMetricData(): array + { + return $this->metricData ?? []; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->entity) { + foreach ($v->requestBody() as $bodyKey => $bodyValue) { + $payload["Entity.$bodyKey"] = $bodyValue; + } + } + if (null !== $v = $this->metricData) { + $index = 0; + foreach ($v as $mapValue) { + ++$index; + foreach ($mapValue->requestBody() as $bodyKey => $bodyValue) { + $payload["MetricData.member.$index.$bodyKey"] = $bodyValue; + } + } + } + + return $payload; + } +} diff --git a/src/Service/Iot/CHANGELOG.md b/src/Service/Iot/CHANGELOG.md index a7b28070a..97ba59206 100644 --- a/src/Service/Iot/CHANGELOG.md +++ b/src/Service/Iot/CHANGELOG.md @@ -2,6 +2,10 @@ ## NOT RELEASED +### Added + +- AWS api-change: This release allows AWS IoT Core users to enrich MQTT messages with propagating attributes, to associate a thing to a connection, and to enable Online Certificate Status Protocol (OCSP) stapling for TLS X.509 server certificates through private endpoints. + ### Changed - use strict comparison `null !==` instead of `!` diff --git a/src/Service/Iot/composer.json b/src/Service/Iot/composer.json index 4a767931a..3d891b694 100644 --- a/src/Service/Iot/composer.json +++ b/src/Service/Iot/composer.json @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } } } diff --git a/src/Service/Iot/src/Result/ListThingTypesResponse.php b/src/Service/Iot/src/Result/ListThingTypesResponse.php index 69e662795..154eb4d4d 100644 --- a/src/Service/Iot/src/Result/ListThingTypesResponse.php +++ b/src/Service/Iot/src/Result/ListThingTypesResponse.php @@ -7,6 +7,8 @@ use AsyncAws\Core\Result; use AsyncAws\Iot\Input\ListThingTypesRequest; use AsyncAws\Iot\IotClient; +use AsyncAws\Iot\ValueObject\Mqtt5Configuration; +use AsyncAws\Iot\ValueObject\PropagatingAttribute; use AsyncAws\Iot\ValueObject\ThingTypeDefinition; use AsyncAws\Iot\ValueObject\ThingTypeMetadata; use AsyncAws\Iot\ValueObject\ThingTypeProperties; @@ -101,6 +103,35 @@ protected function populateResult(Response $response): void $this->nextToken = isset($data['nextToken']) ? (string) $data['nextToken'] : null; } + private function populateResultMqtt5Configuration(array $json): Mqtt5Configuration + { + return new Mqtt5Configuration([ + 'propagatingAttributes' => !isset($json['propagatingAttributes']) ? null : $this->populateResultPropagatingAttributeList($json['propagatingAttributes']), + ]); + } + + private function populateResultPropagatingAttribute(array $json): PropagatingAttribute + { + return new PropagatingAttribute([ + 'userPropertyKey' => isset($json['userPropertyKey']) ? (string) $json['userPropertyKey'] : null, + 'thingAttribute' => isset($json['thingAttribute']) ? (string) $json['thingAttribute'] : null, + 'connectionAttribute' => isset($json['connectionAttribute']) ? (string) $json['connectionAttribute'] : null, + ]); + } + + /** + * @return PropagatingAttribute[] + */ + private function populateResultPropagatingAttributeList(array $json): array + { + $items = []; + foreach ($json as $item) { + $items[] = $this->populateResultPropagatingAttribute($item); + } + + return $items; + } + /** * @return string[] */ @@ -154,6 +185,7 @@ private function populateResultThingTypeProperties(array $json): ThingTypeProper return new ThingTypeProperties([ 'thingTypeDescription' => isset($json['thingTypeDescription']) ? (string) $json['thingTypeDescription'] : null, 'searchableAttributes' => !isset($json['searchableAttributes']) ? null : $this->populateResultSearchableAttributes($json['searchableAttributes']), + 'mqtt5Configuration' => empty($json['mqtt5Configuration']) ? null : $this->populateResultMqtt5Configuration($json['mqtt5Configuration']), ]); } } diff --git a/src/Service/Iot/src/ValueObject/Mqtt5Configuration.php b/src/Service/Iot/src/ValueObject/Mqtt5Configuration.php new file mode 100644 index 000000000..ab8d9bb0c --- /dev/null +++ b/src/Service/Iot/src/ValueObject/Mqtt5Configuration.php @@ -0,0 +1,62 @@ +, + * } $input + */ + public function __construct(array $input) + { + $this->propagatingAttributes = isset($input['propagatingAttributes']) ? array_map([PropagatingAttribute::class, 'create'], $input['propagatingAttributes']) : null; + } + + /** + * @param array{ + * propagatingAttributes?: null|array, + * }|Mqtt5Configuration $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + /** + * @return PropagatingAttribute[] + */ + public function getPropagatingAttributes(): array + { + return $this->propagatingAttributes ?? []; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->propagatingAttributes) { + $index = -1; + $payload['propagatingAttributes'] = []; + foreach ($v as $listValue) { + ++$index; + $payload['propagatingAttributes'][$index] = $listValue->requestBody(); + } + } + + return $payload; + } +} diff --git a/src/Service/Iot/src/ValueObject/PropagatingAttribute.php b/src/Service/Iot/src/ValueObject/PropagatingAttribute.php new file mode 100644 index 000000000..f67f2f85f --- /dev/null +++ b/src/Service/Iot/src/ValueObject/PropagatingAttribute.php @@ -0,0 +1,90 @@ +userPropertyKey = $input['userPropertyKey'] ?? null; + $this->thingAttribute = $input['thingAttribute'] ?? null; + $this->connectionAttribute = $input['connectionAttribute'] ?? null; + } + + /** + * @param array{ + * userPropertyKey?: null|string, + * thingAttribute?: null|string, + * connectionAttribute?: null|string, + * }|PropagatingAttribute $input + */ + public static function create($input): self + { + return $input instanceof self ? $input : new self($input); + } + + public function getConnectionAttribute(): ?string + { + return $this->connectionAttribute; + } + + public function getThingAttribute(): ?string + { + return $this->thingAttribute; + } + + public function getUserPropertyKey(): ?string + { + return $this->userPropertyKey; + } + + /** + * @internal + */ + public function requestBody(): array + { + $payload = []; + if (null !== $v = $this->userPropertyKey) { + $payload['userPropertyKey'] = $v; + } + if (null !== $v = $this->thingAttribute) { + $payload['thingAttribute'] = $v; + } + if (null !== $v = $this->connectionAttribute) { + $payload['connectionAttribute'] = $v; + } + + return $payload; + } +} diff --git a/src/Service/Iot/src/ValueObject/ThingTypeProperties.php b/src/Service/Iot/src/ValueObject/ThingTypeProperties.php index 286cd7805..ebac880a8 100644 --- a/src/Service/Iot/src/ValueObject/ThingTypeProperties.php +++ b/src/Service/Iot/src/ValueObject/ThingTypeProperties.php @@ -22,22 +22,32 @@ final class ThingTypeProperties */ private $searchableAttributes; + /** + * The configuration to add user-defined properties to enrich MQTT 5 messages. + * + * @var Mqtt5Configuration|null + */ + private $mqtt5Configuration; + /** * @param array{ * thingTypeDescription?: null|string, * searchableAttributes?: null|string[], + * mqtt5Configuration?: null|Mqtt5Configuration|array, * } $input */ public function __construct(array $input) { $this->thingTypeDescription = $input['thingTypeDescription'] ?? null; $this->searchableAttributes = $input['searchableAttributes'] ?? null; + $this->mqtt5Configuration = isset($input['mqtt5Configuration']) ? Mqtt5Configuration::create($input['mqtt5Configuration']) : null; } /** * @param array{ * thingTypeDescription?: null|string, * searchableAttributes?: null|string[], + * mqtt5Configuration?: null|Mqtt5Configuration|array, * }|ThingTypeProperties $input */ public static function create($input): self @@ -45,6 +55,11 @@ public static function create($input): self return $input instanceof self ? $input : new self($input); } + public function getMqtt5Configuration(): ?Mqtt5Configuration + { + return $this->mqtt5Configuration; + } + /** * @return string[] */ @@ -75,6 +90,9 @@ public function requestBody(): array $payload['searchableAttributes'][$index] = $listValue; } } + if (null !== $v = $this->mqtt5Configuration) { + $payload['mqtt5Configuration'] = $v->requestBody(); + } return $payload; }