Add basic clockwork support

This commit is contained in:
Matias Griese
2019-05-23 15:39:44 +03:00
parent 9e5363b4df
commit 0bd227c22d
5 changed files with 210 additions and 13 deletions

View File

@@ -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
View File

@@ -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",

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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));
}
}