Skip to content

Commit 40f5571

Browse files
committed
MAGETWO-67501: Enable/Disable DB query logging commands #9264
- Merge Pull Request #9264 from federivo/magento2:develop
2 parents c30a05a + 8209744 commit 40f5571

File tree

9 files changed

+664
-1
lines changed

9 files changed

+664
-1
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Developer\Console\Command;
8+
9+
use Symfony\Component\Console\Command\Command;
10+
use Symfony\Component\Console\Input\InputInterface;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
use Magento\Framework\App\DeploymentConfig\Writer;
13+
use Magento\Framework\Config\File\ConfigFilePool;
14+
use Magento\Framework\DB\Logger\LoggerProxy;
15+
16+
class QueryLogDisableCommand extends Command
17+
{
18+
/**
19+
* command name
20+
*/
21+
const COMMAND_NAME = 'dev:query-log:disable';
22+
23+
/**
24+
* Success message
25+
*/
26+
const SUCCESS_MESSAGE = "DB query logging disabled.";
27+
28+
/**
29+
* @var Writer
30+
*/
31+
private $deployConfigWriter;
32+
33+
/**
34+
* QueryLogDisableCommand constructor.
35+
* @param Writer $deployConfigWriter
36+
* @param null $name
37+
*/
38+
public function __construct(
39+
Writer $deployConfigWriter,
40+
$name = null
41+
) {
42+
parent::__construct($name);
43+
$this->deployConfigWriter = $deployConfigWriter;
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
protected function configure()
50+
{
51+
$this->setName(self::COMMAND_NAME)
52+
->setDescription('Disable DB query logging');
53+
54+
parent::configure();
55+
}
56+
57+
/**
58+
* {@inheritdoc}
59+
* @throws \InvalidArgumentException
60+
*/
61+
protected function execute(InputInterface $input, OutputInterface $output)
62+
{
63+
$data = [LoggerProxy::PARAM_ALIAS => LoggerProxy::LOGGER_ALIAS_DISABLED];
64+
$this->deployConfigWriter->saveConfig([ConfigFilePool::APP_ENV => [LoggerProxy::CONF_GROUP_NAME => $data]]);
65+
66+
$output->writeln("<info>". self::SUCCESS_MESSAGE . "</info>");
67+
}
68+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Developer\Console\Command;
8+
9+
use Magento\Framework\DB\Logger\LoggerProxy;
10+
use Symfony\Component\Console\Command\Command;
11+
use Symfony\Component\Console\Input\InputInterface;
12+
use Symfony\Component\Console\Input\InputOption;
13+
use Symfony\Component\Console\Output\OutputInterface;
14+
use Magento\Framework\App\DeploymentConfig\Writer;
15+
use Magento\Framework\Config\File\ConfigFilePool;
16+
17+
class QueryLogEnableCommand extends Command
18+
{
19+
/**
20+
* input parameter log-all-queries
21+
*/
22+
const INPUT_ARG_LOG_ALL_QUERIES = 'include-all-queries';
23+
24+
/**
25+
* input parameter log-query-time
26+
*/
27+
const INPUT_ARG_LOG_QUERY_TIME = 'query-time-threshold';
28+
29+
/**
30+
* input parameter log-call-stack
31+
*/
32+
const INPUT_ARG_LOG_CALL_STACK = 'include-call-stack';
33+
34+
/**
35+
* command name
36+
*/
37+
const COMMAND_NAME = 'dev:query-log:enable';
38+
39+
/**
40+
* Success message
41+
*/
42+
const SUCCESS_MESSAGE = "DB query logging enabled.";
43+
44+
/**
45+
* @var Writer
46+
*/
47+
private $deployConfigWriter;
48+
49+
/**
50+
* QueryLogEnableCommand constructor.
51+
* @param Writer $deployConfigWriter
52+
* @param null $name
53+
*/
54+
public function __construct(
55+
Writer $deployConfigWriter,
56+
$name = null
57+
) {
58+
parent::__construct($name);
59+
$this->deployConfigWriter = $deployConfigWriter;
60+
}
61+
62+
/**
63+
* {@inheritdoc}
64+
*/
65+
protected function configure()
66+
{
67+
$this->setName(self::COMMAND_NAME)
68+
->setDescription('Enable DB query logging')
69+
->setDefinition(
70+
[
71+
new InputOption(
72+
self::INPUT_ARG_LOG_ALL_QUERIES,
73+
null,
74+
InputOption::VALUE_OPTIONAL,
75+
'Log all queries. [true|false]',
76+
"true"
77+
),
78+
new InputOption(
79+
self::INPUT_ARG_LOG_QUERY_TIME,
80+
null,
81+
InputOption::VALUE_OPTIONAL,
82+
'Query time thresholds.',
83+
"0.001"
84+
),
85+
new InputOption(
86+
self::INPUT_ARG_LOG_CALL_STACK,
87+
null,
88+
InputOption::VALUE_OPTIONAL,
89+
'Include call stack. [true|false]',
90+
"true"
91+
),
92+
]
93+
);
94+
95+
parent::configure();
96+
}
97+
98+
/**
99+
* {@inheritdoc}
100+
* @throws \InvalidArgumentException
101+
*/
102+
protected function execute(InputInterface $input, OutputInterface $output)
103+
{
104+
$data = [LoggerProxy::PARAM_ALIAS => LoggerProxy::LOGGER_ALIAS_FILE];
105+
106+
$logAllQueries = $input->getOption(self::INPUT_ARG_LOG_ALL_QUERIES);
107+
$logQueryTime = $input->getOption(self::INPUT_ARG_LOG_QUERY_TIME);
108+
$logCallStack = $input->getOption(self::INPUT_ARG_LOG_CALL_STACK);
109+
110+
$data[LoggerProxy::PARAM_LOG_ALL] = (int)($logAllQueries != 'false');
111+
$data[LoggerProxy::PARAM_QUERY_TIME] = number_format($logQueryTime, 3);
112+
$data[LoggerProxy::PARAM_CALL_STACK] = (int)($logCallStack != 'false');
113+
114+
$configGroup[LoggerProxy::CONF_GROUP_NAME] = $data;
115+
116+
$this->deployConfigWriter->saveConfig([ConfigFilePool::APP_ENV => $configGroup]);
117+
118+
$output->writeln("<info>". self::SUCCESS_MESSAGE . "</info>");
119+
}
120+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Developer\Test\Unit\Console\Command;
8+
9+
use Magento\Developer\Console\Command\QueryLogDisableCommand;
10+
use Magento\Framework\App\DeploymentConfig\Writer;
11+
use Magento\Framework\Config\File\ConfigFilePool;
12+
use Magento\Framework\DB\Logger\LoggerProxy;
13+
use Symfony\Component\Console\Tester\CommandTester;
14+
15+
/**
16+
* Class QueryLogDisableCommandTest
17+
*
18+
* Tests dev:query-log:disable command.
19+
* Tests that the correct configuration is passed to the deployment config writer.
20+
*/
21+
class QueryLogDisableCommandTest extends \PHPUnit_Framework_TestCase
22+
{
23+
/**
24+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\DeploymentConfig\Writer
25+
*/
26+
private $configWriter;
27+
28+
/**
29+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Developer\Console\Command\QueryLogEnableCommand
30+
*/
31+
private $command;
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function setUp()
37+
{
38+
$this->configWriter = $this->getMockBuilder(Writer::class)
39+
->disableOriginalConstructor()
40+
->getMock();
41+
$this->command = new QueryLogDisableCommand($this->configWriter);
42+
}
43+
44+
/**
45+
* Test execute()
46+
*/
47+
public function testExecute()
48+
{
49+
$data = [LoggerProxy::PARAM_ALIAS => LoggerProxy::LOGGER_ALIAS_DISABLED];
50+
51+
$this->configWriter
52+
->expects($this->once())
53+
->method('saveConfig')
54+
->with([ConfigFilePool::APP_ENV => [LoggerProxy::CONF_GROUP_NAME => $data]]);
55+
56+
$commandTester = new CommandTester($this->command);
57+
$commandTester->execute([]);
58+
$this->assertSame(
59+
QueryLogDisableCommand::SUCCESS_MESSAGE . PHP_EOL,
60+
$commandTester->getDisplay()
61+
);
62+
}
63+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Developer\Test\Unit\Console\Command;
8+
9+
use Magento\Developer\Console\Command\QueryLogEnableCommand;
10+
use Magento\Framework\App\DeploymentConfig\Writer;
11+
use Magento\Framework\Config\File\ConfigFilePool;
12+
use Magento\Framework\DB\Logger\LoggerProxy;
13+
use Symfony\Component\Console\Tester\CommandTester;
14+
15+
/**
16+
* Class QueryLogEnableCommandTest
17+
*
18+
* Tests dev:query-log:enable command.
19+
* Tests that the correct configuration is passed to the deployment config writer with and without parameters.
20+
*/
21+
class QueryLogEnableCommandTest extends \PHPUnit_Framework_TestCase
22+
{
23+
/**
24+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\DeploymentConfig\Writer
25+
*/
26+
private $configWriter;
27+
28+
/**
29+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Developer\Console\Command\QueryLogEnableCommand
30+
*/
31+
private $command;
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function setUp()
37+
{
38+
$this->configWriter = $this->getMockBuilder(Writer::class)
39+
->disableOriginalConstructor()
40+
->getMock();
41+
$this->command = new QueryLogEnableCommand($this->configWriter);
42+
}
43+
44+
/**
45+
* Test execute() without parameters.
46+
*/
47+
public function testExecuteWithNoParams()
48+
{
49+
$data = [LoggerProxy::PARAM_ALIAS => LoggerProxy::LOGGER_ALIAS_FILE];
50+
$data[LoggerProxy::PARAM_LOG_ALL] = 1;
51+
$data[LoggerProxy::PARAM_QUERY_TIME] = 0.001;
52+
$data[LoggerProxy::PARAM_CALL_STACK] = 1;
53+
54+
$this->configWriter = $this->getMockBuilder(Writer::class)
55+
->disableOriginalConstructor()
56+
->getMock();
57+
$this->configWriter
58+
->expects($this->any())
59+
->method('saveConfig')
60+
->with([ConfigFilePool::APP_ENV => [LoggerProxy::CONF_GROUP_NAME => $data]]);
61+
62+
$commandTester = new CommandTester($this->command);
63+
$commandTester->execute([]);
64+
$this->assertSame(
65+
QueryLogEnableCommand::SUCCESS_MESSAGE . PHP_EOL,
66+
$commandTester->getDisplay()
67+
);
68+
}
69+
70+
/**
71+
* Test execute() with parameters.
72+
*/
73+
public function testExecuteWithParams()
74+
{
75+
$data = [LoggerProxy::PARAM_ALIAS => LoggerProxy::LOGGER_ALIAS_FILE];
76+
$data[LoggerProxy::PARAM_LOG_ALL] = 0;
77+
$data[LoggerProxy::PARAM_QUERY_TIME] = '0.05';
78+
$data[LoggerProxy::PARAM_CALL_STACK] = 0;
79+
80+
$this->configWriter = $this->getMockBuilder(Writer::class)
81+
->disableOriginalConstructor()
82+
->getMock();
83+
$this->configWriter
84+
->expects($this->any())
85+
->method('saveConfig')
86+
->with([ConfigFilePool::APP_ENV => [LoggerProxy::CONF_GROUP_NAME => $data]]);
87+
88+
$commandTester = new CommandTester($this->command);
89+
$commandTester->execute(
90+
[
91+
'--include-all-queries' => 'false',
92+
'--include-call-stack' => 'false',
93+
'--query-time-threshold' => '0.05',
94+
]
95+
);
96+
$this->assertSame(
97+
QueryLogEnableCommand::SUCCESS_MESSAGE . PHP_EOL,
98+
$commandTester->getDisplay()
99+
);
100+
}
101+
}

app/code/Magento/Developer/etc/di.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
<item name="xml_converter" xsi:type="object">Magento\Developer\Console\Command\XmlConverterCommand</item>
9999
<item name="xml_catalog_generator" xsi:type="object">Magento\Developer\Console\Command\XmlCatalogGenerateCommand</item>
100100
<item name="dev_di_info" xsi:type="object">Magento\Developer\Console\Command\DiInfoCommand</item>
101+
<item name="dev_query_log_enable" xsi:type="object">Magento\Developer\Console\Command\QueryLogEnableCommand</item>
102+
<item name="dev_query_log_disable" xsi:type="object">Magento\Developer\Console\Command\QueryLogDisableCommand</item>
101103
</argument>
102104
</arguments>
103105
</type>

app/etc/di.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
<preference for="Magento\Framework\Api\MetadataObjectInterface" type="Magento\Framework\Api\AttributeMetadata"/>
103103
<preference for="Magento\Framework\Api\SearchCriteriaInterface" type="Magento\Framework\Api\SearchCriteria"/>
104104
<preference for="Magento\Framework\App\Rss\UrlBuilderInterface" type="Magento\Framework\App\Rss\UrlBuilder"/>
105-
<preference for="Magento\Framework\DB\LoggerInterface" type="Magento\Framework\DB\Logger\Quiet"/>
105+
<preference for="Magento\Framework\DB\LoggerInterface" type="Magento\Framework\DB\Logger\LoggerProxy"/>
106106
<preference for="Magento\Framework\App\ResourceConnection\ConnectionAdapterInterface" type="Magento\Framework\Model\ResourceModel\Type\Db\Pdo\Mysql"/>
107107
<preference for="Magento\Framework\DB\QueryInterface" type="Magento\Framework\DB\Query"/>
108108
<preference for="Magento\Framework\App\ProductMetadataInterface" type="Magento\Framework\App\ProductMetadata"/>
@@ -1318,4 +1318,13 @@
13181318
</argument>
13191319
</arguments>
13201320
</type>
1321+
<type name="Magento\Framework\DB\Logger\LoggerProxy">
1322+
<arguments>
1323+
<argument name="loggerAlias" xsi:type="init_parameter">Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_OUTPUT</argument>
1324+
<argument name="logAllQueries" xsi:type="init_parameter">Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_LOG_EVERYTHING</argument>
1325+
<argument name="logQueryTime" xsi:type="init_parameter">Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_QUERY_TIME_THRESHOLD</argument>
1326+
<argument name="logCallStack" xsi:type="init_parameter">Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_INCLUDE_STACKTRACE</argument>
1327+
</arguments>
1328+
</type>
1329+
13211330
</config>

lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class ConfigOptionsListConstants
3030
const CONFIG_PATH_DB = 'db';
3131
const CONFIG_PATH_RESOURCE = 'resource';
3232
const CONFIG_PATH_CACHE_TYPES = 'cache_types';
33+
const CONFIG_PATH_DB_LOGGER_OUTPUT = 'db_logger/output';
34+
const CONFIG_PATH_DB_LOGGER_LOG_EVERYTHING = 'db_logger/log_everything';
35+
const CONFIG_PATH_DB_LOGGER_QUERY_TIME_THRESHOLD = 'db_logger/query_time_threshold';
36+
const CONFIG_PATH_DB_LOGGER_INCLUDE_STACKTRACE = 'db_logger/include_stacktrace';
3337
/**#@-*/
3438

3539
/**#@+

0 commit comments

Comments
 (0)