Improve output: distinguish between failed assertions (failures) and unexpected exceptions (errors), and print a filtered stack trace for any exception.
This commit is contained in:
commit
4f2e303079
1839 changed files with 235630 additions and 0 deletions
408
webapp/web/src/logging/Logger.js
Normal file
408
webapp/web/src/logging/Logger.js
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
Copyright (c) 2004-2006, The Dojo Foundation
|
||||
All Rights Reserved.
|
||||
|
||||
Licensed under the Academic Free License version 2.1 or above OR the
|
||||
modified BSD license. For more information on Dojo licensing, see:
|
||||
|
||||
http://dojotoolkit.org/community/licensing.shtml
|
||||
*/
|
||||
|
||||
/* This is the dojo logging facility, which is imported from nWidgets
|
||||
(written by Alex Russell, CLA on file), which is patterned on the
|
||||
Python logging module, which in turn has been heavily influenced by
|
||||
log4j (execpt with some more pythonic choices, which we adopt as well).
|
||||
|
||||
While the dojo logging facilities do provide a set of familiar
|
||||
interfaces, many of the details are changed to reflect the constraints
|
||||
of the browser environment. Mainly, file and syslog-style logging
|
||||
facilites are not provided, with HTTP POST and GET requests being the
|
||||
only ways of getting data from the browser back to a server. Minimal
|
||||
support for this (and XML serialization of logs) is provided, but may
|
||||
not be of practical use in a deployment environment.
|
||||
|
||||
The Dojo logging classes are agnostic of any environment, and while
|
||||
default loggers are provided for browser-based interpreter
|
||||
environments, this file and the classes it define are explicitly
|
||||
designed to be portable to command-line interpreters and other
|
||||
ECMA-262v3 envrionments.
|
||||
|
||||
the logger needs to accomidate:
|
||||
log "levels"
|
||||
type identifiers
|
||||
file?
|
||||
message
|
||||
tic/toc?
|
||||
|
||||
The logger should ALWAYS record:
|
||||
time/date logged
|
||||
message
|
||||
type
|
||||
level
|
||||
*/
|
||||
// TODO: conver documentation to javadoc style once we confirm that is our choice
|
||||
// TODO: define DTD for XML-formatted log messages
|
||||
// TODO: write XML Formatter class
|
||||
// TODO: write HTTP Handler which uses POST to send log lines/sections
|
||||
|
||||
// Filename: LogCore.js
|
||||
// Purpose: a common logging infrastructure for dojo
|
||||
// Classes: dojo.logging, dojo.logging.Logger, dojo.logging.Record, dojo.logging.LogFilter
|
||||
// Global Objects: dojo.logging
|
||||
// Dependencies: none
|
||||
|
||||
dojo.provide("dojo.logging.Logger");
|
||||
dojo.provide("dojo.log");
|
||||
dojo.require("dojo.lang");
|
||||
|
||||
/*
|
||||
A simple data structure class that stores information for and about
|
||||
a logged event. Objects of this type are created automatically when
|
||||
an event is logged and are the internal format in which information
|
||||
about log events is kept.
|
||||
*/
|
||||
|
||||
dojo.logging.Record = function(lvl, msg){
|
||||
this.level = lvl;
|
||||
this.message = msg;
|
||||
this.time = new Date();
|
||||
// FIXME: what other information can we receive/discover here?
|
||||
}
|
||||
|
||||
// an empty parent (abstract) class which concrete filters should inherit from.
|
||||
dojo.logging.LogFilter = function(loggerChain){
|
||||
this.passChain = loggerChain || "";
|
||||
this.filter = function(record){
|
||||
// FIXME: need to figure out a way to enforce the loggerChain
|
||||
// restriction
|
||||
return true; // pass all records
|
||||
}
|
||||
}
|
||||
|
||||
dojo.logging.Logger = function(){
|
||||
this.cutOffLevel = 0;
|
||||
this.propagate = true;
|
||||
this.parent = null;
|
||||
// storage for dojo.logging.Record objects seen and accepted by this logger
|
||||
this.data = [];
|
||||
this.filters = [];
|
||||
this.handlers = [];
|
||||
}
|
||||
|
||||
dojo.lang.extend(dojo.logging.Logger, {
|
||||
argsToArr: function(args){
|
||||
// utility function, reproduced from __util__ here to remove dependency
|
||||
var ret = [];
|
||||
for(var x=0; x<args.length; x++){
|
||||
ret.push(args[x]);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
setLevel: function(lvl){
|
||||
this.cutOffLevel = parseInt(lvl);
|
||||
},
|
||||
|
||||
isEnabledFor: function(lvl){
|
||||
return parseInt(lvl) >= this.cutOffLevel;
|
||||
},
|
||||
|
||||
getEffectiveLevel: function(){
|
||||
if((this.cutOffLevel==0)&&(this.parent)){
|
||||
return this.parent.getEffectiveLevel();
|
||||
}
|
||||
return this.cutOffLevel;
|
||||
},
|
||||
|
||||
addFilter: function(flt){
|
||||
this.filters.push(flt);
|
||||
return this.filters.length-1;
|
||||
},
|
||||
|
||||
removeFilterByIndex: function(fltIndex){
|
||||
if(this.filters[fltIndex]){
|
||||
delete this.filters[fltIndex];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
removeFilter: function(fltRef){
|
||||
for(var x=0; x<this.filters.length; x++){
|
||||
if(this.filters[x]===fltRef){
|
||||
delete this.filters[x];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
removeAllFilters: function(){
|
||||
this.filters = []; // clobber all of them
|
||||
},
|
||||
|
||||
filter: function(rec){
|
||||
for(var x=0; x<this.filters.length; x++){
|
||||
if((this.filters[x]["filter"])&&
|
||||
(!this.filters[x].filter(rec))||
|
||||
(rec.level<this.cutOffLevel)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
addHandler: function(hdlr){
|
||||
this.handlers.push(hdlr);
|
||||
return this.handlers.length-1;
|
||||
},
|
||||
|
||||
handle: function(rec){
|
||||
if((!this.filter(rec))||(rec.level<this.cutOffLevel)){ return false; }
|
||||
for(var x=0; x<this.handlers.length; x++){
|
||||
if(this.handlers[x]["handle"]){
|
||||
this.handlers[x].handle(rec);
|
||||
}
|
||||
}
|
||||
// FIXME: not sure what to do about records to be propagated that may have
|
||||
// been modified by the handlers or the filters at this logger. Should
|
||||
// parents always have pristine copies? or is passing the modified record
|
||||
// OK?
|
||||
// if((this.propagate)&&(this.parent)){ this.parent.handle(rec); }
|
||||
return true;
|
||||
},
|
||||
|
||||
// the heart and soul of the logging system
|
||||
log: function(lvl, msg){
|
||||
if( (this.propagate)&&(this.parent)&&
|
||||
(this.parent.rec.level>=this.cutOffLevel)){
|
||||
this.parent.log(lvl, msg);
|
||||
return false;
|
||||
}
|
||||
// FIXME: need to call logging providers here!
|
||||
this.handle(new dojo.logging.Record(lvl, msg));
|
||||
return true;
|
||||
},
|
||||
|
||||
// logger helpers
|
||||
debug:function(msg){
|
||||
return this.logType("DEBUG", this.argsToArr(arguments));
|
||||
},
|
||||
|
||||
info: function(msg){
|
||||
return this.logType("INFO", this.argsToArr(arguments));
|
||||
},
|
||||
|
||||
warning: function(msg){
|
||||
return this.logType("WARNING", this.argsToArr(arguments));
|
||||
},
|
||||
|
||||
error: function(msg){
|
||||
return this.logType("ERROR", this.argsToArr(arguments));
|
||||
},
|
||||
|
||||
critical: function(msg){
|
||||
return this.logType("CRITICAL", this.argsToArr(arguments));
|
||||
},
|
||||
|
||||
exception: function(msg, e, squelch){
|
||||
// FIXME: this needs to be modified to put the exception in the msg
|
||||
// if we're on Moz, we can get the following from the exception object:
|
||||
// lineNumber
|
||||
// message
|
||||
// fileName
|
||||
// stack
|
||||
// name
|
||||
// on IE, we get:
|
||||
// name
|
||||
// message (from MDA?)
|
||||
// number
|
||||
// description (same as message!)
|
||||
if(e){
|
||||
var eparts = [e.name, (e.description||e.message)];
|
||||
if(e.fileName){
|
||||
eparts.push(e.fileName);
|
||||
eparts.push("line "+e.lineNumber);
|
||||
// eparts.push(e.stack);
|
||||
}
|
||||
msg += " "+eparts.join(" : ");
|
||||
}
|
||||
|
||||
this.logType("ERROR", msg);
|
||||
if(!squelch){
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
logType: function(type, args){
|
||||
var na = [dojo.logging.log.getLevel(type)];
|
||||
if(typeof args == "array"){
|
||||
na = na.concat(args);
|
||||
}else if((typeof args == "object")&&(args["length"])){
|
||||
na = na.concat(this.argsToArr(args));
|
||||
/* for(var x=0; x<args.length; x++){
|
||||
na.push(args[x]);
|
||||
} */
|
||||
}else{
|
||||
na = na.concat(this.argsToArr(arguments).slice(1));
|
||||
/* for(var x=1; x<arguments.length; x++){
|
||||
na.push(arguments[x]);
|
||||
} */
|
||||
}
|
||||
return this.log.apply(this, na);
|
||||
}
|
||||
});
|
||||
|
||||
void(function(){
|
||||
var ptype = dojo.logging.Logger.prototype;
|
||||
ptype.warn = ptype.warning;
|
||||
ptype.err = ptype.error;
|
||||
ptype.crit = ptype.critical;
|
||||
})();
|
||||
|
||||
// the Handler class
|
||||
dojo.logging.LogHandler = function(level){
|
||||
this.cutOffLevel = (level) ? level : 0;
|
||||
this.formatter = null; // FIXME: default formatter?
|
||||
this.data = [];
|
||||
this.filters = [];
|
||||
}
|
||||
|
||||
dojo.logging.LogHandler.prototype.setFormatter = function(fmtr){
|
||||
// FIXME: need to vet that it is indeed a formatter object
|
||||
dojo.unimplemented("setFormatter");
|
||||
}
|
||||
|
||||
dojo.logging.LogHandler.prototype.flush = function(){
|
||||
dojo.unimplemented("flush");
|
||||
}
|
||||
|
||||
dojo.logging.LogHandler.prototype.close = function(){
|
||||
dojo.unimplemented("close");
|
||||
}
|
||||
|
||||
dojo.logging.LogHandler.prototype.handleError = function(){
|
||||
dojo.unimplemented("handleError");
|
||||
}
|
||||
|
||||
dojo.logging.LogHandler.prototype.handle = function(record){
|
||||
// emits the passed record if it passes this object's filters
|
||||
if((this.filter(record))&&(record.level>=this.cutOffLevel)){
|
||||
this.emit(record);
|
||||
}
|
||||
}
|
||||
|
||||
dojo.logging.LogHandler.prototype.emit = function(record){
|
||||
// do whatever is necessaray to actually log the record
|
||||
dojo.unimplemented("emit");
|
||||
}
|
||||
|
||||
// set aliases since we don't want to inherit from dojo.logging.Logger
|
||||
void(function(){ // begin globals protection closure
|
||||
var names = [
|
||||
"setLevel", "addFilter", "removeFilterByIndex", "removeFilter",
|
||||
"removeAllFilters", "filter"
|
||||
];
|
||||
var tgt = dojo.logging.LogHandler.prototype;
|
||||
var src = dojo.logging.Logger.prototype;
|
||||
for(var x=0; x<names.length; x++){
|
||||
tgt[names[x]] = src[names[x]];
|
||||
}
|
||||
})(); // end globals protection closure
|
||||
|
||||
dojo.logging.log = new dojo.logging.Logger();
|
||||
|
||||
// an associative array of logger objects. This object inherits from
|
||||
// a list of level names with their associated numeric levels
|
||||
dojo.logging.log.levels = [ {"name": "DEBUG", "level": 1},
|
||||
{"name": "INFO", "level": 2},
|
||||
{"name": "WARNING", "level": 3},
|
||||
{"name": "ERROR", "level": 4},
|
||||
{"name": "CRITICAL", "level": 5} ];
|
||||
|
||||
dojo.logging.log.loggers = {};
|
||||
|
||||
dojo.logging.log.getLogger = function(name){
|
||||
if(!this.loggers[name]){
|
||||
this.loggers[name] = new dojo.logging.Logger();
|
||||
this.loggers[name].parent = this;
|
||||
}
|
||||
return this.loggers[name];
|
||||
}
|
||||
|
||||
dojo.logging.log.getLevelName = function(lvl){
|
||||
for(var x=0; x<this.levels.length; x++){
|
||||
if(this.levels[x].level == lvl){
|
||||
return this.levels[x].name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
dojo.logging.log.addLevelName = function(name, lvl){
|
||||
if(this.getLevelName(name)){
|
||||
this.err("could not add log level "+name+" because a level with that name already exists");
|
||||
return false;
|
||||
}
|
||||
this.levels.append({"name": name, "level": parseInt(lvl)});
|
||||
return true;
|
||||
}
|
||||
|
||||
dojo.logging.log.getLevel = function(name){
|
||||
for(var x=0; x<this.levels.length; x++){
|
||||
if(this.levels[x].name.toUpperCase() == name.toUpperCase()){
|
||||
return this.levels[x].level;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// a default handler class, it simply saves all of the handle()'d records in
|
||||
// memory. Useful for attaching to with dojo.event.connect()
|
||||
dojo.logging.MemoryLogHandler = function(level, recordsToKeep, postType, postInterval){
|
||||
// mixin style inheritance
|
||||
dojo.logging.LogHandler.call(this, level);
|
||||
// default is unlimited
|
||||
this.numRecords = (typeof djConfig['loggingNumRecords'] != 'undefined') ? djConfig['loggingNumRecords'] : ((recordsToKeep) ? recordsToKeep : -1);
|
||||
// 0=count, 1=time, -1=don't post TODO: move this to a better location for prefs
|
||||
this.postType = (typeof djConfig['loggingPostType'] != 'undefined') ? djConfig['loggingPostType'] : ( postType || -1);
|
||||
// milliseconds for time, interger for number of records, -1 for non-posting,
|
||||
this.postInterval = (typeof djConfig['loggingPostInterval'] != 'undefined') ? djConfig['loggingPostInterval'] : ( postType || -1);
|
||||
|
||||
}
|
||||
// prototype inheritance
|
||||
dojo.logging.MemoryLogHandler.prototype = new dojo.logging.LogHandler();
|
||||
|
||||
// FIXME
|
||||
// dojo.inherits(dojo.logging.MemoryLogHandler,
|
||||
|
||||
// over-ride base-class
|
||||
dojo.logging.MemoryLogHandler.prototype.emit = function(record){
|
||||
this.data.push(record);
|
||||
if(this.numRecords != -1){
|
||||
while(this.data.length>this.numRecords){
|
||||
this.data.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dojo.logging.logQueueHandler = new dojo.logging.MemoryLogHandler(0,50,0,10000);
|
||||
// actual logging event handler
|
||||
dojo.logging.logQueueHandler.emit = function(record){
|
||||
// we should probably abstract this in the future
|
||||
var logStr = String(dojo.log.getLevelName(record.level)+": "+record.time.toLocaleTimeString())+": "+record.message;
|
||||
if(!dj_undef("debug", dj_global)){
|
||||
dojo.debug(logStr);
|
||||
}else if((typeof dj_global["print"] == "function")&&(!dojo.render.html.capable)){
|
||||
print(logStr);
|
||||
}
|
||||
this.data.push(record);
|
||||
if(this.numRecords != -1){
|
||||
while(this.data.length>this.numRecords){
|
||||
this.data.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dojo.logging.log.addHandler(dojo.logging.logQueueHandler);
|
||||
dojo.log = dojo.logging.log;
|
Loading…
Add table
Add a link
Reference in a new issue