Skip to content
This repository has been archived by the owner on Jan 17, 2022. It is now read-only.

Commit

Permalink
fix(logging): log collecting in the symfony profiler works
Browse files Browse the repository at this point in the history
  • Loading branch information
Rastusik committed Jun 10, 2020
1 parent 496c5fe commit 9b7735d
Show file tree
Hide file tree
Showing 14 changed files with 265 additions and 6 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"symfony/messenger": "^4.3.1|^5.0",
"symfony/monolog-bridge": "^4.3.1|^5.0",
"symfony/monolog-bundle": "^3.3",
"symfony/profiler-pack": "^1.0",
"symfony/twig-bundle": "^4.3.1|^5.0",
"symfony/var-dumper": "^4.3.1|^5.0",
"symfony/yaml": "^4.3.1|^5.0",
Expand Down
37 changes: 33 additions & 4 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace K911\Swoole\Bridge\Symfony\Bundle\DependencyInjection\CompilerPass;

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

/**
* This is an override for Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass
* which removes debug processor from loggers when Symfony is run from CLI.
* Without debug log processor, there are no logs being shown in the symfony profiler. This override
* replaces the original configurator for 'monolog.logger_prototype' with a custom one, which removes
* the debug log processor only when being run from PHPDBG.
*/
final class DebugLogProcessorPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (!$container->hasDefinition('profiler')) {
return;
}
if (!$container->hasDefinition('monolog.logger_prototype')) {
return;
}
if (!$container->hasDefinition('debug.log_processor')) {
return;
}

$definition = $container->getDefinition('monolog.logger_prototype');
$definition->setConfigurator([__CLASS__, 'configureLogger']);
}

public static function configureLogger(object $logger): void
{
if (!\method_exists($logger, 'removeDebugLogger')) {
return;
}

if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
return;
}

if (\PHP_SAPI === 'cli') {
foreach ($_SERVER['argv'] as $arg) {
if (false !== \mb_strpos($arg, 'swoole:server:')) {
return;
}
}
}

$logger->removeDebugLogger();
}
}
6 changes: 6 additions & 0 deletions src/Bridge/Symfony/Bundle/SwooleBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@

namespace K911\Swoole\Bridge\Symfony\Bundle;

use K911\Swoole\Bridge\Symfony\Bundle\DependencyInjection\CompilerPass\DebugLogProcessorPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

final class SwooleBundle extends Bundle
{
public function build(ContainerBuilder $container): void
{
$container->addCompilerPass(new DebugLogProcessorPass());
}
}
47 changes: 47 additions & 0 deletions tests/Feature/SymfonyProfilerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace K911\Swoole\Tests\Feature;

use K911\Swoole\Client\HttpClient;
use K911\Swoole\Tests\Fixtures\Symfony\TestBundle\Test\ServerTestCase;

final class SymfonyProfilerTest extends ServerTestCase
{
protected function setUp(): void
{
// problem with messenger support in symfony profiler in symfony 4.3
$this->markTestSkippedIfSymfonyVersionIsLoverThan('4.4.0');
$this->markTestSkippedIfXdebugEnabled();
}

public function testAdvancedStaticFilesServerWithAutoRegistration(): void
{
$serverRun = $this->createConsoleProcess([
'swoole:server:run',
'--host=localhost',
'--port=9999',
], ['APP_ENV' => 'profiler']);

$serverRun->setTimeout(10);
$serverRun->start();

$this->runAsCoroutineAndWait(function (): void {
$client = HttpClient::fromDomain('localhost', 9999, false);
$this->assertTrue($client->connect());

$response = $client->send('/twig')['response'];

$this->assertSame(200, $response['statusCode']);
$this->assertNotEmpty($response['headers']['x-debug-token']);
$debugToken = $response['headers']['x-debug-token'];

$profilerResponse = $client->send('/_wdt/'.$debugToken)['response'];

$this->assertStringContainsString('sf-toolbar-block-logger sf-toolbar-status-red', $profilerResponse['body']);
});

$serverRun->stop();
}
}
19 changes: 18 additions & 1 deletion tests/Fixtures/Symfony/TestAppKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Bundle\MonologBundle\MonologBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;
Expand All @@ -26,6 +27,8 @@ class TestAppKernel extends Kernel

private $coverageEnabled;

private $profilerEnabled = false;

public function __construct(string $environment, bool $debug)
{
if ('_cov' === \mb_substr($environment, -4, 4)) {
Expand All @@ -37,6 +40,10 @@ public function __construct(string $environment, bool $debug)
$this->coverageEnabled = false;
}

if ('profiler' === $environment) {
$this->profilerEnabled = true;
}

parent::__construct($environment, $debug);
}

