Skip to content

Commit 67b0210

Browse files
committed
display auto discovered clients in the profiler
1 parent 7b5bdf7 commit 67b0210

File tree

2 files changed

+138
-44
lines changed

2 files changed

+138
-44
lines changed

DependencyInjection/HttplugExtension.php

Lines changed: 137 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Http\Discovery\HttpClientDiscovery;
1111
use Http\HttplugBundle\ClientFactory\DummyClient;
1212
use Http\HttplugBundle\ClientFactory\PluginClientFactory;
13+
use Http\HttplugBundle\Collector\ProfileClientFactory;
1314
use Http\HttplugBundle\Collector\ProfilePlugin;
1415
use Http\Message\Authentication\BasicAuth;
1516
use Http\Message\Authentication\Bearer;
@@ -272,16 +273,7 @@ private function configureClient(ContainerBuilder $container, $clientName, array
272273
} elseif ('authentication' === $pluginName) {
273274
$plugins = array_merge($plugins, $this->configureAuthentication($container, $pluginConfig, $serviceId.'.authentication'));
274275
} else {
275-
$pluginServiceId = $serviceId.'.plugin.'.$pluginName;
276-
277-
$definition = class_exists(ChildDefinition::class)
278-
? new ChildDefinition('httplug.plugin'.'.'.$pluginName)
279-
: new DefinitionDecorator('httplug.plugin'.'.'.$pluginName)
280-
;
281-
282-
$this->configurePluginByName($pluginName, $definition, $pluginConfig, $container, $pluginServiceId);
283-
$container->setDefinition($pluginServiceId, $definition);
284-
$plugins[] = $pluginServiceId;
276+
$plugins[] = $this->configurePlugin($container, $serviceId, $pluginName, $pluginConfig);
285277
}
286278
}
287279

@@ -294,27 +286,12 @@ private function configureClient(ContainerBuilder $container, $clientName, array
294286

295287
//Decorate each plugin with a ProfilePlugin instance.
296288
foreach ($plugins as $pluginServiceId) {
297-
$container->register($pluginServiceId.'.debug', ProfilePlugin::class)
298-
->setDecoratedService($pluginServiceId)
299-
->setArguments([
300-
new Reference($pluginServiceId.'.debug.inner'),
301-
new Reference('httplug.collector.collector'),
302-
new Reference('httplug.collector.formatter'),
303-
$pluginServiceId,
304-
])
305-
->setPublic(false)
306-
;
289+
$this->decoratePluginWithProfilePlugin($container, $pluginServiceId);
307290
}
308291

309-
// Add the newstack plugin
310-
$definition = class_exists(ChildDefinition::class)
311-
? new ChildDefinition('httplug.plugin.stack')
312-
: new DefinitionDecorator('httplug.plugin.stack')
313-
;
314-
315-
$definition->addArgument($clientName);
316-
$container->setDefinition($serviceId.'.plugin.newstack', $definition);
317-
array_unshift($plugins, $serviceId.'.plugin.newstack');
292+
// To profile the requests, add a StackPlugin as first plugin in the chain.
293+
$stackPluginId = $this->configureStackPlugin($container, $clientName, $serviceId);
294+
array_unshift($plugins, $stackPluginId);
318295
}
319296

