diff options
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/ClientSideMonitoring/AbstractMonitoringMiddleware.php')
-rw-r--r-- | vendor/aws/aws-sdk-php/src/ClientSideMonitoring/AbstractMonitoringMiddleware.php | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/AbstractMonitoringMiddleware.php b/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/AbstractMonitoringMiddleware.php new file mode 100644 index 0000000..130de6b --- /dev/null +++ b/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/AbstractMonitoringMiddleware.php @@ -0,0 +1,289 @@ +<?php + +namespace Aws\ClientSideMonitoring; + +use Aws\CommandInterface; +use Aws\Exception\AwsException; +use Aws\MonitoringEventsInterface; +use Aws\ResponseContainerInterface; +use Aws\ResultInterface; +use GuzzleHttp\Promise; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +/** + * @internal + */ +abstract class AbstractMonitoringMiddleware + implements MonitoringMiddlewareInterface +{ + private static $socket; + + private $nextHandler; + private $options; + protected $credentialProvider; + protected $region; + protected $service; + + protected static function getAwsExceptionHeader(AwsException $e, $headerName) + { + $response = $e->getResponse(); + if ($response !== null) { + $header = $response->getHeader($headerName); + if (!empty($header[0])) { + return $header[0]; + } + } + return null; + } + + protected static function getResultHeader(ResultInterface $result, $headerName) + { + if (isset($result['@metadata']['headers'][$headerName])) { + return $result['@metadata']['headers'][$headerName]; + } + return null; + } + + protected static function getExceptionHeader(\Exception $e, $headerName) + { + if ($e instanceof ResponseContainerInterface) { + $response = $e->getResponse(); + if ($response instanceof ResponseInterface) { + $header = $response->getHeader($headerName); + if (!empty($header[0])) { + return $header[0]; + } + } + } + return null; + } + + /** + * Constructor stores the passed in handler and options. + * + * @param callable $handler + * @param callable $credentialProvider + * @param $options + * @param $region + * @param $service + */ + public function __construct( + callable $handler, + callable $credentialProvider, + $options, + $region, + $service + ) { + $this->nextHandler = $handler; + $this->credentialProvider = $credentialProvider; + $this->options = $options; + $this->region = $region; + $this->service = $service; + } + + /** + * Standard invoke pattern for middleware execution to be implemented by + * child classes. + * + * @param CommandInterface $cmd + * @param RequestInterface $request + * @return Promise\PromiseInterface + */ + public function __invoke(CommandInterface $cmd, RequestInterface $request) + { + $handler = $this->nextHandler; + $eventData = null; + $enabled = $this->isEnabled(); + + if ($enabled) { + $cmd['@http']['collect_stats'] = true; + $eventData = $this->populateRequestEventData( + $cmd, + $request, + $this->getNewEvent($cmd, $request) + ); + } + + $g = function ($value) use ($eventData, $enabled) { + if ($enabled) { + $eventData = $this->populateResultEventData( + $value, + $eventData + ); + $this->sendEventData($eventData); + + if ($value instanceof MonitoringEventsInterface) { + $value->appendMonitoringEvent($eventData); + } + } + if ($value instanceof \Exception || $value instanceof \Throwable) { + return Promise\Create::rejectionFor($value); + } + return $value; + }; + + return Promise\Create::promiseFor($handler($cmd, $request))->then($g, $g); + } + + private function getClientId() + { + return $this->unwrappedOptions()->getClientId(); + } + + private function getNewEvent( + CommandInterface $cmd, + RequestInterface $request + ) { + $event = [ + 'Api' => $cmd->getName(), + 'ClientId' => $this->getClientId(), + 'Region' => $this->getRegion(), + 'Service' => $this->getService(), + 'Timestamp' => (int) floor(microtime(true) * 1000), + 'UserAgent' => substr( + $request->getHeaderLine('User-Agent') . ' ' . \Aws\default_user_agent(), + 0, + 256 + ), + 'Version' => 1 + ]; + return $event; + } + + private function getHost() + { + return $this->unwrappedOptions()->getHost(); + } + + private function getPort() + { + return $this->unwrappedOptions()->getPort(); + } + + private function getRegion() + { + return $this->region; + } + + private function getService() + { + return $this->service; + } + + /** + * Returns enabled flag from options, unwrapping options if necessary. + * + * @return bool + */ + private function isEnabled() + { + return $this->unwrappedOptions()->isEnabled(); + } + + /** + * Returns $eventData array with information from the request and command. + * + * @param CommandInterface $cmd + * @param RequestInterface $request + * @param array $event + * @return array + */ + protected function populateRequestEventData( + CommandInterface $cmd, + RequestInterface $request, + array $event + ) { + $dataFormat = static::getRequestData($request); + foreach ($dataFormat as $eventKey => $value) { + if ($value !== null) { + $event[$eventKey] = $value; + } + } + return $event; + } + + /** + * Returns $eventData array with information from the response, including + * the calculation for attempt latency. + * + * @param ResultInterface|\Exception $result + * @param array $event + * @return array + */ + protected function populateResultEventData( + $result, + array $event + ) { + $dataFormat = static::getResponseData($result); + foreach ($dataFormat as $eventKey => $value) { + if ($value !== null) { + $event[$eventKey] = $value; + } + } + return $event; + } + + /** + * Creates a UDP socket resource and stores it with the class, or retrieves + * it if already instantiated and connected. Handles error-checking and + * re-connecting if necessary. If $forceNewConnection is set to true, a new + * socket will be created. + * + * @param bool $forceNewConnection + * @return Resource + */ + private function prepareSocket($forceNewConnection = false) + { + if (!is_resource(self::$socket) + || $forceNewConnection + || socket_last_error(self::$socket) + ) { + self::$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + socket_clear_error(self::$socket); + socket_connect(self::$socket, $this->getHost(), $this->getPort()); + } + + return self::$socket; + } + + /** + * Sends formatted monitoring event data via the UDP socket connection to + * the CSM agent endpoint. + * + * @param array $eventData + * @return int + */ + private function sendEventData(array $eventData) + { + $socket = $this->prepareSocket(); + $datagram = json_encode($eventData); + $result = socket_write($socket, $datagram, strlen($datagram)); + if ($result === false) { + $this->prepareSocket(true); + } + return $result; + } + + /** + * Unwraps options, if needed, and returns them. + * + * @return ConfigurationInterface + */ + private function unwrappedOptions() + { + if (!($this->options instanceof ConfigurationInterface)) { + try { + $this->options = ConfigurationProvider::unwrap($this->options); + } catch (\Exception $e) { + // Errors unwrapping CSM config defaults to disabling it + $this->options = new Configuration( + false, + ConfigurationProvider::DEFAULT_HOST, + ConfigurationProvider::DEFAULT_PORT + ); + } + } + return $this->options; + } +}
\ No newline at end of file |