Seditio Source
Root |
./othercms/dle15_0/upload/engine/classes/composer/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/AbstractMonitoringMiddleware.php
<?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\rejection_for($value);
            }
            return
$value;
        };

        return
Promise\promise_for($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;
    }
}