AutorÃa | Ultima modificación | Ver Log |
<?phpnamespace Aws;use Aws\Credentials\CredentialsInterface;use Aws\Credentials\CredentialSources;/*** A placeholder for gathering metrics in a request.** @internal*/final class MetricsBuilder{const WAITER = "B";const PAGINATOR = "C";const RETRY_MODE_LEGACY = "D";const RETRY_MODE_STANDARD = "E";const RETRY_MODE_ADAPTIVE = "F";const S3_TRANSFER = "G";const S3_CRYPTO_V1N = "H";const S3_CRYPTO_V2 = "I";const S3_EXPRESS_BUCKET = "J";const GZIP_REQUEST_COMPRESSION = "L";const ENDPOINT_OVERRIDE = "N";const ACCOUNT_ID_ENDPOINT = "O";const ACCOUNT_ID_MODE_PREFERRED = "P";const ACCOUNT_ID_MODE_DISABLED = "Q";const ACCOUNT_ID_MODE_REQUIRED = "R";const SIGV4A_SIGNING = "S";const RESOLVED_ACCOUNT_ID = "T";const FLEXIBLE_CHECKSUMS_REQ_CRC32 = "U";const FLEXIBLE_CHECKSUMS_REQ_CRC32C = "V";const FLEXIBLE_CHECKSUMS_REQ_CRC64 = "W";const FLEXIBLE_CHECKSUMS_REQ_SHA1 = "X";const FLEXIBLE_CHECKSUMS_REQ_SHA256 = "Y";const FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED = "Z";const FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED = "a";const FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED = "b";const FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED = "c";const CREDENTIALS_CODE = "e";const CREDENTIALS_ENV_VARS = "g";const CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN = "h";const CREDENTIALS_STS_ASSUME_ROLE = "i";const CREDENTIALS_STS_ASSUME_ROLE_WEB_ID = "k";const CREDENTIALS_PROFILE = "n";const CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN = "q";const CREDENTIALS_HTTP = "z";const CREDENTIALS_IMDS = "0";const CREDENTIALS_PROFILE_PROCESS = "v";const CREDENTIALS_PROFILE_SSO = "r";const CREDENTIALS_PROFILE_SSO_LEGACY = "t";/** @var int */private static $MAX_METRICS_SIZE = 1024; // 1KB or 1024 B/** @var string */private static $METRIC_SEPARATOR = ",";/** @var array $metrics */private $metrics;/** @var int $metricsSize */private $metricsSize;public function __construct(){$this->metrics = [];// The first metrics does not include the separator// therefore it is reduced by default.$this->metricsSize = -(strlen(self::$METRIC_SEPARATOR));}/*** Build the metrics string value.** @return string*/public function build(): string{if (empty($this->metrics)) {return "";}return $this->encode();}/*** Encodes the metrics by separating each metric* with a comma. Example: for the metrics[A,B,C] then* the output would be "A,B,C".** @return string*/private function encode(): string{return implode(self::$METRIC_SEPARATOR, array_keys($this->metrics));}/*** Appends a metric to the internal metrics holder after validating it.* Increases the current metrics size by the length of the new metric* plus the length of the encoding separator.* Example: $currentSize = $currentSize + len($newMetric) + len($separator)** @param string $metric The metric to append.** @return void*/public function append(string $metric): void{if (!$this->canMetricBeAppended($metric)) {return;}$this->metrics[$metric] = true;$this->metricsSize += strlen($metric) + strlen(self::$METRIC_SEPARATOR);}/*** Receives a feature group and a value to identify which one is the metric.* For example, a group could be `signature` and a value could be `v4a`,* then the metric will be `SIGV4A_SIGNING`.** @param string $featureGroup the feature group such as `signature`.* @param mixed $value the value for identifying the metric.** @return void*/public function identifyMetricByValueAndAppend(string $featureGroup,$value): void{if (empty($value)) {return;}static $appendMetricFns = ['signature' => 'appendSignatureMetric','request_compression' => 'appendRequestCompressionMetric','request_checksum' => 'appendRequestChecksumMetric','credentials' => 'appendCredentialsMetric','account_id_endpoint_mode' => 'appendAccountIdEndpointMode','account_id_endpoint' => 'appendAccountIdEndpoint','request_checksum_calculation' => 'appendRequestChecksumCalculationMetric',];$fn = $appendMetricFns[$featureGroup];$this->{$fn}($value);}/*** Appends the signature metric based on the signature value.** @param string $signature** @return void*/private function appendSignatureMetric(string $signature): void{if ($signature === 'v4-s3express') {$this->append(self::S3_EXPRESS_BUCKET);} elseif ($signature === 'v4a') {$this->append(self::SIGV4A_SIGNING);}}/*** Appends the request compression metric based on the format resolved.** @param string $format** @return void*/private function appendRequestCompressionMetric(string $format): void{if ($format === 'gzip') {$this->append(self::GZIP_REQUEST_COMPRESSION);}}/*** Appends the request checksum metric based on the algorithm.** @param string $algorithm** @return void*/private function appendRequestChecksumMetric(string $algorithm): void{if ($algorithm === 'crc32') {$this->append(self::FLEXIBLE_CHECKSUMS_REQ_CRC32);} elseif ($algorithm === 'crc32c') {$this->append(self::FLEXIBLE_CHECKSUMS_REQ_CRC32C);} elseif ($algorithm === 'crc64') {$this->append(self::FLEXIBLE_CHECKSUMS_REQ_CRC64);} elseif ($algorithm === 'sha1') {$this->append(self::FLEXIBLE_CHECKSUMS_REQ_SHA1);} elseif ($algorithm === 'sha256') {$this->append(self::FLEXIBLE_CHECKSUMS_REQ_SHA256);}}/*** Appends the credentials metric based on the type of credentials* resolved.** @param CredentialsInterface $credentials** @return void*/private function appendCredentialsMetric(CredentialsInterface $credentials): void{$source = $credentials->toArray()['source'] ?? null;if (empty($source)) {return;}static $credentialsMetricMapping = [CredentialSources::STATIC =>self::CREDENTIALS_CODE,CredentialSources::ENVIRONMENT =>self::CREDENTIALS_ENV_VARS,CredentialSources::ENVIRONMENT_STS_WEB_ID_TOKEN =>self::CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN,CredentialSources::STS_ASSUME_ROLE =>self::CREDENTIALS_STS_ASSUME_ROLE,CredentialSources::STS_WEB_ID_TOKEN =>self::CREDENTIALS_STS_ASSUME_ROLE_WEB_ID,CredentialSources::PROFILE =>self::CREDENTIALS_PROFILE,CredentialSources::IMDS =>self::CREDENTIALS_IMDS,CredentialSources::ECS =>self::CREDENTIALS_HTTP,CredentialSources::PROFILE_STS_WEB_ID_TOKEN =>self::CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN,CredentialSources::PROFILE_PROCESS =>self::CREDENTIALS_PROFILE_PROCESS,CredentialSources::PROFILE_SSO =>self::CREDENTIALS_PROFILE_SSO,CredentialSources::PROFILE_SSO_LEGACY =>self::CREDENTIALS_PROFILE_SSO_LEGACY,];if (isset($credentialsMetricMapping[$source])) {$this->append($credentialsMetricMapping[$source]);}}private function appendRequestChecksumCalculationMetric(string $checkSumCalculation): void{static $checksumCalculationMetricMapping = ['when_supported' => self::FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED,'when_required' => self::FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED,];if (isset($checksumCalculationMetricMapping[$checkSumCalculation])) {$this->append($checksumCalculationMetricMapping[$checkSumCalculation]);}}/*** Appends the account_id_endpoint_mode metrics based on* the value resolved.** @param string $accountIdEndpointMode** @return void*/private function appendAccountIdEndpointMode(string $accountIdEndpointMode): void{if (empty($accountIdEndpointMode)) {return;}if ($accountIdEndpointMode === 'preferred') {$this->append(self::ACCOUNT_ID_MODE_PREFERRED);} elseif ($accountIdEndpointMode === 'disabled') {$this->append(self::ACCOUNT_ID_MODE_DISABLED);} elseif ($accountIdEndpointMode === 'required') {$this->append(self::ACCOUNT_ID_MODE_REQUIRED);}}/*** Appends the account_id_endpoint metric whenever a resolved endpoint* matches an account_id endpoint pattern which also defined here.** @param string $endpoint** @return void*/private function appendAccountIdEndpoint(string $endpoint): void{static $pattern = "/(https|http):\\/\\/\\d{12}\\.ddb/";if (preg_match($pattern, $endpoint)) {$this->append(self::ACCOUNT_ID_ENDPOINT);}}/*** Resolves metrics from client arguments.** @param array $args** @return void*/public function resolveAndAppendFromArgs(array $args = []): void{static $metricsFnList = ['appendEndpointMetric','appendRetryConfigMetric','appendResponseChecksumValidationMetric',];foreach ($metricsFnList as $metricFn) {$this->{$metricFn}($args);}}/*** Appends the endpoint metric into the metrics builder,* just if a custom endpoint was provided at client construction.** @param array $args** @return void*/private function appendEndpointMetric(array $args): void{if (!empty($args['endpoint_override'])) {$this->append(MetricsBuilder::ENDPOINT_OVERRIDE);}}/*** Appends the retry mode metric into the metrics builder,* based on the resolved retry config mode.** @param array $args** @return void*/private function appendRetryConfigMetric(array $args): void{$retries = $args['retries'] ?? null;if ($retries === null) {return;}$retryMode = '';if ($retries instanceof \Aws\Retry\Configuration) {$retryMode = $retries->getMode();} elseif (is_array($retries)&& isset($retries["mode"])) {$retryMode = $retries["mode"];}if ($retryMode === 'legacy') {$this->append(MetricsBuilder::RETRY_MODE_LEGACY);} elseif ($retryMode === 'standard') {$this->append(MetricsBuilder::RETRY_MODE_STANDARD);} elseif ($retryMode === 'adaptive') {$this->append(MetricsBuilder::RETRY_MODE_ADAPTIVE);}}/*** Appends the provided/resolved response checksum validation mode.** @param array $args** @return void*/private function appendResponseChecksumValidationMetric(array $args): void{if (empty($args['response_checksum_validation'])) {return;}$checksumValidation = $args['response_checksum_validation'];static $checksumValidationMetricMapping = ['when_supported' => MetricsBuilder::FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED,'when_required' => MetricsBuilder::FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED,];if (isset($checksumValidationMetricMapping[$checksumValidation])) {$this->append($checksumValidationMetricMapping[$checksumValidation]);}}/*** Validates if a metric can be appended by ensuring the total size,* including the new metric and separator, does not exceed the limit.* Also checks that the metric does not already exist.* Example: Appendable if:* $currentSize + len($newMetric) + len($separator) <= MAX_SIZE* and:* $newMetric not in $existingMetrics** @param string $newMetric The metric to validate.** @return bool True if the metric can be appended, false otherwise.*/private function canMetricBeAppended(string $newMetric): bool{if ($newMetric === "") {return false;}if ($this->metricsSize+ (strlen($newMetric) + strlen(self::$METRIC_SEPARATOR))> self::$MAX_METRICS_SIZE) {return false;}if (isset($this->metrics[$newMetric])) {return false;}return true;}/*** Returns the metrics builder from the property @context of a command.** @param Command $command** @return MetricsBuilder*/public static function fromCommand(CommandInterface $command): MetricsBuilder{return $command->getMetricsBuilder();}/*** Helper method for appending a metrics capture middleware into a* handler stack given. The middleware appended here is on top of the* build step.** @param HandlerList $handlerList* @param $metric** @return void*/public static function appendMetricsCaptureMiddleware(HandlerList $handlerList,$metric): void{$middlewareName = 'metrics-capture-'.$metric;if (!$handlerList->hasMiddleware($middlewareName)) {$handlerList->appendBuild(Middleware::tap(function (CommandInterface $command) use ($metric) {self::fromCommand($command)->append($metric);}),$middlewareName);}}}