-
Notifications
You must be signed in to change notification settings - Fork 34
[STALE] Add datacollector for debug #275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Meilisearch\Bundle\DataCollector; | ||
|
|
||
| use Meilisearch\Bundle\Debug\TraceableMeilisearchService; | ||
| use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector; | ||
| use Symfony\Component\HttpFoundation\Request; | ||
| use Symfony\Component\HttpFoundation\Response; | ||
|
|
||
| /** | ||
| * @author Antoine Makdessi <[email protected]> | ||
| */ | ||
| final class MeilisearchDataCollector extends AbstractDataCollector | ||
| { | ||
| private TraceableMeilisearchService $meilisearchService; | ||
|
|
||
| public function __construct(TraceableMeilisearchService $meilisearchService) | ||
| { | ||
| $this->meilisearchService = $meilisearchService; | ||
| } | ||
| public function collect(Request $request, Response $response, \Throwable $exception = null): void | ||
| { | ||
| $data = $this->meilisearchService->getData(); | ||
|
|
||
| $this->data[$this->getName()] = !empty($data) ? $this->cloneVar($data) : null; | ||
| } | ||
|
|
||
| public function getName(): string | ||
| { | ||
| return 'meilisearch'; | ||
| } | ||
|
|
||
| /** @internal used in the DataCollector view template */ | ||
| public function getMeilisearch(): mixed | ||
| { | ||
| return $this->data[$this->getName()] ?? null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Meilisearch\Bundle\Debug; | ||
|
|
||
| use Doctrine\Persistence\ObjectManager; | ||
| use Meilisearch\Bundle\Collection; | ||
| use Meilisearch\Bundle\SearchService; | ||
| use Symfony\Component\Stopwatch\Stopwatch; | ||
|
|
||
| /** | ||
| * @author Antoine Makdessi <[email protected]> | ||
| */ | ||
| final class TraceableMeilisearchService implements SearchService | ||
| { | ||
| private SearchService $searchService; | ||
| private Stopwatch $stopwatch; | ||
| private array $data = []; | ||
|
|
||
| public function __construct(SearchService $searchService, Stopwatch $stopwatch) | ||
| { | ||
| $this->searchService = $searchService; | ||
| $this->stopwatch = $stopwatch; | ||
| } | ||
|
|
||
| public function index(ObjectManager $objectManager, $searchable): array | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function remove(ObjectManager $objectManager, $searchable): array | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function clear(string $className): array | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function deleteByIndexName(string $indexName): ?array | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function delete(string $className): ?array | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function search(ObjectManager $objectManager, string $className, string $query = '', array $searchParams = []): array | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function rawSearch(string $className, string $query = '', array $searchParams = []): array | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function count(string $className, string $query = '', array $searchParams = []): int | ||
| { | ||
| return $this->innerSearchService(__FUNCTION__, \func_get_args()); | ||
| } | ||
|
|
||
| public function isSearchable($className): bool | ||
| { | ||
| return $this->searchService->isSearchable($className); | ||
| } | ||
|
|
||
| public function getSearchable(): array | ||
| { | ||
| return $this->searchService->getSearchable(); | ||
| } | ||
|
|
||
| public function getConfiguration(): Collection | ||
| { | ||
| return $this->searchService->getConfiguration(); | ||
| } | ||
|
|
||
| public function searchableAs(string $className): string | ||
| { | ||
| return $this->searchService->searchableAs($className); | ||
| } | ||
|
|
||
| /** @internal used in the DataCollector class */ | ||
| public function getData(): array | ||
| { | ||
| return $this->data; | ||
| } | ||
|
|
||
| private function innerSearchService(string $function, array $args): mixed | ||
| { | ||
| $this->stopwatch->start($function); | ||
|
|
||
| $result = $this->searchService->{$function}(...$args); | ||
|
|
||
| $event = $this->stopwatch->stop($function); | ||
|
|
||
| $this->data[$function] = [ | ||
| '_params' => $args, | ||
| '_results' => $result, | ||
| '_duration' => $event->getDuration(), | ||
| '_memory' => $event->getMemory(), | ||
| ]; | ||
|
|
||
| return $result; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,8 +4,11 @@ | |||||||
|
|
||||||||
| namespace Meilisearch\Bundle\DependencyInjection; | ||||||||
|
|
||||||||
| use Meilisearch\Bundle\DataCollector\MeilisearchDataCollector; | ||||||||
| use Meilisearch\Bundle\Debug\TraceableMeilisearchService; | ||||||||
| use Meilisearch\Bundle\Engine; | ||||||||
| use Meilisearch\Bundle\MeilisearchBundle; | ||||||||
| use Meilisearch\Bundle\SearchService; | ||||||||
| use Meilisearch\Bundle\Services\MeilisearchService; | ||||||||
| use Symfony\Component\Config\FileLocator; | ||||||||
| use Symfony\Component\DependencyInjection\ContainerBuilder; | ||||||||
|
|
@@ -40,24 +43,39 @@ public function load(array $configs, ContainerBuilder $container): void | |||||||
| $container->setParameter('meili_symfony_version', MeilisearchBundle::qualifiedVersion()); | ||||||||
|
|
||||||||
| if (\count($doctrineEvents = $config['doctrineSubscribedEvents']) > 0) { | ||||||||
| $subscriber = $container->getDefinition('search.search_indexer_subscriber'); | ||||||||
| $subscriber = $container->getDefinition('meilisearch.search_indexer_subscriber'); | ||||||||
|
|
||||||||
| foreach ($doctrineEvents as $event) { | ||||||||
| $subscriber->addTag('doctrine.event_listener', ['event' => $event]); | ||||||||
| $subscriber->addTag('doctrine_mongodb.odm.event_listener', ['event' => $event]); | ||||||||
| } | ||||||||
| } else { | ||||||||
| $container->removeDefinition('search.search_indexer_subscriber'); | ||||||||
| $container->removeDefinition('meilisearch.search_indexer_subscriber'); | ||||||||
| } | ||||||||
|
|
||||||||
| $engineDefinition = new Definition(Engine::class, [new Reference('search.client')]); | ||||||||
| $engineDefinition = new Definition(Engine::class, [new Reference('meilisearch.client')]); | ||||||||
|
|
||||||||
| $searchDefinition = (new Definition( | ||||||||
| MeilisearchService::class, | ||||||||
| [new Reference($config['serializer']), $engineDefinition, $config] | ||||||||
| )); | ||||||||
|
|
||||||||
| $container->setDefinition('search.service', $searchDefinition->setPublic(true)); | ||||||||
| $container->setDefinition('meilisearch.service', $searchDefinition->setPublic(true)); | ||||||||
| $container->setAlias('search.service', 'meilisearch.service')->setPublic(true); | ||||||||
|
|
||||||||
| if ($container->getParameter('kernel.debug')) { | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd instead introduce |
||||||||
| $container->register('debug.meilisearch.service', TraceableMeilisearchService::class) | ||||||||
| ->setDecoratedService(SearchService::class) | ||||||||
| ->addArgument(new Reference('debug.meilisearch.service.inner')) | ||||||||
| ->addArgument(new Reference('debug.stopwatch')) | ||||||||
| ; | ||||||||
|
Comment on lines
+70
to
+71
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| $container->register('data_collector.meilisearch', MeilisearchDataCollector::class) | ||||||||
| ->addArgument(new Reference('debug.meilisearch.service')) | ||||||||
| ->addTag('data_collector', [ | ||||||||
| 'id' => 'meilisearch', | ||||||||
| 'template' => '@Meilisearch/DataCollector/meilisearch.html.twig', | ||||||||
| ]); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
|
|
||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| {% extends '@WebProfiler/Profiler/layout.html.twig' %} | ||
|
|
||
| {% block toolbar %} | ||
| {% set _data = collector.meilisearch %} | ||
| {% if _data is not null %} | ||
| {% set icon %} | ||
| {{ include('@Meilisearch/DataCollector/meilisearch.svg') }} | ||
| <span class="sf-toolbar-value">Meilisearch</span> | ||
| {% endset %} | ||
| {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: 'meilisearch' }) }} | ||
| {% endif %} | ||
| {% endblock %} | ||
|
|
||
| {% block menu %} | ||
| {% set _data = collector.meilisearch %} | ||
| <span class="label{{ _data is null ? ' disabled' }}"> | ||
| <span class="icon"> | ||
| {{ include('@Meilisearch/DataCollector/meilisearch.svg') }} | ||
| </span> | ||
| <strong>Meilisearch</strong> | ||
| </span> | ||
| {% endblock %} | ||
|
|
||
| {% block panel %} | ||
| <h2>Meilisearch</h2> | ||
| {% set _data = collector.meilisearch %} | ||
| {% if _data is not null %} | ||
| <div class="sf-tabs"> | ||
| {% for _name, _d in _data %} | ||
| <div class="tab"> | ||
| <h3 class="tab-title">{{ _name|title }}</h3> | ||
| <div class="tab-content"> | ||
| <div class="metrics"> | ||
| <div class="metric"> | ||
| <span class="value">{{ '%.0f'|format(_d._duration) }} <span class="unit">ms</span></span> | ||
| <span class="label">Total execution time</span> | ||
| </div> | ||
| <div class="metric"> | ||
| <span class="value">{{ '%.2f'|format(_d._memory / 1024 / 1024) }} <span class="unit">MB</span></span> | ||
| <span class="label">Peak memory usage</span> | ||
| </div> | ||
| </div> | ||
| <h3>Params</h3> | ||
| <table> | ||
| {% for _pk, _pv in _d._params %} | ||
| <tr> | ||
| <td>{{ _pk }}</td> | ||
| <td>{{ profiler_dump(_pv) }}</td> | ||
| </tr> | ||
| {% endfor %} | ||
| </table> | ||
| <h3>Result</h3> | ||
| <table> | ||
| {% for _rk, _rv in _d._results %} | ||
| <tr> | ||
| <td>{{ _rk }}</td> | ||
| <td>{{ profiler_dump(_rv) }}</td> | ||
| </tr> | ||
| {% endfor %} | ||
| </table> | ||
| </div> | ||
| </div> | ||
| {% endfor %} | ||
| </div> | ||
| <p class="help"> | ||
| You can also see the HTTP Client & Performance{% if constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') >= '6.1.0' %} & Serializer{% endif %} tabs to learn more. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the string version comparing really works? Maybe better to use |
||
| </p> | ||
| {% else %} | ||
| <div class="empty"> | ||
| <p>No Meilisearch data collected.</p> | ||
| </div> | ||
| {% endif %} | ||
| <p> | ||
| <a href="https://www.meilisearch.com/docs">Read Meilisearch documentation</a> | ||
| <br /> | ||
| <a href="https://github.com/meilisearch/meilisearch-php">Read Meilisearch PHP SDK documentation</a> | ||
| <br /> | ||
| <a href="https://github.com/meilisearch/meilisearch-symfony">Read Meilisearch Symfony bundle documentation</a> | ||
| </p> | ||
| {% endblock %} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.