зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1480327: Part 2 - Modernize what's left of Log.jsm a bit. r=Mossop
MozReview-Commit-ID: H06rpiZuIEF --HG-- extra : rebase_source : e10781ffdfaa264370ca95a720298dc3607a079b
This commit is contained in:
Родитель
bf729d7e98
Коммит
c50886cf4e
|
@ -14,44 +14,36 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
|
||||
var EXPORTED_SYMBOLS = ["GeckoViewUtils"];
|
||||
|
||||
var {Appender, BasicFormatter} = Log;
|
||||
|
||||
/**
|
||||
* A formatter that does not prepend time/name/level information to messages,
|
||||
* because those fields are logged separately when using the Android logger.
|
||||
*/
|
||||
function AndroidFormatter() {
|
||||
BasicFormatter.call(this);
|
||||
}
|
||||
AndroidFormatter.prototype = Object.freeze({
|
||||
__proto__: BasicFormatter.prototype,
|
||||
|
||||
class AndroidFormatter extends Log.BasicFormatter {
|
||||
format(message) {
|
||||
return this.formatText(message);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AndroidAppender
|
||||
* Logs to Android logcat using AndroidLog.jsm
|
||||
*/
|
||||
function AndroidAppender(aFormatter) {
|
||||
Appender.call(this, aFormatter || new AndroidFormatter());
|
||||
this._name = "AndroidAppender";
|
||||
}
|
||||
AndroidAppender.prototype = {
|
||||
__proto__: Appender.prototype,
|
||||
class AndroidAppender extends Log.Appender {
|
||||
constructor(aFormatter) {
|
||||
super(aFormatter || new AndroidFormatter());
|
||||
this._name = "AndroidAppender";
|
||||
|
||||
// Map log level to AndroidLog.foo method.
|
||||
_mapping: {
|
||||
[Log.Level.Fatal]: "e",
|
||||
[Log.Level.Error]: "e",
|
||||
[Log.Level.Warn]: "w",
|
||||
[Log.Level.Info]: "i",
|
||||
[Log.Level.Config]: "d",
|
||||
[Log.Level.Debug]: "d",
|
||||
[Log.Level.Trace]: "v",
|
||||
},
|
||||
// Map log level to AndroidLog.foo method.
|
||||
this._mapping = {
|
||||
[Log.Level.Fatal]: "e",
|
||||
[Log.Level.Error]: "e",
|
||||
[Log.Level.Warn]: "w",
|
||||
[Log.Level.Info]: "i",
|
||||
[Log.Level.Config]: "d",
|
||||
[Log.Level.Debug]: "d",
|
||||
[Log.Level.Trace]: "v",
|
||||
};
|
||||
}
|
||||
|
||||
append(aMessage) {
|
||||
if (!aMessage) {
|
||||
|
@ -63,8 +55,8 @@ AndroidAppender.prototype = {
|
|||
const tag = aMessage.loggerName.replace(/^Gecko|\./g, "");
|
||||
const msg = this._formatter.format(aMessage);
|
||||
AndroidLog[this._mapping[aMessage.level]](tag, msg);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var GeckoViewUtils = {
|
||||
/**
|
||||
|
|
|
@ -42,8 +42,6 @@ var consoleAppender;
|
|||
// A set of all preference roots used by all instances.
|
||||
var allBranches = new Set();
|
||||
|
||||
let {Appender} = Log;
|
||||
|
||||
const ONE_BYTE = 1;
|
||||
const ONE_KILOBYTE = 1024 * ONE_BYTE;
|
||||
const ONE_MEGABYTE = 1024 * ONE_KILOBYTE;
|
||||
|
@ -59,18 +57,16 @@ const PR_UINT32_MAX = 0xffffffff;
|
|||
* during logging. Instead, one can periodically consume the input stream and
|
||||
* e.g. write it to disk asynchronously.
|
||||
*/
|
||||
function StorageStreamAppender(formatter) {
|
||||
Appender.call(this, formatter);
|
||||
this._name = "StorageStreamAppender";
|
||||
}
|
||||
class StorageStreamAppender extends Log.Appender {
|
||||
constructor(formatter) {
|
||||
super(formatter);
|
||||
this._name = "StorageStreamAppender";
|
||||
|
||||
StorageStreamAppender.prototype = {
|
||||
__proto__: Appender.prototype,
|
||||
this._converterStream = null; // holds the nsIConverterOutputStream
|
||||
this._outputStream = null; // holds the underlying nsIOutputStream
|
||||
|
||||
_converterStream: null, // holds the nsIConverterOutputStream
|
||||
_outputStream: null, // holds the underlying nsIOutputStream
|
||||
|
||||
_ss: null,
|
||||
this._ss = null;
|
||||
}
|
||||
|
||||
get outputStream() {
|
||||
if (!this._outputStream) {
|
||||
|
@ -89,30 +85,30 @@ StorageStreamAppender.prototype = {
|
|||
this._converterStream.init(this._outputStream, "UTF-8");
|
||||
}
|
||||
return this._converterStream;
|
||||
},
|
||||
}
|
||||
|
||||
newOutputStream: function newOutputStream() {
|
||||
newOutputStream() {
|
||||
let ss = this._ss = Cc["@mozilla.org/storagestream;1"]
|
||||
.createInstance(Ci.nsIStorageStream);
|
||||
ss.init(STREAM_SEGMENT_SIZE, PR_UINT32_MAX, null);
|
||||
return ss.getOutputStream(0);
|
||||
},
|
||||
}
|
||||
|
||||
getInputStream: function getInputStream() {
|
||||
getInputStream() {
|
||||
if (!this._ss) {
|
||||
return null;
|
||||
}
|
||||
return this._ss.newInputStream(0);
|
||||
},
|
||||
}
|
||||
|
||||
reset: function reset() {
|
||||
reset() {
|
||||
if (!this._outputStream) {
|
||||
return;
|
||||
}
|
||||
this.outputStream.close();
|
||||
this._outputStream = null;
|
||||
this._ss = null;
|
||||
},
|
||||
}
|
||||
|
||||
doAppend(formatted) {
|
||||
if (!formatted) {
|
||||
|
@ -132,31 +128,29 @@ StorageStreamAppender.prototype = {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// A storage appender that is flushable to a file on disk. Policies for
|
||||
// when to flush, to what file, log rotation etc are up to the consumer
|
||||
// (although it does maintain a .sawError property to help the consumer decide
|
||||
// based on its policies)
|
||||
function FlushableStorageAppender(formatter) {
|
||||
StorageStreamAppender.call(this, formatter);
|
||||
this.sawError = false;
|
||||
}
|
||||
|
||||
FlushableStorageAppender.prototype = {
|
||||
__proto__: StorageStreamAppender.prototype,
|
||||
class FlushableStorageAppender extends StorageStreamAppender {
|
||||
constructor(formatter) {
|
||||
super(formatter);
|
||||
this.sawError = false;
|
||||
}
|
||||
|
||||
append(message) {
|
||||
if (message.level >= Log.Level.Error) {
|
||||
this.sawError = true;
|
||||
}
|
||||
StorageStreamAppender.prototype.append.call(this, message);
|
||||
},
|
||||
}
|
||||
|
||||
reset() {
|
||||
Log.StorageStreamAppender.prototype.reset.call(this);
|
||||
super.reset();
|
||||
this.sawError = false;
|
||||
},
|
||||
}
|
||||
|
||||
// Flush the current stream to a file. Somewhat counter-intuitively, you
|
||||
// must pass a log which will be written to with details of the operation.
|
||||
|
@ -175,7 +169,7 @@ FlushableStorageAppender.prototype = {
|
|||
} catch (ex) {
|
||||
log.error("Failed to copy log stream to file", ex);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy an input stream to the named file, doing everything off the main
|
||||
|
@ -216,8 +210,8 @@ FlushableStorageAppender.prototype = {
|
|||
}
|
||||
}
|
||||
log.trace("finished copy to", fullOutputFileName);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// The public LogManager object.
|
||||
function LogManager(prefRoot, logNames, logFilePrefix) {
|
||||
|
|
|
@ -64,50 +64,38 @@ var Log = {
|
|||
Log.repository = value;
|
||||
},
|
||||
|
||||
LogMessage,
|
||||
Logger,
|
||||
LoggerRepository,
|
||||
|
||||
BasicFormatter,
|
||||
|
||||
Appender,
|
||||
DumpAppender,
|
||||
ConsoleAppender,
|
||||
|
||||
ParameterFormatter,
|
||||
|
||||
_formatError: function _formatError(e) {
|
||||
let result = e.toString();
|
||||
_formatError(e) {
|
||||
let result = String(e);
|
||||
if (e.fileName) {
|
||||
result += " (" + e.fileName;
|
||||
let loc = [e.fileName];
|
||||
if (e.lineNumber) {
|
||||
result += ":" + e.lineNumber;
|
||||
loc.push(e.lineNumber);
|
||||
}
|
||||
if (e.columnNumber) {
|
||||
result += ":" + e.columnNumber;
|
||||
loc.push(e.columnNumber);
|
||||
}
|
||||
result += ")";
|
||||
result += `(${loc.join(":")})`;
|
||||
}
|
||||
return result + " " + Log.stackTrace(e);
|
||||
return `${result} ${Log.stackTrace(e)}`;
|
||||
},
|
||||
|
||||
// This is for back compatibility with services/common/utils.js; we duplicate
|
||||
// some of the logic in ParameterFormatter
|
||||
exceptionStr: function exceptionStr(e) {
|
||||
exceptionStr(e) {
|
||||
if (!e) {
|
||||
return "" + e;
|
||||
return String(e);
|
||||
}
|
||||
if (e instanceof Ci.nsIException) {
|
||||
return e.toString() + " " + Log.stackTrace(e);
|
||||
return `${e} ${Log.stackTrace(e)}`;
|
||||
} else if (isError(e)) {
|
||||
return Log._formatError(e);
|
||||
}
|
||||
// else
|
||||
let message = e.message || e;
|
||||
return message + " " + Log.stackTrace(e);
|
||||
return `${message} ${Log.stackTrace(e)}`;
|
||||
},
|
||||
|
||||
stackTrace: function stackTrace(e) {
|
||||
stackTrace(e) {
|
||||
// Wrapped nsIException
|
||||
if (e.location) {
|
||||
let frame = e.location;
|
||||
|
@ -136,7 +124,7 @@ var Log = {
|
|||
}
|
||||
frame = frame.caller;
|
||||
}
|
||||
return "Stack trace: " + output.join("\n");
|
||||
return `Stack trace: ${output.join("\n")}`;
|
||||
}
|
||||
// Standard JS exception
|
||||
if (e.stack) {
|
||||
|
@ -156,70 +144,72 @@ var Log = {
|
|||
* LogMessage
|
||||
* Encapsulates a single log event's data
|
||||
*/
|
||||
function LogMessage(loggerName, level, message, params) {
|
||||
this.loggerName = loggerName;
|
||||
this.level = level;
|
||||
/*
|
||||
* Special case to handle "log./level/(object)", for example logging a caught exception
|
||||
* without providing text or params like: catch(e) { logger.warn(e) }
|
||||
* Treating this as an empty text with the object in the 'params' field causes the
|
||||
* object to be formatted properly by BasicFormatter.
|
||||
*/
|
||||
if (!params && message && (typeof(message) == "object") &&
|
||||
(typeof(message.valueOf()) != "string")) {
|
||||
this.message = null;
|
||||
this.params = message;
|
||||
} else {
|
||||
// If the message text is empty, or a string, or a String object, normal handling
|
||||
this.message = message;
|
||||
this.params = params;
|
||||
class LogMessage {
|
||||
constructor(loggerName, level, message, params) {
|
||||
this.loggerName = loggerName;
|
||||
this.level = level;
|
||||
/*
|
||||
* Special case to handle "log./level/(object)", for example logging a caught exception
|
||||
* without providing text or params like: catch(e) { logger.warn(e) }
|
||||
* Treating this as an empty text with the object in the 'params' field causes the
|
||||
* object to be formatted properly by BasicFormatter.
|
||||
*/
|
||||
if (!params && message && (typeof(message) == "object") &&
|
||||
(typeof(message.valueOf()) != "string")) {
|
||||
this.message = null;
|
||||
this.params = message;
|
||||
} else {
|
||||
// If the message text is empty, or a string, or a String object, normal handling
|
||||
this.message = message;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
// The _structured field will correspond to whether this message is to
|
||||
// be interpreted as a structured message.
|
||||
this._structured = this.params && this.params.action;
|
||||
this.time = Date.now();
|
||||
}
|
||||
|
||||
// The _structured field will correspond to whether this message is to
|
||||
// be interpreted as a structured message.
|
||||
this._structured = this.params && this.params.action;
|
||||
this.time = Date.now();
|
||||
}
|
||||
LogMessage.prototype = {
|
||||
get levelDesc() {
|
||||
if (this.level in Log.Level.Desc)
|
||||
return Log.Level.Desc[this.level];
|
||||
return "UNKNOWN";
|
||||
},
|
||||
|
||||
toString: function LogMsg_toString() {
|
||||
let msg = "LogMessage [" + this.time + " " + this.level + " " +
|
||||
this.message;
|
||||
if (this.params) {
|
||||
msg += " " + JSON.stringify(this.params);
|
||||
}
|
||||
return msg + "]";
|
||||
}
|
||||
};
|
||||
|
||||
toString() {
|
||||
let msg = `${this.time} ${this.level} ${this.message}`;
|
||||
if (this.params) {
|
||||
msg += ` ${JSON.stringify(this.params)}`;
|
||||
}
|
||||
return `LogMessage [${msg}]`;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Logger
|
||||
* Hierarchical version. Logs to all appenders, assigned or inherited
|
||||
*/
|
||||
|
||||
function Logger(name, repository) {
|
||||
if (!repository)
|
||||
repository = Log.repository;
|
||||
this._name = name;
|
||||
this.children = [];
|
||||
this.ownAppenders = [];
|
||||
this.appenders = [];
|
||||
this._repository = repository;
|
||||
}
|
||||
Logger.prototype = {
|
||||
_levelPrefName: null,
|
||||
_levelPrefValue: null,
|
||||
class Logger {
|
||||
constructor(name, repository) {
|
||||
if (!repository)
|
||||
repository = Log.repository;
|
||||
this._name = name;
|
||||
this.children = [];
|
||||
this.ownAppenders = [];
|
||||
this.appenders = [];
|
||||
this._repository = repository;
|
||||
|
||||
this._levelPrefName = null;
|
||||
this._levelPrefValue = null;
|
||||
this._level = null;
|
||||
this._parent = null;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
},
|
||||
}
|
||||
|
||||
_level: null,
|
||||
get level() {
|
||||
if (this._levelPrefName) {
|
||||
// We've been asked to use a preference to configure the logs. If the
|
||||
|
@ -245,7 +235,7 @@ Logger.prototype = {
|
|||
return this.parent.level;
|
||||
dumpError("Log warning: root logger configuration error: no level defined");
|
||||
return Log.Level.All;
|
||||
},
|
||||
}
|
||||
set level(level) {
|
||||
if (this._levelPrefName) {
|
||||
// I guess we could honor this by nuking this._levelPrefValue, but it
|
||||
|
@ -257,12 +247,11 @@ Logger.prototype = {
|
|||
return;
|
||||
}
|
||||
this._level = level;
|
||||
},
|
||||
}
|
||||
|
||||
_parent: null,
|
||||
get parent() {
|
||||
return this._parent;
|
||||
},
|
||||
}
|
||||
set parent(parent) {
|
||||
if (this._parent == parent) {
|
||||
return;
|
||||
|
@ -277,7 +266,7 @@ Logger.prototype = {
|
|||
this._parent = parent;
|
||||
parent.children.push(this);
|
||||
this.updateAppenders();
|
||||
},
|
||||
}
|
||||
|
||||
manageLevelFromPref(prefName) {
|
||||
if (prefName == this._levelPrefName) {
|
||||
|
@ -292,9 +281,9 @@ Logger.prototype = {
|
|||
}
|
||||
this._levelPrefName = prefName;
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "_levelPrefValue", prefName);
|
||||
},
|
||||
}
|
||||
|
||||
updateAppenders: function updateAppenders() {
|
||||
updateAppenders() {
|
||||
if (this._parent) {
|
||||
let notOwnAppenders = this._parent.appenders.filter(function(appender) {
|
||||
return !this.ownAppenders.includes(appender);
|
||||
|
@ -308,24 +297,24 @@ Logger.prototype = {
|
|||
for (let i = 0; i < this.children.length; i++) {
|
||||
this.children[i].updateAppenders();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
addAppender: function Logger_addAppender(appender) {
|
||||
addAppender(appender) {
|
||||
if (this.ownAppenders.includes(appender)) {
|
||||
return;
|
||||
}
|
||||
this.ownAppenders.push(appender);
|
||||
this.updateAppenders();
|
||||
},
|
||||
}
|
||||
|
||||
removeAppender: function Logger_removeAppender(appender) {
|
||||
removeAppender(appender) {
|
||||
let index = this.ownAppenders.indexOf(appender);
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
this.ownAppenders.splice(index, 1);
|
||||
this.updateAppenders();
|
||||
},
|
||||
}
|
||||
|
||||
_unpackTemplateLiteral(string, params) {
|
||||
if (!Array.isArray(params)) {
|
||||
|
@ -355,7 +344,7 @@ Logger.prototype = {
|
|||
concat += `\${${i}}${string[i + 1]}`;
|
||||
}
|
||||
return [concat, params];
|
||||
},
|
||||
}
|
||||
|
||||
log(level, string, params) {
|
||||
if (this.level > level)
|
||||
|
@ -375,53 +364,54 @@ Logger.prototype = {
|
|||
}
|
||||
appender.append(message);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
fatal(string, ...params) {
|
||||
this.log(Log.Level.Fatal, string, params);
|
||||
},
|
||||
}
|
||||
error(string, ...params) {
|
||||
this.log(Log.Level.Error, string, params);
|
||||
},
|
||||
}
|
||||
warn(string, ...params) {
|
||||
this.log(Log.Level.Warn, string, params);
|
||||
},
|
||||
}
|
||||
info(string, ...params) {
|
||||
this.log(Log.Level.Info, string, params);
|
||||
},
|
||||
}
|
||||
config(string, ...params) {
|
||||
this.log(Log.Level.Config, string, params);
|
||||
},
|
||||
}
|
||||
debug(string, ...params) {
|
||||
this.log(Log.Level.Debug, string, params);
|
||||
},
|
||||
}
|
||||
trace(string, ...params) {
|
||||
this.log(Log.Level.Trace, string, params);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* LoggerRepository
|
||||
* Implements a hierarchy of Loggers
|
||||
*/
|
||||
|
||||
function LoggerRepository() {}
|
||||
LoggerRepository.prototype = {
|
||||
_loggers: {},
|
||||
class LoggerRepository {
|
||||
constructor() {
|
||||
this._loggers = {};
|
||||
this._rootLogger = null;
|
||||
}
|
||||
|
||||
_rootLogger: null,
|
||||
get rootLogger() {
|
||||
if (!this._rootLogger) {
|
||||
this._rootLogger = new Logger("root", this);
|
||||
this._rootLogger.level = Log.Level.All;
|
||||
}
|
||||
return this._rootLogger;
|
||||
},
|
||||
}
|
||||
set rootLogger(logger) {
|
||||
throw "Cannot change the root logger";
|
||||
},
|
||||
}
|
||||
|
||||
_updateParents: function LogRep__updateParents(name) {
|
||||
_updateParents(name) {
|
||||
let pieces = name.split(".");
|
||||
let cur, parent;
|
||||
|
||||
|
@ -448,7 +438,7 @@ LoggerRepository.prototype = {
|
|||
if (logger != name && logger.indexOf(name) == 0)
|
||||
this._updateParents(logger);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a named Logger.
|
||||
|
@ -465,7 +455,7 @@ LoggerRepository.prototype = {
|
|||
this._loggers[name] = new Logger(name, this);
|
||||
this._updateParents(name);
|
||||
return this._loggers[name];
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a Logger that logs all string messages with a prefix.
|
||||
|
@ -499,8 +489,8 @@ LoggerRepository.prototype = {
|
|||
return log.log(level, string, params);
|
||||
};
|
||||
return proxy;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Formatters
|
||||
|
@ -508,13 +498,14 @@ LoggerRepository.prototype = {
|
|||
*/
|
||||
|
||||
// Basic formatter that doesn't do anything fancy.
|
||||
function BasicFormatter(dateFormat) {
|
||||
if (dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
class BasicFormatter {
|
||||
constructor(dateFormat) {
|
||||
if (dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
this.parameterFormatter = new ParameterFormatter();
|
||||
}
|
||||
this.parameterFormatter = new ParameterFormatter();
|
||||
}
|
||||
BasicFormatter.prototype = {
|
||||
|
||||
/**
|
||||
* Format the text of a message with optional parameters.
|
||||
* If the text contains ${identifier}, replace that with
|
||||
|
@ -564,15 +555,15 @@ BasicFormatter.prototype = {
|
|||
return textParts.join(": ");
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}
|
||||
|
||||
format: function BF_format(message) {
|
||||
format(message) {
|
||||
return message.time + "\t" +
|
||||
message.loggerName + "\t" +
|
||||
message.levelDesc + "\t" +
|
||||
this.formatText(message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an object to see if it is a Mozilla JS Error.
|
||||
|
@ -588,10 +579,11 @@ function isError(aObj) {
|
|||
* a string representation of the object.
|
||||
*/
|
||||
|
||||
function ParameterFormatter() {
|
||||
this._name = "ParameterFormatter";
|
||||
}
|
||||
ParameterFormatter.prototype = {
|
||||
class ParameterFormatter {
|
||||
constructor() {
|
||||
this._name = "ParameterFormatter";
|
||||
}
|
||||
|
||||
format(ob) {
|
||||
try {
|
||||
if (ob === undefined) {
|
||||
|
@ -606,7 +598,7 @@ ParameterFormatter.prototype = {
|
|||
return ob;
|
||||
}
|
||||
if (ob instanceof Ci.nsIException) {
|
||||
return ob.toString() + " " + Log.stackTrace(ob);
|
||||
return `${ob} ${Log.stackTrace(ob)}`;
|
||||
} else if (isError(ob)) {
|
||||
return Log._formatError(ob);
|
||||
}
|
||||
|
@ -619,19 +611,19 @@ ParameterFormatter.prototype = {
|
|||
return val;
|
||||
});
|
||||
} catch (e) {
|
||||
dumpError("Exception trying to format object for log message: " + Log.exceptionStr(e));
|
||||
dumpError(`Exception trying to format object for log message: ${Log.exceptionStr(e)}`);
|
||||
}
|
||||
// Fancy formatting failed. Just toSource() it - but even this may fail!
|
||||
try {
|
||||
return ob.toSource();
|
||||
} catch (_) { }
|
||||
try {
|
||||
return "" + ob;
|
||||
return String(ob);
|
||||
} catch (_) {
|
||||
return "[object]";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Appenders
|
||||
|
@ -639,55 +631,53 @@ ParameterFormatter.prototype = {
|
|||
* Simply subclass and override doAppend to implement a new one
|
||||
*/
|
||||
|
||||
function Appender(formatter) {
|
||||
this._name = "Appender";
|
||||
this._formatter = formatter || new BasicFormatter();
|
||||
}
|
||||
Appender.prototype = {
|
||||
level: Log.Level.All,
|
||||
class Appender {
|
||||
constructor(formatter) {
|
||||
this.level = Log.Level.All;
|
||||
this._name = "Appender";
|
||||
this._formatter = formatter || new BasicFormatter();
|
||||
}
|
||||
|
||||
append: function App_append(message) {
|
||||
append(message) {
|
||||
if (message) {
|
||||
this.doAppend(this._formatter.format(message));
|
||||
}
|
||||
},
|
||||
toString: function App_toString() {
|
||||
return this._name + " [level=" + this.level +
|
||||
", formatter=" + this._formatter + "]";
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this._name} [level=${this.level}, formatter=${this._formatter}]`;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DumpAppender
|
||||
* Logs to standard out
|
||||
*/
|
||||
|
||||
function DumpAppender(formatter) {
|
||||
Appender.call(this, formatter);
|
||||
this._name = "DumpAppender";
|
||||
}
|
||||
DumpAppender.prototype = {
|
||||
__proto__: Appender.prototype,
|
||||
class DumpAppender extends Appender {
|
||||
constructor(formatter) {
|
||||
super(formatter);
|
||||
this._name = "DumpAppender";
|
||||
}
|
||||
|
||||
doAppend: function DApp_doAppend(formatted) {
|
||||
doAppend(formatted) {
|
||||
dump(formatted + "\n");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* ConsoleAppender
|
||||
* Logs to the javascript console
|
||||
*/
|
||||
|
||||
function ConsoleAppender(formatter) {
|
||||
Appender.call(this, formatter);
|
||||
this._name = "ConsoleAppender";
|
||||
}
|
||||
ConsoleAppender.prototype = {
|
||||
__proto__: Appender.prototype,
|
||||
class ConsoleAppender extends Appender {
|
||||
constructor(formatter) {
|
||||
super(formatter);
|
||||
this._name = "ConsoleAppender";
|
||||
}
|
||||
|
||||
// XXX this should be replaced with calls to the Browser Console
|
||||
append: function App_append(message) {
|
||||
append(message) {
|
||||
if (message) {
|
||||
let m = this._formatter.format(message);
|
||||
if (message.level > Log.Level.Warn) {
|
||||
|
@ -696,9 +686,23 @@ ConsoleAppender.prototype = {
|
|||
}
|
||||
this.doAppend(m);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
doAppend: function CApp_doAppend(formatted) {
|
||||
doAppend(formatted) {
|
||||
Services.console.logStringMessage(formatted);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Object.assign(Log, {
|
||||
LogMessage,
|
||||
Logger,
|
||||
LoggerRepository,
|
||||
|
||||
BasicFormatter,
|
||||
|
||||
Appender,
|
||||
DumpAppender,
|
||||
ConsoleAppender,
|
||||
|
||||
ParameterFormatter,
|
||||
});
|
||||
|
|
|
@ -16,17 +16,16 @@ var testFormatter = {
|
|||
}
|
||||
};
|
||||
|
||||
function MockAppender(formatter) {
|
||||
Log.Appender.call(this, formatter);
|
||||
this.messages = [];
|
||||
}
|
||||
MockAppender.prototype = {
|
||||
__proto__: Log.Appender.prototype,
|
||||
class MockAppender extends Log.Appender {
|
||||
constructor(formatter) {
|
||||
super(formatter);
|
||||
this.messages = [];
|
||||
}
|
||||
|
||||
doAppend: function DApp_doAppend(message) {
|
||||
doAppend(message) {
|
||||
this.messages.push(message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
add_task(function test_Logger() {
|
||||
let log = Log.repository.getLogger("test.logger");
|
||||
|
|
Загрузка…
Ссылка в новой задаче