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:
Kris Maglione 2018-08-01 23:23:34 -07:00
Родитель bf729d7e98
Коммит c50886cf4e
4 изменённых файлов: 210 добавлений и 221 удалений

Просмотреть файл

@ -14,36 +14,27 @@ XPCOMUtils.defineLazyModuleGetters(this, {
var EXPORTED_SYMBOLS = ["GeckoViewUtils"]; var EXPORTED_SYMBOLS = ["GeckoViewUtils"];
var {Appender, BasicFormatter} = Log;
/** /**
* A formatter that does not prepend time/name/level information to messages, * A formatter that does not prepend time/name/level information to messages,
* because those fields are logged separately when using the Android logger. * because those fields are logged separately when using the Android logger.
*/ */
function AndroidFormatter() { class AndroidFormatter extends Log.BasicFormatter {
BasicFormatter.call(this);
}
AndroidFormatter.prototype = Object.freeze({
__proto__: BasicFormatter.prototype,
format(message) { format(message) {
return this.formatText(message); return this.formatText(message);
}, }
}); }
/* /*
* AndroidAppender * AndroidAppender
* Logs to Android logcat using AndroidLog.jsm * Logs to Android logcat using AndroidLog.jsm
*/ */
function AndroidAppender(aFormatter) { class AndroidAppender extends Log.Appender {
Appender.call(this, aFormatter || new AndroidFormatter()); constructor(aFormatter) {
super(aFormatter || new AndroidFormatter());
this._name = "AndroidAppender"; this._name = "AndroidAppender";
}
AndroidAppender.prototype = {
__proto__: Appender.prototype,
// Map log level to AndroidLog.foo method. // Map log level to AndroidLog.foo method.
_mapping: { this._mapping = {
[Log.Level.Fatal]: "e", [Log.Level.Fatal]: "e",
[Log.Level.Error]: "e", [Log.Level.Error]: "e",
[Log.Level.Warn]: "w", [Log.Level.Warn]: "w",
@ -51,7 +42,8 @@ AndroidAppender.prototype = {
[Log.Level.Config]: "d", [Log.Level.Config]: "d",
[Log.Level.Debug]: "d", [Log.Level.Debug]: "d",
[Log.Level.Trace]: "v", [Log.Level.Trace]: "v",
}, };
}
append(aMessage) { append(aMessage) {
if (!aMessage) { if (!aMessage) {
@ -63,8 +55,8 @@ AndroidAppender.prototype = {
const tag = aMessage.loggerName.replace(/^Gecko|\./g, ""); const tag = aMessage.loggerName.replace(/^Gecko|\./g, "");
const msg = this._formatter.format(aMessage); const msg = this._formatter.format(aMessage);
AndroidLog[this._mapping[aMessage.level]](tag, msg); AndroidLog[this._mapping[aMessage.level]](tag, msg);
}, }
}; }
var GeckoViewUtils = { var GeckoViewUtils = {
/** /**

Просмотреть файл

@ -42,8 +42,6 @@ var consoleAppender;
// A set of all preference roots used by all instances. // A set of all preference roots used by all instances.
var allBranches = new Set(); var allBranches = new Set();
let {Appender} = Log;
const ONE_BYTE = 1; const ONE_BYTE = 1;
const ONE_KILOBYTE = 1024 * ONE_BYTE; const ONE_KILOBYTE = 1024 * ONE_BYTE;
const ONE_MEGABYTE = 1024 * ONE_KILOBYTE; const ONE_MEGABYTE = 1024 * ONE_KILOBYTE;
@ -59,19 +57,17 @@ const PR_UINT32_MAX = 0xffffffff;
* during logging. Instead, one can periodically consume the input stream and * during logging. Instead, one can periodically consume the input stream and
* e.g. write it to disk asynchronously. * e.g. write it to disk asynchronously.
*/ */
function StorageStreamAppender(formatter) { class StorageStreamAppender extends Log.Appender {
Appender.call(this, formatter); constructor(formatter) {
super(formatter);
this._name = "StorageStreamAppender"; this._name = "StorageStreamAppender";
this._converterStream = null; // holds the nsIConverterOutputStream
this._outputStream = null; // holds the underlying nsIOutputStream
this._ss = null;
} }
StorageStreamAppender.prototype = {
__proto__: Appender.prototype,
_converterStream: null, // holds the nsIConverterOutputStream
_outputStream: null, // holds the underlying nsIOutputStream
_ss: null,
get outputStream() { get outputStream() {
if (!this._outputStream) { if (!this._outputStream) {
// First create a raw stream. We can bail out early if that fails. // First create a raw stream. We can bail out early if that fails.
@ -89,30 +85,30 @@ StorageStreamAppender.prototype = {
this._converterStream.init(this._outputStream, "UTF-8"); this._converterStream.init(this._outputStream, "UTF-8");
} }
return this._converterStream; return this._converterStream;
}, }
newOutputStream: function newOutputStream() { newOutputStream() {
let ss = this._ss = Cc["@mozilla.org/storagestream;1"] let ss = this._ss = Cc["@mozilla.org/storagestream;1"]
.createInstance(Ci.nsIStorageStream); .createInstance(Ci.nsIStorageStream);
ss.init(STREAM_SEGMENT_SIZE, PR_UINT32_MAX, null); ss.init(STREAM_SEGMENT_SIZE, PR_UINT32_MAX, null);
return ss.getOutputStream(0); return ss.getOutputStream(0);
}, }
getInputStream: function getInputStream() { getInputStream() {
if (!this._ss) { if (!this._ss) {
return null; return null;
} }
return this._ss.newInputStream(0); return this._ss.newInputStream(0);
}, }
reset: function reset() { reset() {
if (!this._outputStream) { if (!this._outputStream) {
return; return;
} }
this.outputStream.close(); this.outputStream.close();
this._outputStream = null; this._outputStream = null;
this._ss = null; this._ss = null;
}, }
doAppend(formatted) { doAppend(formatted) {
if (!formatted) { if (!formatted) {
@ -132,31 +128,29 @@ StorageStreamAppender.prototype = {
} }
} }
} }
}; }
// A storage appender that is flushable to a file on disk. Policies for // 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 // 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 // (although it does maintain a .sawError property to help the consumer decide
// based on its policies) // based on its policies)
function FlushableStorageAppender(formatter) { class FlushableStorageAppender extends StorageStreamAppender {
StorageStreamAppender.call(this, formatter); constructor(formatter) {
super(formatter);
this.sawError = false; this.sawError = false;
} }
FlushableStorageAppender.prototype = {
__proto__: StorageStreamAppender.prototype,
append(message) { append(message) {
if (message.level >= Log.Level.Error) { if (message.level >= Log.Level.Error) {
this.sawError = true; this.sawError = true;
} }
StorageStreamAppender.prototype.append.call(this, message); StorageStreamAppender.prototype.append.call(this, message);
}, }
reset() { reset() {
Log.StorageStreamAppender.prototype.reset.call(this); super.reset();
this.sawError = false; this.sawError = false;
}, }
// Flush the current stream to a file. Somewhat counter-intuitively, you // 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. // must pass a log which will be written to with details of the operation.
@ -175,7 +169,7 @@ FlushableStorageAppender.prototype = {
} catch (ex) { } catch (ex) {
log.error("Failed to copy log stream to file", ex); log.error("Failed to copy log stream to file", ex);
} }
}, }
/** /**
* Copy an input stream to the named file, doing everything off the main * 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); log.trace("finished copy to", fullOutputFileName);
}, }
}; }
// The public LogManager object. // The public LogManager object.
function LogManager(prefRoot, logNames, logFilePrefix) { function LogManager(prefRoot, logNames, logFilePrefix) {

Просмотреть файл

@ -64,50 +64,38 @@ var Log = {
Log.repository = value; Log.repository = value;
}, },
LogMessage, _formatError(e) {
Logger, let result = String(e);
LoggerRepository,
BasicFormatter,
Appender,
DumpAppender,
ConsoleAppender,
ParameterFormatter,
_formatError: function _formatError(e) {
let result = e.toString();
if (e.fileName) { if (e.fileName) {
result += " (" + e.fileName; let loc = [e.fileName];
if (e.lineNumber) { if (e.lineNumber) {
result += ":" + e.lineNumber; loc.push(e.lineNumber);
} }
if (e.columnNumber) { 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 // This is for back compatibility with services/common/utils.js; we duplicate
// some of the logic in ParameterFormatter // some of the logic in ParameterFormatter
exceptionStr: function exceptionStr(e) { exceptionStr(e) {
if (!e) { if (!e) {
return "" + e; return String(e);
} }
if (e instanceof Ci.nsIException) { if (e instanceof Ci.nsIException) {
return e.toString() + " " + Log.stackTrace(e); return `${e} ${Log.stackTrace(e)}`;
} else if (isError(e)) { } else if (isError(e)) {
return Log._formatError(e); return Log._formatError(e);
} }
// else // else
let message = e.message || e; let message = e.message || e;
return message + " " + Log.stackTrace(e); return `${message} ${Log.stackTrace(e)}`;
}, },
stackTrace: function stackTrace(e) { stackTrace(e) {
// Wrapped nsIException // Wrapped nsIException
if (e.location) { if (e.location) {
let frame = e.location; let frame = e.location;
@ -136,7 +124,7 @@ var Log = {
} }
frame = frame.caller; frame = frame.caller;
} }
return "Stack trace: " + output.join("\n"); return `Stack trace: ${output.join("\n")}`;
} }
// Standard JS exception // Standard JS exception
if (e.stack) { if (e.stack) {
@ -156,7 +144,8 @@ var Log = {
* LogMessage * LogMessage
* Encapsulates a single log event's data * Encapsulates a single log event's data
*/ */
function LogMessage(loggerName, level, message, params) { class LogMessage {
constructor(loggerName, level, message, params) {
this.loggerName = loggerName; this.loggerName = loggerName;
this.level = level; this.level = level;
/* /*
@ -180,29 +169,29 @@ function LogMessage(loggerName, level, message, params) {
this._structured = this.params && this.params.action; this._structured = this.params && this.params.action;
this.time = Date.now(); this.time = Date.now();
} }
LogMessage.prototype = {
get levelDesc() { get levelDesc() {
if (this.level in Log.Level.Desc) if (this.level in Log.Level.Desc)
return Log.Level.Desc[this.level]; return Log.Level.Desc[this.level];
return "UNKNOWN"; return "UNKNOWN";
}, }
toString: function LogMsg_toString() { toString() {
let msg = "LogMessage [" + this.time + " " + this.level + " " + let msg = `${this.time} ${this.level} ${this.message}`;
this.message;
if (this.params) { if (this.params) {
msg += " " + JSON.stringify(this.params); msg += ` ${JSON.stringify(this.params)}`;
}
return `LogMessage [${msg}]`;
} }
return msg + "]";
} }
};
/* /*
* Logger * Logger
* Hierarchical version. Logs to all appenders, assigned or inherited * Hierarchical version. Logs to all appenders, assigned or inherited
*/ */
function Logger(name, repository) { class Logger {
constructor(name, repository) {
if (!repository) if (!repository)
repository = Log.repository; repository = Log.repository;
this._name = name; this._name = name;
@ -210,16 +199,17 @@ function Logger(name, repository) {
this.ownAppenders = []; this.ownAppenders = [];
this.appenders = []; this.appenders = [];
this._repository = repository; this._repository = repository;
this._levelPrefName = null;
this._levelPrefValue = null;
this._level = null;
this._parent = null;
} }
Logger.prototype = {
_levelPrefName: null,
_levelPrefValue: null,
get name() { get name() {
return this._name; return this._name;
}, }
_level: null,
get level() { get level() {
if (this._levelPrefName) { if (this._levelPrefName) {
// We've been asked to use a preference to configure the logs. If the // We've been asked to use a preference to configure the logs. If the
@ -245,7 +235,7 @@ Logger.prototype = {
return this.parent.level; return this.parent.level;
dumpError("Log warning: root logger configuration error: no level defined"); dumpError("Log warning: root logger configuration error: no level defined");
return Log.Level.All; return Log.Level.All;
}, }
set level(level) { set level(level) {
if (this._levelPrefName) { if (this._levelPrefName) {
// I guess we could honor this by nuking this._levelPrefValue, but it // I guess we could honor this by nuking this._levelPrefValue, but it
@ -257,12 +247,11 @@ Logger.prototype = {
return; return;
} }
this._level = level; this._level = level;
}, }
_parent: null,
get parent() { get parent() {
return this._parent; return this._parent;
}, }
set parent(parent) { set parent(parent) {
if (this._parent == parent) { if (this._parent == parent) {
return; return;
@ -277,7 +266,7 @@ Logger.prototype = {
this._parent = parent; this._parent = parent;
parent.children.push(this); parent.children.push(this);
this.updateAppenders(); this.updateAppenders();
}, }
manageLevelFromPref(prefName) { manageLevelFromPref(prefName) {
if (prefName == this._levelPrefName) { if (prefName == this._levelPrefName) {
@ -292,9 +281,9 @@ Logger.prototype = {
} }
this._levelPrefName = prefName; this._levelPrefName = prefName;
XPCOMUtils.defineLazyPreferenceGetter(this, "_levelPrefValue", prefName); XPCOMUtils.defineLazyPreferenceGetter(this, "_levelPrefValue", prefName);
}, }
updateAppenders: function updateAppenders() { updateAppenders() {
if (this._parent) { if (this._parent) {
let notOwnAppenders = this._parent.appenders.filter(function(appender) { let notOwnAppenders = this._parent.appenders.filter(function(appender) {
return !this.ownAppenders.includes(appender); return !this.ownAppenders.includes(appender);
@ -308,24 +297,24 @@ Logger.prototype = {
for (let i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
this.children[i].updateAppenders(); this.children[i].updateAppenders();
} }
}, }
addAppender: function Logger_addAppender(appender) { addAppender(appender) {
if (this.ownAppenders.includes(appender)) { if (this.ownAppenders.includes(appender)) {
return; return;
} }
this.ownAppenders.push(appender); this.ownAppenders.push(appender);
this.updateAppenders(); this.updateAppenders();
}, }
removeAppender: function Logger_removeAppender(appender) { removeAppender(appender) {
let index = this.ownAppenders.indexOf(appender); let index = this.ownAppenders.indexOf(appender);
if (index == -1) { if (index == -1) {
return; return;
} }
this.ownAppenders.splice(index, 1); this.ownAppenders.splice(index, 1);
this.updateAppenders(); this.updateAppenders();
}, }
_unpackTemplateLiteral(string, params) { _unpackTemplateLiteral(string, params) {
if (!Array.isArray(params)) { if (!Array.isArray(params)) {
@ -355,7 +344,7 @@ Logger.prototype = {
concat += `\${${i}}${string[i + 1]}`; concat += `\${${i}}${string[i + 1]}`;
} }
return [concat, params]; return [concat, params];
}, }
log(level, string, params) { log(level, string, params) {
if (this.level > level) if (this.level > level)
@ -375,53 +364,54 @@ Logger.prototype = {
} }
appender.append(message); appender.append(message);
} }
}, }
fatal(string, ...params) { fatal(string, ...params) {
this.log(Log.Level.Fatal, string, params); this.log(Log.Level.Fatal, string, params);
}, }
error(string, ...params) { error(string, ...params) {
this.log(Log.Level.Error, string, params); this.log(Log.Level.Error, string, params);
}, }
warn(string, ...params) { warn(string, ...params) {
this.log(Log.Level.Warn, string, params); this.log(Log.Level.Warn, string, params);
}, }
info(string, ...params) { info(string, ...params) {
this.log(Log.Level.Info, string, params); this.log(Log.Level.Info, string, params);
}, }
config(string, ...params) { config(string, ...params) {
this.log(Log.Level.Config, string, params); this.log(Log.Level.Config, string, params);
}, }
debug(string, ...params) { debug(string, ...params) {
this.log(Log.Level.Debug, string, params); this.log(Log.Level.Debug, string, params);
}, }
trace(string, ...params) { trace(string, ...params) {
this.log(Log.Level.Trace, string, params); this.log(Log.Level.Trace, string, params);
} }
}; }
/* /*
* LoggerRepository * LoggerRepository
* Implements a hierarchy of Loggers * Implements a hierarchy of Loggers
*/ */
function LoggerRepository() {} class LoggerRepository {
LoggerRepository.prototype = { constructor() {
_loggers: {}, this._loggers = {};
this._rootLogger = null;
}
_rootLogger: null,
get rootLogger() { get rootLogger() {
if (!this._rootLogger) { if (!this._rootLogger) {
this._rootLogger = new Logger("root", this); this._rootLogger = new Logger("root", this);
this._rootLogger.level = Log.Level.All; this._rootLogger.level = Log.Level.All;
} }
return this._rootLogger; return this._rootLogger;
}, }
set rootLogger(logger) { set rootLogger(logger) {
throw "Cannot change the root logger"; throw "Cannot change the root logger";
}, }
_updateParents: function LogRep__updateParents(name) { _updateParents(name) {
let pieces = name.split("."); let pieces = name.split(".");
let cur, parent; let cur, parent;
@ -448,7 +438,7 @@ LoggerRepository.prototype = {
if (logger != name && logger.indexOf(name) == 0) if (logger != name && logger.indexOf(name) == 0)
this._updateParents(logger); this._updateParents(logger);
} }
}, }
/** /**
* Obtain a named Logger. * Obtain a named Logger.
@ -465,7 +455,7 @@ LoggerRepository.prototype = {
this._loggers[name] = new Logger(name, this); this._loggers[name] = new Logger(name, this);
this._updateParents(name); this._updateParents(name);
return this._loggers[name]; return this._loggers[name];
}, }
/** /**
* Obtain a Logger that logs all string messages with a prefix. * Obtain a Logger that logs all string messages with a prefix.
@ -499,8 +489,8 @@ LoggerRepository.prototype = {
return log.log(level, string, params); return log.log(level, string, params);
}; };
return proxy; return proxy;
}, }
}; }
/* /*
* Formatters * Formatters
@ -508,13 +498,14 @@ LoggerRepository.prototype = {
*/ */
// Basic formatter that doesn't do anything fancy. // Basic formatter that doesn't do anything fancy.
function BasicFormatter(dateFormat) { class BasicFormatter {
constructor(dateFormat) {
if (dateFormat) { if (dateFormat) {
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
} }
this.parameterFormatter = new ParameterFormatter(); this.parameterFormatter = new ParameterFormatter();
} }
BasicFormatter.prototype = {
/** /**
* Format the text of a message with optional parameters. * Format the text of a message with optional parameters.
* If the text contains ${identifier}, replace that with * If the text contains ${identifier}, replace that with
@ -564,15 +555,15 @@ BasicFormatter.prototype = {
return textParts.join(": "); return textParts.join(": ");
} }
return undefined; return undefined;
}, }
format: function BF_format(message) { format(message) {
return message.time + "\t" + return message.time + "\t" +
message.loggerName + "\t" + message.loggerName + "\t" +
message.levelDesc + "\t" + message.levelDesc + "\t" +
this.formatText(message); this.formatText(message);
} }
}; }
/** /**
* Test an object to see if it is a Mozilla JS Error. * 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. * a string representation of the object.
*/ */
function ParameterFormatter() { class ParameterFormatter {
constructor() {
this._name = "ParameterFormatter"; this._name = "ParameterFormatter";
} }
ParameterFormatter.prototype = {
format(ob) { format(ob) {
try { try {
if (ob === undefined) { if (ob === undefined) {
@ -606,7 +598,7 @@ ParameterFormatter.prototype = {
return ob; return ob;
} }
if (ob instanceof Ci.nsIException) { if (ob instanceof Ci.nsIException) {
return ob.toString() + " " + Log.stackTrace(ob); return `${ob} ${Log.stackTrace(ob)}`;
} else if (isError(ob)) { } else if (isError(ob)) {
return Log._formatError(ob); return Log._formatError(ob);
} }
@ -619,19 +611,19 @@ ParameterFormatter.prototype = {
return val; return val;
}); });
} catch (e) { } 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! // Fancy formatting failed. Just toSource() it - but even this may fail!
try { try {
return ob.toSource(); return ob.toSource();
} catch (_) { } } catch (_) { }
try { try {
return "" + ob; return String(ob);
} catch (_) { } catch (_) {
return "[object]"; return "[object]";
} }
} }
}; }
/* /*
* Appenders * Appenders
@ -639,55 +631,53 @@ ParameterFormatter.prototype = {
* Simply subclass and override doAppend to implement a new one * Simply subclass and override doAppend to implement a new one
*/ */
function Appender(formatter) { class Appender {
constructor(formatter) {
this.level = Log.Level.All;
this._name = "Appender"; this._name = "Appender";
this._formatter = formatter || new BasicFormatter(); this._formatter = formatter || new BasicFormatter();
} }
Appender.prototype = {
level: Log.Level.All,
append: function App_append(message) { append(message) {
if (message) { if (message) {
this.doAppend(this._formatter.format(message)); this.doAppend(this._formatter.format(message));
} }
}, }
toString: function App_toString() {
return this._name + " [level=" + this.level + toString() {
", formatter=" + this._formatter + "]"; return `${this._name} [level=${this.level}, formatter=${this._formatter}]`;
}, }
}; }
/* /*
* DumpAppender * DumpAppender
* Logs to standard out * Logs to standard out
*/ */
function DumpAppender(formatter) { class DumpAppender extends Appender {
Appender.call(this, formatter); constructor(formatter) {
super(formatter);
this._name = "DumpAppender"; this._name = "DumpAppender";
} }
DumpAppender.prototype = {
__proto__: Appender.prototype,
doAppend: function DApp_doAppend(formatted) { doAppend(formatted) {
dump(formatted + "\n"); dump(formatted + "\n");
} }
}; }
/* /*
* ConsoleAppender * ConsoleAppender
* Logs to the javascript console * Logs to the javascript console
*/ */
function ConsoleAppender(formatter) { class ConsoleAppender extends Appender {
Appender.call(this, formatter); constructor(formatter) {
super(formatter);
this._name = "ConsoleAppender"; this._name = "ConsoleAppender";
} }
ConsoleAppender.prototype = {
__proto__: Appender.prototype,
// XXX this should be replaced with calls to the Browser Console // XXX this should be replaced with calls to the Browser Console
append: function App_append(message) { append(message) {
if (message) { if (message) {
let m = this._formatter.format(message); let m = this._formatter.format(message);
if (message.level > Log.Level.Warn) { if (message.level > Log.Level.Warn) {
@ -696,9 +686,23 @@ ConsoleAppender.prototype = {
} }
this.doAppend(m); this.doAppend(m);
} }
}, }
doAppend: function CApp_doAppend(formatted) { doAppend(formatted) {
Services.console.logStringMessage(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) { class MockAppender extends Log.Appender {
Log.Appender.call(this, formatter); constructor(formatter) {
super(formatter);
this.messages = []; this.messages = [];
} }
MockAppender.prototype = {
__proto__: Log.Appender.prototype,
doAppend: function DApp_doAppend(message) { doAppend(message) {
this.messages.push(message); this.messages.push(message);
} }
}; }
add_task(function test_Logger() { add_task(function test_Logger() {
let log = Log.repository.getLogger("test.logger"); let log = Log.repository.getLogger("test.logger");