Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,35 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<defaults autowire="true" autoconfigure="true"/>
<defaults autowire="true" autoconfigure="true" />

<prototype namespace="Meilisearch\Bundle\Command\" resource="../src/Command" />

<service id="search.search_indexer_subscriber"
<service id="meilisearch.search_indexer_subscriber"
class="Meilisearch\Bundle\EventListener\DoctrineEventSubscriber"
public="true">
<argument type="service" id="search.service"/>
<argument type="service" id="meilisearch.service" />
</service>
<service id="search.search_indexer_subscriber" alias="meilisearch.search_indexer_subscriber">
<deprecated package="meilisearch/search-bundle" version="0.14">The "%alias_id%" service alias is deprecated. Use "meilisearch.search_indexer_subscriber" instead.</deprecated>
</service>

<service id="search.client" class="Meilisearch\Client" public="true" lazy="true">
<service id="meilisearch.client" class="Meilisearch\Client" public="true" lazy="true">
<argument key="$url">%meili_url%</argument>
<argument key="$apiKey">%meili_api_key%</argument>
<argument key="$httpClient" type="service" id="psr18.http_client" on-invalid="ignore" />
<argument key="$clientAgents" type="collection">
<argument>%meili_symfony_version%</argument>
</argument>
</service>
<service id="search.client" alias="meilisearch.client" public="true">
<deprecated package="meilisearch/search-bundle" version="0.14">The "%alias_id%" service alias is deprecated. Use "meilisearch.client" instead.</deprecated>
</service>

<service id="Meilisearch\Client" alias="search.client"/>
<service id="Meilisearch\Bundle\SearchService" alias="search.service"/>
<service id="Meilisearch\Client" alias="meilisearch.client" public="true" />
<service id="search.client" alias="meilisearch.client" public="true">
<deprecated package="meilisearch/search-bundle" version="0.14">The "%alias_id%" service alias is deprecated. Use "meilisearch.client" instead.</deprecated>
</service>
<service id="Meilisearch\Bundle\SearchService" alias="meilisearch.service" />
</services>
</container>
40 changes: 40 additions & 0 deletions src/DataCollector/MeilisearchDataCollector.php
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
Comment on lines +22 to +23
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
public function collect(Request $request, Response $response, \Throwable $exception = null): void
}
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;
}
}
110 changes: 110 additions & 0 deletions src/Debug/TraceableMeilisearchService.php
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;
}
}
26 changes: 22 additions & 4 deletions src/DependencyInjection/MeilisearchExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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')) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd instead introduce debug.xml where you configure these things and import the file if it's debug mode :)

$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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
->addArgument(new Reference('debug.stopwatch'))
;
->addArgument(new Reference('debug.stopwatch'));

$container->register('data_collector.meilisearch', MeilisearchDataCollector::class)
->addArgument(new Reference('debug.meilisearch.service'))
->addTag('data_collector', [
'id' => 'meilisearch',
'template' => '@Meilisearch/DataCollector/meilisearch.html.twig',
]);
}
}

/**
Expand Down
80 changes: 80 additions & 0 deletions templates/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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the string version comparing really works? Maybe better to use Kernel::VERSION_ID?

</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 %}
23 changes: 23 additions & 0 deletions templates/DataCollector/meilisearch.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/BaseKernelTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected function setUp(): void
self::bootKernel();

$this->entityManager = $this->get('doctrine.orm.entity_manager');
$this->searchService = $this->get('search.service');
$this->searchService = $this->get('meilisearch.service');

$metaData = $this->entityManager->getMetadataFactory()->getAllMetadata();
$tool = new SchemaTool($this->entityManager);
Expand Down
4 changes: 2 additions & 2 deletions tests/Integration/CommandsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected function setUp(): void
{
parent::setUp();

$this->client = $this->get('search.client');
$this->client = $this->get('meilisearch.client');
$this->index = $this->client->index($this->getPrefix().self::$indexName);
$this->application = new Application(self::createKernel());
}
Expand Down Expand Up @@ -498,7 +498,7 @@ public function testImportWithDynamicSettings(string $command): void
EOD, $importOutput);
}

$settings = $this->get('search.client')->index('sf_phpunit__dynamic_settings')->getSettings();
$settings = $this->get('meilisearch.client')->index('sf_phpunit__dynamic_settings')->getSettings();

$getSetting = static fn ($value) => $value instanceof \IteratorAggregate ? iterator_to_array($value) : $value;

Expand Down
2 changes: 1 addition & 1 deletion tests/Integration/DependencyInjectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function testHasMeilisearchVersionDefinitionAfterLoad(): void
{
$this->load();

$this->assertContainerBuilderHasServiceDefinitionWithArgument('search.client', '$clientAgents', ['%meili_symfony_version%']);
$this->assertContainerBuilderHasServiceDefinitionWithArgument('meilisearch.client', '$clientAgents', ['%meili_symfony_version%']);
}

public function testHasMeilisearchVersionFromConstantAfterLoad(): void
Expand Down
2 changes: 1 addition & 1 deletion tests/Integration/EngineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function setUp(): void
{
parent::setUp();

$this->engine = new Engine($this->get('search.client'));
$this->engine = new Engine($this->get('meilisearch.client'));
}

/**
Expand Down
Loading