You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by jm...@apache.org on 2007/02/07 01:47:57 UTC
svn commit: r504408 - /incubator/xap/trunk/codebase/src/xap/log/Logger.js
Author: jmargaris
Date: Tue Feb 6 17:47:56 2007
New Revision: 504408
URL: http://svn.apache.org/viewvc?view=rev&rev=504408
Log:
log4j style logger, the code that actually uses the new logger
is not checked in yet as release is imminent
Added:
incubator/xap/trunk/codebase/src/xap/log/Logger.js (with props)
Added: incubator/xap/trunk/codebase/src/xap/log/Logger.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/log/Logger.js?view=auto&rev=504408
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/log/Logger.js (added)
+++ incubator/xap/trunk/codebase/src/xap/log/Logger.js Tue Feb 6 17:47:56 2007
@@ -0,0 +1,573 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+Xap.provide("xap.log.Logger");
+Xap.provide("xap.log.LoggingEvent");
+Xap.provide("xap.log.ConsoleAppender");
+
+Xap.require("xap.util.XapException");
+
+
+/**
+ * @fileoverview
+ * A logging framework based on log4j.
+ *
+ * @author jmargaris
+ *
+ */
+
+
+/**
+ * Creates a new Logger with name in the form 'a.b.c.' This constructor should never
+ * be called directly, new Loggers should be obtained by calling
+ * xap.log.Logger.getLogger().
+ *
+ * @class A logging framework based on log4j. It supports multiple
+ * logs with parents and level inheritance and multiple log
+ * appenders. Currently all logs are additive. Methods names and classes
+ * are the same as in log4j except that some simple getter/setters
+ * are just properties and log level is a simple integer constant
+ * rather than a class.
+ *
+ * @see xap.log.LoggingEvent
+ * @see xap.log.ConsoleAppender
+ * @see xap.log.AlertAppender
+ *
+ * @constructor
+ * @param {String} logName The name of the logger to create.
+ * @author jmargaris
+ */
+xap.log.Logger = function( logName ){
+
+ /** @private */
+ this._name = logName;
+
+ /** @private */
+ this._appenders = [];
+
+ /** @private a map of child log names to child logs */
+ this._childLogs = {};
+
+ /** @private level of ancestor tree */
+ this._inheritedLevel = 0;
+
+ /** @private level specifically set here */
+ this._level = 0;
+}
+
+/**
+ * Adds an appender to the log.
+ * @param appender An object with a 'doAppend()' method on it.
+ */
+xap.log.Logger.prototype.addAppender = function(appender){
+ this._appenders.push(appender);
+}
+
+
+/**
+ * Sets the logging level for this logger.
+ *
+ * @level One of
+ * xap.log.Logger.TRACE, xap.log.Logger.DEBUG, xap.log.Logger.INFO,
+ * xap.log.Logger.WARN, xap.log.Logger.ERROR, xap.log.Logger.FATAL or
+ * xap.log.Logger.NONE
+ */
+xap.log.Logger.prototype.setLevel = function( level ){
+ this._level = level;
+
+ //cascade level to children
+ for (var i in this._childLogs){
+ this._childLogs[i]._setParent(this);
+ }
+}
+
+/**
+ * Returns the logging level as set on this logger or
+ * as inherited from the ancestor chain.
+ *
+ * @return A constant corresponding to one of
+ * xap.log.Logger.TRACE, xap.log.Logger.DEBUG, xap.log.Logger.INFO,
+ * xap.log.Logger.WARN, xap.log.Logger.ERROR, xap.log.Logger.FATAL or
+ * xap.log.Logger.NONE or zero if the level is not set or inherited.
+ */
+xap.log.Logger.prototype.getEffectiveLevel = function(){
+ return (this._level?this._level:(this._inheritedLevel?this._inheritedLevel:0));
+}
+
+
+/**
+ * Logs a message at the given level with the given message
+ * and optional exception/error/thrown object.
+ *
+ * @param level A log level constant to log at.
+ * @param {String} message A string message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ */
+xap.log.Logger.prototype.log = function( level, message, exception ){
+ if (level < this.getEffectiveLevel()) return;
+
+ var loggingEvent = new xap.log.LoggingEvent(this._name,this,
+ new Date(),level,message,exception);
+
+ //dispatch to appenders and to parent appenders
+ this._dispatchLogEvent(loggingEvent);
+}
+
+/**
+ * Logs a message and optional thrown object at the TRACE level.
+ *
+ * @param {String} message A string message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ */
+xap.log.Logger.prototype.trace = function( message, exception ){
+ this.log(xap.log.Logger.TRACE, message, exception);
+}
+
+/**
+ * Logs a message and optional thrown object at the DEBUG level.
+ *
+ * @param {String} message A string message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ */
+xap.log.Logger.prototype.debug = function( message, exception ){
+ this.log(xap.log.Logger.DEBUG, message, exception);
+}
+
+/**
+ * Logs a message and optional thrown object at the INFO level.
+ *
+ * @param {String} message A string message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ */
+xap.log.Logger.prototype.info = function( message, exception ){
+ this.log(xap.log.Logger.INFO, message, exception);
+}
+
+/**
+ * Logs a message and optional thrown object at the WARN level.
+ *
+ * @param {String} message A string message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ */
+xap.log.Logger.prototype.warn = function( message, exception ){
+ this.log(xap.log.Logger.WARN, message, exception);
+}
+
+/**
+ * Logs a message and optional thrown object at the ERROR level.
+ *
+ * @param {String} message A string message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ */
+xap.log.Logger.prototype.error = function( message, exception ){
+ this.log(xap.log.Logger.ERROR, message, exception);
+}
+
+/**
+ * Logs a message and optional thrown object at the FATAL level.
+ *
+ * @param {String} message A string message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ */
+xap.log.Logger.prototype.fatal = function( message, exception ){
+ this.log(xap.log.Logger.FATAL, message, exception);
+}
+
+/**
+ * Returns true if a message at the given level would be logged
+ * according to the current logging level.
+ * @param level The level to check if the logger is enabled for.
+ * @return {boolean} True if a message at the given level should be logged.
+ */
+xap.log.Logger.prototype.isEnabledFor = function( level ){
+ return (level >= this.getEffectiveLevel());
+}
+
+/**
+ * Returns true if a message would be logged
+ * at the TRACE level.
+ *
+ * @return {boolean} True if a TRACE message should be logged.
+ */
+xap.log.Logger.prototype.isTrace = function( ){
+ return (xap.log.Logger.TRACE >= this.getEffectiveLevel());
+}
+
+/**
+ * Returns true if a message would be logged
+ * at the DEBUG level.
+ *
+ * @return {boolean} True if a DEBUG message should be logged.
+ */
+xap.log.Logger.prototype.isDebug = function( ){
+ return (xap.log.Logger.DEBUG >= this.getEffectiveLevel());
+}
+
+/**
+ * Returns true if a message would be logged
+ * at the INFO level.
+ *
+ * @return {boolean} True if an INFO message should be logged.
+ */
+xap.log.Logger.prototype.isInfo= function( ){
+ return (xap.log.Logger.INFO >= this.getEffectiveLevel());
+}
+
+/**
+ * Returns true if a message would be logged
+ * at the WARN level.
+ *
+ * @return {boolean} True if a WARN message should be logged.
+ */
+xap.log.Logger.prototype.isWarn = function( ){
+ return (xap.log.Logger.WARN >= this.getEffectiveLevel());
+}
+
+/**
+ * Returns true if a message would be logged
+ * at the ERROR level.
+ *
+ * @return {boolean} True if an ERROR message should be logged.
+ */
+xap.log.Logger.prototype.isError = function( ){
+ return (xap.log.Logger.ERROR >= this.getEffectiveLevel());
+}
+
+
+/**
+ * Returns true if a message would be logged
+ * at the FATAL level.
+ *
+ * @return {boolean} True if a FATAL message should be logged.
+ */
+xap.log.Logger.prototype.isFatal = function( ){
+ return (xap.log.Logger.FATAL >= this.getEffectiveLevel());
+}
+
+
+/**
+ * Dispatch a log event to appenders and parent appenders.
+ * @private
+ */
+xap.log.Logger.prototype._dispatchLogEvent = function( loggingEvent){
+ for (var i =0; i<this._appenders.length; i++){
+ this._appenders[i].doAppend(loggingEvent);
+ }
+
+ //TODO this should be optional, need a way to turn the additivity
+ //off
+ if (this._parent){
+ this._parent._dispatchLogEvent(loggingEvent);
+ }
+}
+
+/**
+ * Sets the parent of this log. This will adjust inheritance of
+ * log levels accordingly.
+ * @private
+ */
+xap.log.Logger.prototype._setParent = function( parentLog ){
+ this._parent = parentLog;
+
+ //add ourselves to child list
+ parentLog._childLogs[this._name] = this;
+
+ //inerit level from parent
+ this._inheritedLevel = parentLog.getEffectiveLevel();
+
+ //cascade inherited level to children
+ for (var i in this._childLogs){
+ this._childLogs[i]._setParent(this);
+ }
+}
+
+
+/**
+ * @private
+ * The root of every other logger
+ */
+xap.log.Logger._rootLog = new xap.log.Logger("root");
+
+/**
+ * 'Hashtable' for quick lookup so we don't have to traverse hierarchy
+ * each time we want a logger.
+ * @private
+ */
+xap.log.Logger._namesToLogs = {};
+
+
+/** Constant for the TRACE level.*/
+xap.log.Logger.TRACE = 1;
+
+/** Constant for the DEBUG level.*/
+xap.log.Logger.DEBUG = 2;
+
+/** Constant for the INFO level.*/
+xap.log.Logger.INFO = 3;
+
+/** Constant for the WARN level.*/
+xap.log.Logger.WARN = 4;
+
+/** Constant for the ERROR level.*/
+xap.log.Logger.ERROR = 5;
+
+/** Constant for the FATAL level.*/
+xap.log.Logger.FATAL = 6;
+
+/** Constant for the NONE level.*/
+xap.log.Logger.NONE = 7;
+
+
+/**
+ * An array indexed by constant with entries being
+ * the logical names of the levels.
+ */
+xap.log.Logger.LEVEL_NAMES = ['','TRACE','DEBUG','INFO','WARN','ERROR','FATAL', 'NONE'];
+
+
+/**
+ * Returns the root logger. All loggers are descendents
+ * of the root logger.
+ *
+ * @return {xap.log.Logger} The root logger.
+ */
+xap.log.Logger.getRootLogger = function(){
+ return xap.log.Logger._rootLog;
+}
+
+
+/**
+ * Returns a logger of the given name, creating a new one
+ * if it does not exist.
+ *
+ * @param {String} logName A log name in the form of 'a.b.c'.
+ * @return {xap.log.Logger} A logger of the given name.
+ */
+xap.log.Logger.getLogger = function( logName ){
+ //see if a.b.c.d already exists, if so return that log.
+ var existingLog = xap.log.Logger._namesToLogs[logName];
+
+ //if it doesn't, create a.b.c.d, creating parent logs as needed
+ //(for example a.b and a.b.c)
+ //hook up parenting relationship
+ if (!existingLog){
+ var packageNames = logName.split('.');
+ var currentLog = xap.log.Logger._rootLog;
+
+ for (var i = 0; i<packageNames.length;i++){
+ //look for child log a.b.c of parent log a.b
+ var childLogName = packageNames.slice(0,i+1).join('.');
+ existingLog = currentLog._childLogs[childLogName];
+
+ //if it doesn't exist we need to create it and hook it up to parent
+ if (!existingLog){
+ existingLog = new xap.log.Logger( childLogName );
+ xap.log.Logger._namesToLogs[childLogName] = existingLog;
+ existingLog._setParent(currentLog);
+ }
+ currentLog = existingLog;
+ }
+ }
+ return existingLog;
+}
+
+
+/**
+ * Creates a new LoggingEvent. Creation of new LoggingEvents is handled
+ * by the logging framework, users should never need to create
+ * their own LoggingEvents.
+ *
+ * @class LoggingEvent corresponds to the log4j equivalent with simple
+ * get/set converted to properties.
+ *
+ * @constructor
+ * @param {String} logName The name of the logger that message was logged to.
+ * @param {xap.log.Logger} logger The logger that the message was logged to.
+ * @param {Date} date The date the message was logged.
+ * @param level The log level of the message.
+ * @param {String} message The message to log.
+ * @param exception An optional thrown exception/error object
+ * to accompany the message.
+ * @constructor
+ * @author jmargaris
+ */
+xap.log.LoggingEvent = function( logName, logger, date, level, message, exception ){
+
+ /** The name of the logger that message was logged to.
+ * @type String */
+ this.logName = logName;
+
+ /** The logger that the message was logged to.
+ * @type xap.log.Logger */
+ this.logger = logger;
+
+ /** The date the message was logged.
+ * @type Date */
+ this.date = date;
+
+ /** The log level of the message.*/
+ this.level = level;
+
+ /** The message to log.
+ * @type String */
+ this.message = message;
+
+ /** An optional thrown exception/error object
+ * to accompany the message. */
+ this.exception = exception;
+
+ /** @private */
+ this._renderedMessage = '[' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds() + ' ' + xap.log.Logger.LEVEL_NAMES[level] + ' ' + logName +'] ' + message;
+
+ if (exception){
+ this._renderedMessage += ' exception: ' + xap.util.XapException.exceptionToString(exception);
+
+ }
+}
+
+/**
+ * Returns a string representing the LoggingEvent as it should be
+ * rendered to a log.
+ *
+ * @return {String} A log message in default rendered format.
+ */
+xap.log.LoggingEvent.prototype.getRenderedMessage = function(){
+ return this._renderedMessage;
+}
+
+
+/**
+ * Creates a new AlertAppender.
+ *
+ * @class AlertAppender is an appender that reports LoggingEvents
+ * of level ERROR or FATAL as onscreen alerts.
+ *
+ * @constructor
+ * @author jmargaris
+ */
+xap.log.AlertAppender = function(){
+
+}
+
+/**
+ * Conforms to the appender contract.
+ * @param {xap.log.LoggingEvent} logEvent The event to log.
+ */
+xap.log.AlertAppender.prototype.doAppend = function( logEvent ){
+ if (logEvent.level<xap.log.Logger.ERROR){
+ return;//TODO make configurable what the threshold is??
+ }
+ alert( logEvent.getRenderedMessage() );
+}
+
+/**
+ * Creates a new ConsoleAppender.
+ *
+ * @class ConsoleAppender is an appender that reports LoggingEvents
+ * to a div onscreen. At this time multiple ConsoleAppenders
+ * don't work well together.
+ *
+ * @constructor
+ * @author jmargaris
+ */
+xap.log.ConsoleAppender = function(){
+
+ /** @private cheesy handler that points back here for easy scripting */
+ xap.log.ConsoleAppender._log = this;
+}
+
+
+/**
+ * Conforms to the appender contract.
+ * @param {xap.log.LoggingEvent} logEvent The event to log.
+ */
+xap.log.ConsoleAppender.prototype.doAppend = function( logEvent ){
+ this._logEvent( logEvent.getRenderedMessage(), true);
+}
+
+
+/**
+ * Logs a rendered message.
+ * @private
+ */
+xap.log.ConsoleAppender.prototype._logEvent = function(text){
+ if (!this._logDiv){
+ var l = document.createElement('div');
+ l.style.position = 'absolute';
+ l.style.right = '5px';
+ l.style.top = '5px';
+ l.style.width = '200px';
+ l.style.height = '350px';
+ l.style.overflow = 'auto';
+ l.style.backgroundColor = '#f0f0f0';
+ l.style.border = '1px solid gray';
+ l.style.fontSize = '10px';
+ l.style.padding = '5px';
+ document.body.appendChild(l);
+ this._logDiv = l;
+
+ }
+ this._logDiv.style.display = "block";
+
+ //the way this works is extremely wacky
+ //and probably won't work for multiple console logs
+ if(this._logDiv.innerHTML == "")
+ this._logDiv.innerHTML="<A HREF=\"javascript:xap.log.ConsoleAppender._log._clear()\">Clear</A><br/><A HREF=\"javascript:xap.log.ConsoleAppender._log._resizeOutput(true)\">Bigger</A> | <A HREF=\"javascript:xap.log.ConsoleAppender._log._resizeOutput(false)\">Smaller</A>";
+
+ //we used to keep appending to inner HTML here but that was super expensive
+ //although it did allow nice formatting
+ this._logDiv.appendChild(document.createElement('br'));
+ this._logDiv.appendChild(document.createElement('br'));
+ this._logDiv.appendChild(document.createTextNode(text));
+
+ this._logDiv.scrollTop = this._logDiv.scrollHeight;
+
+}
+
+/**
+ * Makes the log window bigger/smaller.
+ * @private
+ */
+xap.log.ConsoleAppender.prototype._resizeOutput = function(bigger){
+ if(bigger){
+ this._logDiv.style.width = (parseInt(this._logDiv.style.width) + 100) + "px";
+ this._logDiv.style.height = (parseInt(this._logDiv.style.height) + 100) + "px";
+ }
+ else{
+ this._logDiv.style.width = Math.max(parseInt(this._logDiv.style.width) - 100, 150) + "px";
+ this._logDiv.style.height = Math.max(parseInt(this._logDiv.style.height) - 100, 100) + "px";
+ }
+}
+
+
+/**
+ * Clears and hides the log window.
+ * @private
+ */
+xap.log.ConsoleAppender.prototype._clear = function(){
+ if (this._logDiv){
+ this._logDiv.style.display = "none";
+ this._logDiv.innerHTML = "" ;
+ }
+}
Propchange: incubator/xap/trunk/codebase/src/xap/log/Logger.js
------------------------------------------------------------------------------
svn:eol-style = native