mirror of
https://github.com/maximebf/php-debugbar.git
synced 2025-01-17 05:18:32 +01:00
Merge pull request #224 from Big-Shark/propel2
Added propel2 collector and tests
This commit is contained in:
commit
6812102772
307
src/DebugBar/Bridge/Propel2Collector.php
Normal file
307
src/DebugBar/Bridge/Propel2Collector.php
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the DebugBar package.
|
||||||
|
*
|
||||||
|
* (c) 2013 Maxime Bouroumeau-Fuseau
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DebugBar\Bridge;
|
||||||
|
|
||||||
|
use DebugBar\DataCollector\AssetProvider;
|
||||||
|
use DebugBar\DataCollector\DataCollector;
|
||||||
|
use DebugBar\DataCollector\Renderable;
|
||||||
|
use Monolog\Handler\TestHandler;
|
||||||
|
use Monolog\Logger;
|
||||||
|
use Propel\Runtime\Connection\ConnectionInterface;
|
||||||
|
use Propel\Runtime\Connection\ProfilerConnectionWrapper;
|
||||||
|
use Propel\Runtime\Propel;
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Propel logger which acts as a data collector
|
||||||
|
*
|
||||||
|
* http://propelorm.org/
|
||||||
|
*
|
||||||
|
* Will log queries and display them using the SQLQueries widget.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* <code>
|
||||||
|
* $debugbar->addCollector(new \DebugBar\Bridge\Propel2Collector(\Propel\Runtime\Propel::getServiceContainer()->getReadConnection()));
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
class Propel2Collector extends DataCollector implements Renderable, AssetProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var null|TestHandler
|
||||||
|
*/
|
||||||
|
protected $handler = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var null|Logger
|
||||||
|
*/
|
||||||
|
protected $logger = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $config = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $errors = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $queryCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ConnectionInterface $connection Propel connection
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ConnectionInterface $connection,
|
||||||
|
array $logMethods = array(
|
||||||
|
'beginTransaction',
|
||||||
|
'commit',
|
||||||
|
'rollBack',
|
||||||
|
'forceRollBack',
|
||||||
|
'exec',
|
||||||
|
'query',
|
||||||
|
'execute'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if ($connection instanceof ProfilerConnectionWrapper) {
|
||||||
|
$connection->setLogMethods($logMethods);
|
||||||
|
|
||||||
|
$this->config = $connection->getProfiler()->getConfiguration();
|
||||||
|
|
||||||
|
$this->handler = new TestHandler();
|
||||||
|
|
||||||
|
if ($connection->getLogger() instanceof Logger) {
|
||||||
|
$this->logger = $connection->getLogger();
|
||||||
|
$this->logger->pushHandler($this->handler);
|
||||||
|
} else {
|
||||||
|
$this->errors[] = 'Supported only monolog logger';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->errors[] = 'You need set ProfilerConnectionWrapper';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TestHandler|null
|
||||||
|
*/
|
||||||
|
public function getHandler()
|
||||||
|
{
|
||||||
|
return $this->handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getConfig()
|
||||||
|
{
|
||||||
|
return $this->config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Logger|null
|
||||||
|
*/
|
||||||
|
public function getLogger()
|
||||||
|
{
|
||||||
|
return $this->logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return LoggerInterface
|
||||||
|
*/
|
||||||
|
protected function getDefaultLogger()
|
||||||
|
{
|
||||||
|
return Propel::getServiceContainer()->getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function getQueryCount()
|
||||||
|
{
|
||||||
|
return $this->queryCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $records
|
||||||
|
* @param array $config
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getStatements($records, $config)
|
||||||
|
{
|
||||||
|
$statements = array();
|
||||||
|
foreach ($records as $record) {
|
||||||
|
$duration = null;
|
||||||
|
$memory = null;
|
||||||
|
|
||||||
|
$isSuccess = ( LogLevel::INFO === strtolower($record['level_name']) );
|
||||||
|
|
||||||
|
$detailsCount = count($config['details']);
|
||||||
|
$parameters = explode($config['outerGlue'], $record['message'], $detailsCount + 1);
|
||||||
|
if (count($parameters) === ($detailsCount + 1)) {
|
||||||
|
$parameters = array_map('trim', $parameters);
|
||||||
|
$_details = array();
|
||||||
|
foreach (array_splice($parameters, 0, $detailsCount) as $string) {
|
||||||
|
list($key, $value) = array_map('trim', explode($config['innerGlue'], $string, 2));
|
||||||
|
$_details[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$details = array();
|
||||||
|
foreach ($config['details'] as $key => $detail) {
|
||||||
|
if (isset($_details[$detail['name']])) {
|
||||||
|
$value = $_details[$detail['name']];
|
||||||
|
if ('time' === $key) {
|
||||||
|
if (substr_count($value, 'ms')) {
|
||||||
|
$value = (float)$value / 1000;
|
||||||
|
} else {
|
||||||
|
$value = (float)$value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$suffixes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
|
||||||
|
$suffix = substr($value, -2);
|
||||||
|
$i = array_search($suffix, $suffixes, true);
|
||||||
|
$i = (false === $i) ? 0 : $i;
|
||||||
|
|
||||||
|
$value = ((float)$value) * pow(1024, $i);
|
||||||
|
}
|
||||||
|
$details[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($details['time'])) {
|
||||||
|
$duration = $details['time'];
|
||||||
|
}
|
||||||
|
if (isset($details['memDelta'])) {
|
||||||
|
$memory = $details['memDelta'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = end($parameters);
|
||||||
|
|
||||||
|
if ($isSuccess) {
|
||||||
|
$this->queryCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$message = $record['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$statement = array(
|
||||||
|
'sql' => $message,
|
||||||
|
'is_success' => $isSuccess,
|
||||||
|
'duration' => $duration,
|
||||||
|
'duration_str' => $this->getDataFormatter()->formatDuration($duration),
|
||||||
|
'memory' => $memory,
|
||||||
|
'memory_str' => $this->getDataFormatter()->formatBytes($memory),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (false === $isSuccess) {
|
||||||
|
$statement['sql'] = '';
|
||||||
|
$statement['error_code'] = $record['level'];
|
||||||
|
$statement['error_message'] = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
$statements[] = $statement;
|
||||||
|
}
|
||||||
|
return $statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function collect()
|
||||||
|
{
|
||||||
|
if (count($this->errors)) {
|
||||||
|
return array(
|
||||||
|
'statements' => array_map(function ($message) {
|
||||||
|
return array('sql' => '', 'is_success' => false, 'error_code' => 500, 'error_message' => $message);
|
||||||
|
}, $this->errors),
|
||||||
|
'nb_statements' => 0,
|
||||||
|
'nb_failed_statements' => count($this->errors),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getHandler() === null) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$statements = $this->getStatements($this->getHandler()->getRecords(), $this->getConfig());
|
||||||
|
|
||||||
|
$failedStatement = count(array_filter($statements, function ($statement) {
|
||||||
|
return false === $statement['is_success'];
|
||||||
|
}));
|
||||||
|
$accumulatedDuration = array_reduce($statements, function ($accumulatedDuration, $statement) {
|
||||||
|
|
||||||
|
$time = isset($statement['duration']) ? $statement['duration'] : 0;
|
||||||
|
return $accumulatedDuration += $time;
|
||||||
|
});
|
||||||
|
$memoryUsage = array_reduce($statements, function ($memoryUsage, $statement) {
|
||||||
|
|
||||||
|
$time = isset($statement['memory']) ? $statement['memory'] : 0;
|
||||||
|
return $memoryUsage += $time;
|
||||||
|
});
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'nb_statements' => $this->getQueryCount(),
|
||||||
|
'nb_failed_statements' => $failedStatement,
|
||||||
|
'accumulated_duration' => $accumulatedDuration,
|
||||||
|
'accumulated_duration_str' => $this->getDataFormatter()->formatDuration($accumulatedDuration),
|
||||||
|
'memory_usage' => $memoryUsage,
|
||||||
|
'memory_usage_str' => $this->getDataFormatter()->formatBytes($memoryUsage),
|
||||||
|
'statements' => $statements
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
$additionalName = '';
|
||||||
|
if ($this->getLogger() !== $this->getDefaultLogger()) {
|
||||||
|
$additionalName = ' ('.$this->getLogger()->getName().')';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'propel2'.$additionalName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getWidgets()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
$this->getName() => array(
|
||||||
|
'icon' => 'bolt',
|
||||||
|
'widget' => 'PhpDebugBar.Widgets.SQLQueriesWidget',
|
||||||
|
'map' => $this->getName(),
|
||||||
|
'default' => '[]'
|
||||||
|
),
|
||||||
|
$this->getName().':badge' => array(
|
||||||
|
'map' => $this->getName().'.nb_statements',
|
||||||
|
'default' => 0
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAssets()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'css' => 'widgets/sqlqueries/widget.css',
|
||||||
|
'js' => 'widgets/sqlqueries/widget.js'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
239
tests/DebugBar/Tests/DataCollector/Propel2CollectorTest.php
Normal file
239
tests/DebugBar/Tests/DataCollector/Propel2CollectorTest.php
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DebugBar\Tests\DataCollector;
|
||||||
|
|
||||||
|
use DebugBar\DataFormatter\DataFormatter;
|
||||||
|
use DebugBar\Tests\DebugBarTestCase;
|
||||||
|
|
||||||
|
class Propel2CollectorTest extends DebugBarTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var null|\PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
protected $stub = null;
|
||||||
|
/* @var null|DataFormatter */
|
||||||
|
protected $dataFormatter = null;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$config = array(
|
||||||
|
'slowTreshold' => 0.1,
|
||||||
|
'details' => array(
|
||||||
|
'time' => array(
|
||||||
|
'name' => 'Time',
|
||||||
|
'precision' => 3,
|
||||||
|
'pad' => 8,
|
||||||
|
),
|
||||||
|
'mem' => array(
|
||||||
|
'name' => 'Memory',
|
||||||
|
'precision' => 3,
|
||||||
|
'pad' => 8,
|
||||||
|
),
|
||||||
|
'memDelta' => array(
|
||||||
|
'name' => 'Memory Delta',
|
||||||
|
'precision' => 3,
|
||||||
|
'pad' => 8,
|
||||||
|
),
|
||||||
|
'memPeak' => array(
|
||||||
|
'name' => 'Memory Peak',
|
||||||
|
'precision' => 3,
|
||||||
|
'pad' => 8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'innerGlue' => ': ',
|
||||||
|
'outerGlue' => ' | ',
|
||||||
|
);
|
||||||
|
|
||||||
|
$stub = $this->getMockBuilder('DebugBar\Bridge\Propel2Collector')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->setMethods(array('getDataFormatter', 'getHandler', 'getConfig'))
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$this->dataFormatter = new DataFormatter();
|
||||||
|
|
||||||
|
$stub->method('getDataFormatter')->willReturn($this->dataFormatter);
|
||||||
|
|
||||||
|
$stub->method('getConfig')->willReturn($config);
|
||||||
|
|
||||||
|
$this->stub = $stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function equals($correctResult, $record)
|
||||||
|
{
|
||||||
|
$this->stub->method('getHandler')->willReturn(new MockHandler($record));
|
||||||
|
$this->assertEquals($correctResult, $this->stub->collect());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSimpleMessage()
|
||||||
|
{
|
||||||
|
$record = array(
|
||||||
|
'message' => 'Simple message',
|
||||||
|
'context' => 'propel',
|
||||||
|
'level' => 200,
|
||||||
|
'level_name' => 'INFO',
|
||||||
|
'channel' => 'propel',
|
||||||
|
'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
|
||||||
|
'extra' => array(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$correctResult = array(
|
||||||
|
'nb_statements' => 0,
|
||||||
|
'nb_failed_statements' => 0,
|
||||||
|
'accumulated_duration' => 0,
|
||||||
|
'accumulated_duration_str' => $this->dataFormatter->formatDuration(0),
|
||||||
|
'memory_usage' => 0,
|
||||||
|
'memory_usage_str' => $this->dataFormatter->formatBytes(0),
|
||||||
|
'statements' => array(
|
||||||
|
array(
|
||||||
|
'sql' => 'Simple message',
|
||||||
|
'is_success' => true,
|
||||||
|
'duration' => null,
|
||||||
|
'duration_str' => $this->dataFormatter->formatDuration(0),
|
||||||
|
'memory' => null,
|
||||||
|
'memory_str' => $this->dataFormatter->formatBytes(0),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->equals($correctResult, array($record));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testErrorMessage()
|
||||||
|
{
|
||||||
|
$record = array(
|
||||||
|
'message' => 'Error message',
|
||||||
|
'context' => 'propel',
|
||||||
|
'level' => 500,
|
||||||
|
'level_name' => 'critical',
|
||||||
|
'channel' => 'propel',
|
||||||
|
'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
|
||||||
|
'extra' => array(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$correctResult = array(
|
||||||
|
'nb_statements' => 0,
|
||||||
|
'nb_failed_statements' => 1,
|
||||||
|
'accumulated_duration' => 0,
|
||||||
|
'accumulated_duration_str' => $this->dataFormatter->formatDuration(0),
|
||||||
|
'memory_usage' => 0,
|
||||||
|
'memory_usage_str' => $this->dataFormatter->formatBytes(0),
|
||||||
|
'statements' => array(
|
||||||
|
array(
|
||||||
|
'sql' => '',
|
||||||
|
'is_success' => false,
|
||||||
|
'error_code' => 500,
|
||||||
|
'error_message' => 'Error message',
|
||||||
|
'duration' => null,
|
||||||
|
'duration_str' => $this->dataFormatter->formatDuration(0),
|
||||||
|
'memory' => null,
|
||||||
|
'memory_str' => $this->dataFormatter->formatBytes(0),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->equals($correctResult, array($record));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProfileMessage()
|
||||||
|
{
|
||||||
|
$record = array(
|
||||||
|
'message' => ' Time: 0.100ms | Memory: 1MB | Memory Delta: +1.0kB | Memory Peak: 2MB | SELECT id, first_name, last_name FROM author WHERE id = 1',
|
||||||
|
'context' => 'propel',
|
||||||
|
'level' => 200,
|
||||||
|
'level_name' => 'info',
|
||||||
|
'channel' => 'propel',
|
||||||
|
'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
|
||||||
|
'extra' => array(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$correctResult = array(
|
||||||
|
'nb_statements' => 1,
|
||||||
|
'nb_failed_statements' => 0,
|
||||||
|
'accumulated_duration' => 0.0001,
|
||||||
|
'accumulated_duration_str' => $this->dataFormatter->formatDuration(0.0001),
|
||||||
|
'memory_usage' => 1024.0,
|
||||||
|
'memory_usage_str' => $this->dataFormatter->formatBytes(1024.0),
|
||||||
|
'statements' => array(
|
||||||
|
array(
|
||||||
|
'sql' => 'SELECT id, first_name, last_name FROM author WHERE id = 1',
|
||||||
|
'is_success' => true,
|
||||||
|
'duration' => 0.0001,
|
||||||
|
'duration_str' => $this->dataFormatter->formatDuration(0.0001),
|
||||||
|
'memory' => 1024.0,
|
||||||
|
'memory_str' => $this->dataFormatter->formatBytes(1024.0),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->equals($correctResult, array($record));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSummaryProfileMessage()
|
||||||
|
{
|
||||||
|
$records = array(
|
||||||
|
array(
|
||||||
|
'message' => ' Time: 0.100ms | Memory: 1MB | Memory Delta: +1.0kB | Memory Peak: 2MB | SELECT id, first_name, last_name FROM author WHERE id = 1',
|
||||||
|
'context' => 'propel',
|
||||||
|
'level' => 200,
|
||||||
|
'level_name' => 'info',
|
||||||
|
'channel' => 'propel',
|
||||||
|
'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
|
||||||
|
'extra' => array(),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'message' => ' Time: 0.100ms | Memory: 1MB | Memory Delta: +1.0kB | Memory Peak: 2MB | SELECT id, first_name, last_name FROM author WHERE id = 1',
|
||||||
|
'context' => 'propel',
|
||||||
|
'level' => 200,
|
||||||
|
'level_name' => 'info',
|
||||||
|
'channel' => 'propel',
|
||||||
|
'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
|
||||||
|
'extra' => array(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$correctResult = array(
|
||||||
|
'nb_statements' => 2,
|
||||||
|
'nb_failed_statements' => 0,
|
||||||
|
'accumulated_duration' => 0.0002,
|
||||||
|
'accumulated_duration_str' => $this->dataFormatter->formatDuration(0.0002),
|
||||||
|
'memory_usage' => 2048,
|
||||||
|
'memory_usage_str' => $this->dataFormatter->formatBytes(2048),
|
||||||
|
'statements' => array(
|
||||||
|
array(
|
||||||
|
'sql' => 'SELECT id, first_name, last_name FROM author WHERE id = 1',
|
||||||
|
'is_success' => true,
|
||||||
|
'duration' => 0.0001,
|
||||||
|
'duration_str' => $this->dataFormatter->formatDuration(0.0001),
|
||||||
|
'memory' => 1024.0,
|
||||||
|
'memory_str' => $this->dataFormatter->formatBytes(1024.0),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sql' => 'SELECT id, first_name, last_name FROM author WHERE id = 1',
|
||||||
|
'is_success' => true,
|
||||||
|
'duration' => 0.0001,
|
||||||
|
'duration_str' => $this->dataFormatter->formatDuration(0.0001),
|
||||||
|
'memory' => 1024.0,
|
||||||
|
'memory_str' => $this->dataFormatter->formatBytes(1024.0),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->equals($correctResult, $records);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $records = array();
|
||||||
|
public function __construct($records)
|
||||||
|
{
|
||||||
|
$this->records = $records;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRecords()
|
||||||
|
{
|
||||||
|
return $this->records;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user