Skip to content

Commit a128f67

Browse files
committed
Add datacollector for debug
1 parent 796ae08 commit a128f67

File tree

5 files changed

+270
-0
lines changed

5 files changed

+270
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Meilisearch\Bundle\DataCollector;
6+
7+
use Meilisearch\Bundle\Debug\TraceableMeilisearchService;
8+
use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
9+
use Symfony\Component\HttpFoundation\Request;
10+
use Symfony\Component\HttpFoundation\Response;
11+
12+
/**
13+
* @author Antoine Makdessi <[email protected]>
14+
*/
15+
final class MeilisearchDataCollector extends AbstractDataCollector
16+
{
17+
private TraceableMeilisearchService $meilisearchService;
18+
19+
public function __construct(TraceableMeilisearchService $meilisearchService)
20+
{
21+
$this->meilisearchService = $meilisearchService;
22+
}
23+
public function collect(Request $request, Response $response, \Throwable $exception = null): void
24+
{
25+
$data = $this->meilisearchService->getData();
26+
27+
$this->data[$this->getName()] = !empty($data) ? $this->cloneVar($data) : null;
28+
}
29+
30+
public function getName(): string
31+
{
32+
return 'meilisearch';
33+
}
34+
35+
/** @internal */
36+
public function getMeilisearch(): mixed
37+
{
38+
return $this->data[$this->getName()] ?? null;
39+
}
40+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Meilisearch\Bundle\Debug;
6+
7+
use Doctrine\Persistence\ObjectManager;
8+
use Meilisearch\Bundle\Collection;
9+
use Meilisearch\Bundle\SearchService;
10+
use Symfony\Component\Stopwatch\Stopwatch;
11+
12+
/**
13+
* @author Antoine Makdessi <[email protected]>
14+
*/
15+
final class TraceableMeilisearchService implements SearchService
16+
{
17+
private SearchService $searchService;
18+
private Stopwatch $stopwatch;
19+
private array $data = [];
20+
21+
public function __construct(SearchService $searchService, Stopwatch $stopwatch)
22+
{
23+
$this->searchService = $searchService;
24+
$this->stopwatch = $stopwatch;
25+
}
26+
27+
public function index(ObjectManager $objectManager, $searchable): array
28+
{
29+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
30+
}
31+
32+
public function remove(ObjectManager $objectManager, $searchable): array
33+
{
34+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
35+
}
36+
37+
public function clear(string $className): array
38+
{
39+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
40+
}
41+
42+
public function deleteByIndexName(string $indexName): ?array
43+
{
44+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
45+
}
46+
47+
public function delete(string $className): ?array
48+
{
49+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
50+
}
51+
52+
public function search(ObjectManager $objectManager, string $className, string $query = '', array $searchParams = []): array
53+
{
54+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
55+
}
56+
57+
public function rawSearch(string $className, string $query = '', array $searchParams = []): array
58+
{
59+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
60+
}
61+
62+
public function count(string $className, string $query = '', array $searchParams = []): int
63+
{
64+
return $this->innerSearchService(__FUNCTION__, \func_get_args());
65+
}
66+
67+
public function isSearchable($className): bool
68+
{
69+
return $this->searchService->isSearchable($className);
70+
}
71+
72+
public function getSearchable(): array
73+
{
74+
return $this->searchService->getSearchable();
75+
}
76+
77+
public function getConfiguration(): Collection
78+
{
79+
return $this->searchService->getConfiguration();
80+
}
81+
82+
public function searchableAs(string $className): string
83+
{
84+
return $this->searchService->searchableAs($className);
85+
}
86+
87+
/** @internal */
88+
public function getData(): array
89+
{
90+
return $this->data;
91+
}
92+
93+
private function innerSearchService(string $function, array $args): mixed
94+
{
95+
$this->stopwatch->start($function);
96+
97+
$result = $this->searchService->{$function}(...$args);
98+
99+
$event = $this->stopwatch->stop($function);
100+
101+
$this->data[$function] = [
102+
'_params' => $args,
103+
'_results' => $result,
104+
'_duration' => $event->getDuration(),
105+
'_memory' => $event->getMemory(),
106+
];
107+
108+
return $result;
109+
}
110+
}

src/DependencyInjection/MeilisearchExtension.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
namespace Meilisearch\Bundle\DependencyInjection;
66

7+
use Meilisearch\Bundle\DataCollector\MeilisearchDataCollector;
8+
use Meilisearch\Bundle\Debug\TraceableMeilisearchService;
79
use Meilisearch\Bundle\Engine;
810
use Meilisearch\Bundle\MeilisearchBundle;
11+
use Meilisearch\Bundle\SearchService;
912
use Meilisearch\Bundle\Services\MeilisearchService;
1013
use Symfony\Component\Config\FileLocator;
1114
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -59,6 +62,20 @@ public function load(array $configs, ContainerBuilder $container): void
5962

6063
$container->setDefinition('meilisearch.service', $searchDefinition->setPublic(true));
6164
$container->setAlias('search.service', 'meilisearch.service')->setPublic(true);
65+
66+
if ($container->getParameter('kernel.debug')) {
67+
$container->register('debug.meilisearch.service', TraceableMeilisearchService::class)
68+
->setDecoratedService(SearchService::class)
69+
->addArgument(new Reference('debug.meilisearch.service.inner'))
70+
->addArgument(new Reference('debug.stopwatch'))
71+
;
72+
$container->register('data_collector.meilisearch', MeilisearchDataCollector::class)
73+
->addArgument(new Reference('debug.meilisearch.service'))
74+
->addTag('data_collector', [
75+
'id' => 'meilisearch',
76+
'template' => '@Meilisearch/DataCollector/meilisearch.html.twig',
77+
]);
78+
}
6279
}
6380