320297
$container
@@ -397,7 +374,12 @@ private function configureAutoDiscoveryClients(ContainerBuilder $container, arra
397374
$httpClient = $this->registerAutoDiscoverableClient(
398375
$container,
399376
'auto_discovered_client',
400-
[HttpClientDiscovery::class, 'find'],
377+
$this->configureAutoDiscoveryFactory(
378+
$container,
379+
HttpClientDiscovery::class,
380+
'auto_discovered_client',
381+
$config
382+
),
401383
$this->isConfigEnabled($container, $config['profiling'])
402384
);
403385
}
@@ -412,7 +394,12 @@ private function configureAutoDiscoveryClients(ContainerBuilder $container, arra
412394
$asyncHttpClient = $this->registerAutoDiscoverableClient(
413395
$container,
414396
'auto_discovered_async',
415-
[HttpAsyncClientDiscovery::class, 'find'],
397+
$this->configureAutoDiscoveryFactory(
398+
$container,
399+
HttpAsyncClientDiscovery::class,
400+
'auto_discovered_async',
401+
$config
402+
),
416403
$this->isConfigEnabled($container, $config['profiling'])
417404
);
418405
}
@@ -430,33 +417,46 @@ private function configureAutoDiscoveryClients(ContainerBuilder $container, arra
430417
/**
431418
* Find a client with auto discovery and return a service Reference to it.
432419
*
433-
* @param ContainerBuilder $container
434-
* @param string $name
435-
* @param callable $factory
436-
* @param bool $profiling
420+
* @param ContainerBuilder $container
421+
* @param string $name
422+
* @param Reference|callable $factory
423+
* @param bool $profiling
437424
*
438425
* @return string service id
439426
*/
440427
private function registerAutoDiscoverableClient(ContainerBuilder $container, $name, $factory, $profiling)
441428
{
442429
$serviceId = 'httplug.auto_discovery.'.$name;
443430

444-
$pluginClientOptions = [];
445-
431+
$plugins = [];
446432
if ($profiling) {
447-
// Tell the plugin journal what plugins we used
448-
$container
449-
->getDefinition('httplug.collector.plugin_journal')
450-
->addMethodCall('setPlugins', [$name, ['httplug.plugin.stopwatch']])
451-
;
433+
// To profile the requests, add a StackPlugin as first plugin in the chain.
434+
$plugins[] = $this->configureStackPlugin($container, $name, $serviceId);
435+
436+
$this->decoratePluginWithProfilePlugin($container, 'httplug.plugin.stopwatch');
437+
$plugins[] = 'httplug.plugin.stopwatch';
452438
}
453439

454440
$container
455441
->register($serviceId, DummyClient::class)
456442
->setFactory([PluginClientFactory::class, 'createPluginClient'])
457-
->setArguments([[new Reference('httplug.plugin.stopwatch')], $factory, [], $pluginClientOptions])
443+
->setArguments([
444+
array_map(
445+
function ($id) {
446+
return new Reference($id);
447+
},
448+
$plugins
449+
),
450+
$factory,
451+
[],
452+
])
458453
;
459454

455+
if ($profiling) {
456+
$collector = $container->getDefinition('httplug.collector.collector');
457+
$collector->replaceArgument(0, array_merge($collector->getArgument(0), [$name]));
458+
}
459+
460460
return $serviceId;
461461
}
462462

@@ -467,4 +467,98 @@ public function getConfiguration(array $config, ContainerBuilder $container)
467467
{
468468
return new Configuration($container->getParameter('kernel.debug'));
469469
}
470+
471+
/**
472+
* Configure a plugin using the parent definition from plugins.xml.
473+
*
474+
* @param ContainerBuilder $container
475+
* @param string $serviceId
476+
* @param string $pluginName
477+
* @param array $pluginConfig
478+
*
479+
* @return string configured service id
480+
*/
481+
private function configurePlugin(ContainerBuilder $container, $serviceId, $pluginName, array $pluginConfig)
482+
{
483+
$pluginServiceId = $serviceId.'.plugin.'.$pluginName;
484+
485+
$definition = class_exists(ChildDefinition::class)
486+
? new ChildDefinition('httplug.plugin.'.$pluginName)
487+
: new DefinitionDecorator('httplug.plugin.'.$pluginName);
488+
489+
$this->configurePluginByName($pluginName, $definition, $pluginConfig, $container, $pluginServiceId);
490+
$container->setDefinition($pluginServiceId, $definition);
491+
492+
return $pluginServiceId;
493+
}
494+
495+
/**
496+
* Decorate the plugin service with a ProfilePlugin service.
497+
*
498+
* @param ContainerBuilder $container
499+
* @param string $pluginServiceId
500+
*/
501+
private function decoratePluginWithProfilePlugin(ContainerBuilder $container, $pluginServiceId)
502+
{
503+
$container->register($pluginServiceId.'.debug', ProfilePlugin::class)
504+
->setDecoratedService($pluginServiceId)
505+
->setArguments([
506+
new Reference($pluginServiceId.'.debug.inner'),
507+
new Reference('httplug.collector.collector'),
508+
new Reference('httplug.collector.formatter'),
509+
$pluginServiceId,
510+
])
511+
->setPublic(false);
512+
}
513+
514+
/**
515+
* Configure a StackPlugin for a client.
516+
*
517+
* @param ContainerBuilder $container
518+
* @param string $clientName Client name to display in the profiler.
519+
* @param string $serviceId Client service id. Used as base for the StackPlugin service id.
520+
*
521+
* @return string configured StackPlugin service id
522+
*/
523+
private function configureStackPlugin(ContainerBuilder $container, $clientName, $serviceId)
524+
{
525+
$pluginServiceId = $serviceId.'.plugin.stack';
526+
527+
$definition = class_exists(ChildDefinition::class)
528+
? new ChildDefinition('httplug.plugin.stack')
529+
: new DefinitionDecorator('httplug.plugin.stack');
530+
531+
$definition->addArgument($clientName);
532+
$container->setDefinition($pluginServiceId, $definition);
533+
534+
return $pluginServiceId;
535+
}
536+
537+
/**
538+
* Configure the discovery factory when profiling is enabled to get client decorated with a ProfileClient.
539+
*
540+
* @param ContainerBuilder $container
541+
* @param string $discovery
542+
* @param string $name
543+
* @param array $config
544+
*
545+
* @return callable|Reference
546+
*/
547+
private function configureAutoDiscoveryFactory(ContainerBuilder $container, $discovery, $name, array $config)
548+
{
549+
$factory = [$discovery, 'find'];
550+
if ($this->isConfigEnabled($container, $config['profiling'])) {
551+
$factoryServiceId = 'httplug.auto_discovery.'.$name.'.factory';
552+
$container->register($factoryServiceId, ProfileClientFactory::class)
553+
->setPublic(false)
554+
->setArguments([
555+
$factory,
556+
new Reference('httplug.collector.collector'),
557+
new Reference('httplug.collector.formatter'),
558+
]);
559+
$factory = new Reference($factoryServiceId);
560+
}
561+
562+
return $factory;
563+
}
470564
}

Tests/Unit/DependencyInjection/HttplugExtensionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public function testClientPlugins()
116116
]);
117117

118118
$plugins = [
119-
'httplug.client.acme.plugin.newstack',
119+
'httplug.client.acme.plugin.stack',
120120
'httplug.plugin.stopwatch',
121121
'httplug.client.acme.plugin.decoder',
122122
'httplug.plugin.redirect',

0 commit comments

Comments
 (0)