merged branch stof/doctrine_profiling (PR #2895)
Commits
-------
8713c2d
[DoctrineBridge][DoctrineBundle] Refactored the DBAL logging
Discussion
----------
[DoctrineBridge][DoctrineBundle] Refactored the DBAL logging
This allows enabling the logging and the profiling separately. This is useful for instance when doing batch processing leading to memory issue because of the profiling. In such case, the only solution currently is to disable the logging totally whereas disabling only the use of the profiler would allow seeing the queries in the logs (and the profiles are not collected in the CLI anyway).
I'm not sure about the place where the ``Stopwatch`` should be used. Keeping it in the ``DbalLogger`` with Monolog was the easy way as it allows using the DBAL class directly to collect queries for the profiler but technically the ``Stopwatch`` is used by the profiler.
the bundle changes are part of the PR to avoid letting the bundle in a broken state. I will also submit them to the doctrine/DoctrineBundle repo
---------------------------------------------------------------------------
by fabpot at 2011/12/16 02:33:05 -0800
Tests do not pass for me (even after upgrading the Doctrine deps to their latest versions):
There was 1 error:
1) Symfony\Bundle\DoctrineBundle\Tests\ContainerTest::testContainer
Argument 1 passed to Doctrine\DBAL\Logging\LoggerChain::addLogger() must implement interface Doctrine\DBAL\Logging\SQLLogger, instance of Doctrine\Dbal\Logging\DebugStack given
vendor/doctrine-dbal/lib/Doctrine/DBAL/Logging/LoggerChain.php:39
src/Symfony/Component/DependencyInjection/ContainerBuilder.php:777
src/Symfony/Component/DependencyInjection/ContainerBuilder.php:349
src/Symfony/Bundle/DoctrineBundle/Tests/ContainerTest.php:22
---------------------------------------------------------------------------
by stof at 2011/12/16 04:24:46 -0800
this is weird. DebugStack implements the interface, and the test passes for me
---------------------------------------------------------------------------
by fabpot at 2011/12/16 05:30:11 -0800
actually, the test pass when I run the `ContainerTest.php` file alone, but fail when I'm running the whole test suite.
---------------------------------------------------------------------------
by stof at 2011/12/16 05:39:15 -0800
I'm not able to run the whole testsuite. With intl enabled, it fails before the first test somewhere in the Locale component tests (Intl seems to be broken on 5.3.8 on windows as using the constructor of the intl classes gives me ``null`` in the variable). And after disabling intl, I got an error about allowed memory size exhausted during the EntityType tests
---------------------------------------------------------------------------
by stloyd at 2011/12/16 05:42:09 -0800
@stof And here goes Travis with help! ;-)
Just log in there, enable hook for your symfony repo, force an push, and watch result at: http://travis-ci.org/#!/stof/symfony
---------------------------------------------------------------------------
by stof at 2011/12/16 05:47:57 -0800
Note: when running only the testsuite for bundles, I also get such an error after about 450 of the 500 tests. It seems like the garbage collector does not clean the memory between tests...
---------------------------------------------------------------------------
by stof at 2011/12/16 05:52:08 -0800
anyway, the error seems really weird as the class implements the interface. I don't see how it could be passed without implementing it
---------------------------------------------------------------------------
by stof at 2011/12/16 06:10:43 -0800
@stloyd Travis allows me to see that this issue is not specific to @fabpot's computer. But it does not allow me to debug the test as I only get the result of the test, which does not make any sense
This commit is contained in:
commit
4a88287b29
@ -12,10 +12,10 @@
|
||||
namespace Symfony\Bridge\Doctrine\DataCollector;
|
||||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Doctrine\DBAL\Logging\DebugStack;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Bridge\Doctrine\Logger\DbalLogger;
|
||||
|
||||
/**
|
||||
* DoctrineDataCollector.
|
||||
@ -28,7 +28,7 @@ class DoctrineDataCollector extends DataCollector
|
||||
private $managers;
|
||||
private $logger;
|
||||
|
||||
public function __construct(ManagerRegistry $registry, DbalLogger $logger = null)
|
||||
public function __construct(ManagerRegistry $registry, DebugStack $logger = null)
|
||||
{
|
||||
$this->connections = $registry->getConnectionNames();
|
||||
$this->managers = $registry->getManagerNames();
|
||||
|
@ -13,14 +13,14 @@ namespace Symfony\Bridge\Doctrine\Logger;
|
||||
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpKernel\Debug\Stopwatch;
|
||||
use Doctrine\DBAL\Logging\DebugStack;
|
||||
use Doctrine\DBAL\Logging\SQLLogger;
|
||||
|
||||
/**
|
||||
* DbalLogger.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class DbalLogger extends DebugStack
|
||||
class DbalLogger implements SQLLogger
|
||||
{
|
||||
protected $logger;
|
||||
protected $stopwatch;
|
||||
@ -42,8 +42,6 @@ class DbalLogger extends DebugStack
|
||||
*/
|
||||
public function startQuery($sql, array $params = null, array $types = null)
|
||||
{
|
||||
parent::startQuery($sql, $params, $types);
|
||||
|
||||
if (null !== $this->stopwatch) {
|
||||
$this->stopwatch->start('doctrine', 'doctrine');
|
||||
}
|
||||
@ -58,8 +56,6 @@ class DbalLogger extends DebugStack
|
||||
*/
|
||||
public function stopQuery()
|
||||
{
|
||||
parent::stopQuery();
|
||||
|
||||
if (null !== $this->stopwatch) {
|
||||
$this->stopwatch->stop('doctrine');
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ class Configuration implements ConfigurationInterface
|
||||
'platform_service',
|
||||
'charset',
|
||||
'logging',
|
||||
'profiling',
|
||||
'mapping_types',
|
||||
) as $key) {
|
||||
if (array_key_exists($key, $v)) {
|
||||
@ -130,6 +131,7 @@ class Configuration implements ConfigurationInterface
|
||||
->scalarNode('platform_service')->end()
|
||||
->scalarNode('charset')->end()
|
||||
->booleanNode('logging')->defaultValue($this->debug)->end()
|
||||
->booleanNode('profiling')->defaultValue($this->debug)->end()
|
||||
->scalarNode('driver_class')->end()
|
||||
->scalarNode('wrapper_class')->end()
|
||||
->arrayNode('options')
|
||||
|
@ -92,9 +92,18 @@ class DoctrineExtension extends AbstractDoctrineExtension
|
||||
{
|
||||
// configuration
|
||||
$configuration = $container->setDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $name), new DefinitionDecorator('doctrine.dbal.connection.configuration'));
|
||||
if (isset($connection['logging']) && $connection['logging']) {
|
||||
$configuration->addMethodCall('setSQLLogger', array(new Reference('doctrine.dbal.logger')));
|
||||
unset ($connection['logging']);
|
||||
$logger = null;
|
||||
if ($connection['logging']) {
|
||||
$logger = new Reference('doctrine.dbal.logger');
|
||||
}
|
||||
unset ($connection['logging']);
|
||||
if ($connection['profiling']) {
|
||||
$logger = $logger ? new Reference('doctrine.dbal.logger.chain') : new Reference('doctrine.dbal.logger.profiling');
|
||||
}
|
||||
unset($connection['profiling']);
|
||||
|
||||
if ($logger) {
|
||||
$configuration->addMethodCall('setSQLLogger', array($logger));
|
||||
}
|
||||
|
||||
// event manager
|
||||
|
@ -5,7 +5,8 @@
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<parameters>
|
||||
<parameter key="doctrine.dbal.logger.debug.class">Doctrine\DBAL\Logging\DebugStack</parameter>
|
||||
<parameter key="doctrine.dbal.logger.chain.class">Doctrine\DBAL\Logging\LoggerChain</parameter>
|
||||
<parameter key="doctrine.dbal.logger.profiling.class">Doctrine\DBAL\Logging\DebugStack</parameter>
|
||||
<parameter key="doctrine.dbal.logger.class">Symfony\Bridge\Doctrine\Logger\DbalLogger</parameter>
|
||||
<parameter key="doctrine.dbal.configuration.class">Doctrine\DBAL\Configuration</parameter>
|
||||
<parameter key="doctrine.data_collector.class">Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector</parameter>
|
||||
@ -19,7 +20,16 @@
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="doctrine.dbal.logger.debug" class="%doctrine.dbal.logger.debug.class%" public="false" />
|
||||
<service id="doctrine.dbal.logger.chain" class="%doctrine.dbal.logger.chain.class%" public="false">
|
||||
<call method="addLogger">
|
||||
<argument type="service" id="doctrine.dbal.logger" />
|
||||
</call>
|
||||
<call method="addLogger">
|
||||
<argument type="service" id="doctrine.dbal.logger.profiling" />
|
||||
</call>
|
||||
</service>
|
||||
|
||||
<service id="doctrine.dbal.logger.profiling" class="%doctrine.dbal.logger.profiling.class%" public="false" />
|
||||
|
||||
<service id="doctrine.dbal.logger" class="%doctrine.dbal.logger.class%" public="false">
|
||||
<tag name="monolog.logger" channel="doctrine" />
|
||||
@ -30,7 +40,7 @@
|
||||
<service id="data_collector.doctrine" class="%doctrine.data_collector.class%" public="false">
|
||||
<tag name="data_collector" template="DoctrineBundle:Collector:db" id="db" />
|
||||
<argument type="service" id="doctrine" />
|
||||
<argument type="service" id="doctrine.dbal.logger" />
|
||||
<argument type="service" id="doctrine.dbal.logger.profiling" />
|
||||
</service>
|
||||
|
||||
<service id="doctrine.dbal.connection_factory" class="%doctrine.dbal.connection_factory.class%">
|
||||
|
@ -29,6 +29,7 @@
|
||||
<xsd:attribute name="wrapper-class" type="xsd:string" />
|
||||
<xsd:attribute name="platform-service" type="xsd:string" />
|
||||
<xsd:attribute name="logging" type="xsd:string" default="false" />
|
||||
<xsd:attribute name="profiling" type="xsd:string" default="false" />
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:complexType name="dbal">
|
||||
|
@ -18,8 +18,9 @@ class ContainerTest extends TestCase
|
||||
public function testContainer()
|
||||
{
|
||||
$container = $this->createYamlBundleTestContainer();
|
||||
$this->assertInstanceOf('Doctrine\DBAL\Logging\DebugStack', $container->get('doctrine.dbal.logger.debug'));
|
||||
$this->assertInstanceOf('Doctrine\DBAL\Logging\DebugStack', $container->get('doctrine.dbal.logger'));
|
||||
$this->assertInstanceOf('Doctrine\DBAL\Logging\DebugStack', $container->get('doctrine.dbal.logger.profiling'));
|
||||
$this->assertInstanceOf('Doctrine\DBAL\Logging\LoggerChain', $container->get('doctrine.dbal.logger.chain'));
|
||||
$this->assertInstanceOf('Symfony\Bridge\Doctrine\Logger\DbalLogger', $container->get('doctrine.dbal.logger'));
|
||||
$this->assertInstanceOf('Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector', $container->get('data_collector.doctrine'));
|
||||
$this->assertInstanceOf('Doctrine\DBAL\Configuration', $container->get('doctrine.dbal.default_connection.configuration'));
|
||||
$this->assertInstanceOf('Doctrine\Common\EventManager', $container->get('doctrine.dbal.default_connection.event_manager'));
|
||||
|
@ -218,7 +218,6 @@ abstract class AbstractDoctrineExtensionTest extends TestCase
|
||||
'user' => 'root',
|
||||
'password' => null,
|
||||
'driver' => 'pdo_mysql',
|
||||
'logging' => false,
|
||||
'driverOptions' => array(),
|
||||
),
|
||||
new Reference('doctrine.dbal.default_connection.configuration'),
|
||||
@ -258,7 +257,6 @@ abstract class AbstractDoctrineExtensionTest extends TestCase
|
||||
'password' => 'sqlite_s3cr3t',
|
||||
'dbname' => 'sqlite_db',
|
||||
'memory' => true,
|
||||
'logging' => false,
|
||||
),
|
||||
new Reference('doctrine.dbal.default_connection.configuration'),
|
||||
new Reference('doctrine.dbal.default_connection.event_manager'),
|
||||
@ -337,6 +335,26 @@ abstract class AbstractDoctrineExtensionTest extends TestCase
|
||||
$this->assertEquals('%doctrine.orm.cache.array.class%', $definition->getClass());
|
||||
}
|
||||
|
||||
public function testLoadLogging()
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
$loader = new DoctrineExtension();
|
||||
$container->registerExtension($loader);
|
||||
|
||||
$this->loadFromFile($container, 'dbal_logging');
|
||||
|
||||
$this->compileContainer($container);
|
||||
|
||||
$definition = $container->getDefinition('doctrine.dbal.log_connection.configuration');
|
||||
$this->assertDICDefinitionMethodCallOnce($definition, 'setSQLLogger', array(new Reference('doctrine.dbal.logger')));
|
||||
|
||||
$definition = $container->getDefinition('doctrine.dbal.profile_connection.configuration');
|
||||
$this->assertDICDefinitionMethodCallOnce($definition, 'setSQLLogger', array(new Reference('doctrine.dbal.logger.profiling')));
|
||||
|
||||
$definition = $container->getDefinition('doctrine.dbal.both_connection.configuration');
|
||||
$this->assertDICDefinitionMethodCallOnce($definition, 'setSQLLogger', array(new Reference('doctrine.dbal.logger.chain')));
|
||||
}
|
||||
|
||||
public function testBundleEntityAliases()
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
|
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<srv:container xmlns="http://symfony.com/schema/dic/doctrine"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:srv="http://symfony.com/schema/dic/services"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd">
|
||||
|
||||
<config>
|
||||
<dbal default-connection="mysql">
|
||||
<connection
|
||||
name="log"
|
||||
logging="true"
|
||||
profiling="false" />
|
||||
<connection
|
||||
name="profile"
|
||||
logging="false"
|
||||
profiling="true" />
|
||||
<connection
|
||||
name="both"
|
||||
logging="true"
|
||||
profiling="true" />
|
||||
<connection
|
||||
name="none"
|
||||
logging="false"
|
||||
profiling="false" />
|
||||
</dbal>
|
||||
</config>
|
||||
</srv:container>
|
@ -0,0 +1,13 @@
|
||||
doctrine:
|
||||
dbal:
|
||||
default_connection: mysql
|
||||
connections:
|
||||
log:
|
||||
logging: true
|
||||
profiling: false
|
||||
profile:
|
||||
logging: false
|
||||
profiling: true
|
||||
both:
|
||||
logging: true
|
||||
profiling: true
|
@ -123,7 +123,7 @@ class DoctrineDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||
->method('getManagerNames')
|
||||
->will($this->returnValue(array('default' => 'doctrine.orm.default_entity_manager')));
|
||||
|
||||
$logger = $this->getMock('Symfony\Bridge\Doctrine\Logger\DbalLogger');
|
||||
$logger = $this->getMock('Doctrine\Dbal\Logging\DebugStack');
|
||||
$logger->queries = $queries;
|
||||
|
||||
return new DoctrineDataCollector($registry, $logger);
|
||||
|
Reference in New Issue
Block a user