Expand Down Expand Up @@ -70,6 +77,10 @@ public function registerBundles(): Generator
if ($this->coverageEnabled) {
yield new CoverageBundle();
}

if ($this->profilerEnabled) {
yield new WebProfilerBundle();
}
}

/**
Expand All @@ -88,6 +99,12 @@ public function getProjectDir(): string
protected function configureRoutes(RouteCollectionBuilder $routes): void
{
$routes->import($this->getProjectDir().'/routing.yml');

$envRoutingFile = $this->getProjectDir().'/config/'.$this->environment.'/routing/routing.yaml';

if (\file_exists($envRoutingFile)) {
$routes->import($envRoutingFile);
}
}

/**
Expand All @@ -103,7 +120,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load

$loader->load($confDir.'/*'.self::CONFIG_EXTENSIONS, 'glob');
if (\is_dir($confDir.'/'.$this->environment)) {
$loader->load($confDir.'/'.$this->environment.'/**/*'.self::CONFIG_EXTENSIONS, 'glob');
$loader->load($confDir.'/'.$this->environment.'/*'.self::CONFIG_EXTENSIONS, 'glob');
}

if ($this->coverageEnabled && 'cov' !== $this->environment) {
Expand Down
48 changes: 48 additions & 0 deletions tests/Fixtures/Symfony/TestBundle/Controller/TwigController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace K911\Swoole\Tests\Fixtures\Symfony\TestBundle\Controller;

use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;

class TwigController
{
/**
* @var Environment
*/
private $environment;

/**
* @var LoggerInterface
*/
private $logger;

public function __construct(Environment $environment, LoggerInterface $logger)
{
$this->environment = $environment;
$this->logger = $logger;
}

/**
* @Route("/twig")
*
* @throws InvalidArgumentException
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
public function indexAction(): Response
{
$this->logger->error('Profiler logging test.');

return new Response($this->environment->render('base.html.twig'));
}
}
8 changes: 8 additions & 0 deletions tests/Fixtures/Symfony/TestBundle/Test/ServerTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Swoole\Coroutine\Scheduler;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
Expand Down Expand Up @@ -169,6 +170,13 @@ protected function markTestSkippedIfInotifyDisabled(): void
}
}

protected function markTestSkippedIfSymfonyVersionIsLoverThan(string $version): void
{
if (\version_compare(Kernel::VERSION, $version, 'lt')) {
$this->markTestSkipped(\sprintf('This test needs Symfony in version : %s.', $version));
}
}

protected function generateUniqueHash(int $factor = 8): string
{
try {
Expand Down
2 changes: 2 additions & 0 deletions tests/Fixtures/Symfony/app/config/profiler/framework.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
framework:
profiler: { only_exceptions: false }
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
prefix: /_wdt

web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
prefix: /_profiler
3 changes: 3 additions & 0 deletions tests/Fixtures/Symfony/app/config/profiler/web_profiler.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
web_profiler:
toolbar: true
intercept_redirects: false
26 changes: 26 additions & 0 deletions tests/Fixtures/Symfony/app/config/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
services:
# default configuration for services in *this* file
_defaults:
# automatically injects dependencies in your services
autowire: true
# automatically registers your services as commands, event subscribers, etc.
autoconfigure: true
# this means you cannot fetch services directly from the container via $container->get()
# if you need to do this, you can override this setting on individual services
public: false

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
K911\Swoole\Tests\Fixtures\Symfony\TestBundle\:
resource: '../../TestBundle/*'
# you can exclude directories or files
# but if a service is unused, it's removed anyway
exclude: '../../TestBundle/{Message,Test,Controller}'

# controllers are imported separately to make sure they
# have the tag that allows actions to type-hint services
K911\Swoole\Tests\Fixtures\Symfony\TestBundle\Controller\:
resource: '../../TestBundle/Controller'
# without this the HMR tests break, might be a bug in HMR
exclude: '../../TestBundle/Controller/ReplacedContentTestController.php'
tags: ['controller.service_arguments']
2 changes: 1 addition & 1 deletion tests/Fixtures/Symfony/app/console
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use K911\Swoole\Tests\Fixtures\Symfony\TestAppKernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;
use Symfony\Component\ErrorHandler\Debug;

\set_time_limit(0);

Expand Down
10 changes: 10 additions & 0 deletions tests/Fixtures/Symfony/app/templates/base.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Welcome!</title>
</head>
<body>
<h1>Welcome to Swoole Server</h1>
</body>
</html>

0 comments on commit 9b7735d

Please sign in to comment.