PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
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.3.11, at includes/sdk/s3/Aws/ClientSideMonitoring/AbstractMonitoringMiddleware.php

245 lines 8.3 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 * Checks if the socket is created. If PHP version is greater or equals to 8 then,
176 * it will check if the var is instance of \Socket otherwise it will check if is
177 * a resource.
178 *
179 * @return bool Returns true if the socket is created, false otherwise.
180 */
181 private function isSocketCreated() : bool
182 {
183 // Before version 8, sockets are resources
184 // After version 8, sockets are instances of Socket
185 if (\PHP_MAJOR_VERSION >= 8) {
186 $socketClass = '\\Socket';
187 return self::$socket instanceof $socketClass;
188 } else {
189 return \is_resource(self::$socket);
190 }
191 }
192 /**
193 * Creates a UDP socket resource and stores it with the class, or retrieves
194 * it if already instantiated and connected. Handles error-checking and
195 * re-connecting if necessary. If $forceNewConnection is set to true, a new
196 * socket will be created.
197 *
198 * @param bool $forceNewConnection
199 * @return Resource
200 */
201 private function prepareSocket($forceNewConnection = \false)
202 {
203 if (!$this->isSocketCreated() || $forceNewConnection || \socket_last_error(self::$socket)) {
204 self::$socket = \socket_create(\AF_INET, \SOCK_DGRAM, \SOL_UDP);
205 \socket_clear_error(self::$socket);
206 \socket_connect(self::$socket, $this->getHost(), $this->getPort());
207 }
208 return self::$socket;
209 }
210 /**
211 * Sends formatted monitoring event data via the UDP socket connection to
212 * the CSM agent endpoint.
213 *
214 * @param array $eventData
215 * @return int
216 */
217 private function sendEventData(array $eventData)
218 {
219 $socket = $this->prepareSocket();
220 $datagram = \json_encode($eventData);
221 $result = \socket_write($socket, $datagram, \strlen($datagram));
222 if ($result === \false) {
223 $this->prepareSocket(\true);
224 }
225 return $result;
226 }
227 /**
228 * Unwraps options, if needed, and returns them.
229 *
230 * @return ConfigurationInterface
231 */
232 private function unwrappedOptions()
233 {
234 if (!$this->options instanceof ConfigurationInterface) {
235 try {
236 $this->options = ConfigurationProvider::unwrap($this->options);
237 } catch (\Exception $e) {
238 // Errors unwrapping CSM config defaults to disabling it
239 $this->options = new Configuration(\false, ConfigurationProvider::DEFAULT_HOST, ConfigurationProvider::DEFAULT_PORT);
240 }
241 }
242 return $this->options;
243 }
244 }
245