Updated Clockwork to v5.0 [#3072]

This commit is contained in:
Matias Griese
2020-11-24 11:47:31 +02:00
parent 65a18fd270
commit cf052b5bd4
9 changed files with 148 additions and 165 deletions

View File

@@ -10,6 +10,7 @@
* Added search option `same_as` to Flex Objects
* Added PHP 8 compatible `function_exists()`: `Utils::functionExists()`
* New sites have `compatibility` features turned off by default, upgrading from older versions will keep the settings on
* Updated Clockwork to v5.0
1. [](#improved)
* Updated bundled JQuery to latest version `3.5.1`
* Forward a `sid` to GPM when downloading a premium package via CLI

View File

@@ -55,7 +55,7 @@
"dragonmantank/cron-expression": "^1.2",
"phive/twig-extensions-deferred": "^1.0",
"willdurand/negotiation": "2.x-dev",
"itsgoingd/clockwork": "^4.1",
"itsgoingd/clockwork": "^5.0",
"enshrined/svg-sanitize": "~0.13",
"symfony/http-client": "^4.4"
},

20
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": "2bef5ff955b35b0f8f2e7f05956a18a0",
"content-hash": "5018a33d28d9548d37318a86986c8d07",
"packages": [
{
"name": "antoligy/dom-string-iterators",
@@ -730,21 +730,21 @@
},
{
"name": "itsgoingd/clockwork",
"version": "v4.1.8",
"version": "v5.0.1",
"source": {
"type": "git",
"url": "https://github.com/itsgoingd/clockwork.git",
"reference": "0dc2e5be39de88b18719bb4f3cdacfa605ad2146"
"reference": "a6665903018ea5ac2d0219ccb6e9e03ed1339c3f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/0dc2e5be39de88b18719bb4f3cdacfa605ad2146",
"reference": "0dc2e5be39de88b18719bb4f3cdacfa605ad2146",
"url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/a6665903018ea5ac2d0219ccb6e9e03ed1339c3f",
"reference": "a6665903018ea5ac2d0219ccb6e9e03ed1339c3f",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": ">=5.5",
"php": ">=5.6",
"psr/log": "1.*"
},
"type": "library",
@@ -774,7 +774,7 @@
"homepage": "https://twitter.com/itsgoingd"
}
],
"description": "php dev tools integrated to your browser",
"description": "php dev tools in your browser",
"homepage": "https://underground.works/clockwork",
"keywords": [
"Devtools",
@@ -785,11 +785,7 @@
"profiling",
"slim"
],
"support": {
"issues": "https://github.com/itsgoingd/clockwork/issues",
"source": "https://github.com/itsgoingd/clockwork/tree/v4.1.8"
},
"time": "2020-09-17T19:21:25+00:00"
"time": "2020-11-22T00:14:53+00:00"
},
{
"name": "kodus/psr7-server",

View File

@@ -38,6 +38,7 @@ use Psr\Http\Message\ServerRequestInterface;
use ReflectionObject;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Throwable;
use Twig\Environment;
use Twig\Template;
use Twig\TemplateWrapper;
use function array_slice;
@@ -162,16 +163,17 @@ class Debugger
$clockwork->addDataSource(new MonologDataSource($log));
}
$clockwork->addDataSource(new TwigClockworkDataSource());
$timeLine = $clockwork->getTimeline();
$timeline = $clockwork->timeline();
if ($this->requestTime !== GRAV_REQUEST_TIME) {
$timeLine->addEvent('server', 'Server', $this->requestTime, GRAV_REQUEST_TIME);
$event = $timeline->event('Server');
$event->finalize($this->requestTime, GRAV_REQUEST_TIME);
}
if ($this->currentTime !== GRAV_REQUEST_TIME) {
$timeLine->addEvent('loading', 'Loading', GRAV_REQUEST_TIME, $this->currentTime);
$event = $timeline->event('Loading');
$event->finalize(GRAV_REQUEST_TIME, $this->currentTime);
}
$timeLine->addEvent('setup', 'Site Setup', $this->currentTime, microtime(true));
$event = $timeline->event('Site Setup');
$event->finalize($this->currentTime, microtime(true));
}
if ($this->censored) {
@@ -253,7 +255,7 @@ class Debugger
$this->finalize();
$clockwork->getTimeline()->finalize($request->getAttribute('request_time'));
$clockwork->timeline()->finalize($request->getAttribute('request_time'));
if ($this->censored) {
$censored = 'CENSORED';
@@ -344,21 +346,20 @@ class Debugger
}
$nowTime = microtime(true);
$clkTimeLine = $this->clockwork ? $this->clockwork->getTimeline() : null;
$clkTimeLine = $this->clockwork ? $this->clockwork->timeline() : null;
$debTimeLine = $this->debugbar ? $this->debugbar['time'] : null;
foreach ($this->timers as $name => $data) {
$description = $data[0];
$startTime = $data[1] ?? null;
$endTime = $data[2] ?? $nowTime;
if ($endTime - $startTime < 0.001) {
continue;
}
if ($clkTimeLine) {
$clkTimeLine->addEvent($name, $description ?? $name, $startTime, $endTime);
}
$event = $clkTimeLine->event($description);
$event->finalize($startTime, $endTime);
} elseif ($debTimeLine) {
if ($endTime - $startTime < 0.001) {
continue;
}
if ($debTimeLine) {
$debTimeLine->addMeasure($description ?? $name, $startTime, $endTime);
}
}
@@ -412,7 +413,7 @@ class Debugger
$this->renderer = $this->debugbar->getJavascriptRenderer();
$this->renderer->setIncludeVendors(false);
list($css_files, $js_files) = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
[$css_files, $js_files] = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
foreach ((array)$css_files as $css) {
$assets->addCss($css);
@@ -545,6 +546,16 @@ class Debugger
return $response;
}
public function addTwigProfiler(Environment $twig): void
{
$clockwork = $this->getClockwork();
if ($clockwork) {
$source = new TwigClockworkDataSource($twig);
$source->listenToEvents();
$clockwork->addDataSource($source);
}
}
/**
* Start profiling code.
*
@@ -756,20 +767,18 @@ class Debugger
*/
public function addEvent(string $name, $event, EventDispatcherInterface $dispatcher)
{
if ($this->enabled) {
if ($this->clockwork) {
$data = null;
if ($event && method_exists($event, '__debugInfo')) {
$data = $event;
}
$listeners = [];
foreach ($dispatcher->getListeners($name) as $listener) {
$listeners[] = $this->resolveCallable($listener);
}
$this->clockwork->addEvent($name, $data, microtime(true), ['listeners' => $listeners]);
if ($this->enabled && $this->clockwork) {
$data = null;
if ($event && method_exists($event, '__debugInfo')) {
$data = $event;
}
$listeners = [];
foreach ($dispatcher->getListeners($name) as $listener) {
$listeners[] = $this->resolveCallable($listener);
}
$this->clockwork->addEvent($name, $data, microtime(true), ['listeners' => $listeners]);
}
return $this;

View File

@@ -461,10 +461,11 @@ class Grav extends Container
{
/** @var EventDispatcherInterface $events */
$events = $this['events'];
$eventName = get_class($event);
/** @var Debugger $debugger */
$debugger = $this['debugger'];
$debugger->addEvent(get_class($event), $event, $events);
$debugger->addEvent($eventName, $event, $events);
return $events->dispatch($event);
}

View File

@@ -9,6 +9,7 @@
namespace Grav\Common\Twig;
use Grav\Common\Debugger;
use Grav\Common\Grav;
use Grav\Common\Config\Config;
use Grav\Common\Language\Language;
@@ -24,7 +25,6 @@ use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Extension\CoreExtension;
use Twig\Extension\DebugExtension;
use Twig\Extension\ProfilerExtension;
use Twig\Extension\StringLoaderExtension;
use Twig\Loader\ArrayLoader;
use Twig\Loader\ChainLoader;
@@ -192,8 +192,9 @@ class Twig
$this->twig->addExtension(new DeferredExtension());
$this->twig->addExtension(new StringLoaderExtension());
$this->profile = new Profile();
$this->twig->addExtension(new ProfilerExtension($this->profile));
/** @var Debugger $debugger */
$debugger = $this->grav['debugger'];
$debugger->addTwigProfiler($this->twig);
$this->grav->fireEvent('onTwigExtensions');

View File

@@ -11,8 +11,9 @@ namespace Grav\Common\Twig;
use Clockwork\DataSource\DataSource;
use Clockwork\Request\Request;
use Clockwork\Request\Timeline;
use Grav\Common\Grav;
use Twig\Environment;
use Twig\Extension\ProfilerExtension;
use Twig\Profiler\Profile;
/**
* Class TwigClockworkDataSource
@@ -20,33 +21,37 @@ use Grav\Common\Grav;
*/
class TwigClockworkDataSource extends DataSource
{
/** @var Timeline Views data structure */
protected $views;
/** @var Environment */
protected $twig;
/**
* TwigClockworkDataSource constructor.
*/
public function __construct()
/** @var Profile */
protected $profile;
// Create a new data source, takes Twig instance as an argument
public function __construct(Environment $twig)
{
$this->views = new Timeline();
$this->twig = $twig;
}
/**
* Resolves and adds the Twig profiler data to the request
* Register the Twig profiler extension
*/
public function listenToEvents(): void
{
$this->twig->addExtension(new ProfilerExtension($this->profile = new Profile()));
}
/**
* Adds rendered views to the request
*
* @param Request $request
* @return Request
*/
public function resolve(Request $request)
{
$profile = Grav::instance()['twig']->profile();
$timeline = (new TwigClockworkDumper())->dump($this->profile);
if ($profile) {
$processor = new TwigProfileProcessor();
$processor->process($profile, $this->views);
$request->viewsData = $this->views->finalize();
}
$request->viewsData = array_merge($request->viewsData, $timeline->finalize());
return $request;
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* @package Grav\Common\Twig
*
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Twig;
use Clockwork\Request\Timeline\Timeline;
use Twig\Profiler\Profile;
/**
* Class TwigClockworkDumper
* @package Grav\Common\Twig
*/
class TwigClockworkDumper
{
protected $lastId = 1;
/**
* Dumps a profile into a new rendered views timeline
*
* @param Profile $profile
* @return Timeline
*/
public function dump(Profile $profile)
{
$timeline = new Timeline;
$this->dumpProfile($profile, $timeline);
return $timeline;
}
/**
* @param Profile $profile
* @param Timeline $timeline
* @param null $parent
*/
public function dumpProfile(Profile $profile, Timeline $timeline, $parent = null)
{
$id = $this->lastId++;
if ($profile->isRoot()) {
$name = $profile->getName();
} elseif ($profile->isTemplate()) {
$name = $profile->getTemplate();
} else {
$name = $profile->getTemplate() . '::' . $profile->getType() . '(' . $profile->getName() . ')';
}
foreach ($profile as $p) {
$this->dumpProfile($p, $timeline, $id);
}
$data = $profile->__serialize();
$timeline->event($name, [
'name' => $id,
'start' => $data[3]['wt'] ?? null,
'end' => $data[4]['wt'] ?? null,
'data' => [
'data' => [],
'memoryUsage' => $data[4]['mu'] ?? null,
'parent' => $parent
]
]);
}
}

View File

@@ -1,102 +0,0 @@
<?php
/**
* @package Grav\Common\Twig
*
* @copyright Copyright (C) 2015 - 2020 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Twig;
use Grav\Common\Utils;
use Twig\Profiler\Profile;
use Clockwork\Request\Timeline;
/**
* Class TwigProfileProcessor
* @package Grav\Common\Twig
*/
class TwigProfileProcessor
{
/** @var float */
private $root;
/**
* @param Profile $profile
* @param Timeline $views
* @param int $counter
* @param string $prefix
* @param false $sibling
* @return void
*/
public function process(Profile $profile, Timeline $views, $counter = 0, $prefix = '', $sibling = false)
{
if ($profile->isRoot()) {
$this->root = $profile->getDuration();
$name = $profile->getName();
} else {
if ($profile->isTemplate()) {
$name = $this->formatTemplate($profile, $prefix);
} else {
$name = $this->formatNonTemplate($profile, $prefix);
}
$prefix .= '⎯⎯';
}
$percent = $this->root ? $profile->getDuration() / $this->root * 100 : 0;
$data = [
'tm' => $this->formatTime($profile, $percent),
'mu' => Utils::prettySize($profile->getMemoryUsage())
];
if ($profile->isRoot()) {
$data += ['pmu' => Utils::prettySize($profile->getPeakMemoryUsage())];
}
$views->addEvent(
$counter,
$profile->getTemplate(),
0,
$profile->getDuration(),
[ 'name' => $name, 'data' => $data ]
);
$nCount = count($profile->getProfiles());
foreach ($profile as $i => $p) {
$this->process($p, $views, ++$counter, $prefix, $i + 1 !== $nCount);
}
}
/**
* @param Profile $profile
* @param string $prefix
* @return string
*/
protected function formatTemplate(Profile $profile, $prefix)
{
return sprintf('%s⤍ %s', $prefix, $profile->getTemplate());
}
/**
* @param Profile $profile
* @param string $prefix
* @return string
*/
protected function formatNonTemplate(Profile $profile, $prefix)
{
return sprintf('%s⤍ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName());
}
/**
* @param Profile $profile
* @param float $percent
* @return string
*/
protected function formatTime(Profile $profile, $percent)
{
return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent);
}
}