10000 feature #51204 [Workflow] Add a profiler (lyrixx) · symfony/symfony@1300cc2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1300cc2

Browse files
committed
feature #51204 [Workflow] Add a profiler (lyrixx)
This PR was merged into the 6.4 branch. Discussion ---------- [Workflow] Add a profiler | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | | License | MIT | Doc PR | --- With [this project lyrixx/SFLive-Paris2016-Workflow](https://github.com/lyrixx/SFLive-Paris2016-Workflow) ![image](https://github.com/symfony/symfony/assets/408368/b6c1334f-9f6a-4bae-a94f-dd430187a448) [workflow.webm](https://github.com/symfony/symfony/assets/408368/e86aad22-812d-461d-950f-68d50ac31390) Commits ------- df292cb [Workflow] Add a profiler
2 parents a3414e4 + df292cb commit 1300cc2

File tree

6 files changed

+156
-0
lines changed

6 files changed

+156
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ public function load(array $configs, ContainerBuilder $container)
280280
$this->readConfigEnabled('translator', $container, $config['translator']);
281281
$this->readConfigEnabled('property_access', $container, $config['property_access']);
282282
$this->readConfigEnabled('profiler', $container, $config['profiler']);
283+
$this->readConfigEnabled('workflows', $container, $config['workflows']);
283284

284285
// A translator must always be registered (as support is included by
285286
// default in the Form and Validator component). If disabled, an identity
@@ -876,6 +877,10 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $
876877
$loader->load('mailer_debug.php');
877878
}
878879

880+
if ($this->isInitializedConfigEnabled('workflows')) {
881+
$loader->load('workflow_debug.php');
882+
}
883+
879884
if ($this->isInitializedConfigEnabled('http_client')) {
880885
$loader->load('http_client_debug.php');
881886
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
use Symfony\Component\Workflow\DataCollector\WorkflowDataCollector;
15+
16+
return static function (ContainerConfigurator $container) {
17+
$container->services()
18+
->set('data_collector.workflow', WorkflowDataCollector::class)
19+
->tag('data_collector', [
20+
'template' => '@WebProfiler/Collector/workflow.html.twig',
21+
'id' => 'workflow',
22+
])
23+
->args([
24+
tagged_iterator('workflow', 'name'),
25+
])
26+
;
27+
};
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
2+
3+
{% block menu %}
4+
<span class="label {{ collector.workflows|length == 0 ? 'disabled' }}">
5+
<span class="icon">
6+
{{ source('@WebProfiler/Icon/workflow.svg') }}
7+
</span>
8+
<strong>Workflow</strong>
9+
</span>
10+
{% endblock %}
11+
12+
{% block panel %}
13+
<h2>Workflow</h2>
14+
15+
{% if collector.workflows|length == 0 %}
16+
<div class="empty empty-panel">
17+
<p>There are no workflows configured.</p>
18+
</div>
19+
{% else %}
20+
<script type="module">
21+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
22+
mermaid.initialize({
23+
flowchart: { useMaxWidth: false },
24+
securityLevel: 'loose',
25+
});
26+
// We do not load all mermaid diagrams at once, but only when the tab is opened
27+
// This is because mermaid diagrams are in a tab, and cannot be renderer with a
28+
// "good size" if they are not visible
29+
document.addEventListener('DOMContentLoaded', () => {
30+
document.querySelectorAll('.tab').forEach((el) => {
31+
const observer = new MutationObserver(() => {
32+
if (!el.classList.contains('block')) {
33+
return;
34+
}
35+
const mEl = el.querySelector('.sf-mermaid');
36+
if (mEl.dataset.processed) {
37+
return;
38+
}
39+
mermaid.run({
40+
nodes: [mEl],
41+
});
42+
});
43+
observer.observe(el, { attributeFilter: ['class'] });
44+
});
45+
});
46+
</script>
47+
48+
<h2>Definitions</h2>
49+
<div class="sf-tabs js-tabs">
50+
{% for name, data in collector.workflows %}
51+
<div class="tab">
52+
<h3 class="tab-title">{{ name }}</h3>
53+
<div class="tab-content">
54+
<pre class="sf-mermaid">
55+
{{ data.dump|raw }}
56+
</pre>
57+
</div>
58+
</div>
59+
{% endfor %}
60+
</div>
61+
{% endif %}
62+
{% endblock %}
Lines changed: 1 addition & 0 deletions
Loading

src/Symfony/Component/Workflow/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add `with-metadata` option to the `workflow:dump` command to include places,
88
transitions and workflow's metadata into dumped graph
99
* Add support for storing marking in a property
10+
* Add a profiler
1011

1112
6.2
1213
---
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Workflow\DataCollector;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
17+
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
18+
use Symfony\Component\Workflow\Dumper\MermaidDumper;
19+
use Symfony\Component\Workflow\StateMachine;
20+
21+
/**
22+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
23+
*/
24+
final class WorkflowDataCollector extends DataCollector implements LateDataCollectorInterface
25+
{
26+
public function __construct(
27+
private readonly iterable $workflows,
28+
) {
29+
}
30+
31+
public function collect(Request $request, Response $response, \Throwable $exception = null): void
32+
{
33+
}
34+
35+
public function lateCollect(): void
36+
{
37+
foreach ($this->workflows as $workflow) {
38+
$type = $workflow instanceof StateMachine ? MermaidDumper::TRANSITION_TYPE_STATEMACHINE : MermaidDumper::TRANSITION_TYPE_WORKFLOW;
39+
$dumper = new MermaidDumper($type);
40+
$this->data['workflows'][$workflow->getName()] = [
41+
'dump' => $dumper->dump($workflow->getDefinition()),
42+
];
43+
}
44+
}
45+
46+
public function getName(): string
47+
{
48+
return 'workflow';
49+
}
50+
51+
public function reset(): void
52+
{
53+
$this->data = [];
54+
}
55+
56+
public function getWorkflows(): array
57+
{
58+
return $this->data['workflows'] ?? [];
59+
}
60+
}

0 commit comments

Comments
 (0)
0