mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 09:02:12 +00:00
Add template events data collector
This commit is contained in:
parent
5d020ae84f
commit
d917f2d088
8 changed files with 372 additions and 0 deletions
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\UiBundle\DataCollector;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class TemplateBlockDataCollector extends DataCollector
|
||||
{
|
||||
/** @var TemplateBlockRenderingHistory */
|
||||
private $templateBlockRenderingHistory;
|
||||
|
||||
public function __construct(TemplateBlockRenderingHistory $templateBlockRenderingHistory)
|
||||
{
|
||||
$this->templateBlockRenderingHistory = $templateBlockRenderingHistory;
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
public function collect(Request $request, Response $response): void
|
||||
{
|
||||
$this->data['renderedEvents'] = $this->templateBlockRenderingHistory->getRenderedEvents();
|
||||
}
|
||||
|
||||
public function getRenderedEvents(): array
|
||||
{
|
||||
return $this->data['renderedEvents'];
|
||||
}
|
||||
|
||||
public function getNumberOfRenderedEvents(): int
|
||||
{
|
||||
return count($this->data['renderedEvents']);
|
||||
}
|
||||
|
||||
public function getNumberOfRenderedBlocks(): int
|
||||
{
|
||||
return array_reduce($this->data['renderedEvents'], static function (int $accumulator, array $event): int {
|
||||
return $accumulator + count($event['blocks']);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public function getTotalDuration(): float
|
||||
{
|
||||
return array_reduce($this->data['renderedEvents'], static function (float $accumulator, array $event): float {
|
||||
return $accumulator + $event['time'];
|
||||
}, 0.0);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'sylius_ui.template_block';
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->data['renderedEvents'] = [];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\UiBundle\DataCollector;
|
||||
|
||||
use Sylius\Bundle\UiBundle\Registry\TemplateBlock;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class TemplateBlockRenderingHistory
|
||||
{
|
||||
/** @psalm-var list<array{name: string, start: float, stop: float, time: float, blocks: list<array{definition: TemplateBlock, start: float, stop: float, time: float}>}> */
|
||||
private $renderedEvents = [];
|
||||
|
||||
/** @psalm-var array{name: string, start: float, stop?: float, time?: float, blocks: list<array{definition: TemplateBlock, start: float, stop: float, time: float}>} */
|
||||
private $currentlyRenderedEvent = [];
|
||||
|
||||
/** @psalm-var array{definition: TemplateBlock, start: float, stop?: float, time?: float} */
|
||||
private $currentlyRenderedBlock = [];
|
||||
|
||||
public function startRenderingEvent(string $eventName, array $context): void
|
||||
{
|
||||
$this->currentlyRenderedEvent = ['name' => $eventName, 'start' => microtime(true), 'blocks' => []];
|
||||
}
|
||||
|
||||
public function startRenderingBlock(string $eventName, TemplateBlock $templateBlock, array $context): void
|
||||
{
|
||||
$this->currentlyRenderedBlock = ['definition' => $templateBlock, 'start' => microtime(true)];
|
||||
}
|
||||
|
||||
public function stopRenderingBlock(string $eventName, TemplateBlock $templateBlock, array $context): void
|
||||
{
|
||||
$this->currentlyRenderedBlock['stop'] = microtime(true);
|
||||
$this->currentlyRenderedBlock['time'] = $this->currentlyRenderedBlock['stop'] - $this->currentlyRenderedBlock['start'];
|
||||
$this->currentlyRenderedEvent['blocks'][] = $this->currentlyRenderedBlock;
|
||||
$this->currentlyRenderedBlock = [];
|
||||
}
|
||||
|
||||
public function stopRenderingEvent(string $eventName, array $context): void
|
||||
{
|
||||
$this->currentlyRenderedEvent['stop'] = microtime(true);
|
||||
$this->currentlyRenderedEvent['time'] = $this->currentlyRenderedEvent['stop'] - $this->currentlyRenderedEvent['start'];
|
||||
$this->renderedEvents[] = $this->currentlyRenderedEvent;
|
||||
$this->currentlyRenderedEvent = [];
|
||||
}
|
||||
|
||||
public function getRenderedEvents(): array
|
||||
{
|
||||
return $this->renderedEvents;
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->renderedEvents = $this->currentlyRenderedEvent = $this->currentlyRenderedBlock = [];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\UiBundle\DataCollector;
|
||||
|
||||
use Sylius\Bundle\UiBundle\Registry\TemplateBlock;
|
||||
use Sylius\Bundle\UiBundle\Renderer\TemplateBlockRendererInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class TraceableTemplateBlockRenderer implements TemplateBlockRendererInterface
|
||||
{
|
||||
/** @var TemplateBlockRendererInterface */
|
||||
private $templateBlockRenderer;
|
||||
|
||||
/** @var TemplateBlockRenderingHistory */
|
||||
private $templateBlockRenderingHistory;
|
||||
|
||||
public function __construct(TemplateBlockRendererInterface $templateBlockRenderer, TemplateBlockRenderingHistory $templateBlockRenderingHistory)
|
||||
{
|
||||
$this->templateBlockRenderer = $templateBlockRenderer;
|
||||
$this->templateBlockRenderingHistory = $templateBlockRenderingHistory;
|
||||
}
|
||||
|
||||
public function render(string $eventName, TemplateBlock $templateBlock, array $context = []): string
|
||||
{
|
||||
$this->templateBlockRenderingHistory->startRenderingBlock($eventName, $templateBlock, $context);
|
||||
|
||||
$renderedBlock = $this->templateBlockRenderer->render($eventName, $templateBlock, $context);
|
||||
|
||||
$this->templateBlockRenderingHistory->stopRenderingBlock($eventName, $templateBlock, $context);
|
||||
|
||||
return $renderedBlock;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\UiBundle\DataCollector;
|
||||
|
||||
use Sylius\Bundle\UiBundle\Renderer\TemplateEventRendererInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class TraceableTemplateEventRenderer implements TemplateEventRendererInterface
|
||||
{
|
||||
/** @var TemplateEventRendererInterface */
|
||||
private $templateEventRenderer;
|
||||
|
||||
/** @var TemplateBlockRenderingHistory */
|
||||
private $templateBlockRenderingHistory;
|
||||
|
||||
public function __construct(TemplateEventRendererInterface $templateEventRenderer, TemplateBlockRenderingHistory $templateBlockRenderingHistory)
|
||||
{
|
||||
$this->templateEventRenderer = $templateEventRenderer;
|
||||
$this->templateBlockRenderingHistory = $templateBlockRenderingHistory;
|
||||
}
|
||||
|
||||
public function render(string $eventName, array $context = []): string
|
||||
{
|
||||
$this->templateBlockRenderingHistory->startRenderingEvent($eventName, $context);
|
||||
|
||||
$renderedEvent = $this->templateEventRenderer->render($eventName, $context);
|
||||
|
||||
$this->templateBlockRenderingHistory->stopRenderingEvent($eventName, $context);
|
||||
|
||||
return $renderedEvent;
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,10 @@ final class SyliusUiExtension extends Extension
|
|||
|
||||
$loader->load('services.xml');
|
||||
|
||||
if ($container->getParameter('kernel.debug')) {
|
||||
$loader->load('services/debug/template_event.xml');
|
||||
}
|
||||
|
||||
$this->loadEvents($config['events'], $container);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
|
||||
This file is part of the Sylius package.
|
||||
|
||||
(c) Paweł Jędrzejewski
|
||||
|
||||
For the full copyright and license information, please view the LICENSE
|
||||
file that was distributed with this source code.
|
||||
|
||||
-->
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
<services>
|
||||
<service id="Sylius\Bundle\UiBundle\DataCollector\TemplateBlockRenderingHistory" />
|
||||
|
||||
<service id="Sylius\Bundle\UiBundle\DataCollector\TemplateBlockDataCollector">
|
||||
<argument type="service" id="Sylius\Bundle\UiBundle\DataCollector\TemplateBlockRenderingHistory" />
|
||||
<tag name="data_collector" template="@SyliusUi/DataCollector/templateBlock.html.twig" id="sylius_ui.template_block" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\UiBundle\DataCollector\TraceableTemplateBlockRenderer" decorates="Sylius\Bundle\UiBundle\Renderer\TemplateBlockRendererInterface">
|
||||
<argument type="service" id="Sylius\Bundle\UiBundle\DataCollector\TraceableTemplateBlockRenderer.inner" />
|
||||
<argument type="service" id="Sylius\Bundle\UiBundle\DataCollector\TemplateBlockRenderingHistory" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\UiBundle\DataCollector\TraceableTemplateEventRenderer" decorates="Sylius\Bundle\UiBundle\Renderer\TemplateEventRendererInterface">
|
||||
<argument type="service" id="Sylius\Bundle\UiBundle\DataCollector\TraceableTemplateEventRenderer.inner" />
|
||||
<argument type="service" id="Sylius\Bundle\UiBundle\DataCollector\TemplateBlockRenderingHistory" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
|
||||
|
||||
{% block toolbar %}
|
||||
<div class="sf-toolbar-block">
|
||||
<a href="{{ path('_profiler', { 'token': token, 'panel': name }) }}">
|
||||
<div class="sf-toolbar-icon">
|
||||
{{ include('@SonataBlock/Profiler/icon.svg') }}
|
||||
<span class="sf-toolbar-value">{{ collector.numberOfRenderedEvents }}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="sf-toolbar-info">
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Rendered events</b>
|
||||
<span class="sf-toolbar-status">{{ collector.numberOfRenderedEvents }}</span>
|
||||
</div>
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Rendered blocks</b>
|
||||
<span class="sf-toolbar-status">{{ collector.numberOfRenderedBlocks }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block menu %}
|
||||
<span class="label">
|
||||
<span class="icon">
|
||||
{{ include('@SonataBlock/Profiler/icon.svg') }}
|
||||
</span>
|
||||
<strong>Template events</strong>
|
||||
<span class="count">
|
||||
<span>{{ collector.numberOfRenderedEvents }}</span>
|
||||
</span>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
<h2>Template events metrics</h2>
|
||||
|
||||
<div class="metrics">
|
||||
<div class="metric">
|
||||
<span class="value">{{ '%.0f'|format(collector.totalDuration * 1000) }} <span class="unit">ms</span></span>
|
||||
<span class="label">Total execution time</span>
|
||||
</div>
|
||||
|
||||
<div class="metric">
|
||||
<span class="value">{{ '%.0f'|format(collector.numberOfRenderedEvents) }}</span>
|
||||
<span class="label">Rendered events</span>
|
||||
</div>
|
||||
|
||||
<div class="metric">
|
||||
<span class="value">{{ '%.0f'|format(collector.numberOfRenderedBlocks) }}</span>
|
||||
<span class="label">Rendered blocks</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Rendered template events</h2>
|
||||
|
||||
{% if collector.renderedEvents|length > 0 %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Event</th>
|
||||
<th>Duration</th>
|
||||
<th>Blocks</th>
|
||||
</tr>
|
||||
|
||||
{% for event in collector.renderedEvents %}
|
||||
<tr>
|
||||
<td>{{ event.name }}</td>
|
||||
<td>{{ '%.0f'|format(event.time * 1000) }}ms</td>
|
||||
<td>
|
||||
{% if event.blocks|length > 0 %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Template</th>
|
||||
<th>Duration</th>
|
||||
<th>Priority</th>
|
||||
</tr>
|
||||
{% for block in event.blocks %}
|
||||
<tr>
|
||||
<td>{{ block.definition.name }}</td>
|
||||
<td>{{ block.definition.template }}</td>
|
||||
<td>{{ '%.0f'|format(block.time * 1000) }}ms</td>
|
||||
<td>{{ block.definition.priority }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<i>no blocks rendered</i>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="empty">
|
||||
No template events have been rendered.
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
@ -24,6 +24,8 @@ final class SyliusUiExtensionTest extends AbstractExtensionTestCase
|
|||
/** @test */
|
||||
public function it_configures_the_multiple_event_block_listener_service_with_events_and_blocks_data(): void
|
||||
{
|
||||
$this->container->setParameter('kernel.debug', true);
|
||||
|
||||
$this->load(['events' => [
|
||||
'first_event' => ['blocks' => [
|
||||
'first_block' => ['template' => 'first.html.twig', 'enabled' => true, 'priority' => 0],
|
||||
|
|
@ -52,6 +54,8 @@ final class SyliusUiExtensionTest extends AbstractExtensionTestCase
|
|||
/** @test */
|
||||
public function it_sorts_blocks_by_their_priority_and_uses_fifo_ordering(): void
|
||||
{
|
||||
$this->container->setParameter('kernel.debug', true);
|
||||
|
||||
$this->load(['events' => [
|
||||
'event_name' => ['blocks' => [
|
||||
'fourth_block' => ['template' => 'fourth.html.twig', 'enabled' => true, 'priority' => -5],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue