1085 lines
30 KiB
JavaScript
Executable File
1085 lines
30 KiB
JavaScript
Executable File
/**
|
|
* @license
|
|
* Copyright The Closure Library Authors.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview Basic strippable logging definitions.
|
|
* @see http://go/closurelogging
|
|
*/
|
|
|
|
goog.provide('goog.log');
|
|
goog.provide('goog.log.Level');
|
|
goog.provide('goog.log.LogBuffer');
|
|
goog.provide('goog.log.LogRecord');
|
|
goog.provide('goog.log.Logger');
|
|
|
|
goog.require('goog.asserts');
|
|
goog.require('goog.debug');
|
|
|
|
|
|
/**
|
|
* A message value that can be handled by a goog.log.Logger.
|
|
*
|
|
* Functions are treated like callbacks, but are only called when the event's
|
|
* log level is enabled. This is useful for logging messages that are expensive
|
|
* to construct.
|
|
*
|
|
* @typedef {string|function(): string}
|
|
*/
|
|
goog.log.Loggable;
|
|
|
|
/** @define {boolean} Whether logging is enabled. */
|
|
goog.log.ENABLED = goog.define('goog.log.ENABLED', goog.debug.LOGGING_ENABLED);
|
|
|
|
/** @const */
|
|
goog.log.ROOT_LOGGER_NAME = '';
|
|
|
|
|
|
// TODO(user): Make goog.log.Level an enum.
|
|
/**
|
|
* The goog.log.Level class defines a set of standard logging levels that
|
|
* can be used to control logging output. The logging goog.log.Level objects
|
|
* are ordered and are specified by ordered integers. Enabling logging
|
|
* at a given level also enables logging at all higher levels.
|
|
* <p>
|
|
* Clients should normally use the predefined goog.log.Level constants such
|
|
* as goog.log.Level.SEVERE.
|
|
* <p>
|
|
* The levels in descending order are:
|
|
* <ul>
|
|
* <li>SEVERE (highest value)
|
|
* <li>WARNING
|
|
* <li>INFO
|
|
* <li>CONFIG
|
|
* <li>FINE
|
|
* <li>FINER
|
|
* <li>FINEST (lowest value)
|
|
* </ul>
|
|
* In addition there is a level OFF that can be used to turn
|
|
* off logging, and a level ALL that can be used to enable
|
|
* logging of all messages.
|
|
*
|
|
* @final
|
|
*/
|
|
goog.log.Level = class Level {
|
|
/**
|
|
* @param {string} name The name of the level.
|
|
* @param {number} value The numeric value of the level.
|
|
*/
|
|
constructor(name, value) {
|
|
/**
|
|
* The name of the level
|
|
* @type {string}
|
|
* @const
|
|
*/
|
|
this.name = name;
|
|
|
|
/**
|
|
* The numeric value of the level
|
|
* @type {number}
|
|
*/
|
|
this.value = value;
|
|
}
|
|
|
|
/**
|
|
* @return {string} String representation of the logger level.
|
|
* @override
|
|
*/
|
|
toString() {
|
|
return this.name;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* OFF is a special level that can be used to turn off logging.
|
|
* This level is initialized to <CODE>Infinity</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.OFF = new goog.log.Level('OFF', Infinity);
|
|
|
|
|
|
/**
|
|
* SHOUT is a message level for extra debugging loudness.
|
|
* This level is initialized to <CODE>1200</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.SHOUT = new goog.log.Level('SHOUT', 1200);
|
|
|
|
|
|
/**
|
|
* SEVERE is a message level indicating a serious failure.
|
|
* This level is initialized to <CODE>1000</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.SEVERE = new goog.log.Level('SEVERE', 1000);
|
|
|
|
|
|
/**
|
|
* WARNING is a message level indicating a potential problem.
|
|
* This level is initialized to <CODE>900</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.WARNING = new goog.log.Level('WARNING', 900);
|
|
|
|
|
|
/**
|
|
* INFO is a message level for informational messages.
|
|
* This level is initialized to <CODE>800</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.INFO = new goog.log.Level('INFO', 800);
|
|
|
|
|
|
/**
|
|
* CONFIG is a message level for static configuration messages.
|
|
* This level is initialized to <CODE>700</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.CONFIG = new goog.log.Level('CONFIG', 700);
|
|
|
|
|
|
/**
|
|
* FINE is a message level providing tracing information.
|
|
* This level is initialized to <CODE>500</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.FINE = new goog.log.Level('FINE', 500);
|
|
|
|
|
|
/**
|
|
* FINER indicates a fairly detailed tracing message.
|
|
* This level is initialized to <CODE>400</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.FINER = new goog.log.Level('FINER', 400);
|
|
|
|
/**
|
|
* FINEST indicates a highly detailed tracing message.
|
|
* This level is initialized to <CODE>300</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
|
|
goog.log.Level.FINEST = new goog.log.Level('FINEST', 300);
|
|
|
|
|
|
/**
|
|
* ALL indicates that all messages should be logged.
|
|
* This level is initialized to <CODE>0</CODE>.
|
|
* @type {!goog.log.Level}
|
|
*/
|
|
goog.log.Level.ALL = new goog.log.Level('ALL', 0);
|
|
|
|
|
|
/**
|
|
* The predefined levels.
|
|
* @type {!Array<!goog.log.Level>}
|
|
* @final
|
|
*/
|
|
goog.log.Level.PREDEFINED_LEVELS = [
|
|
goog.log.Level.OFF, goog.log.Level.SHOUT, goog.log.Level.SEVERE,
|
|
goog.log.Level.WARNING, goog.log.Level.INFO, goog.log.Level.CONFIG,
|
|
goog.log.Level.FINE, goog.log.Level.FINER, goog.log.Level.FINEST,
|
|
goog.log.Level.ALL
|
|
];
|
|
|
|
|
|
/**
|
|
* A lookup map used to find the level object based on the name or value of
|
|
* the level object.
|
|
* @type {?Object}
|
|
* @private
|
|
*/
|
|
goog.log.Level.predefinedLevelsCache_ = null;
|
|
|
|
|
|
/**
|
|
* Creates the predefined levels cache and populates it.
|
|
* @private
|
|
*/
|
|
goog.log.Level.createPredefinedLevelsCache_ = function() {
|
|
goog.log.Level.predefinedLevelsCache_ = {};
|
|
for (let i = 0, level; level = goog.log.Level.PREDEFINED_LEVELS[i]; i++) {
|
|
goog.log.Level.predefinedLevelsCache_[level.value] = level;
|
|
goog.log.Level.predefinedLevelsCache_[level.name] = level;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the predefined level with the given name.
|
|
* @param {string} name The name of the level.
|
|
* @return {!goog.log.Level|null} The level, or null if none found.
|
|
*/
|
|
goog.log.Level.getPredefinedLevel = function(name) {
|
|
if (!goog.log.Level.predefinedLevelsCache_) {
|
|
goog.log.Level.createPredefinedLevelsCache_();
|
|
}
|
|
|
|
return goog.log.Level.predefinedLevelsCache_[name] || null;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the highest predefined level <= #value.
|
|
* @param {number} value goog.log.Level value.
|
|
* @return {!goog.log.Level|null} The level, or null if none found.
|
|
*/
|
|
goog.log.Level.getPredefinedLevelByValue = function(value) {
|
|
if (!goog.log.Level.predefinedLevelsCache_) {
|
|
goog.log.Level.createPredefinedLevelsCache_();
|
|
}
|
|
|
|
if (value in /** @type {!Object} */ (goog.log.Level.predefinedLevelsCache_)) {
|
|
return goog.log.Level.predefinedLevelsCache_[value];
|
|
}
|
|
|
|
for (let i = 0; i < goog.log.Level.PREDEFINED_LEVELS.length; ++i) {
|
|
let level = goog.log.Level.PREDEFINED_LEVELS[i];
|
|
if (level.value <= value) {
|
|
return level;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
|
|
/** @interface */
|
|
goog.log.Logger = class Logger {
|
|
/**
|
|
* Gets the name of the Logger.
|
|
* @return {string}
|
|
* @public
|
|
*/
|
|
getName() {}
|
|
};
|
|
|
|
|
|
/**
|
|
* Only for compatibility with goog.debug.Logger.Level, which is how many users
|
|
* access Level.
|
|
* TODO(user): Remove these definitions.
|
|
* @final
|
|
*/
|
|
goog.log.Logger.Level = goog.log.Level;
|
|
|
|
|
|
/**
|
|
* A buffer for log records. The purpose of this is to improve
|
|
* logging performance by re-using old objects when the buffer becomes full and
|
|
* to eliminate the need for each app to implement their own log buffer. The
|
|
* disadvantage to doing this is that log handlers cannot maintain references to
|
|
* log records and expect that they are not overwriten at a later point.
|
|
* @final
|
|
*/
|
|
goog.log.LogBuffer = class LogBuffer {
|
|
/**
|
|
* @param {number=} capacity The capacity of this LogBuffer instance.
|
|
*/
|
|
constructor(capacity) {
|
|
/**
|
|
* The buffer's capacity.
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.capacity_ =
|
|
typeof capacity === 'number' ? capacity : goog.log.LogBuffer.CAPACITY;
|
|
|
|
/**
|
|
* The array to store the records.
|
|
* @type {!Array<!goog.log.LogRecord|undefined>}
|
|
* @private
|
|
*/
|
|
this.buffer_;
|
|
|
|
/**
|
|
* The index of the most recently added record, or -1 if there are no
|
|
* records.
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.curIndex_;
|
|
|
|
/**
|
|
* Whether the buffer is at capacity.
|
|
* @type {boolean}
|
|
* @private
|
|
*/
|
|
this.isFull_;
|
|
|
|
this.clear();
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds a log record to the buffer, possibly overwriting the oldest record.
|
|
* @param {!goog.log.Level} level One of the level identifiers.
|
|
* @param {string} msg The string message.
|
|
* @param {string} loggerName The name of the source logger.
|
|
* @return {!goog.log.LogRecord} The log record.
|
|
*/
|
|
addRecord(level, msg, loggerName) {
|
|
if (!this.isBufferingEnabled()) {
|
|
return new goog.log.LogRecord(level, msg, loggerName);
|
|
}
|
|
const curIndex = (this.curIndex_ + 1) % this.capacity_;
|
|
this.curIndex_ = curIndex;
|
|
if (this.isFull_) {
|
|
const ret = this.buffer_[curIndex];
|
|
ret.reset(level, msg, loggerName);
|
|
return ret;
|
|
}
|
|
this.isFull_ = curIndex == this.capacity_ - 1;
|
|
return this.buffer_[curIndex] =
|
|
new goog.log.LogRecord(level, msg, loggerName);
|
|
}
|
|
|
|
/**
|
|
* Calls the given function for each buffered log record, starting with the
|
|
* oldest one.
|
|
* TODO(user): Make this a [Symbol.iterator] once all usages of
|
|
* goog.debug.LogBuffer can be deleted.
|
|
* @param {!goog.log.LogRecordHandler} func The function to call.
|
|
*/
|
|
forEachRecord(func) {
|
|
const buffer = this.buffer_;
|
|
// Corner case: no records.
|
|
if (!buffer[0]) {
|
|
return;
|
|
}
|
|
const curIndex = this.curIndex_;
|
|
let i = this.isFull_ ? curIndex : -1;
|
|
do {
|
|
i = (i + 1) % this.capacity_;
|
|
func(/** @type {!goog.log.LogRecord} */ (buffer[i]));
|
|
} while (i !== curIndex);
|
|
}
|
|
|
|
/**
|
|
* @return {boolean} Whether the log buffer is enabled.
|
|
*/
|
|
isBufferingEnabled() {
|
|
return this.capacity_ > 0;
|
|
}
|
|
|
|
/**
|
|
* @return {boolean} Return whether the log buffer is full.
|
|
*/
|
|
isFull() {
|
|
return this.isFull_;
|
|
}
|
|
|
|
/**
|
|
* Removes all buffered log records.
|
|
*/
|
|
clear() {
|
|
this.buffer_ = new Array(this.capacity_);
|
|
this.curIndex_ = -1;
|
|
this.isFull_ = false;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @type {!goog.log.LogBuffer|undefined}
|
|
* @private
|
|
*/
|
|
goog.log.LogBuffer.instance_;
|
|
|
|
|
|
/**
|
|
* @define {number} The number of log records to buffer. 0 means disable
|
|
* buffering.
|
|
*/
|
|
goog.log.LogBuffer.CAPACITY = goog.define('goog.debug.LogBuffer.CAPACITY', 0);
|
|
|
|
|
|
/**
|
|
* A static method that always returns the same instance of goog.log.LogBuffer.
|
|
* @return {!goog.log.LogBuffer} The goog.log.LogBuffer singleton instance.
|
|
*/
|
|
goog.log.LogBuffer.getInstance = function() {
|
|
if (!goog.log.LogBuffer.instance_) {
|
|
goog.log.LogBuffer.instance_ =
|
|
new goog.log.LogBuffer(goog.log.LogBuffer.CAPACITY);
|
|
}
|
|
return goog.log.LogBuffer.instance_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Whether the log buffer is enabled.
|
|
* @return {boolean}
|
|
*/
|
|
goog.log.LogBuffer.isBufferingEnabled = function() {
|
|
return goog.log.LogBuffer.getInstance().isBufferingEnabled();
|
|
};
|
|
|
|
|
|
/**
|
|
* LogRecord objects are used to pass logging requests between the logging
|
|
* framework and individual log handlers. These objects should not be
|
|
* constructed or reset by application code.
|
|
*/
|
|
goog.log.LogRecord = class LogRecord {
|
|
/**
|
|
* @param {?goog.log.Level} level One of the level identifiers.
|
|
* @param {string} msg The string message.
|
|
* @param {string} loggerName The name of the source logger.
|
|
* @param {number=} time Time this log record was created if other than
|
|
* now. If 0, we use #goog.now.
|
|
* @param {number=} sequenceNumber Sequence number of this log record.
|
|
* This should only be passed in when restoring a log record from
|
|
* persistence.
|
|
*/
|
|
constructor(level, msg, loggerName, time, sequenceNumber) {
|
|
/**
|
|
* Level of the LogRecord.
|
|
* @type {!goog.log.Level}
|
|
* @private
|
|
*/
|
|
this.level_;
|
|
|
|
/**
|
|
* Name of the logger that created the record.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
this.loggerName_;
|
|
|
|
/**
|
|
* Message associated with the record
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
this.msg_;
|
|
|
|
/**
|
|
* Time the LogRecord was created.
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.time_;
|
|
|
|
/**
|
|
* Sequence number for the LogRecord. Each record has a unique sequence
|
|
* number that is greater than all log records created before it.
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.sequenceNumber_;
|
|
|
|
/**
|
|
* Exception associated with the record
|
|
* @type {*}
|
|
* @private
|
|
*/
|
|
this.exception_ = undefined;
|
|
|
|
this.reset(
|
|
level || goog.log.Level.OFF, msg, loggerName, time, sequenceNumber);
|
|
};
|
|
|
|
/**
|
|
* Sets all fields of the log record.
|
|
* @param {!goog.log.Level} level One of the level identifiers.
|
|
* @param {string} msg The string message.
|
|
* @param {string} loggerName The name of the source logger.
|
|
* @param {number=} time Time this log record was created if other than
|
|
* now. If 0, we use #goog.now.
|
|
* @param {number=} sequenceNumber Sequence number of this log record.
|
|
* This should only be passed in when restoring a log record from
|
|
* persistence.
|
|
*/
|
|
reset(level, msg, loggerName, time, sequenceNumber) {
|
|
this.time_ = time || goog.now();
|
|
this.level_ = level;
|
|
this.msg_ = msg;
|
|
this.loggerName_ = loggerName;
|
|
this.exception_ = undefined;
|
|
this.sequenceNumber_ = typeof sequenceNumber === 'number' ?
|
|
sequenceNumber :
|
|
goog.log.LogRecord.nextSequenceNumber_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the source Logger's name.
|
|
*
|
|
* @return {string} source logger name (may be null).
|
|
*/
|
|
getLoggerName() {
|
|
return this.loggerName_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Sets the source Logger's name.
|
|
*
|
|
* @param {string} name The logger name.
|
|
*/
|
|
setLoggerName(name) {
|
|
this.loggerName_ = name;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the exception that is part of the log record.
|
|
*
|
|
* @return {*} the exception.
|
|
*/
|
|
getException() {
|
|
return this.exception_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Sets the exception that is part of the log record.
|
|
* @param {*} exception the exception.
|
|
*/
|
|
setException(exception) {
|
|
this.exception_ = exception;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the logging message level, for example Level.SEVERE.
|
|
* @return {!goog.log.Level} the logging message level.
|
|
*/
|
|
getLevel() {
|
|
return this.level_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Sets the logging message level, for example Level.SEVERE.
|
|
* @param {!goog.log.Level} level the logging message level.
|
|
*/
|
|
setLevel(level) {
|
|
this.level_ = level;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the "raw" log message, before localization or formatting.
|
|
* @return {string} the raw message string.
|
|
*/
|
|
getMessage() {
|
|
return this.msg_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Sets the "raw" log message, before localization or formatting.
|
|
*
|
|
* @param {string} msg the raw message string.
|
|
*/
|
|
setMessage(msg) {
|
|
this.msg_ = msg;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets event time in milliseconds since 1970.
|
|
* @return {number} event time in millis since 1970.
|
|
*/
|
|
getMillis() {
|
|
return this.time_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Sets event time in milliseconds since 1970.
|
|
* @param {number} time event time in millis since 1970.
|
|
*/
|
|
setMillis(time) {
|
|
this.time_ = time;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the sequence number. Sequence numbers are normally assigned when a
|
|
* LogRecord is constructed or reset in incrementally increasing order.
|
|
* @return {number}
|
|
*/
|
|
getSequenceNumber() {
|
|
return this.sequenceNumber_;
|
|
};
|
|
};
|
|
|
|
|
|
/**
|
|
* A sequence counter for assigning increasing sequence numbers to LogRecord
|
|
* objects.
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
goog.log.LogRecord.nextSequenceNumber_ = 0;
|
|
|
|
|
|
/**
|
|
* A type that describes a function that handles logs.
|
|
* @typedef {function(!goog.log.LogRecord): ?}
|
|
*/
|
|
goog.log.LogRecordHandler;
|
|
|
|
|
|
/**
|
|
* A LogRegistryEntry_ contains data about a Logger.
|
|
* @final
|
|
*/
|
|
goog.log.LogRegistryEntry_ = class LogRegistryEntry_ {
|
|
/**
|
|
* @param {string} name
|
|
* @param {!goog.log.LogRegistryEntry_|null=} parent
|
|
*/
|
|
constructor(name, parent = null) {
|
|
/**
|
|
* The minimum log level that a message must be for it to be logged by the
|
|
* Logger corresponding to this LogRegistryEntry_. If null, the parent's
|
|
* log level is used instead.
|
|
* @type {?goog.log.Level}
|
|
*/
|
|
this.level = null;
|
|
|
|
/**
|
|
* A list of functions that will be called when the Logger corresponding to
|
|
* this LogRegistryEntry_ is used to log a message.
|
|
* @type {!Array<!goog.log.LogRecordHandler>}
|
|
*/
|
|
this.handlers = [];
|
|
|
|
/**
|
|
* A reference to LogRegistryEntry_ objects that correspond to the direct
|
|
* ancestor of the Logger represented by this LogRegistryEntry_ object
|
|
* (via name, treated as a dot-separated namespace).
|
|
* @type {!goog.log.LogRegistryEntry_|null}
|
|
*/
|
|
this.parent = parent || null;
|
|
|
|
/**
|
|
* A list of references to LogRegistryEntry_ objects that correspond to the
|
|
* direct descendants of the Logger represented by this LogRegistryEntry_
|
|
* object (via name, treated as a dot-separated namespace).
|
|
* @type {!Array<!goog.log.LogRegistryEntry_>}
|
|
*/
|
|
this.children = [];
|
|
|
|
/**
|
|
* A reference to the Logger itself.
|
|
* @type {!goog.log.Logger}
|
|
*/
|
|
this.logger = /** @type {!goog.log.Logger} */ ({getName: () => name});
|
|
}
|
|
|
|
/**
|
|
* Returns the effective level of the logger based on its ancestors' levels.
|
|
* @return {!goog.log.Level} The level.
|
|
*/
|
|
getEffectiveLevel() {
|
|
if (this.level) {
|
|
return this.level;
|
|
} else if (this.parent) {
|
|
return this.parent.getEffectiveLevel();
|
|
}
|
|
goog.asserts.fail('Root logger has no level set.');
|
|
return goog.log.Level.OFF;
|
|
};
|
|
|
|
/**
|
|
* Calls the log handlers associated with this Logger, followed by those of
|
|
* its parents, etc. until the root Logger's associated log handlers are
|
|
* called.
|
|
* @param {!goog.log.LogRecord} logRecord The log record to pass to each
|
|
* handler.
|
|
*/
|
|
publish(logRecord) {
|
|
let target = this;
|
|
while (target) {
|
|
target.handlers.forEach(handler => {
|
|
handler(logRecord);
|
|
});
|
|
target = target.parent;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* A LogRegistry_ owns references to all loggers, and is responsible for storing
|
|
* all the internal state needed for loggers to operate correctly.
|
|
*
|
|
* @final
|
|
*/
|
|
goog.log.LogRegistry_ = class LogRegistry_ {
|
|
constructor() {
|
|
/**
|
|
* Per-log information retained by this LogRegistry_.
|
|
* @type {!Object<string, !goog.log.LogRegistryEntry_>}
|
|
*/
|
|
this.entries = {};
|
|
|
|
// The root logger.
|
|
const rootLogRegistryEntry =
|
|
new goog.log.LogRegistryEntry_(goog.log.ROOT_LOGGER_NAME);
|
|
rootLogRegistryEntry.level = goog.log.Level.CONFIG;
|
|
this.entries[goog.log.ROOT_LOGGER_NAME] = rootLogRegistryEntry;
|
|
}
|
|
|
|
/**
|
|
* Gets the LogRegistry_ entry under the given name, creating the entry if one
|
|
* doesn't already exist.
|
|
* @param {string} name The name to look up.
|
|
* @param {?goog.log.Level=} level If provided, override the default logging
|
|
* level of the returned Logger with the provided level.
|
|
* @return {!goog.log.LogRegistryEntry_}
|
|
*/
|
|
getLogRegistryEntry(name, level) {
|
|
const entry = this.entries[name];
|
|
if (entry) {
|
|
if (level !== undefined) {
|
|
entry.level = level;
|
|
}
|
|
return entry;
|
|
} else {
|
|
// The logger and its associated registry entry needs to be created.
|
|
|
|
// Get its parent first.
|
|
const lastDotIndex = name.lastIndexOf('.');
|
|
const parentName = name.substr(0, lastDotIndex);
|
|
const parentLogRegistryEntry = this.getLogRegistryEntry(parentName);
|
|
|
|
// Now create the new entry, linking it with its parent.
|
|
const logRegistryEntry =
|
|
new goog.log.LogRegistryEntry_(name, parentLogRegistryEntry);
|
|
this.entries[name] = logRegistryEntry;
|
|
parentLogRegistryEntry.children.push(logRegistryEntry);
|
|
|
|
if (level !== undefined) {
|
|
logRegistryEntry.level = level;
|
|
}
|
|
|
|
return logRegistryEntry;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a list of all loggers.
|
|
* @return {!Array<!goog.log.Logger>}
|
|
*/
|
|
getAllLoggers() {
|
|
return Object.keys(this.entries)
|
|
.map(loggerName => this.entries[loggerName].logger);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* A static method that always returns the same instance of LogRegistry_.
|
|
* @return {!goog.log.LogRegistry_} The LogRegistry_ singleton instance.
|
|
*/
|
|
goog.log.LogRegistry_.getInstance = function() {
|
|
if (!goog.log.LogRegistry_.instance_) {
|
|
goog.log.LogRegistry_.instance_ = new goog.log.LogRegistry_();
|
|
}
|
|
return /** @type {!goog.log.LogRegistry_} */ (
|
|
goog.log.LogRegistry_.instance_);
|
|
};
|
|
|
|
/**
|
|
* @type {!goog.log.LogRegistry_|undefined}
|
|
* @private
|
|
*/
|
|
goog.log.LogRegistry_.instance_;
|
|
|
|
|
|
/**
|
|
* Finds or creates a logger for a named subsystem. If a logger has already been
|
|
* created with the given name it is returned. Otherwise, a new logger is
|
|
* created. If a new logger is created, it will be configured to send logging
|
|
* output to its parent's handlers.
|
|
*
|
|
* @param {string} name A name for the logger. This should be a dot-separated
|
|
* name and should normally be based on the package name or class name of
|
|
* the subsystem, such as goog.net.BrowserChannel.
|
|
* @param {?goog.log.Level=} level If provided, override the default logging
|
|
* level with the provided level. This parameter is deprecated; prefer using
|
|
* goog.log.setLevel to set the logger's level instead.
|
|
* TODO(user): Delete this parameter.
|
|
* @return {!goog.log.Logger|null} The named logger, or null if logging is
|
|
* disabled.
|
|
*/
|
|
goog.log.getLogger = function(name, level) {
|
|
if (goog.log.ENABLED) {
|
|
const loggerEntry =
|
|
goog.log.LogRegistry_.getInstance().getLogRegistryEntry(name, level);
|
|
return loggerEntry.logger;
|
|
} else {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Returns the root logger.
|
|
*
|
|
* @return {!goog.log.Logger|null} The root logger, or null if logging is
|
|
* disabled.
|
|
*/
|
|
goog.log.getRootLogger = function() {
|
|
if (goog.log.ENABLED) {
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
goog.log.ROOT_LOGGER_NAME);
|
|
return loggerEntry.logger;
|
|
} else {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
|
|
// TODO(johnlenz): try to tighten the types to these functions.
|
|
/**
|
|
* Adds a handler to the logger. This doesn't use the event system because
|
|
* we want to be able to add logging to the event system.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.LogRecordHandler} handler Handler function to
|
|
* add.
|
|
*/
|
|
goog.log.addHandler = function(logger, handler) {
|
|
if (goog.log.ENABLED && logger) {
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
logger.getName());
|
|
loggerEntry.handlers.push(handler);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Removes a handler from the logger. This doesn't use the event system because
|
|
* we want to be able to add logging to the event system.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.LogRecordHandler} handler Handler function to
|
|
* remove.
|
|
* @return {boolean} Whether the handler was removed.
|
|
*/
|
|
goog.log.removeHandler = function(logger, handler) {
|
|
if (goog.log.ENABLED && logger) {
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
logger.getName());
|
|
const indexOfHandler = loggerEntry.handlers.indexOf(handler);
|
|
if (indexOfHandler !== -1) {
|
|
loggerEntry.handlers.splice(indexOfHandler, 1);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
|
|
/**
|
|
* Set the log level specifying which message levels will be logged by this
|
|
* logger. Message levels lower than this value will be discarded.
|
|
* The level value goog.log.Level.OFF can be used to turn off logging. If the
|
|
* new level is null, it means that this node should inherit its level from its
|
|
* nearest ancestor with a specific (non-null) level value.
|
|
*
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.Level|null} level The new level.
|
|
*/
|
|
goog.log.setLevel = function(logger, level) {
|
|
if (goog.log.ENABLED && logger) {
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
logger.getName());
|
|
loggerEntry.level = level;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the log level specifying which message levels will be logged by this
|
|
* logger. Message levels lower than this value will be discarded.
|
|
* The level value goog.log.Level.OFF can be used to turn off logging. If the
|
|
* level is null, it means that this node should inherit its level from its
|
|
* nearest ancestor with a specific (non-null) level value.
|
|
*
|
|
* @param {?goog.log.Logger} logger
|
|
* @return {!goog.log.Level|null} The level.
|
|
*/
|
|
goog.log.getLevel = function(logger) {
|
|
if (goog.log.ENABLED && logger) {
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
logger.getName());
|
|
return loggerEntry.level;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
|
|
/**
|
|
* Returns the effective level of the logger based on its ancestors' levels.
|
|
* @param {?goog.log.Logger} logger
|
|
* @return {!goog.log.Level} The level.
|
|
*/
|
|
goog.log.getEffectiveLevel = function(logger) {
|
|
if (goog.log.ENABLED && logger) {
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
logger.getName());
|
|
return loggerEntry.getEffectiveLevel();
|
|
}
|
|
return goog.log.Level.OFF;
|
|
};
|
|
|
|
|
|
/**
|
|
* Checks if a message of the given level would actually be logged by this
|
|
* logger. This check is based on the goog.log.Loggers effective level, which
|
|
* may be inherited from its parent.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {?goog.log.Level} level The level to check.
|
|
* @return {boolean} Whether the message would be logged.
|
|
*/
|
|
goog.log.isLoggable = function(logger, level) {
|
|
if (goog.log.ENABLED && logger && level) {
|
|
return level.value >= goog.log.getEffectiveLevel(logger).value;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets a list of all loggers.
|
|
* @return {!Array<!goog.log.Logger>}
|
|
*/
|
|
goog.log.getAllLoggers = function() {
|
|
if (goog.log.ENABLED) {
|
|
return goog.log.LogRegistry_.getInstance().getAllLoggers();
|
|
}
|
|
return [];
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates a log record. If the logger is currently enabled for the
|
|
* given message level then the given message is forwarded to all the
|
|
* registered output Handler objects.
|
|
* TODO(user): Delete this method from the public API.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {?goog.log.Level} level One of the level identifiers.
|
|
* @param {string} msg The message to log.
|
|
* @param {*=} exception An exception associated with the message.
|
|
* @return {!goog.log.LogRecord}
|
|
*/
|
|
goog.log.getLogRecord = function(logger, level, msg, exception = undefined) {
|
|
const logRecord = goog.log.LogBuffer.getInstance().addRecord(
|
|
level || goog.log.Level.OFF, msg, logger.getName());
|
|
logRecord.setException(exception);
|
|
return logRecord;
|
|
};
|
|
|
|
|
|
/**
|
|
* Logs a goog.log.LogRecord. If the logger is currently enabled for the
|
|
* given message level then the given message is forwarded to all the
|
|
* registered output Handler objects.
|
|
* TODO(user): Delete this method from the public API.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.LogRecord} logRecord A log record to log.
|
|
*/
|
|
goog.log.publishLogRecord = function(logger, logRecord) {
|
|
if (goog.log.ENABLED && logger &&
|
|
goog.log.isLoggable(logger, logRecord.getLevel())) {
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
logger.getName());
|
|
loggerEntry.publish(logRecord);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Logs a message. If the logger is currently enabled for the
|
|
* given message level then the given message is forwarded to all the
|
|
* registered output Handler objects.
|
|
* TODO(user): The level parameter should be made required.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {?goog.log.Level} level One of the level identifiers.
|
|
* @param {!goog.log.Loggable} msg The message to log.
|
|
* @param {*=} exception An exception associated with the message.
|
|
*/
|
|
goog.log.log = function(logger, level, msg, exception = undefined) {
|
|
if (goog.log.ENABLED && logger && goog.log.isLoggable(logger, level)) {
|
|
level = level || goog.log.Level.OFF;
|
|
const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(
|
|
logger.getName());
|
|
// Message callbacks can be useful when a log message is expensive to build.
|
|
if (typeof msg === 'function') {
|
|
msg = msg();
|
|
}
|
|
const logRecord = goog.log.LogBuffer.getInstance().addRecord(
|
|
level, msg, logger.getName());
|
|
logRecord.setException(exception);
|
|
// Publish logs.
|
|
loggerEntry.publish(logRecord);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Logs a message at the goog.log.Level.SEVERE level.
|
|
* If the logger is currently enabled for the given message level then the
|
|
* given message is forwarded to all the registered output Handler objects.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.Loggable} msg The message to log.
|
|
* @param {*=} exception An exception associated with the message.
|
|
*/
|
|
goog.log.error = function(logger, msg, exception = undefined) {
|
|
if (goog.log.ENABLED && logger) {
|
|
goog.log.log(logger, goog.log.Level.SEVERE, msg, exception);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Logs a message at the goog.log.Level.WARNING level.
|
|
* If the logger is currently enabled for the given message level then the
|
|
* given message is forwarded to all the registered output Handler objects.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.Loggable} msg The message to log.
|
|
* @param {*=} exception An exception associated with the message.
|
|
*/
|
|
goog.log.warning = function(logger, msg, exception = undefined) {
|
|
if (goog.log.ENABLED && logger) {
|
|
goog.log.log(logger, goog.log.Level.WARNING, msg, exception);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Logs a message at the goog.log.Level.INFO level.
|
|
* If the logger is currently enabled for the given message level then the
|
|
* given message is forwarded to all the registered output Handler objects.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.Loggable} msg The message to log.
|
|
* @param {*=} exception An exception associated with the message.
|
|
*/
|
|
goog.log.info = function(logger, msg, exception = undefined) {
|
|
if (goog.log.ENABLED && logger) {
|
|
goog.log.log(logger, goog.log.Level.INFO, msg, exception);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Logs a message at the goog.log.Level.FINE level.
|
|
* If the logger is currently enabled for the given message level then the
|
|
* given message is forwarded to all the registered output Handler objects.
|
|
* @param {?goog.log.Logger} logger
|
|
* @param {!goog.log.Loggable} msg The message to log.
|
|
* @param {*=} exception An exception associated with the message.
|
|
*/
|
|
goog.log.fine = function(logger, msg, exception = undefined) {
|
|
if (goog.log.ENABLED && logger) {
|
|
goog.log.log(logger, goog.log.Level.FINE, msg, exception);
|
|
}
|
|
};
|