Path: blob/trunk/third_party/closure/goog/log/log.js
4532 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Basic strippable logging definitions.8* @see http://go/closurelogging9*/1011goog.provide('goog.log');12goog.provide('goog.log.Level');13goog.provide('goog.log.LogBuffer');14goog.provide('goog.log.LogRecord');15goog.provide('goog.log.Logger');1617goog.require('goog.asserts');18goog.require('goog.debug');192021/**22* A message value that can be handled by a goog.log.Logger.23*24* Functions are treated like callbacks, but are only called when the event's25* log level is enabled. This is useful for logging messages that are expensive26* to construct.27*28* @typedef {string|function(): string}29*/30goog.log.Loggable;3132/** @define {boolean} Whether logging is enabled. */33goog.log.ENABLED = goog.define('goog.log.ENABLED', goog.debug.LOGGING_ENABLED);3435/** @const */36goog.log.ROOT_LOGGER_NAME = '';373839// TODO(user): Make goog.log.Level an enum.40/**41* The goog.log.Level class defines a set of standard logging levels that42* can be used to control logging output. The logging goog.log.Level objects43* are ordered and are specified by ordered integers. Enabling logging44* at a given level also enables logging at all higher levels.45* <p>46* Clients should normally use the predefined goog.log.Level constants such47* as goog.log.Level.SEVERE.48* <p>49* The levels in descending order are:50* <ul>51* <li>SEVERE (highest value)52* <li>WARNING53* <li>INFO54* <li>CONFIG55* <li>FINE56* <li>FINER57* <li>FINEST (lowest value)58* </ul>59* In addition there is a level OFF that can be used to turn60* off logging, and a level ALL that can be used to enable61* logging of all messages.62*63* @final64*/65goog.log.Level = class Level {66/**67* @param {string} name The name of the level.68* @param {number} value The numeric value of the level.69*/70constructor(name, value) {71/**72* The name of the level73* @type {string}74* @const75*/76this.name = name;7778/**79* The numeric value of the level80* @type {number}81*/82this.value = value;83}8485/**86* @return {string} String representation of the logger level.87* @override88*/89toString() {90return this.name;91}92};939495/**96* OFF is a special level that can be used to turn off logging.97* This level is initialized to <CODE>Infinity</CODE>.98* @type {!goog.log.Level}99*/100goog.log.Level.OFF = new goog.log.Level('OFF', Infinity);101102103/**104* SHOUT is a message level for extra debugging loudness.105* This level is initialized to <CODE>1200</CODE>.106* @type {!goog.log.Level}107*/108goog.log.Level.SHOUT = new goog.log.Level('SHOUT', 1200);109110111/**112* SEVERE is a message level indicating a serious failure.113* This level is initialized to <CODE>1000</CODE>.114* @type {!goog.log.Level}115*/116goog.log.Level.SEVERE = new goog.log.Level('SEVERE', 1000);117118119/**120* WARNING is a message level indicating a potential problem.121* This level is initialized to <CODE>900</CODE>.122* @type {!goog.log.Level}123*/124goog.log.Level.WARNING = new goog.log.Level('WARNING', 900);125126127/**128* INFO is a message level for informational messages.129* This level is initialized to <CODE>800</CODE>.130* @type {!goog.log.Level}131*/132goog.log.Level.INFO = new goog.log.Level('INFO', 800);133134135/**136* CONFIG is a message level for static configuration messages.137* This level is initialized to <CODE>700</CODE>.138* @type {!goog.log.Level}139*/140goog.log.Level.CONFIG = new goog.log.Level('CONFIG', 700);141142143/**144* FINE is a message level providing tracing information.145* This level is initialized to <CODE>500</CODE>.146* @type {!goog.log.Level}147*/148goog.log.Level.FINE = new goog.log.Level('FINE', 500);149150151/**152* FINER indicates a fairly detailed tracing message.153* This level is initialized to <CODE>400</CODE>.154* @type {!goog.log.Level}155*/156goog.log.Level.FINER = new goog.log.Level('FINER', 400);157158/**159* FINEST indicates a highly detailed tracing message.160* This level is initialized to <CODE>300</CODE>.161* @type {!goog.log.Level}162*/163164goog.log.Level.FINEST = new goog.log.Level('FINEST', 300);165166167/**168* ALL indicates that all messages should be logged.169* This level is initialized to <CODE>0</CODE>.170* @type {!goog.log.Level}171*/172goog.log.Level.ALL = new goog.log.Level('ALL', 0);173174175/**176* The predefined levels.177* @type {!Array<!goog.log.Level>}178* @final179*/180goog.log.Level.PREDEFINED_LEVELS = [181goog.log.Level.OFF, goog.log.Level.SHOUT, goog.log.Level.SEVERE,182goog.log.Level.WARNING, goog.log.Level.INFO, goog.log.Level.CONFIG,183goog.log.Level.FINE, goog.log.Level.FINER, goog.log.Level.FINEST,184goog.log.Level.ALL185];186187188/**189* A lookup map used to find the level object based on the name or value of190* the level object.191* @type {?Object}192* @private193*/194goog.log.Level.predefinedLevelsCache_ = null;195196197/**198* Creates the predefined levels cache and populates it.199* @private200*/201goog.log.Level.createPredefinedLevelsCache_ = function() {202goog.log.Level.predefinedLevelsCache_ = {};203for (let i = 0, level; level = goog.log.Level.PREDEFINED_LEVELS[i]; i++) {204goog.log.Level.predefinedLevelsCache_[level.value] = level;205goog.log.Level.predefinedLevelsCache_[level.name] = level;206}207};208209210/**211* Gets the predefined level with the given name.212* @param {string} name The name of the level.213* @return {!goog.log.Level|null} The level, or null if none found.214*/215goog.log.Level.getPredefinedLevel = function(name) {216if (!goog.log.Level.predefinedLevelsCache_) {217goog.log.Level.createPredefinedLevelsCache_();218}219220return goog.log.Level.predefinedLevelsCache_[name] || null;221};222223224/**225* Gets the highest predefined level <= #value.226* @param {number} value goog.log.Level value.227* @return {!goog.log.Level|null} The level, or null if none found.228*/229goog.log.Level.getPredefinedLevelByValue = function(value) {230if (!goog.log.Level.predefinedLevelsCache_) {231goog.log.Level.createPredefinedLevelsCache_();232}233234if (value in /** @type {!Object} */ (goog.log.Level.predefinedLevelsCache_)) {235return goog.log.Level.predefinedLevelsCache_[value];236}237238for (let i = 0; i < goog.log.Level.PREDEFINED_LEVELS.length; ++i) {239let level = goog.log.Level.PREDEFINED_LEVELS[i];240if (level.value <= value) {241return level;242}243}244return null;245};246247248/** @interface */249goog.log.Logger = class Logger {250/**251* Gets the name of the Logger.252* @return {string}253* @public254*/255getName() {}256};257258259/**260* Only for compatibility with goog.debug.Logger.Level, which is how many users261* access Level.262* TODO(user): Remove these definitions.263* @final264*/265goog.log.Logger.Level = goog.log.Level;266267268/**269* A buffer for log records. The purpose of this is to improve270* logging performance by re-using old objects when the buffer becomes full and271* to eliminate the need for each app to implement their own log buffer. The272* disadvantage to doing this is that log handlers cannot maintain references to273* log records and expect that they are not overwriten at a later point.274* @final275*/276goog.log.LogBuffer = class LogBuffer {277/**278* @param {number=} capacity The capacity of this LogBuffer instance.279*/280constructor(capacity) {281/**282* The buffer's capacity.283* @type {number}284* @private285*/286this.capacity_ =287typeof capacity === 'number' ? capacity : goog.log.LogBuffer.CAPACITY;288289/**290* The array to store the records.291* @type {!Array<!goog.log.LogRecord|undefined>}292* @private293*/294this.buffer_;295296/**297* The index of the most recently added record, or -1 if there are no298* records.299* @type {number}300* @private301*/302this.curIndex_;303304/**305* Whether the buffer is at capacity.306* @type {boolean}307* @private308*/309this.isFull_;310311this.clear();312}313314315/**316* Adds a log record to the buffer, possibly overwriting the oldest record.317* @param {!goog.log.Level} level One of the level identifiers.318* @param {string} msg The string message.319* @param {string} loggerName The name of the source logger.320* @return {!goog.log.LogRecord} The log record.321*/322addRecord(level, msg, loggerName) {323if (!this.isBufferingEnabled()) {324return new goog.log.LogRecord(level, msg, loggerName);325}326const curIndex = (this.curIndex_ + 1) % this.capacity_;327this.curIndex_ = curIndex;328if (this.isFull_) {329const ret = this.buffer_[curIndex];330ret.reset(level, msg, loggerName);331return ret;332}333this.isFull_ = curIndex == this.capacity_ - 1;334return this.buffer_[curIndex] =335new goog.log.LogRecord(level, msg, loggerName);336}337338/**339* Calls the given function for each buffered log record, starting with the340* oldest one.341* TODO(user): Make this a [Symbol.iterator] once all usages of342* goog.debug.LogBuffer can be deleted.343* @param {!goog.log.LogRecordHandler} func The function to call.344*/345forEachRecord(func) {346const buffer = this.buffer_;347// Corner case: no records.348if (!buffer[0]) {349return;350}351const curIndex = this.curIndex_;352let i = this.isFull_ ? curIndex : -1;353do {354i = (i + 1) % this.capacity_;355func(/** @type {!goog.log.LogRecord} */ (buffer[i]));356} while (i !== curIndex);357}358359/**360* @return {boolean} Whether the log buffer is enabled.361*/362isBufferingEnabled() {363return this.capacity_ > 0;364}365366/**367* @return {boolean} Return whether the log buffer is full.368*/369isFull() {370return this.isFull_;371}372373/**374* Removes all buffered log records.375*/376clear() {377this.buffer_ = new Array(this.capacity_);378this.curIndex_ = -1;379this.isFull_ = false;380}381};382383384/**385* @type {!goog.log.LogBuffer|undefined}386* @private387*/388goog.log.LogBuffer.instance_;389390391/**392* @define {number} The number of log records to buffer. 0 means disable393* buffering.394*/395goog.log.LogBuffer.CAPACITY = goog.define('goog.debug.LogBuffer.CAPACITY', 0);396397398/**399* A static method that always returns the same instance of goog.log.LogBuffer.400* @return {!goog.log.LogBuffer} The goog.log.LogBuffer singleton instance.401*/402goog.log.LogBuffer.getInstance = function() {403if (!goog.log.LogBuffer.instance_) {404goog.log.LogBuffer.instance_ =405new goog.log.LogBuffer(goog.log.LogBuffer.CAPACITY);406}407return goog.log.LogBuffer.instance_;408};409410411/**412* Whether the log buffer is enabled.413* @return {boolean}414*/415goog.log.LogBuffer.isBufferingEnabled = function() {416return goog.log.LogBuffer.getInstance().isBufferingEnabled();417};418419420/**421* LogRecord objects are used to pass logging requests between the logging422* framework and individual log handlers. These objects should not be423* constructed or reset by application code.424*/425goog.log.LogRecord = class LogRecord {426/**427* @param {?goog.log.Level} level One of the level identifiers.428* @param {string} msg The string message.429* @param {string} loggerName The name of the source logger.430* @param {number=} time Time this log record was created if other than431* now. If 0, we use #goog.now.432* @param {number=} sequenceNumber Sequence number of this log record.433* This should only be passed in when restoring a log record from434* persistence.435*/436constructor(level, msg, loggerName, time, sequenceNumber) {437/**438* Level of the LogRecord.439* @type {!goog.log.Level}440* @private441*/442this.level_;443444/**445* Name of the logger that created the record.446* @type {string}447* @private448*/449this.loggerName_;450451/**452* Message associated with the record453* @type {string}454* @private455*/456this.msg_;457458/**459* Time the LogRecord was created.460* @type {number}461* @private462*/463this.time_;464465/**466* Sequence number for the LogRecord. Each record has a unique sequence467* number that is greater than all log records created before it.468* @type {number}469* @private470*/471this.sequenceNumber_;472473/**474* Exception associated with the record475* @type {*}476* @private477*/478this.exception_ = undefined;479480this.reset(481level || goog.log.Level.OFF, msg, loggerName, time, sequenceNumber);482};483484/**485* Sets all fields of the log record.486* @param {!goog.log.Level} level One of the level identifiers.487* @param {string} msg The string message.488* @param {string} loggerName The name of the source logger.489* @param {number=} time Time this log record was created if other than490* now. If 0, we use #goog.now.491* @param {number=} sequenceNumber Sequence number of this log record.492* This should only be passed in when restoring a log record from493* persistence.494*/495reset(level, msg, loggerName, time, sequenceNumber) {496this.time_ = time || goog.now();497this.level_ = level;498this.msg_ = msg;499this.loggerName_ = loggerName;500this.exception_ = undefined;501this.sequenceNumber_ = typeof sequenceNumber === 'number' ?502sequenceNumber :503goog.log.LogRecord.nextSequenceNumber_;504};505506507/**508* Gets the source Logger's name.509*510* @return {string} source logger name (may be null).511*/512getLoggerName() {513return this.loggerName_;514};515516517/**518* Sets the source Logger's name.519*520* @param {string} name The logger name.521*/522setLoggerName(name) {523this.loggerName_ = name;524};525526527/**528* Gets the exception that is part of the log record.529*530* @return {*} the exception.531*/532getException() {533return this.exception_;534};535536537/**538* Sets the exception that is part of the log record.539* @param {*} exception the exception.540*/541setException(exception) {542this.exception_ = exception;543};544545546/**547* Gets the logging message level, for example Level.SEVERE.548* @return {!goog.log.Level} the logging message level.549*/550getLevel() {551return this.level_;552};553554555/**556* Sets the logging message level, for example Level.SEVERE.557* @param {!goog.log.Level} level the logging message level.558*/559setLevel(level) {560this.level_ = level;561};562563564/**565* Gets the "raw" log message, before localization or formatting.566* @return {string} the raw message string.567*/568getMessage() {569return this.msg_;570};571572573/**574* Sets the "raw" log message, before localization or formatting.575*576* @param {string} msg the raw message string.577*/578setMessage(msg) {579this.msg_ = msg;580};581582583/**584* Gets event time in milliseconds since 1970.585* @return {number} event time in millis since 1970.586*/587getMillis() {588return this.time_;589};590591592/**593* Sets event time in milliseconds since 1970.594* @param {number} time event time in millis since 1970.595*/596setMillis(time) {597this.time_ = time;598};599600601/**602* Gets the sequence number. Sequence numbers are normally assigned when a603* LogRecord is constructed or reset in incrementally increasing order.604* @return {number}605*/606getSequenceNumber() {607return this.sequenceNumber_;608};609};610611612/**613* A sequence counter for assigning increasing sequence numbers to LogRecord614* objects.615* @type {number}616* @private617*/618goog.log.LogRecord.nextSequenceNumber_ = 0;619620621/**622* A type that describes a function that handles logs.623* @typedef {function(!goog.log.LogRecord): ?}624*/625goog.log.LogRecordHandler;626627628/**629* A LogRegistryEntry_ contains data about a Logger.630* @final631*/632goog.log.LogRegistryEntry_ = class LogRegistryEntry_ {633/**634* @param {string} name635* @param {!goog.log.LogRegistryEntry_|null=} parent636*/637constructor(name, parent = null) {638/**639* The minimum log level that a message must be for it to be logged by the640* Logger corresponding to this LogRegistryEntry_. If null, the parent's641* log level is used instead.642* @type {?goog.log.Level}643*/644this.level = null;645646/**647* A list of functions that will be called when the Logger corresponding to648* this LogRegistryEntry_ is used to log a message.649* @type {!Array<!goog.log.LogRecordHandler>}650*/651this.handlers = [];652653/**654* A reference to LogRegistryEntry_ objects that correspond to the direct655* ancestor of the Logger represented by this LogRegistryEntry_ object656* (via name, treated as a dot-separated namespace).657* @type {!goog.log.LogRegistryEntry_|null}658*/659this.parent = parent || null;660661/**662* A list of references to LogRegistryEntry_ objects that correspond to the663* direct descendants of the Logger represented by this LogRegistryEntry_664* object (via name, treated as a dot-separated namespace).665* @type {!Array<!goog.log.LogRegistryEntry_>}666*/667this.children = [];668669/**670* A reference to the Logger itself.671* @type {!goog.log.Logger}672*/673this.logger = /** @type {!goog.log.Logger} */ ({getName: () => name});674}675676/**677* Returns the effective level of the logger based on its ancestors' levels.678* @return {!goog.log.Level} The level.679*/680getEffectiveLevel() {681if (this.level) {682return this.level;683} else if (this.parent) {684return this.parent.getEffectiveLevel();685}686goog.asserts.fail('Root logger has no level set.');687return goog.log.Level.OFF;688};689690/**691* Calls the log handlers associated with this Logger, followed by those of692* its parents, etc. until the root Logger's associated log handlers are693* called.694* @param {!goog.log.LogRecord} logRecord The log record to pass to each695* handler.696*/697publish(logRecord) {698let target = this;699while (target) {700target.handlers.forEach(handler => {701handler(logRecord);702});703target = target.parent;704}705}706};707708709/**710* A LogRegistry_ owns references to all loggers, and is responsible for storing711* all the internal state needed for loggers to operate correctly.712*713* @final714*/715goog.log.LogRegistry_ = class LogRegistry_ {716constructor() {717/**718* Per-log information retained by this LogRegistry_.719* @type {!Object<string, !goog.log.LogRegistryEntry_>}720*/721this.entries = {};722723// The root logger.724const rootLogRegistryEntry =725new goog.log.LogRegistryEntry_(goog.log.ROOT_LOGGER_NAME);726rootLogRegistryEntry.level = goog.log.Level.CONFIG;727this.entries[goog.log.ROOT_LOGGER_NAME] = rootLogRegistryEntry;728}729730/**731* Gets the LogRegistry_ entry under the given name, creating the entry if one732* doesn't already exist.733* @param {string} name The name to look up.734* @param {?goog.log.Level=} level If provided, override the default logging735* level of the returned Logger with the provided level.736* @return {!goog.log.LogRegistryEntry_}737*/738getLogRegistryEntry(name, level) {739const entry = this.entries[name];740if (entry) {741if (level !== undefined) {742entry.level = level;743}744return entry;745} else {746// The logger and its associated registry entry needs to be created.747748// Get its parent first.749const lastDotIndex = name.lastIndexOf('.');750const parentName = name.slice(0, Math.max(lastDotIndex, 0));751const parentLogRegistryEntry = this.getLogRegistryEntry(parentName);752753// Now create the new entry, linking it with its parent.754const logRegistryEntry =755new goog.log.LogRegistryEntry_(name, parentLogRegistryEntry);756this.entries[name] = logRegistryEntry;757parentLogRegistryEntry.children.push(logRegistryEntry);758759if (level !== undefined) {760logRegistryEntry.level = level;761}762763return logRegistryEntry;764}765}766767/**768* Get a list of all loggers.769* @return {!Array<!goog.log.Logger>}770*/771getAllLoggers() {772return Object.keys(this.entries)773.map(loggerName => this.entries[loggerName].logger);774}775};776777/**778* A static method that always returns the same instance of LogRegistry_.779* @return {!goog.log.LogRegistry_} The LogRegistry_ singleton instance.780*/781goog.log.LogRegistry_.getInstance = function() {782if (!goog.log.LogRegistry_.instance_) {783goog.log.LogRegistry_.instance_ = new goog.log.LogRegistry_();784}785return /** @type {!goog.log.LogRegistry_} */ (786goog.log.LogRegistry_.instance_);787};788789/**790* @type {!goog.log.LogRegistry_|undefined}791* @private792*/793goog.log.LogRegistry_.instance_;794795796/**797* Finds or creates a logger for a named subsystem. If a logger has already been798* created with the given name it is returned. Otherwise, a new logger is799* created. If a new logger is created, it will be configured to send logging800* output to its parent's handlers.801*802* @param {string} name A name for the logger. This should be a dot-separated803* name and should normally be based on the package name or class name of804* the subsystem, such as goog.net.BrowserChannel.805* @param {?goog.log.Level=} level If provided, override the default logging806* level with the provided level. This parameter is deprecated; prefer using807* goog.log.setLevel to set the logger's level instead.808* TODO(user): Delete this parameter.809* @return {!goog.log.Logger|null} The named logger, or null if logging is810* disabled.811*/812goog.log.getLogger = function(name, level) {813if (goog.log.ENABLED) {814const loggerEntry =815goog.log.LogRegistry_.getInstance().getLogRegistryEntry(name, level);816return loggerEntry.logger;817} else {818return null;819}820};821822823/**824* Returns the root logger.825*826* @return {!goog.log.Logger|null} The root logger, or null if logging is827* disabled.828*/829goog.log.getRootLogger = function() {830if (goog.log.ENABLED) {831const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(832goog.log.ROOT_LOGGER_NAME);833return loggerEntry.logger;834} else {835return null;836}837};838839840// TODO(johnlenz): try to tighten the types to these functions.841/**842* Adds a handler to the logger. This doesn't use the event system because843* we want to be able to add logging to the event system.844* @param {?goog.log.Logger} logger845* @param {!goog.log.LogRecordHandler} handler Handler function to846* add.847*/848goog.log.addHandler = function(logger, handler) {849if (goog.log.ENABLED && logger) {850const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(851logger.getName());852loggerEntry.handlers.push(handler);853}854};855856857/**858* Removes a handler from the logger. This doesn't use the event system because859* we want to be able to add logging to the event system.860* @param {?goog.log.Logger} logger861* @param {!goog.log.LogRecordHandler} handler Handler function to862* remove.863* @return {boolean} Whether the handler was removed.864*/865goog.log.removeHandler = function(logger, handler) {866if (goog.log.ENABLED && logger) {867const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(868logger.getName());869const indexOfHandler = loggerEntry.handlers.indexOf(handler);870if (indexOfHandler !== -1) {871loggerEntry.handlers.splice(indexOfHandler, 1);872return true;873}874}875return false;876};877878879/**880* Set the log level specifying which message levels will be logged by this881* logger. Message levels lower than this value will be discarded.882* The level value goog.log.Level.OFF can be used to turn off logging. If the883* new level is null, it means that this node should inherit its level from its884* nearest ancestor with a specific (non-null) level value.885*886* @param {?goog.log.Logger} logger887* @param {!goog.log.Level|null} level The new level.888*/889goog.log.setLevel = function(logger, level) {890if (goog.log.ENABLED && logger) {891const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(892logger.getName());893loggerEntry.level = level;894}895};896897898/**899* Gets the log level specifying which message levels will be logged by this900* logger. Message levels lower than this value will be discarded.901* The level value goog.log.Level.OFF can be used to turn off logging. If the902* level is null, it means that this node should inherit its level from its903* nearest ancestor with a specific (non-null) level value.904*905* @param {?goog.log.Logger} logger906* @return {!goog.log.Level|null} The level.907*/908goog.log.getLevel = function(logger) {909if (goog.log.ENABLED && logger) {910const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(911logger.getName());912return loggerEntry.level;913}914return null;915};916917918/**919* Returns the effective level of the logger based on its ancestors' levels.920* @param {?goog.log.Logger} logger921* @return {!goog.log.Level} The level.922*/923goog.log.getEffectiveLevel = function(logger) {924if (goog.log.ENABLED && logger) {925const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(926logger.getName());927return loggerEntry.getEffectiveLevel();928}929return goog.log.Level.OFF;930};931932933/**934* Checks if a message of the given level would actually be logged by this935* logger. This check is based on the goog.log.Loggers effective level, which936* may be inherited from its parent.937* @param {?goog.log.Logger} logger938* @param {?goog.log.Level} level The level to check.939* @return {boolean} Whether the message would be logged.940*/941goog.log.isLoggable = function(logger, level) {942if (goog.log.ENABLED && logger && level) {943return level.value >= goog.log.getEffectiveLevel(logger).value;944}945return false;946};947948949/**950* Gets a list of all loggers.951* @return {!Array<!goog.log.Logger>}952*/953goog.log.getAllLoggers = function() {954if (goog.log.ENABLED) {955return goog.log.LogRegistry_.getInstance().getAllLoggers();956}957return [];958};959960961/**962* Creates a log record. If the logger is currently enabled for the963* given message level then the given message is forwarded to all the964* registered output Handler objects.965* TODO(user): Delete this method from the public API.966* @param {?goog.log.Logger} logger967* @param {?goog.log.Level} level One of the level identifiers.968* @param {string} msg The message to log.969* @param {*=} exception An exception associated with the message.970* @return {!goog.log.LogRecord}971*/972goog.log.getLogRecord = function(logger, level, msg, exception = undefined) {973const logRecord = goog.log.LogBuffer.getInstance().addRecord(974level || goog.log.Level.OFF, msg, logger.getName());975logRecord.setException(exception);976return logRecord;977};978979980/**981* Logs a goog.log.LogRecord. If the logger is currently enabled for the982* given message level then the given message is forwarded to all the983* registered output Handler objects.984* TODO(user): Delete this method from the public API.985* @param {?goog.log.Logger} logger986* @param {!goog.log.LogRecord} logRecord A log record to log.987*/988goog.log.publishLogRecord = function(logger, logRecord) {989if (goog.log.ENABLED && logger &&990goog.log.isLoggable(logger, logRecord.getLevel())) {991const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(992logger.getName());993loggerEntry.publish(logRecord);994}995};996997998/**999* Logs a message. If the logger is currently enabled for the1000* given message level then the given message is forwarded to all the1001* registered output Handler objects.1002* TODO(user): The level parameter should be made required.1003* @param {?goog.log.Logger} logger1004* @param {?goog.log.Level} level One of the level identifiers.1005* @param {!goog.log.Loggable} msg The message to log.1006* @param {*=} exception An exception associated with the message.1007*/1008goog.log.log = function(logger, level, msg, exception = undefined) {1009if (goog.log.ENABLED && logger && goog.log.isLoggable(logger, level)) {1010level = level || goog.log.Level.OFF;1011const loggerEntry = goog.log.LogRegistry_.getInstance().getLogRegistryEntry(1012logger.getName());1013// Message callbacks can be useful when a log message is expensive to build.1014if (typeof msg === 'function') {1015msg = msg();1016}1017const logRecord = goog.log.LogBuffer.getInstance().addRecord(1018level, msg, logger.getName());1019logRecord.setException(exception);1020// Publish logs.1021loggerEntry.publish(logRecord);1022}1023};102410251026/**1027* Logs a message at the goog.log.Level.SEVERE level.1028* If the logger is currently enabled for the given message level then the1029* given message is forwarded to all the registered output Handler objects.1030* @param {?goog.log.Logger} logger1031* @param {!goog.log.Loggable} msg The message to log.1032* @param {*=} exception An exception associated with the message.1033*/1034goog.log.error = function(logger, msg, exception = undefined) {1035if (goog.log.ENABLED && logger) {1036goog.log.log(logger, goog.log.Level.SEVERE, msg, exception);1037}1038};103910401041/**1042* Logs a message at the goog.log.Level.WARNING level.1043* If the logger is currently enabled for the given message level then the1044* given message is forwarded to all the registered output Handler objects.1045* @param {?goog.log.Logger} logger1046* @param {!goog.log.Loggable} msg The message to log.1047* @param {*=} exception An exception associated with the message.1048*/1049goog.log.warning = function(logger, msg, exception = undefined) {1050if (goog.log.ENABLED && logger) {1051goog.log.log(logger, goog.log.Level.WARNING, msg, exception);1052}1053};105410551056/**1057* Logs a message at the goog.log.Level.INFO level.1058* If the logger is currently enabled for the given message level then the1059* given message is forwarded to all the registered output Handler objects.1060* @param {?goog.log.Logger} logger1061* @param {!goog.log.Loggable} msg The message to log.1062* @param {*=} exception An exception associated with the message.1063*/1064goog.log.info = function(logger, msg, exception = undefined) {1065if (goog.log.ENABLED && logger) {1066goog.log.log(logger, goog.log.Level.INFO, msg, exception);1067}1068};106910701071/**1072* Logs a message at the goog.log.Level.FINE level.1073* If the logger is currently enabled for the given message level then the1074* given message is forwarded to all the registered output Handler objects.1075* @param {?goog.log.Logger} logger1076* @param {!goog.log.Loggable} msg The message to log.1077* @param {*=} exception An exception associated with the message.1078*/1079goog.log.fine = function(logger, msg, exception = undefined) {1080if (goog.log.ENABLED && logger) {1081goog.log.log(logger, goog.log.Level.FINE, msg, exception);1082}1083};108410851086