/*
* Copyright © 2012, 2013 Pedro Agullo Soliveres.
*
* This file is part of Log4js-ext.
*
* Log4js-ext is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* Commercial use is permitted to the extent that the code/component(s)
* do NOT become part of another Open Source or Commercially developed
* licensed development library or toolkit without explicit permission.
*
* Log4js-ext is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Log4js-ext. If not, see <http://www.gnu.org/licenses/>.
*
* This software uses the ExtJs library (http://extjs.com), which is
* distributed under the GPL v3 license (see http://extjs.com/license).
*/
(function() {
"use strict"; //$NON-NLS-1$
/**
* A logger performs logging using the error, info, debug and other
* functions.
*
* Logged data is handled by the logger appenders
* (see {@link Sm.log.AppenderBase}),
* or its parent's appenders,
* that send it somewhere: the console, a window, etc.
*
* An appender will need to format data, and it will use its
* layout (see {@link Sm.log.LayoutBase}) for that purpose.
*/
Ext.define('Sm.log.Logger', { //$NON-NLS-1$
uses : ['Ext.Array',
'Sm.log.Level',
'Sm.log.LoggingEvent',
'Sm.log.ExtLogAppender',
'Sm.log.util.Assert'],
config : {
/**
* @cfg {String} [=assigned in constructor] (required)
* @accessor
*
* The logger's category.
*
* This can be considered the logger name, too.
*
* @readonly
*/
category : '',
// Method automatically generated for config.category
/**
* @method setCategory
* @private
*/
/**
* @cfg {Sm.log.Level}
* @accessor
*
* The level for this logger, or null.
*
* Logs with a level lesser than this level will be ignored.
* See {@link #getEffectiveLevel} for additional information.
*/
level : null,
/**
* @cfg
* @accessor
*
* If set to false, disables all logging.
*/
enabled : true,
/**
* @cfg {Array}
* @accessor
*
* The appenders to which this logger outputs directly.
*
* See {@link #getEffectiveAppenders} for additional information.
*
*/
appenders : [],
// Method automatically generated for config.appender
/**
* @method setAppenders
* @private
*/
/**
* @cfg
* @accessor
*
* If true, this logger will log to its appenders plus its parent
* appenders.
*/
additivity : true
},
statics : {
/**
* If false, no logger will output to its appenders, independently
* of the logger enabled state.
*
* @static
* @property
*/
enabled : true,
/**
* Returns the root logger, the logger that is the parent of all
* other loggers in the application.
*
* By default, the root logger uses the {@link Sm.log.ExtLogAppender}
* to output logs.
*
* @returns {Sm.log.Logger} The root logger.
*
* @static
*/
getRoot : function() {
if( this.PRIVATE_root === undefined ) {
this.PRIVATE_root =
Ext.create('Sm.log.Logger',
{category:'', level: Sm.log.Level.TRACE});
this.PRIVATE_root.addAppender(Sm.log.ExtLogAppender);
}
return this.PRIVATE_root;
},
/*
loggerExists : function( category ) {
var parts, logger, found;
if( category === '') {
return true;
}
parts = category.split(".");
logger = this.getRoot();
found = true;
Ext.Array.forEach( parts, function(part) {
Sm.log.util.Assert.assert( part );
if( !logger[part] ) {
found = false;
return false;
}
logger = logger[part];
});
return found;
},
*/
/**
* @static
*
* Returns a logger for the specified category.
*
* If there is no such logger, it is created. You should never
* instantiate loggers with the logger constructor, but rather you
* should use this function for that purpose.
*
* @param {String} category The category for which to get the logger.
*
* @returns {Sm.log.Logger}
*
*/
getLogger : function( category ) {
Sm.log.util.Assert.assert( category !== undefined );
if( !Ext.isString(category) ) {
if( category.$isClass ) {
category = category.getName();
}
else if( category.self ) {
category = category.self.geName();
}
else {
category = category.toString();
}
}
if( category === '') {
return this.getRoot();
}
// We take the 'easy' route: we create all the hierachy
// of logger: for 'a.b.c' we create a, a.b and a.b.c logger
// We could optimize this, but we'll wait until/if it is needed
var parts = category.split("."), cat = "",
logger = this.getRoot(),
loggerProperty;
Ext.Array.forEach( parts, function(part) {
Sm.log.util.Assert.assert( part );
cat = cat + part;
loggerProperty = part + "$SmLgr";
if( !logger[loggerProperty] ) {
logger[loggerProperty] = new Sm.log.Logger( {category:cat});
logger[loggerProperty].parentLogger = logger;
}
logger = logger[loggerProperty];
Sm.log.util.Assert.assert( !Ext.isFunction(logger));
cat = cat + ".";
});
return logger;
}
},
/**
* Returns the effective enabled state, taking into account
* both this logger enabled property and the static enabled property.
*
* @returns {Boolean}
*/
getEffectiveEnabled : function() {
return this.getEnabled() && this.self.enabled;
},
/**
* Returns all appenders to which this logger should log.
*
* This includes its own appenders, and, if additivity is true,
* its parent logger appenders -which in turn might contribute
* its own parent appenders if its additivity is set to true.
*
* @returns {Array}
*/
getEffectiveAppenders : function() {
var result = [], appenders = this.getAppenders();
if( appenders && appenders.length > 0 ) {
result = result.concat( appenders);
}
if( this.parentLogger && this.getAdditivity() ) {
result = result.concat( this.parentLogger.getEffectiveAppenders());
}
return result;
},
/**
* Adds a new appender to this logger.
*
* @param {Sm.log.AppenderBase} appender
* The appender to add to this logger.
*
* @returns {void}
*/
addAppender : function(appender) {
this.getAppenders().push(appender);
},
/**
* Removes an appender from this logger.
*
* @param {Sm.log.AppenderBase} appender The appender to remove.
*
* @returns {void}
*/
removeAppender : function(appender) {
Ext.Array.remove( this.getAppenders(), appender );
},
/**
* Removes all appenders from this logger
*
* @returns {void}
*/
removeAllAppenders : function() {
this.setAppenders( [] );
},
/**
* Returns the effective level for this logger.
*
* If a level has been set by calling {@link #setLevel}, then that will
* be the effective level. Else, the parent effective level will be used.
*
* @returns {Sm.log.Level} The effective level.
*/
getEffectiveLevel : function() {
if( !this.getLevel() ) {
return this.parentLogger.getEffectiveLevel();
}
return this.getLevel();
},
/**
* Logs data with the specified level.
*
* Arguments for this function are variable, and it is possible to
* log a simple message, perform advanced formatting or even log objects.
* Check this
* [link](http://http://code.google.com/p/log4js-ext/wiki/LoggingFormatting)
* for examples on how to use this function.
*
* @param level The log level.
* @param messageArgs The arguments for the logging operation.
*
* @returns {void}
*/
log : function(level, messageArgs) {
var args = [], i;
for( i = 1; i < arguments.length; i = i + 1 ) {
args.push(arguments[i]);
}
this.doLog(level, args);
},
/**
* Logs data with a FATAL level.
*
* Arguments for this function are variable, and it is possible to
* log a simple message, perform advanced formatting or even log objects.
* Check this
* [link](http://http://code.google.com/p/log4js-ext/wiki/LoggingFormatting)
* for examples on how to use this function.
*
* @param messageArgs The arguments for the logging operation.
*
* @returns {void}
*/
fatal : function(messageArgs) {
this.doLog(Sm.log.Level.FATAL, arguments);
},
/**
* Logs data with an ERROR level.
*
* Arguments for this function are variable, and it is possible to
* log a simple message, perform advanced formatting or even log objects.
* Check this
* [link](http://http://code.google.com/p/log4js-ext/wiki/LoggingFormatting)
* for examples on how to use this function.
*
* @param messageArgs The arguments for the logging operation.
*
* @returns {void}
*/
error : function(messageArgs) {
this.doLog(Sm.log.Level.ERROR, arguments);
},
/**
* Logs data with a WARN level.
*
* Arguments for this function are variable, and it is possible to
* log a simple message, perform advanced formatting or even log objects.
* Check this
* [link](http://http://code.google.com/p/log4js-ext/wiki/LoggingFormatting)
* for examples on how to use this function.
*
* @param messageArgs The arguments for the logging operation.
*
* @returns {void}
*/
warn : function(messageArgs) {
this.doLog(Sm.log.Level.WARN, arguments);
},
/**
* Logs data with an INFO level.
*
* Arguments for this function are variable, and it is possible to
* log a simple message, perform advanced formatting or even log objects.
* Check this
* [link](http://http://code.google.com/p/log4js-ext/wiki/LoggingFormatting)
* for examples on how to use this function.
*
* @param messageArgs The arguments for the logging operation.
*
* @returns {void}
*/
info : function() {
this.doLog(Sm.log.Level.INFO, arguments);
},
/**
* Logs data with a DEBUG level.
*
* Arguments for this function are variable, and it is possible to
* log a simple message, perform advanced formatting or even log objects.
* Check this
* [link](http://http://code.google.com/p/log4js-ext/wiki/LoggingFormatting)
* for examples on how to use this function.
*
* @param messageArgs The arguments for the logging operation.
*
* @returns {void}
*/
debug : function(messageArgs) {
this.doLog(Sm.log.Level.DEBUG, arguments);
},
/**
* Logs data with a TRACE level.
*
* Arguments for this function are variable, and it is possible to
* log a simple message, perform advanced formatting or even log objects.
* Check this
* [link](http://http://code.google.com/p/log4js-ext/wiki/LoggingFormatting)
* for examples on how to use this function.
*
* @param messageArgs The arguments for the logging operation.
*
* @returns {void}
*/
trace : function(messageArgs) {
this.doLog(Sm.log.Level.TRACE, arguments);
},
/**
* Returns true if this logger will perform logs with the specified level.
*
* @param {Sm.log.Level} level The log level.
* @returns {Boolean}
* true if this logger will perform logs with the specified level.
*/
isLevelEnabled : function(level) {
return this.getEffectiveLevel().le(level);
},
/**
* Returns true if this logger will perform logs with the FATAL level.
*
* @returns {Boolean}
* true if this logger will perform logs with the FATAL level.
*/
isFatalEnabled: function() {
return this.isLevelEnabled( Sm.log.Level.FATAL);
},
/**
* Returns true if this logger will perform logs with the ERROR level.
*
* @returns {Boolean}
* true if this logger will perform logs with the ERROR level.
*/
isErrorEnabled: function() {
return this.isLevelEnabled( Sm.log.Level.ERROR);
},
/**
* Returns true if this logger will perform logs with the WARN level.
*
* @returns {Boolean}
* true if this logger will perform logs with the WARN level.
*/
isWarnEnabled: function() {
return this.isLevelEnabled( Sm.log.Level.WARN);
},
/**
* Returns true if this logger will perform logs with the INFO level.
*
* @returns {Boolean}
* true if this logger will perform logs with the INFO level.
*/
isInfoEnabled: function() {
return this.isLevelEnabled( Sm.log.Level.INFO);
},
/**
* Returns true if this logger will perform logs with the DEBUG level.
*
* @returns {Boolean}
* true if this logger will perform logs with the DEBUG level.
*/
isDebugEnabled: function() {
return this.isLevelEnabled( Sm.log.Level.DEBUG);
},
/**
* Returns true if this logger will perform logs with the TRACE level.
*
* @returns {Boolean}
* true if this logger will perform logs with the TRACE level.
*/
isTraceEnabled: function() {
return this.isLevelEnabled( Sm.log.Level.TRACE);
},
/**
* @private
*
* Performs the real log.
*
* @param {Sm.log.Level} level The log level.
* @param args The log arguments.
*
* @returns {void}
*/
doLog : function(level, args) {
var logEvent, time, cfg, i;
Sm.log.util.Assert.assert( level );
Sm.log.util.Assert.assert( args );
Sm.log.util.Assert.assert( args.length >= 1 );
if( !this.getEffectiveEnabled() ) {
return;
}
if( this.isLevelEnabled(level)) {
cfg = {};
cfg.level = level;
cfg.message = args[0];
cfg.time = new Date();
cfg.category = this.getCategory();
if( args.length > 1 ) {
cfg.formatParams = [];
for( i = 1; i < args.length; i = i + 1 ) {
cfg.formatParams.push( args[i] );
}
}
Ext.Array.forEach( this.getEffectiveAppenders(),
function(appender)
{
// We create a copy for every appender to avoid appenders
// tinkering with events and affecting other appenders
logEvent = Ext.create( 'Sm.log.LoggingEvent', cfg );
appender.log( logEvent );
});
}
},
/**
* @private
*
* Do not use this: use {@link Sm.log.Logger#getLogger} instead.
*
*/
constructor : function (cfg) {
Sm.log.util.Assert.assert(cfg);
Sm.log.util.Assert.assert(cfg.category === '' || cfg.category );
this.initConfig(cfg);
this.setAppenders( [] );
}
});
}());