Fix issue with logging scopes

Logging scopes should be exclusive and not allow messages matching on
level alone to be logged.  By using scopes + levels you opt-in to new
behavior so grabbing all messages by level should not occur.

Fixes #3264
This commit is contained in:
mark_story 2012-10-08 12:57:02 -04:00
parent a59db11e4e
commit 72f4d4fac0
2 changed files with 55 additions and 31 deletions

View file

@ -426,24 +426,29 @@ class CakeLog {
$logged = false; $logged = false;
foreach (self::$_Collection->enabled() as $streamName) { foreach (self::$_Collection->enabled() as $streamName) {
$logger = self::$_Collection->{$streamName}; $logger = self::$_Collection->{$streamName};
$types = null; $types = $scopes = $config = array();
$scopes = array();
if ($logger instanceof BaseLog) { if ($logger instanceof BaseLog) {
$config = $logger->config(); $config = $logger->config();
}
if (isset($config['types'])) { if (isset($config['types'])) {
$types = $config['types']; $types = $config['types'];
} }
if (isset($config['scopes'])) { if (isset($config['scopes'])) {
$scopes = $config['scopes']; $scopes = $config['scopes'];
} }
} $inScope = (count(array_intersect((array)$scope, $scopes)) > 0);
if (is_string($scope)) { $correctLevel = in_array($type, $types);
$inScope = in_array($scope, $scopes);
} else { if (
$intersect = array_intersect($scope, $scopes); // No config is a catch all (bc mode)
$inScope = !empty($intersect); (empty($types) && empty($scopes)) ||
} // BC layer for mixing scope & level
if (empty($types) || in_array($type, $types) || in_array($type, $scopes) && $inScope) { (in_array($type, $scopes)) ||
// no scopes, but has level
(empty($scopes) && $correctLevel) ||
// exact scope + level
($correctLevel && $inScope)
) {
$logger->write($type, $message); $logger->write($type, $message);
$logged = true; $logged = true;
} }

View file

@ -331,21 +331,22 @@ class CakeLogTest extends CakeTestCase {
/** /**
* test backward compatible scoped logging * test backward compatible scoped logging
*
* @return void
*/ */
public function testScopedLoggingBC() { public function testScopedLoggingBC() {
$this->_deleteLogs();
$this->_resetLogConfig(); $this->_resetLogConfig();
CakeLog::config('shops', array( CakeLog::config('shops', array(
'engine' => 'FileLog', 'engine' => 'FileLog',
'types' => array('info', 'notice', 'warning'), 'types' => array('info', 'notice', 'warning'),
'scopes' => array('transactions', 'orders'), 'scopes' => array('transactions', 'orders'),
'file' => 'shops', 'file' => 'shops',
)); ));
$this->_deleteLogs();
CakeLog::write('info', 'info message'); CakeLog::write('info', 'info message');
$this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'error.log'));
$this->assertTrue(file_exists(LOGS . 'shops.log'));
$this->assertTrue(file_exists(LOGS . 'debug.log')); $this->assertTrue(file_exists(LOGS . 'debug.log'));
$this->_deleteLogs(); $this->_deleteLogs();
@ -375,7 +376,6 @@ class CakeLogTest extends CakeTestCase {
CakeLog::write('warning', 'warning message'); CakeLog::write('warning', 'warning message');
$this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertTrue(file_exists(LOGS . 'error.log'));
$this->assertTrue(file_exists(LOGS . 'shops.log'));
$this->assertFalse(file_exists(LOGS . 'debug.log')); $this->assertFalse(file_exists(LOGS . 'debug.log'));
$this->_deleteLogs(); $this->_deleteLogs();
@ -383,28 +383,47 @@ class CakeLogTest extends CakeTestCase {
CakeLog::drop('shops'); CakeLog::drop('shops');
} }
public function testScopedLoggingExclusive() {
$this->_deleteLogs();
CakeLog::config('shops', array(
'engine' => 'FileLog',
'types' => array('info', 'notice', 'warning'),
'scopes' => array('transactions', 'orders'),
'file' => 'shops.log',
));
CakeLog::config('eggs', array(
'engine' => 'FileLog',
'types' => array('info', 'notice', 'warning'),
'scopes' => array('eggs'),
'file' => 'eggs.log',
));
CakeLog::write('info', 'transactions message', 'transactions');
$this->assertFalse(file_exists(LOGS . 'eggs.log'));
$this->assertTrue(file_exists(LOGS . 'shops.log'));
$this->_deleteLogs();
CakeLog::write('info', 'eggs message', 'eggs');
$this->assertTrue(file_exists(LOGS . 'eggs.log'));
$this->assertFalse(file_exists(LOGS . 'shops.log'));
}
/** /**
* test scoped logging * test scoped logging
* *
* @return void * @return void
*/ */
public function testScopedLogging() { public function testScopedLogging() {
if (file_exists(LOGS . 'shops.log')) {
unlink(LOGS . 'shops.log');
}
if (file_exists(LOGS . 'error.log')) {
unlink(LOGS . 'error.log');
}
if (file_exists(LOGS . 'debug.log')) {
unlink(LOGS . 'debug.log');
}
$this->_resetLogConfig(); $this->_resetLogConfig();
$this->_deleteLogs();
CakeLog::config('shops', array( CakeLog::config('shops', array(
'engine' => 'FileLog', 'engine' => 'FileLog',
'types' => array('info', 'notice', 'warning'), 'types' => array('info', 'notice', 'warning'),
'scopes' => array('transactions', 'orders'), 'scopes' => array('transactions', 'orders'),
'file' => 'shops', 'file' => 'shops.log',
)); ));
CakeLog::write('info', 'info message', 'transactions'); CakeLog::write('info', 'info message', 'transactions');