Skip to content

Commit

Permalink
Merge pull request #73 from BedrockStreaming/feat/profiler
Browse files Browse the repository at this point in the history
Better look&feel profiler
  • Loading branch information
hdetang authored Feb 25, 2022
2 parents 7a39e5f + 1d749f4 commit c62b938
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 182 deletions.
152 changes: 30 additions & 122 deletions src/DataCollector/GuzzleHttpDataCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace M6Web\Bundle\GuzzleHttpBundle\DataCollector;

use GuzzleHttp\Client as GuzzleHttpClient;
use M6Web\Bundle\GuzzleHttpBundle\EventDispatcher\AbstractGuzzleHttpEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -12,14 +13,21 @@
*/
class GuzzleHttpDataCollector extends DataCollector
{
/**
* Constructor
*/
/** @var GuzzleHttpClient[] */
private $clients = [];

public function __construct()
{
$this->reset();
}

public function registerClient(string $name, GuzzleHttpClient $client)
{
$this->clients[$name] = $client;
$this->data['clients'][$name]['requests'] = new \SplQueue();
$this->data['clients'][$name]['errors'] = 0;
}

/**
* Collect the data
*
Expand All @@ -36,10 +44,10 @@ public function collect(Request $request, Response $response, \Throwable $except
*/
public function reset()
{
$this->data['guzzleHttp'] = [
'commands' => new \SplQueue(),
'has5x' => false,
'has4x' => false,
$this->data = [
'clients' => [],
'request_count' => 0,
'error_count' => 0,
];
}

Expand All @@ -58,142 +66,42 @@ public function getName()
*/
public function onGuzzleHttpCommand(AbstractGuzzleHttpEvent $event)
{
$client = 'm6web_guzzlehttp_'.$event->getClientId();

$request = $event->getRequest();
$response = $event->getResponse();
$statusCode = $response->getStatusCode();

if ($statusCode > 499) {
$this->data['guzzleHttp']['has5x'] = true;
}

if ($statusCode > 399 && $statusCode < 500) {
$this->data['guzzleHttp']['has4x'] = true;
if ($statusCode >= Response::HTTP_BAD_REQUEST) {
$this->data['error_count']++;
$this->data['clients'][$client]['errors']++;
}

$data = [
'uri' => $request->getUri(),
'method' => $request->getMethod(),
'responseCode' => $statusCode,
'responseReason' => $response->getReasonPhrase(),
'executionTime' => $event->getExecutionTime(),
'curl' => [
'redirectCount' => (isset($response->curlInfo['redirect_count'])) ? $response->curlInfo['redirect_count'] : 0,
'redirectTime' => (isset($response->curlInfo['redirect_time'])) ? $response->curlInfo['redirect_time'] : 0,
],
'cache' => (isset($response->cached)) ? 1 : 0,
'cacheTtl' => (isset($response->cacheTtl)) ? $response->cacheTtl : 0,
'options' => $this->cloneVar($request->getHeaders()),
'response' => $this->cloneVar($response->getHeaders()),
];

$this->data['guzzleHttp']['commands']->enqueue($data);
}

/**
* Return GuzzleHttp command list
*
* @return array
*/
public function getCommands()
{
return $this->data['guzzleHttp']['commands'];
}

/**
* Return true error 400 occurred
*
* @return bool
*/
public function has4x()
{
return $this->data['guzzleHttp']['has4x'];
}

/**
* Return true error 500 occurred
*
* @return bool
*/
public function has5x()
{
return $this->data['guzzleHttp']['has5x'];
}

/**
* Return the total time spent by guzzlehttp
*
* @return float
*/
public function getTotalExecutionTime()
{
return array_reduce(iterator_to_array($this->getCommands()), function ($time, $value) {
$time += $value['executionTime'];

return $time;
});
}

/**
* Return average time spent by guzzlehttp command
*
* @return float
*/
public function getAvgExecutionTime()
{
$totalExecutionTime = $this->getTotalExecutionTime();

return ($totalExecutionTime) ? ($totalExecutionTime / count($this->getCommands())) : 0;
}

/**
* Return total cache hits
*
* @return int
*/
public function getCacheHits()
{
return array_reduce(iterator_to_array($this->getCommands()), function ($hits, $value) {
$hits += $value['cache'];

return $hits;
});
$this->data['request_count']++;
$this->data['clients'][$client]['requests']->enqueue($data);
}

/**
* Return total cache hits
*
* @return int
*/
public function getRedirects()
public function getClients(): array
{
return array_reduce(iterator_to_array($this->getCommands()), function ($redirect, $value) {
$redirect += $value['curl']['redirectCount'];

return $redirect;
});
return $this->data['clients'] ?? [];
}

/**
* Return the total time spent by redirection
*
* @return float
*/
public function getTotalRedirectionTime()
public function getRequestCount(): int
{
return array_reduce(iterator_to_array($this->getCommands()), function ($time, $value) {
$time += $value['curl']['redirectTime'];

return $time;
});
return $this->data['request_count'] ?? 0;
}

/**
* Return average time spent by redirection
*
* @return float
*/
public function getAvgRedirectionTime()
public function getErrorCount(): int
{
$totalExecutionTime = $this->getTotalRedirectionTime();

return ($totalExecutionTime) ? ($totalExecutionTime / count($this->getRedirects())) : 0;
return $this->data['error_count'] ?? 0;
}
}
30 changes: 30 additions & 0 deletions src/DependencyInjection/GuzzleHttpPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace M6Web\Bundle\GuzzleHttpBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class GuzzleHttpPass implements CompilerPassInterface
{
/** @var string */
private $clientTag;

public function __construct(string $clientTag = 'm6web_guzzlehttp.client')
{
$this->clientTag = $clientTag;
}

public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('m6web.data_collector.guzzlehttp')) {
return;
}

foreach ($container->findTaggedServiceIds($this->clientTag) as $id => $tags) {
$container->getDefinition('m6web.data_collector.guzzlehttp')
->addMethodCall('registerClient', [$id, new Reference($id)]);
}
}
}
1 change: 1 addition & 0 deletions src/DependencyInjection/M6WebGuzzleHttpExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ protected function loadClient(ContainerBuilder $container, $clientId, array $con
$guzzleClientDefinition = new Definition('%m6web_guzzlehttp.guzzle.client.class%');
$guzzleClientDefinition->setPublic(true);
$guzzleClientDefinition->addArgument($config);
$guzzleClientDefinition->addTag('m6web_guzzlehttp.client');

$containerKey = ($clientId == 'default') ? 'm6web_guzzlehttp' : 'm6web_guzzlehttp_'.$clientId;

Expand Down
2 changes: 2 additions & 0 deletions src/M6WebGuzzleHttpBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace M6Web\Bundle\GuzzleHttpBundle;

use M6Web\Bundle\GuzzleHttpBundle\DependencyInjection\GuzzleHttpPass;
use M6Web\Bundle\GuzzleHttpBundle\DependencyInjection\MiddlewarePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
Expand All @@ -24,5 +25,6 @@ public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new MiddlewarePass());
$container->addCompilerPass(new GuzzleHttpPass());
}
}
Loading

0 comments on commit c62b938

Please sign in to comment.