6481
/**
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
2+
3+
{% block toolbar %}
4+
{% set _data = collector.meilisearch %}
5+
{% if _data is not null %}
6+
{% set icon %}
7+
{{ include('@Meilisearch/DataCollector/meilisearch.svg') }}
8+
<span class="sf-toolbar-value">Meilisearch</span>
9+
{% endset %}
10+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: 'meilisearch' }) }}
11+
{% endif %}
12+
{% endblock %}
13+
14+
{% block menu %}
15+
{% set _data = collector.meilisearch %}
16+
<span class="label{{ _data is null ? ' disabled' }}">
17+
<span class="icon">
18+
{{ include('@Meilisearch/DataCollector/meilisearch.svg') }}
19+
</span>
20+
<strong>Meilisearch</strong>
21+
</span>
22+
{% endblock %}
23+
24+
{% block panel %}
25+
<h2>Meilisearch</h2>
26+
{% set _data = collector.meilisearch %}
27+
{% if _data is not null %}
28+
<div class="sf-tabs">
29+
{% for _name, _d in _data %}
30+
<div class="tab">
31+
<h3 class="tab-title">{{ _name|title }}</h3>
32+
<div class="tab-content">
33+
<div class="metrics">
34+
<div class="metric">
35+
<span class="value">{{ '%.0f'|format(_d._duration) }} <span class="unit">ms</span></span>
36+
<span class="label">Total execution time</span>
37+
</div>
38+
<div class="metric">
39+
<span class="value">{{ '%.2f'|format(_d._memory / 1024 / 1024) }} <span class="unit">MB</span></span>
40+
<span class="label">Peak memory usage</span>
41+
</div>
42+
</div>
43+
<h3>Params</h3>
44+
<table>
45+
{% for _pk, _pv in _d._params %}
46+
<tr>
47+
<td>{{ _pk }}</td>
48+
<td>{{ profiler_dump(_pv) }}</td>
49+
</tr>
50+
{% endfor %}
51+
</table>
52+
<h3>Result</h3>
53+
<table>
54+
{% for _rk, _rv in _d._results %}
55+
<tr>
56+
<td>{{ _rk }}</td>
57+
<td>{{ profiler_dump(_rv) }}</td>
58+
</tr>
59+
{% endfor %}
60+
</table>
61+
</div>
62+
</div>
63+
{% endfor %}
64+
</div>
65+
<p class="help">
66+
You can also see the HTTP Client & Performance{% if constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') >= '6.1.0' %} & Serializer{% endif %} tabs to learn more.
67+
</p>
68+
{% else %}
69+
<div class="empty">
70+
<p>No Meilisearch data collected.</p>
71+
</div>
72+
{% endif %}
73+
<p>
74+
<a href="https://www.meilisearch.com/docs">Read Meilisearch documentation</a>
75+
<br />
76+
<a href="https://github.com/meilisearch/meilisearch-php">Read Meilisearch PHP SDK documentation</a>
77+
<br />
78+
<a href="https://github.com/meilisearch/meilisearch-symfony">Read Meilisearch Symfony bundle documentation</a>
79+
</p>
80+
{% endblock %}
Lines changed: 23 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)