From 4d0070b9212198b92597e59fa87478d5232cdb9b Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 4 Mar 2014 14:46:32 +0800 Subject: [PATCH 1/2] [core] Split out Y.log tests from core tests --- src/yui/tests/unit/assets/core-tests.js | 238 -------------------- src/yui/tests/unit/assets/logging-test.js | 259 ++++++++++++++++++++++ src/yui/tests/unit/index-full.html | 7 +- src/yui/tests/unit/index-logging.html | 68 ++++++ src/yui/tests/unit/index-static.html | 9 +- src/yui/tests/unit/index.html | 7 +- 6 files changed, 346 insertions(+), 242 deletions(-) create mode 100644 src/yui/tests/unit/assets/logging-test.js create mode 100644 src/yui/tests/unit/index-logging.html diff --git a/src/yui/tests/unit/assets/core-tests.js b/src/yui/tests/unit/assets/core-tests.js index 7568efa65e5..47a1320d3ad 100644 --- a/src/yui/tests/unit/assets/core-tests.js +++ b/src/yui/tests/unit/assets/core-tests.js @@ -53,8 +53,6 @@ YUI.add('core-tests', function(Y) { ignore: { 'getLocation() should return the location object': (Y.UA.nodejs ? true : false), 'getLocation() should return `null` when executing in node.js': (!Y.UA.nodejs || (Y.UA.nodejs && Y.config.win)), //If there is a window object, ignore too - test_log_params: (typeof console == "undefined" || !console.info || Y.UA.nodejs), - test_log_default_category: (typeof console == "undefined" || !console.info || Y.UA.nodejs), 'test: domready delay': !Y.config.win, 'test: window.onload delay': !Y.config.win, 'test: contentready delay': !Y.config.win, @@ -267,242 +265,6 @@ YUI.add('core-tests', function(Y) { //Assert.areSame(info.filter, core_urls[i].filter, 'Filters do not match (' + core_urls[i].path + ')'); } }, - test_log_params: function() { - if (typeof console == "undefined" || !console.info) { - return; - } - var l = console.info, - Assert = Y.Assert, - last; - - // Override all of the console functions so that we can check - // their return values. - console.error = console.log = console.warn = console.debug = console.info = function(str) { - last = str.split(':')[0]; - }; - - YUI().use(function (Y) { - Y.applyConfig({ - logInclude: { - logMe: true, - butNotMe: false - } - }); - - Y.log('test logInclude logMe','info','logMe'); - Assert.areEqual(last, 'logMe', 'logInclude (true) Failed'); - last = undefined; - - Y.log('test logInclude butNotMe','info','butNotMe'); - Assert.isUndefined(last, 'logInclude (false) Failed'); - - Y.applyConfig({ - logInclude: '', - logExclude: { - excludeMe: true, - butDontExcludeMe: false - } - }); - Y.log('test logExclude excludeMe','info','excludeMe'); - Assert.isUndefined(last, 'excludeInclude (true) Failed'); - Y.log('test logExclude butDontExcludeMe','info','butDontExcludeMe'); - Assert.areEqual(last, 'butDontExcludeMe', 'logExclue (false) Failed'); - - Y.applyConfig({ - logInclude: { - davglass: true - }, - logExclude: { - '': true - } - }); - last = undefined; - Y.log('This should be ignored', 'info'); - Assert.isUndefined(last, 'Failed to exclude log param with empty string'); - Y.log('This should NOT be ignored', 'info', 'davglass'); - Assert.areEqual(last, 'davglass', 'Failed to include log param'); - - // Default logLevel is debug - Y.applyConfig({ - logInclude: { - 'logleveltest': true - } - }); - last = undefined; - Y.log('This should be logged', 'debug', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'info', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'warn', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'error', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - - // Debug should also take effect when actively specified - Y.applyConfig({ - logLevel: 'debug' - }); - last = undefined; - Y.log('This should be logged', 'debug', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'info', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'warn', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'error', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - - // An invalid log level has the same effect as 'debug' - Y.applyConfig({ - logLevel: 'invalidloglevel' - }); - last = undefined; - Y.log('This should be logged', 'debug', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'info', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'warn', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'error', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - - Y.applyConfig({ - logLevel: 'info' - }); - last = undefined; - Y.log('This should NOT be logged', 'debug', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold'); - last = undefined; - Y.log('This should be logged', 'info', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'warn', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'error', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - - Y.applyConfig({ - logLevel: 'warn' - }); - last = undefined; - Y.log('This should NOT be logged', 'debug', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold'); - last = undefined; - Y.log('This should NOT be logged', 'info', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold'); - last = undefined; - Y.log('This should be logged', 'warn', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - last = undefined; - Y.log('This should be logged', 'error', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - - Y.applyConfig({ - logLevel: 'error' - }); - last = undefined; - Y.log('This should NOT be logged', 'debug', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold'); - last = undefined; - Y.log('This should NOT be logged', 'info', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold'); - last = undefined; - Y.log('This should NOT be ignored', 'warn', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold'); - last = undefined; - Y.log('This should NOT be ignored', 'error', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - - Y.applyConfig({ - logLevel: 'ERROR' - }); - last = undefined; - Y.log('This should NOT be logged', 'debug', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold - case insensitivty possibly ignored'); - last = undefined; - Y.log('This should NOT be logged', 'info', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold - case insensitivty possibly ignored'); - last = undefined; - Y.log('This should NOT be ignored', 'warn', 'logleveltest'); - Assert.isUndefined(last, 'Failed to exclude log level below threshold - case insensitivty possibly ignored'); - last = undefined; - Y.log('This should NOT be ignored', 'error', 'logleveltest'); - Assert.areEqual(last, 'logleveltest', 'Failed to include log param'); - }); - - console.info = l; - }, - test_log_default_category: function() { - if (typeof console == "undefined" || !console.info) { - return; - } - var l = console.info, - Assert = Y.Assert, - consoleFn, - last, lastCategory; - - // Override all of the console functions so that we can check - // their return values. - consoleFn = function(str) { - last = str.split(':')[0]; - }; - console.error = function(str) { - lastCategory = 'error'; - consoleFn(str); - }; - console.log = function(str) { - lastCategory = 'log'; - consoleFn(str); - }; - console.warn = function(str) { - lastCategory = 'warn'; - consoleFn(str); - }; - console.debug = function(str) { - lastCategory = 'debug'; - consoleFn(str); - }; - console.info = function(str) { - lastCategory = 'info'; - consoleFn(str); - }; - - YUI().use(function (Y) { - Y.applyConfig({ - logLevel: 'debug' - }); - lastCategory = undefined; - Y.log('This has a valid log level', 'debug'); - Assert.areEqual(lastCategory, 'debug', 'Failed to log at debug log category'); - lastCategory = undefined; - Y.log('This has a valid log level', 'info'); - Assert.areEqual(lastCategory, 'info', 'Failed to log at info log category'); - lastCategory = undefined; - Y.log('This has a valid log level', 'warn'); - Assert.areEqual(lastCategory, 'warn', 'Failed to log at warn log category'); - lastCategory = undefined; - Y.log('This has a valid log level', 'error'); - Assert.areEqual(lastCategory, 'error', 'Failed to log at error log category'); - lastCategory = undefined; - Y.log('This has no log level and should use the default'); - Assert.areEqual(lastCategory, 'info', 'Failed to log at default log category of info'); - lastCategory = undefined; - Y.log('This has an invalid log level and should use the default', 'notice'); - Assert.areEqual(lastCategory, 'info', 'Failed to log at default info log category'); - }); - - console.info = l; - }, test_global_apply_config: function() { var Assert = Y.Assert, test = this; diff --git a/src/yui/tests/unit/assets/logging-test.js b/src/yui/tests/unit/assets/logging-test.js new file mode 100644 index 00000000000..9c93b4d99e8 --- /dev/null +++ b/src/yui/tests/unit/assets/logging-test.js @@ -0,0 +1,259 @@ +YUI.add('logging-test', function(Y) { + + YUI.GlobalConfig = YUI.GlobalConfig || {}; + + var lastSource, lastCategory, lastMessage, + stockFunctions = { + log: console.log, + debug: console.debug, + info: console.info, + warn: console.warn, + error: console.error + }; + + var testLogging = new Y.Test.Case({ + + name: "Logging tests", + _should: { + ignore: { + test_log_params: (typeof console == "undefined" || !console.info || Y.UA.nodejs), + test_log_default_category: (typeof console == "undefined" || !console.info || Y.UA.nodejs) + } + }, + + setUp: function() { + // Override all of the console functions so that we can check + // their return values. + var fnName, + // Note, this uses partial function binding so the level is first. + consoleFn = function(level, str) { + var splitString = str.split(':'); + lastCategory = level; + lastSource = splitString && splitString[0] || undefined; + lastMessage = splitString && splitString[1] || str; + }; + for (fnName in stockFunctions) { + console[fnName] = consoleFn.bind(undefined, fnName); + } + }, + + tearDown: function() { + var fnName; + for (fnName in stockFunctions) { + console[fnName] = stockFunctions[fnName]; + } + }, + + test_log_params: function() { + var Assert = Y.Assert; + + YUI().use(function (Y) { + Y.applyConfig({ + logInclude: { + logMe: true, + butNotMe: false + } + }); + + lastSource = undefined; + Y.log('test logInclude logMe','info','logMe'); + Assert.areEqual(lastSource, 'logMe', 'logInclude (true) Failed'); + + lastSource = undefined; + Y.log('test logInclude butNotMe','info','butNotMe'); + Assert.isUndefined(lastSource, 'logInclude (false) Failed'); + + Y.applyConfig({ + logInclude: '', + logExclude: { + excludeMe: true, + butDontExcludeMe: false + } + }); + + lastSource = undefined; + Y.log('test logExclude excludeMe','info','excludeMe'); + Assert.isUndefined(lastSource, 'excludeInclude (true) Failed'); + + lastSource = undefined; + Y.log('test logExclude butDontExcludeMe','info','butDontExcludeMe'); + Assert.areEqual(lastSource, 'butDontExcludeMe', 'logExclue (false) Failed'); + + Y.applyConfig({ + logInclude: { + davglass: true + }, + logExclude: { + '': true + } + }); + + lastSource = undefined; + Y.log('This should be ignored', 'info'); + Assert.isUndefined(lastSource, 'Failed to exclude log param with empty string'); + + lastSource = undefined; + Y.log('This should NOT be ignored', 'info', 'davglass'); + Assert.areEqual(lastSource, 'davglass', 'Failed to include log param'); + + // Default logLevel is debug + Y.applyConfig({ + logInclude: { + 'logleveltest': true + } + }); + + lastSource = undefined; + Y.log('This should be logged', 'debug', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'info', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'warn', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'error', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + // Debug should also take effect when actively specified + Y.applyConfig({ + logLevel: 'debug' + }); + lastSource = undefined; + Y.log('This should be logged', 'debug', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'info', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'warn', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'error', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + // An invalid log level has the same effect as 'debug' + Y.applyConfig({ + logLevel: 'invalidloglevel' + }); + + lastSource = undefined; + Y.log('This should be logged', 'debug', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'info', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'warn', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + lastSource = undefined; + Y.log('This should be logged', 'error', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + Y.applyConfig({ + logLevel: 'info' + }); + lastSource = undefined; + Y.log('This should NOT be logged', 'debug', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold'); + lastSource = undefined; + Y.log('This should be logged', 'info', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + lastSource = undefined; + Y.log('This should be logged', 'warn', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + lastSource = undefined; + Y.log('This should be logged', 'error', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + Y.applyConfig({ + logLevel: 'warn' + }); + lastSource = undefined; + Y.log('This should NOT be logged', 'debug', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold'); + lastSource = undefined; + Y.log('This should NOT be logged', 'info', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold'); + lastSource = undefined; + Y.log('This should be logged', 'warn', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + lastSource = undefined; + Y.log('This should be logged', 'error', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + Y.applyConfig({ + logLevel: 'error' + }); + lastSource = undefined; + Y.log('This should NOT be logged', 'debug', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold'); + lastSource = undefined; + Y.log('This should NOT be logged', 'info', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold'); + lastSource = undefined; + Y.log('This should NOT be ignored', 'warn', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold'); + lastSource = undefined; + Y.log('This should NOT be ignored', 'error', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + + Y.applyConfig({ + logLevel: 'ERROR' + }); + lastSource = undefined; + Y.log('This should NOT be logged', 'debug', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold - case insensitivty possibly ignored'); + lastSource = undefined; + Y.log('This should NOT be logged', 'info', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold - case insensitivty possibly ignored'); + lastSource = undefined; + Y.log('This should NOT be ignored', 'warn', 'logleveltest'); + Assert.isUndefined(lastSource, 'Failed to exclude log level below threshold - case insensitivty possibly ignored'); + lastSource = undefined; + Y.log('This should NOT be ignored', 'error', 'logleveltest'); + Assert.areEqual(lastSource, 'logleveltest', 'Failed to include log param'); + }); + }, + test_log_default_category: function() { + var Assert = Y.Assert; + + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'debug' + }); + lastCategory = undefined; + Y.log('This has a valid log level', 'debug'); + Assert.areEqual(lastCategory, 'debug', 'Failed to log at debug log category'); + lastCategory = undefined; + Y.log('This has a valid log level', 'info'); + Assert.areEqual(lastCategory, 'info', 'Failed to log at info log category'); + lastCategory = undefined; + Y.log('This has a valid log level', 'warn'); + Assert.areEqual(lastCategory, 'warn', 'Failed to log at warn log category'); + lastCategory = undefined; + Y.log('This has a valid log level', 'error'); + Assert.areEqual(lastCategory, 'error', 'Failed to log at error log category'); + lastCategory = undefined; + Y.log('This has no log level and should use the default'); + Assert.areEqual(lastCategory, 'info', 'Failed to log at default log category of info'); + lastCategory = undefined; + Y.log('This has an invalid log level and should use the default', 'notice'); + Assert.areEqual(lastCategory, 'info', 'Failed to log at default info log category'); + }); + } + } + }); + + Y.SeedTests.add(testLogging); +}); diff --git a/src/yui/tests/unit/index-full.html b/src/yui/tests/unit/index-full.html index e1614172907..73689ae24d9 100644 --- a/src/yui/tests/unit/index-full.html +++ b/src/yui/tests/unit/index-full.html @@ -46,6 +46,11 @@ requires: ['classnamemanager', 'node'] }, + 'logging-test': { + fullpath: './assets/logging-test.js', + requires: [ 'test' ] + }, + 'config-test': { fullpath: './assets/config-test.js' }, @@ -59,7 +64,7 @@ } } -}).use('seed-tests', 'core-tests', 'config-test', 'later-test', 'namespace-test', 'test-console', 'test', function(Y) { +}).use('seed-tests', 'core-tests', 'logging-test', 'test-console', 'test', function(Y) { new Y.Test.Console().render('#log'); //This is a YUITest hack to rename this test for reporting diff --git a/src/yui/tests/unit/index-logging.html b/src/yui/tests/unit/index-logging.html new file mode 100644 index 00000000000..2d6b17b670a --- /dev/null +++ b/src/yui/tests/unit/index-logging.html @@ -0,0 +1,68 @@ + + + +YUI Logging Tests + + + +
+ + + + + + + + diff --git a/src/yui/tests/unit/index-static.html b/src/yui/tests/unit/index-static.html index af290f397d2..e4ebe18ecc2 100644 --- a/src/yui/tests/unit/index-static.html +++ b/src/yui/tests/unit/index-static.html @@ -94,9 +94,14 @@ requires: ['classnamemanager', 'node'] }, + 'logging-test': { + fullpath: './assets/logging-test.js', + requires: [ 'test' ] + }, + 'config-test': { fullpath: './assets/config-test.js' - }, + } 'later-test': { fullpath: './assets/later-test.js' @@ -121,7 +126,7 @@ } } -}).use('ua-tests', 'seed-tests', 'core-tests', 'config-test', 'later-test', 'namespace-test', 'array-test', 'object-test', 'lang-test', 'test-console', 'test', function(Y) { +}).use('ua-tests', 'seed-tests', 'core-tests', 'logging-test', 'config-test', 'later-test', 'namespace-test', 'array-test', 'object-test', 'lang-test', 'test-console', 'test', function(Y) { new Y.Test.Console().render('#log'); Y.Test.Runner.setName(TestName); Y.Test.Runner.run(); diff --git a/src/yui/tests/unit/index.html b/src/yui/tests/unit/index.html index 9fb93b4a603..b1b8b94102c 100644 --- a/src/yui/tests/unit/index.html +++ b/src/yui/tests/unit/index.html @@ -57,6 +57,11 @@ requires: ['classnamemanager', 'node'] }, + 'logging-test': { + fullpath: './assets/logging-test.js', + requires: [ 'test' ] + }, + 'config-test': { fullpath: './assets/config-test.js' }, @@ -75,7 +80,7 @@ fullpath: './assets/es-modules-test.js' } } -}).use('seed-tests', 'core-tests', 'config-test', 'later-test', 'namespace-test', 'es-modules-test', 'test-console', 'test', function(Y) { +}).use('seed-tests', 'core-tests', 'logging-test', 'config-test', 'later-test', 'namespace-test', 'es-modules-test', 'test-console', 'test', function(Y) { new Y.Test.Console().render('#log'); Y.Test.Runner.run(); From 8f44b48c92ede1ebe5d78f7ce97991f67dd06522 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 4 Mar 2014 16:23:36 +0800 Subject: [PATCH 2/2] [core] Allow differential logging for different sources This commit adds differential logging support such that different log sources can have independent logLevels specified. This allows warnings to be shown from noisy modules, whilst getting debugging from the item you are actively developing. --- src/yui/js/yui-log.js | 33 +- src/yui/js/yui.js | 68 ++++ src/yui/tests/unit/assets/logging-test.js | 397 +++++++++++++++++++++- 3 files changed, 487 insertions(+), 11 deletions(-) diff --git a/src/yui/js/yui-log.js b/src/yui/js/yui-log.js index cf21014ec4f..39f05f35ea6 100644 --- a/src/yui/js/yui-log.js +++ b/src/yui/js/yui-log.js @@ -47,12 +47,27 @@ INSTANCE.log = function(msg, cat, src, silent) { if (typeof src !== "undefined") { excl = c.logExclude; incl = c.logInclude; - if (incl && !(src in incl)) { - bail = 1; - } else if (incl && (src in incl)) { - bail = !incl[src]; - } else if (excl && (src in excl)) { - bail = excl[src]; + if (incl) { + if (src in incl) { + // Exact match found -g rab the log level and bail setting. + bail = !incl[src]; + minlevel = incl[src]; + } else if (incl['*']) { + // Allow specification of differential logging. + bail = !incl['*']; + minlevel = incl['*']; + } else { + // No matching log categories, bail + bail = 1; + } + } else if (excl) { + if (src in excl) { + // Exact match found - grab the log level and bail setting. + bail = excl[src]; + } else if (excl['*']) { + // Allow specification of differential logging. + bail = excl['*']; + } } // Set a default category of info if the category was not defined or was not @@ -62,8 +77,10 @@ INSTANCE.log = function(msg, cat, src, silent) { } // Determine the current minlevel as defined in configuration - Y.config.logLevel = Y.config.logLevel || 'debug'; - minlevel = LEVELS[Y.config.logLevel.toLowerCase()]; + if (typeof minlevel !== 'string') { + minlevel = Y.config.logLevel || 'debug'; + } + minlevel = LEVELS[minlevel.toLowerCase()]; if (cat in LEVELS && LEVELS[cat] < minlevel) { // Skip this message if the we don't meet the defined minlevel diff --git a/src/yui/js/yui.js b/src/yui/js/yui.js index c7c1c322182..b4eb6d0adc5 100644 --- a/src/yui/js/yui.js +++ b/src/yui/js/yui.js @@ -1673,6 +1673,47 @@ supported console. A hash of log sources that should be logged. If specified, only messages from these sources will be logged. Others will be discarded. +The object key consists of: + + +Each object value in the hash can take either: + + +See Y.config.logLevel for details of the full list of log levels. + +If logExclude has also been specified, then this logInclude setting +will take precedent and logExclude will be ignored entirely. + +An example configuration is shown below: + + YUI_config = { + // The default logLevel will be warn: + logLevel: 'warn', + logInclude: { + // Reduce the logging threshold to debug for event-delegate: + 'event-delegate': 'debug', + + // Reduce the logging threshold to info for event-logged-at-info: + 'event-logged-at-info': 'info', + + // Reduce the logging threshold to Y.config.logLevel for event-logged-at-true: + 'event-logged-at-true': true, + + // Do not log anything for 'event-not-logged': + 'event-not-logged': false, + + // Do not log anything for everything else: + '*': false + } + }; + @property {Object} logInclude @type object **/ @@ -1681,6 +1722,33 @@ these sources will be logged. Others will be discarded. A hash of log sources that should be not be logged. If specified, all sources will be logged *except* those on this list. +The object key consists of: + + +The object value must be a boolean, unlike in logInclude. + +If logInclude has been specified, then it will take precedent and +logExclude setting will be ignored entirely. + +An example configuration which filters out all sources with the exception of event-delegate. + + YUI_config = { + // The default logLevel will be warn: + logLevel: 'warn', + logExclude: { + // Do not exclude event-delegate: + 'event-delegate': false, + + // Exclude everything else: + '*': true, + } + }; + +Note: The above example can be more better achieved using logInclude, but is displayed for completeness. + @property {Object} logExclude **/ diff --git a/src/yui/tests/unit/assets/logging-test.js b/src/yui/tests/unit/assets/logging-test.js index 9c93b4d99e8..33c1fb6a5ed 100644 --- a/src/yui/tests/unit/assets/logging-test.js +++ b/src/yui/tests/unit/assets/logging-test.js @@ -11,13 +11,26 @@ YUI.add('logging-test', function(Y) { error: console.error }; + var hasWorkingConsole = function() { + return !(typeof console === "undefined" || !console.info || Y.UA.nodejs); + }; + var testLogging = new Y.Test.Case({ name: "Logging tests", _should: { ignore: { - test_log_params: (typeof console == "undefined" || !console.info || Y.UA.nodejs), - test_log_default_category: (typeof console == "undefined" || !console.info || Y.UA.nodejs) + test_log_params: !hasWorkingConsole(), + test_log_default_category: !hasWorkingConsole(), + test_log_filter: !hasWorkingConsole(), + 'logInclude: glob override': !hasWorkingConsole(), + 'logInclude: minLevel override - matching': !hasWorkingConsole(), + 'logInclude: minLevel override - not matching': !hasWorkingConsole(), + 'logInclude: truthful boolean - matching': !hasWorkingConsole(), + 'logInclude: truthful boolean - mismatching': !hasWorkingConsole(), + 'logInclude: falsey boolean': !hasWorkingConsole(), + 'logExclude: glob override': !hasWorkingConsole(), + 'logExclude: overridden glob': !hasWorkingConsole() } }, @@ -251,7 +264,385 @@ YUI.add('logging-test', function(Y) { Y.log('This has an invalid log level and should use the default', 'notice'); Assert.areEqual(lastCategory, 'info', 'Failed to log at default info log category'); }); - } + }, + test_log_filter: function() { + var Assert = Y.Assert; + + // Test the default log category override. + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + '*': 'debug' + } + }); + + // Debug is the default level defined in logIncludes and will override the default logLevel: + lastCategory = undefined; + Y.log('This has a valid log level', 'debug'); + Assert.areEqual(lastCategory, 'debug', 'Failed to log at debug log category'); + }); + + // Test overrides for a specific source: + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: 'info' + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('This has a valid log level', 'debug', 'a'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'info', 'a'); + Assert.areEqual(lastCategory, 'info', 'Failed to log at info log category'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'warn', 'a'); + Assert.areEqual(lastCategory, 'warn', 'Failed to log at warn log category'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'error', 'a'); + Assert.areEqual(lastCategory, 'error', 'Failed to log at error log category'); + }); + + // Test not overriding for a specific source: + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: 'debug' + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('This has a valid log level', 'debug', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'info', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + lastCategory = undefined; + Y.log('This has a valid log level', 'warn', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'error', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + }); + + // Test true boolean state for logIncludes + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: true + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('This has a valid log level', 'debug', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'info', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'warn', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'error', 'b'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was higher.'); + }); + + // Test false boolean state for logIncludes + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: false + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('This has a valid log level', 'debug', 'a'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug level when the logInclude level was false.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'info', 'a'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug info when the logInclude level was false.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'warn', 'a'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug warn when the logInclude level was false.'); + + lastCategory = undefined; + Y.log('This has a valid log level', 'error', 'a'); + Assert.areEqual(lastCategory, undefined, 'Failed to filter out a debug error when the logInclude level was false.'); + }); + }, + + 'logInclude: glob override': function() { + var Assert = Y.Assert; + + // Test the default log category override. + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + '*': 'debug' + } + }); + + // Debug is the default level defined in logIncludes and will override the default logLevel: + lastCategory = undefined; + Y.log('This has a valid log level', 'debug'); + Assert.areEqual(lastCategory, 'debug', 'Failed to log at \'debug\' log category'); + }); + }, + + 'logInclude: minLevel override - matching': function() { + var Assert = Y.Assert; + + // Test overrides for a specific source: + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: 'info' + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('Some message', 'debug', 'a'); + Assert.isUndefined(lastCategory, 'Failed to filter out \'debug\' log message.'); + + lastCategory = undefined; + Y.log('Some message', 'info', 'a'); + Assert.areEqual(lastCategory, 'info', 'Failed to log at \'info\' log category'); + + lastCategory = undefined; + Y.log('Some message', 'warn', 'a'); + Assert.areEqual(lastCategory, 'warn', 'Failed to log at \'warn\' log category'); + + lastCategory = undefined; + Y.log('Some message', 'error', 'a'); + Assert.areEqual(lastCategory, 'error', 'Failed to log at \'error\' log category'); + }); + }, + + 'logInclude: minLevel override - not matching': function() { + var Assert = Y.Assert; + + // Test not overriding for a specific source: + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: 'debug' + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('Some message', 'debug', 'b'); + Assert.isUndefined(lastCategory, 'Failed to filter out \'debug\' log message.'); + + lastCategory = undefined; + Y.log('Some message', 'info', 'b'); + Assert.isUndefined(lastCategory, 'Failed to filter out \'info\' log message.'); + + lastCategory = undefined; + Y.log('Some message', 'warn', 'b'); + Assert.isUndefined(lastCategory, 'Failed to filter out \'warn\' log message.'); + + lastCategory = undefined; + Y.log('Some message', 'error', 'b'); + Assert.isUndefined(lastCategory, 'Failed to filter out \'error\' log message.'); + }); + + }, + + 'logInclude: truthful boolean - matching': function() { + var Assert = Y.Assert; + + // Test true boolean state for logIncludes + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: true + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('Some message', 'debug', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'debug' log message."); + + lastCategory = undefined; + Y.log('Some message', 'info', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'info' log message."); + + lastCategory = undefined; + Y.log('Some message', 'warn', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'warn' log message."); + + lastCategory = undefined; + Y.log('Some message', 'error', 'a'); + Assert.areEqual('error', lastCategory, "Failed to log at 'error' log message."); + + }); + }, + + 'logInclude: truthful boolean - mismatching': function() { + var Assert = Y.Assert; + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: true + } + }); + + // Anything with a source of 'b' should not log if it's at 'info' or below: + lastCategory = undefined; + Y.log('Some message', 'debug', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'debug' log message."); + + lastCategory = undefined; + Y.log('Some message', 'info', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'info' log message."); + + lastCategory = undefined; + Y.log('Some message', 'warn', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'warn' log message."); + + lastCategory = undefined; + Y.log('Some message', 'error', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'error' log message."); + }); + }, + + 'logInclude: falsey boolean': function() { + var Assert = Y.Assert; + + // Test false boolean state for logIncludes + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logInclude: { + a: false + } + }); + + // Anything with a source of 'a' should log if it's at 'info' or above: + lastCategory = undefined; + Y.log('Some message', 'debug', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'debug' log message."); + + lastCategory = undefined; + Y.log('Some message', 'info', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'info' log message."); + + lastCategory = undefined; + Y.log('Some message', 'warn', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'warn' log message."); + + lastCategory = undefined; + Y.log('Some message', 'error', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'error' log message."); + }); + }, + + 'logExclude: glob override': function() { + var Assert = Y.Assert; + + // Test the default log category override. + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logExclude: { + '*': true + } + }); + + // Debug is the default level defined in logExcludes and will override the default logLevel: + lastCategory = undefined; + Y.log('Some message', 'debug'); + Assert.isUndefined(lastCategory, "Failed to filter out 'debug' log message."); + + lastCategory = undefined; + Y.log('Some message', 'info'); + Assert.isUndefined(lastCategory, "Failed to filter out 'info' log message."); + + lastCategory = undefined; + Y.log('Some message', 'warn'); + Assert.isUndefined(lastCategory, "Failed to filter out 'warn' log message."); + + lastCategory = undefined; + Y.log('Some message', 'error'); + Assert.isUndefined(lastCategory, "Failed to filter out 'error' log message."); + }); + }, + + 'logExclude: overridden glob': function() { + var Assert = Y.Assert; + + // Test true boolean state for logExcludes + YUI().use(function (Y) { + Y.applyConfig({ + logLevel: 'error', + logExclude: { + '*': true, + a: false + } + }); + + // Anything matching 'a' should log when at error, or above. + lastCategory = undefined; + Y.log('Some message', 'debug', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'debug' log message."); + + lastCategory = undefined; + Y.log('Some message', 'info', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'info' log message."); + + lastCategory = undefined; + Y.log('Some message', 'warn', 'a'); + Assert.isUndefined(lastCategory, "Failed to filter out 'warn' log message."); + + lastCategory = undefined; + Y.log('Some message', 'error', 'a'); + Assert.areEqual('error', lastCategory, "Failed to log 'error' log message at a non-excluded category"); + + + lastCategory = undefined; + Y.log('Some message', 'debug', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'debug' log message."); + + lastCategory = undefined; + Y.log('Some message', 'info', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'info' log message."); + + lastCategory = undefined; + Y.log('Some message', 'warn', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'warn' log message."); + + lastCategory = undefined; + Y.log('Some message', 'error', 'b'); + Assert.isUndefined(lastCategory, "Failed to filter out 'error' log message."); + }); } });