| 199 |
lars |
1 |
<?php namespace Clockwork\Request;
|
|
|
2 |
|
|
|
3 |
use Clockwork\Helpers\Serializer;
|
|
|
4 |
|
|
|
5 |
// Data structure representing a single application request
|
|
|
6 |
class Request
|
|
|
7 |
{
|
|
|
8 |
// Unique request ID
|
|
|
9 |
public $id;
|
|
|
10 |
|
|
|
11 |
// Metadata version
|
|
|
12 |
public $version = 1;
|
|
|
13 |
|
|
|
14 |
// Request type (request, command, queue-job or test)
|
|
|
15 |
public $type = 'request';
|
|
|
16 |
|
|
|
17 |
// Request time
|
|
|
18 |
public $time;
|
|
|
19 |
|
|
|
20 |
// Request method
|
|
|
21 |
public $method;
|
|
|
22 |
|
|
|
23 |
// Request URL
|
|
|
24 |
public $url;
|
|
|
25 |
|
|
|
26 |
// Request URI
|
|
|
27 |
public $uri;
|
|
|
28 |
|
|
|
29 |
// Request headers
|
|
|
30 |
public $headers = [];
|
|
|
31 |
|
|
|
32 |
// Textual representation of the executed controller
|
|
|
33 |
public $controller;
|
|
|
34 |
|
|
|
35 |
// Request GET data
|
|
|
36 |
public $getData = [];
|
|
|
37 |
|
|
|
38 |
// Request POST data
|
|
|
39 |
public $postData = [];
|
|
|
40 |
|
|
|
41 |
// Request body data
|
|
|
42 |
public $requestData = [];
|
|
|
43 |
|
|
|
44 |
// Session data array
|
|
|
45 |
public $sessionData = [];
|
|
|
46 |
|
|
|
47 |
// Authenticated user
|
|
|
48 |
public $authenticatedUser;
|
|
|
49 |
|
|
|
50 |
// Request cookies
|
|
|
51 |
public $cookies = [];
|
|
|
52 |
|
|
|
53 |
// Response time
|
|
|
54 |
public $responseTime;
|
|
|
55 |
|
|
|
56 |
// Response processing time
|
|
|
57 |
public $responseDuration;
|
|
|
58 |
|
|
|
59 |
// Response status code
|
|
|
60 |
public $responseStatus;
|
|
|
61 |
|
|
|
62 |
// Peak memory usage in bytes
|
|
|
63 |
public $memoryUsage;
|
|
|
64 |
|
|
|
65 |
// Executed middleware
|
|
|
66 |
public $middleware = [];
|
|
|
67 |
|
|
|
68 |
// Database queries
|
|
|
69 |
public $databaseQueries = [];
|
|
|
70 |
|
|
|
71 |
// Database queries count
|
|
|
72 |
public $databaseQueriesCount;
|
|
|
73 |
|
|
|
74 |
// Database slow queries count
|
|
|
75 |
public $databaseSlowQueries;
|
|
|
76 |
|
|
|
77 |
// Database query counts of a particular type (selects, inserts, updates, deletes, others)
|
|
|
78 |
public $databaseSelects;
|
|
|
79 |
public $databaseInserts;
|
|
|
80 |
public $databaseUpdates;
|
|
|
81 |
public $databaseDeletes;
|
|
|
82 |
public $databaseOthers;
|
|
|
83 |
public $databaseDuration;
|
|
|
84 |
|
|
|
85 |
// Cache queries
|
|
|
86 |
public $cacheQueries = [];
|
|
|
87 |
|
|
|
88 |
// Cache query counts of a particular type (reads, hits, writes, deletes)
|
|
|
89 |
public $cacheReads;
|
|
|
90 |
public $cacheHits;
|
|
|
91 |
public $cacheWrites;
|
|
|
92 |
public $cacheDeletes;
|
|
|
93 |
|
|
|
94 |
// Cache queries execution time
|
|
|
95 |
public $cacheTime;
|
|
|
96 |
|
|
|
97 |
// Model actions
|
|
|
98 |
public $modelsActions = [];
|
|
|
99 |
|
|
|
100 |
// Model action counts by model
|
|
|
101 |
public $modelsRetrieved = [];
|
|
|
102 |
public $modelsCreated = [];
|
|
|
103 |
public $modelsUpdated = [];
|
|
|
104 |
public $modelsDeleted = [];
|
|
|
105 |
|
|
|
106 |
// Redis commands
|
|
|
107 |
public $redisCommands = [];
|
|
|
108 |
|
|
|
109 |
// Dispatched queue jobs
|
|
|
110 |
public $queueJobs = [];
|
|
|
111 |
|
|
|
112 |
// Timeline events
|
|
|
113 |
public $timelineData = [];
|
|
|
114 |
|
|
|
115 |
// Log messages
|
|
|
116 |
public $log = [];
|
|
|
117 |
|
|
|
118 |
// Fired events
|
|
|
119 |
public $events = [];
|
|
|
120 |
|
|
|
121 |
// Application routes
|
|
|
122 |
public $routes = [];
|
|
|
123 |
|
|
|
124 |
// Sent notifications
|
|
|
125 |
public $notifications = [];
|
|
|
126 |
|
|
|
127 |
// Sent emails (legacy property replaced by notifications)
|
|
|
128 |
public $emailsData = [];
|
|
|
129 |
|
|
|
130 |
// Rendered views
|
|
|
131 |
public $viewsData = [];
|
|
|
132 |
|
|
|
133 |
// Custom user data
|
|
|
134 |
public $userData = [];
|
|
|
135 |
|
|
|
136 |
// Subrequests
|
|
|
137 |
public $subrequests = [];
|
|
|
138 |
|
|
|
139 |
// Xebug profiler data
|
|
|
140 |
public $xdebug = [];
|
|
|
141 |
|
|
|
142 |
// Command name
|
|
|
143 |
public $commandName;
|
|
|
144 |
|
|
|
145 |
// Command arguments passed in
|
|
|
146 |
public $commandArguments = [];
|
|
|
147 |
|
|
|
148 |
// Command arguments defaults
|
|
|
149 |
public $commandArgumentsDefaults = [];
|
|
|
150 |
|
|
|
151 |
// Command options passed in
|
|
|
152 |
public $commandOptions = [];
|
|
|
153 |
|
|
|
154 |
// Command options defaults
|
|
|
155 |
public $commandOptionsDefaults = [];
|
|
|
156 |
|
|
|
157 |
// Command exit code
|
|
|
158 |
public $commandExitCode;
|
|
|
159 |
|
|
|
160 |
// Command output
|
|
|
161 |
public $commandOutput;
|
|
|
162 |
|
|
|
163 |
// Queue job name
|
|
|
164 |
public $jobName;
|
|
|
165 |
|
|
|
166 |
// Queue job description
|
|
|
167 |
public $jobDescription;
|
|
|
168 |
|
|
|
169 |
// Queue job status
|
|
|
170 |
public $jobStatus;
|
|
|
171 |
|
|
|
172 |
// Queue job payload
|
|
|
173 |
public $jobPayload = [];
|
|
|
174 |
|
|
|
175 |
// Queue job queue name
|
|
|
176 |
public $jobQueue;
|
|
|
177 |
|
|
|
178 |
// Queue job connection name
|
|
|
179 |
public $jobConnection;
|
|
|
180 |
|
|
|
181 |
// Queue job additional options
|
|
|
182 |
public $jobOptions = [];
|
|
|
183 |
|
|
|
184 |
// Test name
|
|
|
185 |
public $testName;
|
|
|
186 |
|
|
|
187 |
// Test status
|
|
|
188 |
public $testStatus;
|
|
|
189 |
|
|
|
190 |
// Test status message (eg. in case of failure)
|
|
|
191 |
public $testStatusMessage;
|
|
|
192 |
|
|
|
193 |
// Ran test asserts
|
|
|
194 |
public $testAsserts = [];
|
|
|
195 |
|
|
|
196 |
// Client-side performance metrics in the form of [ metric => value ]
|
|
|
197 |
public $clientMetrics = [];
|
|
|
198 |
|
|
|
199 |
// Web vitals in the form of [ vital => value ]
|
|
|
200 |
public $webVitals = [];
|
|
|
201 |
|
|
|
202 |
// Parent request
|
|
|
203 |
public $parent;
|
|
|
204 |
|
|
|
205 |
// Token to update this request data
|
|
|
206 |
public $updateToken;
|
|
|
207 |
|
|
|
208 |
// Log instance for the current request
|
|
|
209 |
protected $currentLog;
|
|
|
210 |
|
|
|
211 |
// Timeline instance for the current request
|
|
|
212 |
protected $currentTimeline;
|
|
|
213 |
|
|
|
214 |
// Array of property values to override collected values from data sources
|
|
|
215 |
protected $overrides = [];
|
|
|
216 |
|
|
|
217 |
// Create a new request, if optional data array argument is provided, it will be used to populate the request object,
|
|
|
218 |
// otherwise an empty request with current time, autogenerated ID and update token will be created
|
|
|
219 |
public function __construct(array $data = [])
|
|
|
220 |
{
|
|
|
221 |
$this->id = isset($data['id']) ? $data['id'] : $this->generateRequestId();
|
|
|
222 |
$this->time = microtime(true);
|
|
|
223 |
$this->updateToken = isset($data['updateToken']) ? $data['updateToken'] : $this->generateUpdateToken();
|
|
|
224 |
|
|
|
225 |
foreach ($data as $key => $val) $this->$key = $val;
|
|
|
226 |
|
|
|
227 |
$this->currentLog = new Log($this->log);
|
|
|
228 |
$this->currentTimeline = new Timeline\Timeline($this->timelineData);
|
|
|
229 |
}
|
|
|
230 |
|
|
|
231 |
// Compute the sum of durations of all database queries
|
|
|
232 |
public function getDatabaseDuration()
|
|
|
233 |
{
|
|
|
234 |
return array_reduce($this->databaseQueries, function ($total, $query) {
|
|
|
235 |
return isset($query['duration']) ? $total + $query['duration'] : $total;
|
|
|
236 |
}, 0);
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
// Compute response duration in milliseconds
|
|
|
240 |
public function getResponseDuration()
|
|
|
241 |
{
|
|
|
242 |
return ($this->responseTime - $this->time) * 1000;
|
|
|
243 |
}
|
|
|
244 |
|
|
|
245 |
// Get all request data as an array
|
|
|
246 |
public function toArray()
|
|
|
247 |
{
|
|
|
248 |
return [
|
|
|
249 |
'id' => $this->id,
|
|
|
250 |
'version' => $this->version,
|
|
|
251 |
'type' => $this->type,
|
|
|
252 |
'time' => $this->time,
|
|
|
253 |
'method' => $this->method,
|
|
|
254 |
'url' => $this->url,
|
|
|
255 |
'uri' => $this->uri,
|
|
|
256 |
'headers' => $this->headers,
|
|
|
257 |
'controller' => $this->controller,
|
|
|
258 |
'getData' => $this->getData,
|
|
|
259 |
'postData' => $this->postData,
|
|
|
260 |
'requestData' => $this->requestData,
|
|
|
261 |
'sessionData' => $this->sessionData,
|
|
|
262 |
'authenticatedUser' => $this->authenticatedUser,
|
|
|
263 |
'cookies' => $this->cookies,
|
|
|
264 |
'responseTime' => $this->responseTime,
|
|
|
265 |
'responseStatus' => $this->responseStatus,
|
|
|
266 |
'responseDuration' => $this->responseDuration ?: $this->getResponseDuration(),
|
|
|
267 |
'memoryUsage' => $this->memoryUsage,
|
|
|
268 |
'middleware' => $this->middleware,
|
|
|
269 |
'databaseQueries' => $this->databaseQueries,
|
|
|
270 |
'databaseQueriesCount' => $this->databaseQueriesCount,
|
|
|
271 |
'databaseSlowQueries' => $this->databaseSlowQueries,
|
|
|
272 |
'databaseSelects' => $this->databaseSelects,
|
|
|
273 |
'databaseInserts' => $this->databaseInserts,
|
|
|
274 |
'databaseUpdates' => $this->databaseUpdates,
|
|
|
275 |
'databaseDeletes' => $this->databaseDeletes,
|
|
|
276 |
'databaseOthers' => $this->databaseOthers,
|
|
|
277 |
'databaseDuration' => $this->getDatabaseDuration(),
|
|
|
278 |
'cacheQueries' => $this->cacheQueries,
|
|
|
279 |
'cacheReads' => $this->cacheReads,
|
|
|
280 |
'cacheHits' => $this->cacheHits,
|
|
|
281 |
'cacheWrites' => $this->cacheWrites,
|
|
|
282 |
'cacheDeletes' => $this->cacheDeletes,
|
|
|
283 |
'cacheTime' => $this->cacheTime,
|
|
|
284 |
'modelsActions' => $this->modelsActions,
|
|
|
285 |
'modelsRetrieved' => $this->modelsRetrieved,
|
|
|
286 |
'modelsCreated' => $this->modelsCreated,
|
|
|
287 |
'modelsUpdated' => $this->modelsUpdated,
|
|
|
288 |
'modelsDeleted' => $this->modelsDeleted,
|
|
|
289 |
'redisCommands' => $this->redisCommands,
|
|
|
290 |
'queueJobs' => $this->queueJobs,
|
|
|
291 |
'timelineData' => $this->timeline()->toArray(),
|
|
|
292 |
'log' => $this->log()->toArray(),
|
|
|
293 |
'events' => $this->events,
|
|
|
294 |
'routes' => $this->routes,
|
|
|
295 |
'notifications' => $this->notifications,
|
|
|
296 |
'emailsData' => $this->emailsData,
|
|
|
297 |
'viewsData' => $this->viewsData,
|
|
|
298 |
'userData' => array_map(function ($data) {
|
|
|
299 |
return $data instanceof UserData ? $data->toArray() : $data;
|
|
|
300 |
}, $this->userData),
|
|
|
301 |
'subrequests' => $this->subrequests,
|
|
|
302 |
'xdebug' => $this->xdebug,
|
|
|
303 |
'commandName' => $this->commandName,
|
|
|
304 |
'commandArguments' => $this->commandArguments,
|
|
|
305 |
'commandArgumentsDefaults' => $this->commandArgumentsDefaults,
|
|
|
306 |
'commandOptions' => $this->commandOptions,
|
|
|
307 |
'commandOptionsDefaults' => $this->commandOptionsDefaults,
|
|
|
308 |
'commandExitCode' => $this->commandExitCode,
|
|
|
309 |
'commandOutput' => $this->commandOutput,
|
|
|
310 |
'jobName' => $this->jobName,
|
|
|
311 |
'jobDescription' => $this->jobDescription,
|
|
|
312 |
'jobStatus' => $this->jobStatus,
|
|
|
313 |
'jobPayload' => $this->jobPayload,
|
|
|
314 |
'jobQueue' => $this->jobQueue,
|
|
|
315 |
'jobConnection' => $this->jobConnection,
|
|
|
316 |
'jobOptions' => $this->jobOptions,
|
|
|
317 |
'testName' => $this->testName,
|
|
|
318 |
'testStatus' => $this->testStatus,
|
|
|
319 |
'testStatusMessage' => $this->testStatusMessage,
|
|
|
320 |
'testAsserts' => $this->testAsserts,
|
|
|
321 |
'clientMetrics' => $this->clientMetrics,
|
|
|
322 |
'webVitals' => $this->webVitals,
|
|
|
323 |
'parent' => $this->parent,
|
|
|
324 |
'updateToken' => $this->updateToken
|
|
|
325 |
];
|
|
|
326 |
}
|
|
|
327 |
|
|
|
328 |
// Get all request data as a JSON string
|
|
|
329 |
public function toJson()
|
|
|
330 |
{
|
|
|
331 |
return json_encode($this->toArray(), \JSON_PARTIAL_OUTPUT_ON_ERROR);
|
|
|
332 |
}
|
|
|
333 |
|
|
|
334 |
// Return request data except specified keys as an array
|
|
|
335 |
public function except($keys)
|
|
|
336 |
{
|
|
|
337 |
return array_filter($this->toArray(), function ($value, $key) use ($keys) {
|
|
|
338 |
return ! in_array($key, $keys);
|
|
|
339 |
}, ARRAY_FILTER_USE_BOTH);
|
|
|
340 |
}
|
|
|
341 |
|
|
|
342 |
// Return only request data with specified keys as an array
|
|
|
343 |
public function only($keys)
|
|
|
344 |
{
|
|
|
345 |
return array_filter($this->toArray(), function ($value, $key) use ($keys) {
|
|
|
346 |
return in_array($key, $keys);
|
|
|
347 |
}, ARRAY_FILTER_USE_BOTH);
|
|
|
348 |
}
|
|
|
349 |
|
|
|
350 |
// Return log instance for the current request
|
|
|
351 |
public function log()
|
|
|
352 |
{
|
|
|
353 |
return $this->currentLog;
|
|
|
354 |
}
|
|
|
355 |
|
|
|
356 |
// Return timeline instance for the current request
|
|
|
357 |
public function timeline()
|
|
|
358 |
{
|
|
|
359 |
return $this->currentTimeline;
|
|
|
360 |
}
|
|
|
361 |
|
|
|
362 |
// Add a new overridden property
|
|
|
363 |
public function override($property, $value)
|
|
|
364 |
{
|
|
|
365 |
$this->overrides[$property] = $value;
|
|
|
366 |
return $this;
|
|
|
367 |
}
|
|
|
368 |
|
|
|
369 |
// Get or set all overrides at once
|
|
|
370 |
public function overrides($overrides = null)
|
|
|
371 |
{
|
|
|
372 |
if (! $overrides) return $this->overrides;
|
|
|
373 |
|
|
|
374 |
$this->overrides = $overrides;
|
|
|
375 |
return $this;
|
|
|
376 |
}
|
|
|
377 |
|
|
|
378 |
// Add database query, takes query, bindings, duration (in ms) and additional data - connection (connection name),
|
|
|
379 |
// time (when was the query executed), file (caller file name), line (caller line number), trace (serialized trace),
|
|
|
380 |
// model (associated ORM model)
|
|
|
381 |
public function addDatabaseQuery($query, $bindings = [], $duration = null, $data = [])
|
|
|
382 |
{
|
|
|
383 |
$this->databaseQueries[] = [
|
|
|
384 |
'query' => $query,
|
|
|
385 |
'bindings' => (new Serializer)->normalize($bindings),
|
|
|
386 |
'duration' => $duration,
|
|
|
387 |
'connection' => isset($data['connection']) ? $data['connection'] : null,
|
|
|
388 |
'time' => isset($data['time']) ? $data['time'] : microtime(true) - ($duration ?: 0) / 1000,
|
|
|
389 |
'file' => isset($data['file']) ? $data['file'] : null,
|
|
|
390 |
'line' => isset($data['line']) ? $data['line'] : null,
|
|
|
391 |
'trace' => isset($data['trace']) ? $data['trace'] : null,
|
|
|
392 |
'model' => isset($data['model']) ? $data['model'] : null,
|
|
|
393 |
'tags' => array_merge(
|
|
|
394 |
isset($data['tags']) ? $data['tags'] : [], isset($data['slow']) ? [ 'slow' ] : []
|
|
|
395 |
)
|
|
|
396 |
];
|
|
|
397 |
}
|
|
|
398 |
|
|
|
399 |
// Add model action, takes model, action and additional data - key, attributes, changes, time (when was the action
|
|
|
400 |
// executed), query, duration (in ms), connection (connection name), trace (serialized trace), file (caller file
|
|
|
401 |
// name), line (caller line number), tags
|
|
|
402 |
public function addModelAction($model, $action, $data = [])
|
|
|
403 |
{
|
|
|
404 |
$this->modelActions[] = [
|
|
|
405 |
'model' => $model,
|
|
|
406 |
'key' => isset($data['key']) ? $data['key'] : null,
|
|
|
407 |
'action' => $action,
|
|
|
408 |
'attributes' => isset($data['attributes']) ? $data['attributes'] : [],
|
|
|
409 |
'changes' => isset($data['changes']) ? $data['changes'] : [],
|
|
|
410 |
'duration' => $duration = isset($data['duration']) ? $data['duration'] : null,
|
|
|
411 |
'time' => isset($data['time']) ? $data['time'] : microtime(true) - ($duration ?: 0) / 1000,
|
|
|
412 |
'query' => isset($data['query']) ? $data['query'] : null,
|
|
|
413 |
'connection' => isset($data['connection']) ? $data['connection'] : null,
|
|
|
414 |
'trace' => isset($data['trace']) ? $data['trace'] : null,
|
|
|
415 |
'file' => isset($data['file']) ? $data['file'] : null,
|
|
|
416 |
'line' => isset($data['line']) ? $data['line'] : null,
|
|
|
417 |
'tags' => isset($data['tags']) ? $data['tags'] : []
|
|
|
418 |
];
|
|
|
419 |
}
|
|
|
420 |
|
|
|
421 |
// Add cache query, takes type, key, value, duration (in ms) and additional data - connection (connection name),
|
|
|
422 |
// time (when was the query executed), file (caller file name), line (caller line number), trace (serialized trace),
|
|
|
423 |
// expiration
|
|
|
424 |
public function addCacheQuery($type, $key, $value = null, $duration = null, $data = [])
|
|
|
425 |
{
|
|
|
426 |
$this->cacheQueries[] = [
|
|
|
427 |
'type' => $type,
|
|
|
428 |
'key' => $key,
|
|
|
429 |
'value' => (new Serializer)->normalize($value),
|
|
|
430 |
'duration' => $duration,
|
|
|
431 |
'connection' => isset($data['connection']) ? $data['connection'] : null,
|
|
|
432 |
'time' => isset($data['time']) ? $data['time'] : microtime(true) - ($duration ?: 0) / 1000,
|
|
|
433 |
'file' => isset($data['file']) ? $data['file'] : null,
|
|
|
434 |
'line' => isset($data['line']) ? $data['line'] : null,
|
|
|
435 |
'trace' => isset($data['trace']) ? $data['trace'] : null,
|
|
|
436 |
'expiration' => isset($data['expiration']) ? $data['expiration'] : null
|
|
|
437 |
];
|
|
|
438 |
}
|
|
|
439 |
|
|
|
440 |
// Add event, takes event name, data, time and additional data - listeners, duration (in ms), file (caller file
|
|
|
441 |
// name), line (caller line number), trace (serialized trace)
|
|
|
442 |
public function addEvent($event, $eventData = null, $time = null, $data = [])
|
|
|
443 |
{
|
|
|
444 |
$this->events[] = [
|
|
|
445 |
'event' => $event,
|
|
|
446 |
'data' => (new Serializer)->normalize($eventData),
|
|
|
447 |
'duration' => $duration = isset($data['duration']) ? $data['duration'] : null,
|
|
|
448 |
'time' => $time ? $time : microtime(true) - ($duration ?: 0) / 1000,
|
|
|
449 |
'listeners' => isset($data['listeners']) ? $data['listeners'] : null,
|
|
|
450 |
'file' => isset($data['file']) ? $data['file'] : null,
|
|
|
451 |
'line' => isset($data['line']) ? $data['line'] : null,
|
|
|
452 |
'trace' => isset($data['trace']) ? $data['trace'] : null
|
|
|
453 |
];
|
|
|
454 |
}
|
|
|
455 |
|
|
|
456 |
// Add route, takes method, uri, action and additional data - name, middleware, before (before filters), after
|
|
|
457 |
// (after filters)
|
|
|
458 |
public function addRoute($method, $uri, $action, $data = [])
|
|
|
459 |
{
|
|
|
460 |
$this->routes[] = [
|
|
|
461 |
'method' => $method,
|
|
|
462 |
'uri' => $uri,
|
|
|
463 |
'action' => $action,
|
|
|
464 |
'name' => isset($data['name']) ? $data['name'] : null,
|
|
|
465 |
'middleware' => isset($data['middleware']) ? $data['middleware'] : null,
|
|
|
466 |
'before' => isset($data['before']) ? $data['before'] : null,
|
|
|
467 |
'after' => isset($data['after']) ? $data['after'] : null
|
|
|
468 |
];
|
|
|
469 |
}
|
|
|
470 |
|
|
|
471 |
// Add sent notifucation, takes subject, recipient, sender, and additional data - time, duration, type, content, data
|
|
|
472 |
public function addNotification($subject, $to, $from = null, $data = [])
|
|
|
473 |
{
|
|
|
474 |
$this->notifications[] = [
|
|
|
475 |
'subject' => $subject,
|
|
|
476 |
'from' => $from,
|
|
|
477 |
'to' => $to,
|
|
|
478 |
'content' => isset($data['content']) ? $data['content'] : null,
|
|
|
479 |
'type' => isset($data['type']) ? $data['type'] : null,
|
|
|
480 |
'data' => isset($data['data']) ? $data['data'] : [],
|
|
|
481 |
'duration' => $duration = isset($data['duration']) ? $data['duration'] : null,
|
|
|
482 |
'time' => isset($data['time']) ? $data['time'] : microtime(true) - ($duration ?: 0) / 1000,
|
|
|
483 |
'trace' => isset($data['trace']) ? $data['trace'] : null,
|
|
|
484 |
'file' => isset($data['file']) ? $data['file'] : null,
|
|
|
485 |
'line' => isset($data['line']) ? $data['line'] : null
|
|
|
486 |
];
|
|
|
487 |
}
|
|
|
488 |
|
|
|
489 |
// Add sent email, takes subject, recipient address, sender address, array of headers, and additional data - time
|
|
|
490 |
// (when was the email sent), duration (sending time in ms)
|
|
|
491 |
public function addEmail($subject, $to, $from = null, $headers = [], $data = [])
|
|
|
492 |
{
|
|
|
493 |
$this->emailsData[] = [
|
|
|
494 |
'start' => isset($data['time']) ? $data['time'] : null,
|
|
|
495 |
'end' => isset($data['time'], $data['duration']) ? $data['time'] + $data['duration'] / 1000 : null,
|
|
|
496 |
'duration' => isset($data['duration']) ? $data['duration'] : null,
|
|
|
497 |
'description' => 'Sending an email message',
|
|
|
498 |
'data' => [
|
|
|
499 |
'subject' => $subject,
|
|
|
500 |
'to' => $to,
|
|
|
501 |
'from' => $from,
|
|
|
502 |
'headers' => (new Serializer)->normalize($headers)
|
|
|
503 |
]
|
|
|
504 |
];
|
|
|
505 |
}
|
|
|
506 |
|
|
|
507 |
// Add view, takes view name, view data and additional data - time (when was the view rendered), duration (sending
|
|
|
508 |
// time in ms)
|
|
|
509 |
public function addView($name, $viewData = [], $data = [])
|
|
|
510 |
{
|
|
|
511 |
$this->viewsData[] = [
|
|
|
512 |
'start' => isset($data['time']) ? $data['time'] : null,
|
|
|
513 |
'end' => isset($data['time'], $data['duration']) ? $data['time'] + $data['duration'] / 1000 : null,
|
|
|
514 |
'duration' => isset($data['duration']) ? $data['duration'] : null,
|
|
|
515 |
'description' => 'Rendering a view',
|
|
|
516 |
'data' => [
|
|
|
517 |
'name' => $name,
|
|
|
518 |
'data' => (new Serializer)->normalize($viewData)
|
|
|
519 |
]
|
|
|
520 |
];
|
|
|
521 |
}
|
|
|
522 |
|
|
|
523 |
// Add executed subrequest, takes the requested url, subrequest Clockwork ID and additional data - path if non-default
|
|
|
524 |
public function addSubrequest($url, $id, $data = [])
|
|
|
525 |
{
|
|
|
526 |
$this->subrequests[] = [
|
|
|
527 |
'url' => $url,
|
|
|
528 |
'id' => $id,
|
|
|
529 |
'path' => isset($data['path']) ? $data['path'] : null
|
|
|
530 |
];
|
|
|
531 |
}
|
|
|
532 |
|
|
|
533 |
// Set the authenticated user, takes a username, an id and additional data - email and name
|
|
|
534 |
public function setAuthenticatedUser($username, $id = null, $data = [])
|
|
|
535 |
{
|
|
|
536 |
$this->authenticatedUser = [
|
|
|
537 |
'id' => $id,
|
|
|
538 |
'username' => $username,
|
|
|
539 |
'email' => isset($data['email']) ? $data['email'] : null,
|
|
|
540 |
'name' => isset($data['name']) ? $data['name'] : null
|
|
|
541 |
];
|
|
|
542 |
}
|
|
|
543 |
|
|
|
544 |
// Set parent request, takes the request id and additional options - url and path if non-default
|
|
|
545 |
public function setParent($id, $data = [])
|
|
|
546 |
{
|
|
|
547 |
$this->parent = [
|
|
|
548 |
'id' => $id,
|
|
|
549 |
'url' => isset($data['url']) ? $data['url'] : null,
|
|
|
550 |
'path' => isset($data['path']) ? $data['path'] : null
|
|
|
551 |
];
|
|
|
552 |
}
|
|
|
553 |
|
|
|
554 |
// Add custom user data
|
|
|
555 |
public function userData($key = null)
|
|
|
556 |
{
|
|
|
557 |
if ($key && isset($this->userData[$key])) {
|
|
|
558 |
return $this->userData[$key];
|
|
|
559 |
}
|
|
|
560 |
|
|
|
561 |
$userData = (new UserData)->title($key);
|
|
|
562 |
|
|
|
563 |
return $key ? $this->userData[$key] = $userData : $this->userData[] = $userData;
|
|
|
564 |
}
|
|
|
565 |
|
|
|
566 |
// Add a ran test assert, takes the assert name, arguments, whether it passed and trace as arguments
|
|
|
567 |
public function addTestAssert($name, $arguments = null, $passed = true, $trace = null)
|
|
|
568 |
{
|
|
|
569 |
$this->testAsserts[] = [
|
|
|
570 |
'name' => $name,
|
|
|
571 |
'arguments' => (new Serializer)->normalize($arguments),
|
|
|
572 |
'trace' => $trace,
|
|
|
573 |
'passed' => $passed
|
|
|
574 |
];
|
|
|
575 |
}
|
|
|
576 |
|
|
|
577 |
// Generate unique request ID in the form of <current time>-<random number>
|
|
|
578 |
protected function generateRequestId()
|
|
|
579 |
{
|
|
|
580 |
return str_replace('.', '-', sprintf('%.4F', microtime(true))) . '-' . mt_rand();
|
|
|
581 |
}
|
|
|
582 |
|
|
|
583 |
// Generate a random update token
|
|
|
584 |
protected function generateUpdateToken()
|
|
|
585 |
{
|
|
|
586 |
$length = 8;
|
|
|
587 |
$bytes = function_exists('random_bytes') ? random_bytes($length) : openssl_random_pseudo_bytes($length);
|
|
|
588 |
|
|
|
589 |
return substr(bin2hex($bytes), 0, $length);
|
|
|
590 |
}
|
|
|
591 |
}
|