From 6040d967108149e734cf4a1ef5cc8bcad2945f2c Mon Sep 17 00:00:00 2001 From: Rachman Chavik Date: Thu, 10 May 2012 22:40:23 +0700 Subject: [PATCH] adding scoped logging --- lib/Cake/Log/CakeLog.php | 19 +++- lib/Cake/Log/Engine/ConsoleLog.php | 1 + lib/Cake/Log/Engine/FileLog.php | 3 + lib/Cake/Test/Case/Log/CakeLogTest.php | 148 +++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Log/CakeLog.php b/lib/Cake/Log/CakeLog.php index 000f18106..5ccaaa546 100644 --- a/lib/Cake/Log/CakeLog.php +++ b/lib/Cake/Log/CakeLog.php @@ -249,11 +249,14 @@ class CakeLog { * * `CakeLog::write('warning', 'Stuff is broken here');` * - * @param string $type Type of message being written + * @param mixed $type Type of message being written. When value is an integer + * or a string matching the recognized levels, then it will + * be treated log levels. Otherwise it's treated as scope. * @param string $message Message content to log + * @param mixed $scope string or array * @return boolean Success */ - public static function write($type, $message) { + public static function write($type, $message, $scope = array()) { if (empty(self::$_Collection)) { self::_init(); } @@ -269,6 +272,9 @@ class CakeLog { if (is_int($type) && isset($levels[$type])) { $type = $levels[$type]; } + if (is_string($type) && empty($scope) && !in_array($type, $levels)) { + $scope = $type; + } if (empty(self::$_streams)) { self::_autoConfig(); } @@ -276,7 +282,14 @@ class CakeLog { $logger = self::$_Collection->{$streamName}; $config = $logger->config(); $types = $config['types']; - if (empty($types) || in_array($type, $types)) { + $scopes = $config['scopes']; + if (is_string($scope)) { + $inScope = in_array($scope, $scopes); + } else { + $intersect = array_intersect($scope, $scopes); + $inScope = !empty($intersect); + } + if (empty($types) || in_array($type, $types) || in_array($type, $scopes) && $inScope) { $logger->write($type, $message); } } diff --git a/lib/Cake/Log/Engine/ConsoleLog.php b/lib/Cake/Log/Engine/ConsoleLog.php index f3eb32f02..518a8e445 100644 --- a/lib/Cake/Log/Engine/ConsoleLog.php +++ b/lib/Cake/Log/Engine/ConsoleLog.php @@ -50,6 +50,7 @@ class ConsoleLog extends BaseLog { $config = Set::merge(array( 'stream' => 'php://stderr', 'types' => null, + 'scopes' => array(), 'outputAs' => ConsoleOutput::COLOR, ), $this->_config); $config = $this->config($config); diff --git a/lib/Cake/Log/Engine/FileLog.php b/lib/Cake/Log/Engine/FileLog.php index 0d8f73082..7ab738c1e 100644 --- a/lib/Cake/Log/Engine/FileLog.php +++ b/lib/Cake/Log/Engine/FileLog.php @@ -49,6 +49,7 @@ class FileLog extends BaseLog { 'path' => LOGS, 'file' => null, 'types' => null, + 'scopes' => array(), ), $this->_config); $config = $this->config($config); $this->_path = $config['path']; @@ -74,6 +75,8 @@ class FileLog extends BaseLog { $filename = $this->_path . 'error.log'; } elseif (in_array($type, $debugTypes)) { $filename = $this->_path . 'debug.log'; + } elseif (in_array($type, $this->_config['scopes'])) { + $filename = $this->_path . $this->_file; } else { $filename = $this->_path . $type . '.log'; } diff --git a/lib/Cake/Test/Case/Log/CakeLogTest.php b/lib/Cake/Test/Case/Log/CakeLogTest.php index 51ff63dbd..7eec36f4b 100644 --- a/lib/Cake/Test/Case/Log/CakeLogTest.php +++ b/lib/Cake/Test/Case/Log/CakeLogTest.php @@ -281,4 +281,152 @@ class CakeLogTest extends CakeTestCase { CakeLog::disable('bogus_stream'); } + protected function _deleteLogs() { + @unlink(LOGS . 'shops.log'); + @unlink(LOGS . 'error.log'); + @unlink(LOGS . 'debug.log'); + } + +/** + * test backward compatible scoped logging + */ + public function testScopedLoggingBC() { + 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'); + } + + CakeLog::config('debug', array( + 'engine' => 'FileLog', + 'types' => array('notice', 'info', 'debug'), + 'file' => 'debug', + )); + CakeLog::config('error', array( + 'engine' => 'FileLog', + 'types' => array('error', 'warning'), + 'file' => 'error', + )); + CakeLog::config('shops', array( + 'engine' => 'FileLog', + 'types' => array('info', 'notice', 'warning'), + 'scopes' => array('transactions', 'orders'), + 'file' => 'shops', + )); + + CakeLog::write('info', 'info message'); + $this->assertFalse(file_exists(LOGS . 'error.log')); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + $this->assertTrue(file_exists(LOGS . 'debug.log')); + + $this->_deleteLogs(); + + CakeLog::write('transactions', 'transaction message'); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + $this->assertFalse(file_exists(LOGS . 'transactions.log')); + $this->assertFalse(file_exists(LOGS . 'error.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + + $this->_deleteLogs(); + + CakeLog::write('error', 'error message'); + $this->assertTrue(file_exists(LOGS . 'error.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + $this->assertFalse(file_exists(LOGS . 'shops.log')); + + $this->_deleteLogs(); + + CakeLog::write('orders', 'order message'); + $this->assertFalse(file_exists(LOGS . 'error.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + $this->assertFalse(file_exists(LOGS . 'orders.log')); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + + $this->_deleteLogs(); + + CakeLog::write('warning', 'warning message'); + $this->assertTrue(file_exists(LOGS . 'error.log')); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + + $this->_deleteLogs(); + + CakeLog::drop('shops'); + } + +/** + * test scoped logging + */ + 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'); + } + + CakeLog::config('debug', array( + 'engine' => 'FileLog', + 'types' => array('notice', 'info', 'debug'), + 'file' => 'debug', + )); + CakeLog::config('error', array( + 'engine' => 'FileLog', + 'types' => array('error', 'warning'), + 'file' => 'error', + )); + CakeLog::config('shops', array( + 'engine' => 'FileLog', + 'types' => array('info', 'notice', 'warning'), + 'scopes' => array('transactions', 'orders'), + 'file' => 'shops', + )); + + CakeLog::write('info', 'info message', 'transactions'); + $this->assertFalse(file_exists(LOGS . 'error.log')); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + $this->assertTrue(file_exists(LOGS . 'debug.log')); + + $this->_deleteLogs(); + + CakeLog::write('transactions', 'transaction message', 'orders'); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + $this->assertFalse(file_exists(LOGS . 'transactions.log')); + $this->assertFalse(file_exists(LOGS . 'error.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + + $this->_deleteLogs(); + + CakeLog::write('error', 'error message', 'orders'); + $this->assertTrue(file_exists(LOGS . 'error.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + $this->assertFalse(file_exists(LOGS . 'shops.log')); + + $this->_deleteLogs(); + + CakeLog::write('orders', 'order message', 'transactions'); + $this->assertFalse(file_exists(LOGS . 'error.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + $this->assertFalse(file_exists(LOGS . 'orders.log')); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + + $this->_deleteLogs(); + + CakeLog::write('warning', 'warning message', 'orders'); + $this->assertTrue(file_exists(LOGS . 'error.log')); + $this->assertTrue(file_exists(LOGS . 'shops.log')); + $this->assertFalse(file_exists(LOGS . 'debug.log')); + + $this->_deleteLogs(); + + CakeLog::drop('shops'); + } + }