PluginProbe
Media Cloud Sync / 1.2.12
Media Cloud Sync v1.2.12
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
media-cloud-sync / includes / sdk / s3 / Aws / ClientSideMonitoring / AbstractMonitoringMiddleware.php

AbstractMonitoringMiddleware.php in Media Cloud Sync 1.2.12, at includes/sdk/s3/Aws/ClientSideMonitoring/AbstractMonitoringMiddleware.php

227 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\Aws\ClientSideMonitoring;
4
5 use Dudlewebs\WPMCS\s3\Aws\CommandInterface;
6 use Dudlewebs\WPMCS\s3\Aws\Exception\AwsException;
7 use Dudlewebs\WPMCS\s3\Aws\MonitoringEventsInterface;
8 use Dudlewebs\WPMCS\s3\Aws\ResponseContainerInterface;
9 use Dudlewebs\WPMCS\s3\Aws\ResultInterface;
10 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise;
11 use Dudlewebs\WPMCS\s3\Psr\Http\Message\RequestInterface;
12 use Dudlewebs\WPMCS\s3\Psr\Http\Message\ResponseInterface;
13 /**
14 * @internal
15 */
16 abstract class AbstractMonitoringMiddleware implements MonitoringMiddlewareInterface
17 {
18 private static $socket;
19 private $nextHandler;
20 private $options;
21 protected $credentialProvider;
22 protected $region;
23 protected $service;
24 protected static function getAwsExceptionHeader(AwsException $e, $headerName)
25 {
26 $response = $e->getResponse();
27 if ($response !== null) {
28 $header = $response->getHeader($headerName);
29 if (!empty($header[0])) {
30 return $header[0];
31 }
32 }
33 return null;
34 }
35 protected static function getResultHeader(ResultInterface $result, $headerName)
36 {
37 if (isset($result['@metadata']['headers'][$headerName])) {
38 return $result['@metadata']['headers'][$headerName];
39 }
40 return null;
41 }
42 protected static function getExceptionHeader(\Exception $e, $headerName)
43 {
44 if ($e instanceof ResponseContainerInterface) {
45 $response = $e->getResponse();
46 if ($response instanceof ResponseInterface) {
47 $header = $response->getHeader($headerName);
48 if (!empty($header[0])) {
49 return $header[0];
50 }
51 }
52 }
53 return null;
54 }
55 /**
56 * Constructor stores the passed in handler and options.
57 *
58 * @param callable $handler
59 * @param callable $credentialProvider
60 * @param $options
61 * @param $region
62 * @param $service
63 */
64 public function __construct(callable $handler, callable $credentialProvider, $options, $region, $service)
65 {
66 $this->nextHandler = $handler;
67 $this->credentialProvider = $credentialProvider;
68 $this->options = $options;
69 $this->region = $region;
70 $this->service = $service;
71 }
72 /**
73 * Standard invoke pattern for middleware execution to be implemented by
74 * child classes.
75 *
76 * @param CommandInterface $cmd
77 * @param RequestInterface $request
78 * @return Promise\PromiseInterface
79 */
80 public function __invoke(CommandInterface $cmd, RequestInterface $request)
81 {
82 $handler = $this->nextHandler;
83 $eventData = null;
84 $enabled = $this->isEnabled();
85 if ($enabled) {
86 $cmd['@http']['collect_stats'] = \true;
87 $eventData = $this->populateRequestEventData($cmd, $request, $this->getNewEvent($cmd, $request));
88 }
89 $g = function ($value) use($eventData, $enabled) {
90 if ($enabled) {
91 $eventData = $this->populateResultEventData($value, $eventData);
92 $this->sendEventData($eventData);
93 if ($value instanceof MonitoringEventsInterface) {
94 $value->appendMonitoringEvent($eventData);
95 }
96 }
97 if ($value instanceof \Exception || $value instanceof \Throwable) {
98 return Promise\Create::rejectionFor($value);
99 }
100 return $value;
101 };
102 return Promise\Create::promiseFor($handler($cmd, $request))->then($g, $g);
103 }
104 private function getClientId()
105 {
106 return $this->unwrappedOptions()->getClientId();
107 }
108 private function getNewEvent(CommandInterface $cmd, RequestInterface $request)
109 {
110 $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') . ' ' . \Dudlewebs\WPMCS\s3\Aws\default_user_agent(), 0, 256), 'Version' => 1];
111 return $event;
112 }
113 private function getHost()
114 {
115 return $this->unwrappedOptions()->getHost();
116 }
117 private function getPort()
118 {
119 return $this->unwrappedOptions()->getPort();
120 }
121 private function getRegion()
122 {
123 return $this->region;
124 }
125 private function getService()
126 {
127 return $this->service;
128 }
129 /**
130 * Returns enabled flag from options, unwrapping options if necessary.
131 *
132 * @return bool
133 */
134 private function isEnabled()
135 {
136 return $this->unwrappedOptions()->isEnabled();
137 }
138 /**
139 * Returns $eventData array with information from the request and command.
140 *
141 * @param CommandInterface $cmd
142 * @param RequestInterface $request
143 * @param array $event
144 * @return array
145 */
146 protected function populateRequestEventData(CommandInterface $cmd, RequestInterface $request, array $event)
147 {
148 $dataFormat = static::getRequestData($request);
149 foreach ($dataFormat as $eventKey => $value) {
150 if ($value !== null) {
151 $event[$eventKey] = $value;
152 }
153 }
154 return $event;
155 }
156 /**
157 * Returns $eventData array with information from the response, including
158 * the calculation for attempt latency.
159 *
160 * @param ResultInterface|\Exception $result
161 * @param array $event
162 * @return array
163 */
164 protected function populateResultEventData($result, array $event)
165 {
166 $dataFormat = static::getResponseData($result);
167 foreach ($dataFormat as $eventKey => $value) {
168 if ($value !== null) {
169 $event[$eventKey] = $value;
170 }
171 }
172 return $event;
173 }
174 /**
175 * Creates a UDP socket resource and stores it with the class, or retrieves
176 * it if already instantiated and connected. Handles error-checking and
177 * re-connecting if necessary. If $forceNewConnection is set to true, a new
178 * socket will be created.
179 *
180 * @param bool $forceNewConnection
181 * @return Resource
182 */
183 private function prepareSocket($forceNewConnection = \false)
184 {
185 if (!\is_resource(self::$socket) || $forceNewConnection || \socket_last_error(self::$socket)) {
186 self::$socket = \socket_create(\AF_INET, \SOCK_DGRAM, \SOL_UDP);
187 \socket_clear_error(self::$socket);
188 \socket_connect(self::$socket, $this->getHost(), $this->getPort());
189 }
190 return self::$socket;
191 }
192 /**
193 * Sends formatted monitoring event data via the UDP socket connection to
194 * the CSM agent endpoint.
195 *
196 * @param array $eventData
197 * @return int
198 */
199 private function sendEventData(array $eventData)
200 {
201 $socket = $this->prepareSocket();
202 $datagram = \json_encode($eventData);
203 $result = \socket_write($socket, $datagram, \strlen($datagram));
204 if ($result === \false) {
205 $this->prepareSocket(\true);
206 }
207 return $result;
208 }
209 /**
210 * Unwraps options, if needed, and returns them.
211 *
212 * @return ConfigurationInterface
213 */
214 private function unwrappedOptions()
215 {
216 if (!$this->options instanceof ConfigurationInterface) {
217 try {
218 $this->options = ConfigurationProvider::unwrap($this->options);
219 } catch (\Exception $e) {
220 // Errors unwrapping CSM config defaults to disabling it
221 $this->options = new Configuration(\false, ConfigurationProvider::DEFAULT_HOST, ConfigurationProvider::DEFAULT_PORT);
222 }
223 }
224 return $this->options;
225 }
226 }
227