Merge branch 'feature/clockwork' into feature/clockwork-twig

This commit is contained in:
Andy Miller
2019-05-27 13:45:16 +03:00
5 changed files with 210 additions and 239 deletions

View File

@@ -57,7 +57,7 @@ class Debugger
protected $clockwork;
/** @var bool */
protected $enabled;
protected $enabled = false;
protected $initialized = false;
@@ -88,9 +88,6 @@ class Debugger
$this->requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME;
// Enable debugger until $this->init() gets called.
$this->enabled = true;
// Set deprecation collector.
$this->setErrorHandler();
}
@@ -173,6 +170,7 @@ class Debugger
}
$this->addMessage('Grav v' . GRAV_VERSION);
$this->config->debug();
if ($clockwork) {
$clockwork->info('System Configuration', $this->config->get('system'));
@@ -188,6 +186,8 @@ class Debugger
public function finalize(): void
{
if ($this->clockwork && $this->enabled) {
$this->addMeasures();
$deprecations = $this->getDeprecations();
$count = count($deprecations);
if (!$count) {
@@ -195,7 +195,7 @@ class Debugger
}
/** @var UserData $userData */
$userData = $this->clockwork->userData("Deprecated ({$count})");
$userData = $this->clockwork->userData('Deprecated');
$userData->counters([
'Deprecated' => count($deprecations)
]);
@@ -213,6 +213,34 @@ class Debugger
}
}
protected function addMeasures()
{
if (!$this->enabled) {
return;
}
$nowTime = microtime(true);
$clkTimeLine = $this->clockwork ? $this->clockwork->getTimeline() : null;
$debTimeLine = $this->debugbar ? $this->debugbar['time'] : null;
foreach ($this->timers as $name => $data) {
$description = $data[0];
$startTime = $data[1];
$endTime = $data[2] ?? $nowTime;
if ($endTime - $startTime < 0.001) {
continue;
}
if ($clkTimeLine) {
$clkTimeLine->addEvent($name, $description, $startTime, $endTime);
}
if ($debTimeLine) {
$debTimeLine->addMeasure($description, $startTime, $endTime);
}
}
$this->timers = [];
}
/**
* Set/get the enabled state of the debugger
*
@@ -306,6 +334,8 @@ class Debugger
if ($this->debugbar) {
return $this->debugbar->getCollector($collector);
}
return null;
}
/**
@@ -322,6 +352,7 @@ class Debugger
return $this;
}
$this->addMeasures();
$this->addDeprecations();
echo $this->renderer->render();
@@ -338,6 +369,7 @@ class Debugger
public function sendDataInHeaders()
{
if ($this->enabled && $this->debugbar) {
$this->addMeasures();
$this->addDeprecations();
$this->debugbar->sendDataInHeaders();
}
@@ -356,6 +388,7 @@ class Debugger
return null;
}
$this->addMeasures();
$this->addDeprecations();
$this->timers = [];
@@ -372,9 +405,7 @@ class Debugger
*/
public function startTimer($name, $description = null)
{
if ($this->enabled || strpos($name, '_') === 0) {
$this->timers[$name] = [$description, microtime(true)];
}
$this->timers[$name] = [$description, microtime(true)];
return $this;
}
@@ -388,23 +419,10 @@ class Debugger
*/
public function stopTimer($name)
{
if (isset($this->timers[$name]) && (strpos($name, '_') === 0 || $this->enabled)) {
[$description, $startTime] = $this->timers[$name];
if (isset($this->timers[$name])) {
$endTime = microtime(true);
if ($endTime - $startTime < 0.001) {
return $this;
}
if ($this->debugbar) {
$this->debugbar['time']->addMeasure($description, $startTime, $endTime);
}
if ($this->clockwork) {
$timeLine = $this->clockwork->getTimeline();
$timeLine->addEvent($name, $description, $startTime, $endTime);
}
$this->timers[$name][] = $endTime;
}
unset($this->timers[$name]);
return $this;
}

View File

@@ -16,12 +16,8 @@ use Grav\Common\Page\Medium\ImageMedium;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Processors\AssetsProcessor;
use Grav\Common\Processors\BackupsProcessor;
use Grav\Common\Processors\ConfigurationProcessor;
use Grav\Common\Processors\DebuggerAssetsProcessor;
use Grav\Common\Processors\DebuggerProcessor;
use Grav\Common\Processors\ErrorsProcessor;
use Grav\Common\Processors\InitializeProcessor;
use Grav\Common\Processors\LoggerProcessor;
use Grav\Common\Processors\PagesProcessor;
use Grav\Common\Processors\PluginsProcessor;
use Grav\Common\Processors\RenderProcessor;
@@ -89,8 +85,6 @@ class Grav extends Container
* @var array All middleware processors that are processed in $this->process()
*/
protected $middleware = [
'configurationProcessor',
'debuggerProcessor',
'initializeProcessor',
'pluginsProcessor',
'themesProcessor',
@@ -181,12 +175,6 @@ class Grav extends Container
$container = new Container(
[
'configurationProcessor' => function () {
return new ConfigurationProcessor($this);
},
'debuggerProcessor' => function () {
return new DebuggerProcessor($this);
},
'initializeProcessor' => function () {
return new InitializeProcessor($this);
},

View File

@@ -1,60 +0,0 @@
<?php
/**
* @package Grav\Common\Processors
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Processors;
use Grav\Common\Config\Config;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\SyslogHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ConfigurationProcessor extends ProcessorBase
{
public $id = '_config';
public $title = 'Configuration';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$grav = $this->container;
// Initialize Configuration
$this->startTimer('_config', 'Configuration');
/** @var Config $config */
$config = $grav['config'];
$config->init();
$grav['plugins']->setup();
$this->stopTimer('_config');
// Initialize Logging
$this->startTimer('_logger', 'Logger');
switch ($config->get('system.log.handler', 'file')) {
case 'syslog':
$log = $grav['log'];
$log->popHandler();
$facility = $config->get('system.log.syslog.facility', 'local6');
$logHandler = new SyslogHandler('grav', $facility);
$formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
$logHandler->setFormatter($formatter);
$log->pushHandler($logHandler);
break;
}
$this->stopTimer('_logger');
// Initialize Error Handlers
$this->startTimer('_errors', 'Error Handlers Reset');
$this->container['errors']->resetHandlers();
$this->stopTimer('_errors');
return $handler->handle($request);
}
}

View File

@@ -1,138 +0,0 @@
<?php
/**
* @package Grav\Common\Processors
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
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;
class DebuggerProcessor extends ProcessorBase
{
public $id = '_debugger';
public $title = 'Init Debugger';
protected $clockwork;
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$this->startTimer();
/** @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();
$response = $handler->handle($request);
if ($clockwork) {
$debugger->finalize();
return $this->logRequest($request, $response, $clockwork);
}
return $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));
}
}

View File

@@ -9,26 +9,192 @@
namespace Grav\Common\Processors;
use Clockwork\Clockwork;
use Clockwork\DataSource\PsrMessageDataSource;
use Clockwork\Helpers\ServerTiming;
use Grav\Common\Config\Config;
use Grav\Common\Debugger;
use Grav\Common\Uri;
use Grav\Common\Utils;
use Grav\Framework\Psr7\Response;
use Grav\Framework\Session\Exceptions\SessionException;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\SyslogHandler;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class InitializeProcessor extends ProcessorBase
{
public $id = 'init';
public $id = '_init';
public $title = 'Initialize';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$this->startTimer();
$this->startTimer('_config', 'Configuration');
$this->initializeConfig();
$this->stopTimer('_config');
$this->startTimer('_logger', 'Logger');
$this->initializeLogger();
$this->stopTimer('_logger');
$this->startTimer('_errors', 'Error Handlers Reset');
$this->initializeErrors();
$this->stopTimer('_errors');
$this->startTimer('_debugger', 'Init Debugger');
/** @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->debuggerRequest($request, $clockwork);
}
$this->container['clockwork'] = $clockwork;
}
$this->stopTimer('_debugger');
$this->startTimer('_init', 'Initialize');
$this->initialize();
$this->stopTimer('_init');
$response = $handler->handle($request);
if ($clockwork) {
$debugger->finalize();
return $this->logRequest($request, $response, $clockwork);
}
return $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 debuggerRequest(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));
}
protected function initializeConfig()
{
// Initialize Configuration
$grav = $this->container;
/** @var Config $config */
$config = $grav['config'];
$config->init();
$grav['plugins']->setup();
}
protected function initializeLogger()
{
// Initialize Logging
$grav = $this->container;
/** @var Config $config */
$config = $grav['config'];
switch ($config->get('system.log.handler', 'file')) {
case 'syslog':
$log = $grav['log'];
$log->popHandler();
$facility = $config->get('system.log.syslog.facility', 'local6');
$logHandler = new SyslogHandler('grav', $facility);
$formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
$logHandler->setFormatter($formatter);
$log->pushHandler($logHandler);
break;
}
}
protected function initializeErrors()
{
// Initialize Error Handlers
$this->container['errors']->resetHandlers();
}
protected function initialize()
{
/** @var Config $config */
$config = $this->container['config'];
$config->debug();
// Use output buffering to prevent headers from being sent too early.
ob_start();
@@ -73,8 +239,5 @@ class InitializeProcessor extends ProcessorBase
}
$this->container->setLocale();
$this->stopTimer();
return $handler->handle($request);
}
}