mirror of
https://github.com/getgrav/grav.git
synced 2025-10-26 07:56:07 +01:00
Add basic clockwork support
This commit is contained in:
@@ -50,7 +50,8 @@
|
||||
"composer/ca-bundle": "^1.0",
|
||||
"dragonmantank/cron-expression": "^1.2",
|
||||
"phive/twig-extensions-deferred": "^1.0",
|
||||
"willdurand/negotiation": "^2.3"
|
||||
"willdurand/negotiation": "^2.3",
|
||||
"itsgoingd/clockwork": "^3.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "^2.4",
|
||||
|
||||
60
composer.lock
generated
60
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "f9429e7cd2e75a232f968b01a1024983",
|
||||
"content-hash": "1c5e84ccbe601461f02188ff7336c82e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "antoligy/dom-string-iterators",
|
||||
@@ -658,6 +658,64 @@
|
||||
],
|
||||
"time": "2018-12-04T20:46:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "itsgoingd/clockwork",
|
||||
"version": "v3.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/itsgoingd/clockwork.git",
|
||||
"reference": "529b6f9e2ce487b900213cf1d0694d0aebd5977f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/529b6f9e2ce487b900213cf1d0694d0aebd5977f",
|
||||
"reference": "529b6f9e2ce487b900213cf1d0694d0aebd5977f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5",
|
||||
"psr/log": "1.*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Clockwork\\Support\\Laravel\\ClockworkServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Clockwork": "Clockwork\\Support\\Laravel\\Facade"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Clockwork\\": "Clockwork/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "itsgoingd",
|
||||
"email": "itsgoingd@luzer.sk",
|
||||
"homepage": "https://twitter.com/itsgoingd"
|
||||
}
|
||||
],
|
||||
"description": "php dev tools integrated to your browser",
|
||||
"homepage": "https://underground.works/clockwork",
|
||||
"keywords": [
|
||||
"Devtools",
|
||||
"debugging",
|
||||
"laravel",
|
||||
"logging",
|
||||
"lumen",
|
||||
"profiling",
|
||||
"slim"
|
||||
],
|
||||
"time": "2019-03-21T20:24:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kodus/psr7-server",
|
||||
"version": "1.0.0",
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
namespace Grav\Common;
|
||||
|
||||
use Clockwork\Clockwork;
|
||||
use Clockwork\DataSource\PhpDataSource;
|
||||
use Clockwork\Storage\FileStorage;
|
||||
use DebugBar\DataCollector\ConfigCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\ExceptionsCollector;
|
||||
@@ -39,6 +42,9 @@ class Debugger
|
||||
/** @var StandardDebugBar $debugbar */
|
||||
protected $debugbar;
|
||||
|
||||
/** @var Clockwork */
|
||||
protected $clockwork;
|
||||
|
||||
/** @var bool */
|
||||
protected $enabled;
|
||||
|
||||
@@ -64,25 +70,46 @@ class Debugger
|
||||
\define('GRAV_REQUEST_TIME', $currentTime);
|
||||
}
|
||||
|
||||
$requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME;
|
||||
|
||||
// Enable debugger until $this->init() gets called.
|
||||
$this->enabled = true;
|
||||
|
||||
// Clockwork initialization.
|
||||
$clockwork = new Clockwork();
|
||||
$clockwork->addDataSource(new PhpDataSource());
|
||||
$clockwork->setStorage(new FileStorage(GRAV_ROOT . '/cache/clockwork'));
|
||||
$clockwork->getLog()->collectStackTraces(false);
|
||||
|
||||
$this->clockwork = $clockwork;
|
||||
|
||||
// Debugbar initialization.
|
||||
$debugbar = new DebugBar();
|
||||
$debugbar->addCollector(new PhpInfoCollector());
|
||||
$debugbar->addCollector(new MessagesCollector());
|
||||
$debugbar->addCollector(new RequestDataCollector());
|
||||
$debugbar->addCollector(new TimeDataCollector($_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME));
|
||||
$debugbar->addCollector(new TimeDataCollector($requestTime));
|
||||
|
||||
$this->debugbar = $debugbar;
|
||||
|
||||
$timeLine = $clockwork->getTimeline();
|
||||
$timeLine->addEvent('server', 'Server', $requestTime, GRAV_REQUEST_TIME);
|
||||
$timeLine->addEvent('loading', 'Loading', GRAV_REQUEST_TIME, microtime(true));
|
||||
$timeLine->addEvent('debugger', 'Debugger', $currentTime, microtime(true));
|
||||
|
||||
$debugbar['time']->addMeasure('Server', $debugbar['time']->getRequestStartTime(), GRAV_REQUEST_TIME);
|
||||
$debugbar['time']->addMeasure('Loading', GRAV_REQUEST_TIME, $currentTime);
|
||||
$debugbar['time']->addMeasure('Debugger', $currentTime, microtime(true));
|
||||
|
||||
$this->debugbar = $debugbar;
|
||||
|
||||
// Set deprecation collector.
|
||||
$this->setErrorHandler();
|
||||
}
|
||||
|
||||
public function getClockwork(): Clockwork
|
||||
{
|
||||
return $this->clockwork;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the debugger
|
||||
*
|
||||
@@ -276,6 +303,7 @@ class Debugger
|
||||
{
|
||||
if (strpos($name, '_') === 0 || $this->enabled()) {
|
||||
$this->debugbar['time']->startMeasure($name, $description);
|
||||
$this->clockwork->startEvent($name, $description ?? $name);
|
||||
$this->timers[] = $name;
|
||||
}
|
||||
|
||||
@@ -293,6 +321,7 @@ class Debugger
|
||||
{
|
||||
if (\in_array($name, $this->timers, true) && (strpos($name, '_') === 0 || $this->enabled())) {
|
||||
$this->debugbar['time']->stopMeasure($name);
|
||||
$this->clockwork->endEvent($name);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -311,6 +340,7 @@ class Debugger
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
$this->debugbar['messages']->addMessage($message, $label, $isString);
|
||||
$this->clockwork->log($label, $message);
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
@@ -237,13 +237,10 @@ class Grav extends Container
|
||||
]
|
||||
);
|
||||
|
||||
$default = function (ServerRequestInterface $request) {
|
||||
$default = static function () {
|
||||
return new Response(404);
|
||||
};
|
||||
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this['debugger'];
|
||||
|
||||
$collection = new RequestHandler($this->middleware, $default, $container);
|
||||
|
||||
$response = $collection->handle($this['request']);
|
||||
@@ -251,9 +248,13 @@ class Grav extends Container
|
||||
$this->header($response);
|
||||
echo $response->getBody();
|
||||
|
||||
$debugger->render();
|
||||
$this['debugger']->render();
|
||||
|
||||
register_shutdown_function([$this, 'shutdown']);
|
||||
// Response object can turn off all shutdown processing. This can be used for example to speed up AJAX responses.
|
||||
// Note that using this feature will also turn off response compression.
|
||||
if ($response->getHeaderLine('Grav-Internal-SkipShutdown') !== '1') {
|
||||
register_shutdown_function([$this, 'shutdown']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,6 +344,10 @@ class Grav extends Container
|
||||
|
||||
header("HTTP/{$response->getProtocolVersion()} {$response->getStatusCode()} {$response->getReasonPhrase()}");
|
||||
foreach ($response->getHeaders() as $key => $values) {
|
||||
// Skip internal Grav headers.
|
||||
if (strpos($key, 'Grav-Internal-') === 0) {
|
||||
continue;
|
||||
}
|
||||
foreach ($values as $i => $value) {
|
||||
header($key . ': ' . $value, $i === 0);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
|
||||
namespace Grav\Common\Processors;
|
||||
|
||||
use Clockwork\Clockwork;
|
||||
use Clockwork\DataSource\PsrMessageDataSource;
|
||||
use Clockwork\Helpers\ServerTiming;
|
||||
use Grav\Common\Debugger;
|
||||
use Grav\Framework\Psr7\Response;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
@@ -18,12 +24,109 @@ class DebuggerProcessor extends ProcessorBase
|
||||
public $id = '_debugger';
|
||||
public $title = 'Init Debugger';
|
||||
|
||||
protected $clockwork;
|
||||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
|
||||
{
|
||||
$this->startTimer();
|
||||
$this->container['debugger']->init();
|
||||
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this->container['debugger']->init();
|
||||
|
||||
$clockwork = $debugger->getClockwork();
|
||||
if ($clockwork) {
|
||||
$server = $request->getServerParams();
|
||||
$baseUri = parse_url(dirname($server['PHP_SELF']), PHP_URL_PATH);
|
||||
if ($baseUri === '/') {
|
||||
$baseUri = '';
|
||||
}
|
||||
$requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME;
|
||||
|
||||
$request = $request
|
||||
->withAttribute('base_uri', $baseUri)
|
||||
->withAttribute('request_time', $requestTime);
|
||||
|
||||
// Handle clockwork API calls.
|
||||
$uri = $request->getUri();
|
||||
if (mb_strpos($uri->getPath(), $baseUri . '/__clockwork/') === 0) {
|
||||
return $this->retrieveRequest($request, $clockwork);
|
||||
}
|
||||
|
||||
$this->container['clockwork'] = $clockwork;
|
||||
}
|
||||
|
||||
$this->stopTimer();
|
||||
|
||||
return $handler->handle($request);
|
||||
$response = $handler->handle($request);
|
||||
|
||||
return $clockwork ? $this->logRequest($request, $response, $clockwork) : $response;
|
||||
}
|
||||
|
||||
protected function logRequest(ServerRequestInterface $request, ResponseInterface $response, Clockwork $clockwork)
|
||||
{
|
||||
$clockwork->getTimeline()->finalize($request->getAttribute('request_time'));
|
||||
$clockwork->addDataSource(new PsrMessageDataSource($request, $response));
|
||||
|
||||
$clockwork->resolveRequest();
|
||||
$clockwork->storeRequest();
|
||||
|
||||
$clockworkRequest = $clockwork->getRequest();
|
||||
|
||||
$response = $response
|
||||
->withHeader('X-Clockwork-Id', $clockworkRequest->id)
|
||||
->withHeader('X-Clockwork-Version', $clockwork::VERSION);
|
||||
|
||||
$basePath = $request->getAttribute('base_uri');
|
||||
if ($basePath) {
|
||||
$response = $response->withHeader('X-Clockwork-Path', $basePath . '/__clockwork/');
|
||||
}
|
||||
|
||||
return $response->withHeader('Server-Timing', ServerTiming::fromRequest($clockworkRequest)->value());
|
||||
}
|
||||
|
||||
protected function retrieveRequest(RequestInterface $request, Clockwork $clockwork): Response
|
||||
{
|
||||
$headers = [
|
||||
'Content-Type' => 'application/json',
|
||||
'Grav-Internal-SkipShutdown' => 1
|
||||
];
|
||||
|
||||
$path = $request->getUri()->getPath();
|
||||
$clockworkDataUri = '#/__clockwork(?:/(?<id>[0-9-]+))?(?:/(?<direction>(?:previous|next)))?(?:/(?<count>\d+))?#';
|
||||
if (preg_match($clockworkDataUri, $path, $matches) === false) {
|
||||
$response = ['message' => 'Bad Input'];
|
||||
|
||||
return new Response(400, $headers, json_encode($response));
|
||||
}
|
||||
|
||||
$id = $matches['id'] ?? null;
|
||||
$direction = $matches['direction'] ?? null;
|
||||
$count = $matches['count'] ?? null;
|
||||
|
||||
$storage = $clockwork->getStorage();
|
||||
|
||||
if ($direction === 'previous') {
|
||||
$data = $storage->previous($id, $count);
|
||||
} elseif ($direction === 'next') {
|
||||
$data = $storage->next($id, $count);
|
||||
} elseif ($id === 'latest') {
|
||||
$data = $storage->latest();
|
||||
} else {
|
||||
$data = $storage->find($id);
|
||||
}
|
||||
|
||||
if (preg_match('#(?<id>[0-9-]+|latest)/extended#', $path)) {
|
||||
$clockwork->extendRequest($data);
|
||||
}
|
||||
|
||||
if (!$data) {
|
||||
$response = ['message' => 'Not Found'];
|
||||
|
||||
return new Response(404, $headers, json_encode($response));
|
||||
}
|
||||
|
||||
$data = is_array($data) ? array_map(function ($item) { return $item->toArray(); }, $data) : $data->toArray();
|
||||
|
||||
return new Response(200, $headers, json_encode($data));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user