logger.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Definition of the Logger class. Please minimize dependencies
  16. * this file has on other closure classes as any dependency it takes won't be
  17. * able to use the logging infrastructure.
  18. *
  19. * @see ../demos/debug.html
  20. */
  21. goog.provide('goog.debug.LogManager');
  22. goog.provide('goog.debug.Loggable');
  23. goog.provide('goog.debug.Logger');
  24. goog.provide('goog.debug.Logger.Level');
  25. goog.require('goog.array');
  26. goog.require('goog.asserts');
  27. goog.require('goog.debug');
  28. goog.require('goog.debug.LogBuffer');
  29. goog.require('goog.debug.LogRecord');
  30. /**
  31. * A message value that can be handled by a Logger.
  32. *
  33. * Functions are treated like callbacks, but are only called when the event's
  34. * log level is enabled. This is useful for logging messages that are expensive
  35. * to construct.
  36. *
  37. * @typedef {string|function(): string}
  38. */
  39. goog.debug.Loggable;
  40. /**
  41. * The Logger is an object used for logging debug messages. Loggers are
  42. * normally named, using a hierarchical dot-separated namespace. Logger names
  43. * can be arbitrary strings, but they should normally be based on the package
  44. * name or class name of the logged component, such as goog.net.BrowserChannel.
  45. *
  46. * The Logger object is loosely based on the java class
  47. * java.util.logging.Logger. It supports different levels of filtering for
  48. * different loggers.
  49. *
  50. * The logger object should never be instantiated by application code. It
  51. * should always use the goog.debug.Logger.getLogger function.
  52. *
  53. * @constructor
  54. * @param {string} name The name of the Logger.
  55. * @final
  56. */
  57. goog.debug.Logger = function(name) {
  58. /**
  59. * Name of the Logger. Generally a dot-separated namespace
  60. * @private {string}
  61. */
  62. this.name_ = name;
  63. /**
  64. * Parent Logger.
  65. * @private {goog.debug.Logger}
  66. */
  67. this.parent_ = null;
  68. /**
  69. * Level that this logger only filters above. Null indicates it should
  70. * inherit from the parent.
  71. * @private {goog.debug.Logger.Level}
  72. */
  73. this.level_ = null;
  74. /**
  75. * Map of children loggers. The keys are the leaf names of the children and
  76. * the values are the child loggers.
  77. * @private {Object}
  78. */
  79. this.children_ = null;
  80. /**
  81. * Handlers that are listening to this logger.
  82. * @private {Array<Function>}
  83. */
  84. this.handlers_ = null;
  85. };
  86. /** @const */
  87. goog.debug.Logger.ROOT_LOGGER_NAME = '';
  88. /**
  89. * @define {boolean} Toggles whether loggers other than the root logger can have
  90. * log handlers attached to them and whether they can have their log level
  91. * set. Logging is a bit faster when this is set to false.
  92. */
  93. goog.define('goog.debug.Logger.ENABLE_HIERARCHY', true);
  94. if (!goog.debug.Logger.ENABLE_HIERARCHY) {
  95. /**
  96. * @type {!Array<Function>}
  97. * @private
  98. */
  99. goog.debug.Logger.rootHandlers_ = [];
  100. /**
  101. * @type {goog.debug.Logger.Level}
  102. * @private
  103. */
  104. goog.debug.Logger.rootLevel_;
  105. }
  106. /**
  107. * The Level class defines a set of standard logging levels that
  108. * can be used to control logging output. The logging Level objects
  109. * are ordered and are specified by ordered integers. Enabling logging
  110. * at a given level also enables logging at all higher levels.
  111. * <p>
  112. * Clients should normally use the predefined Level constants such
  113. * as Level.SEVERE.
  114. * <p>
  115. * The levels in descending order are:
  116. * <ul>
  117. * <li>SEVERE (highest value)
  118. * <li>WARNING
  119. * <li>INFO
  120. * <li>CONFIG
  121. * <li>FINE
  122. * <li>FINER
  123. * <li>FINEST (lowest value)
  124. * </ul>
  125. * In addition there is a level OFF that can be used to turn
  126. * off logging, and a level ALL that can be used to enable
  127. * logging of all messages.
  128. *
  129. * @param {string} name The name of the level.
  130. * @param {number} value The numeric value of the level.
  131. * @constructor
  132. * @final
  133. */
  134. goog.debug.Logger.Level = function(name, value) {
  135. /**
  136. * The name of the level
  137. * @type {string}
  138. */
  139. this.name = name;
  140. /**
  141. * The numeric value of the level
  142. * @type {number}
  143. */
  144. this.value = value;
  145. };
  146. /**
  147. * @return {string} String representation of the logger level.
  148. * @override
  149. */
  150. goog.debug.Logger.Level.prototype.toString = function() {
  151. return this.name;
  152. };
  153. /**
  154. * OFF is a special level that can be used to turn off logging.
  155. * This level is initialized to <CODE>Infinity</CODE>.
  156. * @type {!goog.debug.Logger.Level}
  157. */
  158. goog.debug.Logger.Level.OFF = new goog.debug.Logger.Level('OFF', Infinity);
  159. /**
  160. * SHOUT is a message level for extra debugging loudness.
  161. * This level is initialized to <CODE>1200</CODE>.
  162. * @type {!goog.debug.Logger.Level}
  163. */
  164. goog.debug.Logger.Level.SHOUT = new goog.debug.Logger.Level('SHOUT', 1200);
  165. /**
  166. * SEVERE is a message level indicating a serious failure.
  167. * This level is initialized to <CODE>1000</CODE>.
  168. * @type {!goog.debug.Logger.Level}
  169. */
  170. goog.debug.Logger.Level.SEVERE = new goog.debug.Logger.Level('SEVERE', 1000);
  171. /**
  172. * WARNING is a message level indicating a potential problem.
  173. * This level is initialized to <CODE>900</CODE>.
  174. * @type {!goog.debug.Logger.Level}
  175. */
  176. goog.debug.Logger.Level.WARNING = new goog.debug.Logger.Level('WARNING', 900);
  177. /**
  178. * INFO is a message level for informational messages.
  179. * This level is initialized to <CODE>800</CODE>.
  180. * @type {!goog.debug.Logger.Level}
  181. */
  182. goog.debug.Logger.Level.INFO = new goog.debug.Logger.Level('INFO', 800);
  183. /**
  184. * CONFIG is a message level for static configuration messages.
  185. * This level is initialized to <CODE>700</CODE>.
  186. * @type {!goog.debug.Logger.Level}
  187. */
  188. goog.debug.Logger.Level.CONFIG = new goog.debug.Logger.Level('CONFIG', 700);
  189. /**
  190. * FINE is a message level providing tracing information.
  191. * This level is initialized to <CODE>500</CODE>.
  192. * @type {!goog.debug.Logger.Level}
  193. */
  194. goog.debug.Logger.Level.FINE = new goog.debug.Logger.Level('FINE', 500);
  195. /**
  196. * FINER indicates a fairly detailed tracing message.
  197. * This level is initialized to <CODE>400</CODE>.
  198. * @type {!goog.debug.Logger.Level}
  199. */
  200. goog.debug.Logger.Level.FINER = new goog.debug.Logger.Level('FINER', 400);
  201. /**
  202. * FINEST indicates a highly detailed tracing message.
  203. * This level is initialized to <CODE>300</CODE>.
  204. * @type {!goog.debug.Logger.Level}
  205. */
  206. goog.debug.Logger.Level.FINEST = new goog.debug.Logger.Level('FINEST', 300);
  207. /**
  208. * ALL indicates that all messages should be logged.
  209. * This level is initialized to <CODE>0</CODE>.
  210. * @type {!goog.debug.Logger.Level}
  211. */
  212. goog.debug.Logger.Level.ALL = new goog.debug.Logger.Level('ALL', 0);
  213. /**
  214. * The predefined levels.
  215. * @type {!Array<!goog.debug.Logger.Level>}
  216. * @final
  217. */
  218. goog.debug.Logger.Level.PREDEFINED_LEVELS = [
  219. goog.debug.Logger.Level.OFF, goog.debug.Logger.Level.SHOUT,
  220. goog.debug.Logger.Level.SEVERE, goog.debug.Logger.Level.WARNING,
  221. goog.debug.Logger.Level.INFO, goog.debug.Logger.Level.CONFIG,
  222. goog.debug.Logger.Level.FINE, goog.debug.Logger.Level.FINER,
  223. goog.debug.Logger.Level.FINEST, goog.debug.Logger.Level.ALL
  224. ];
  225. /**
  226. * A lookup map used to find the level object based on the name or value of
  227. * the level object.
  228. * @type {Object}
  229. * @private
  230. */
  231. goog.debug.Logger.Level.predefinedLevelsCache_ = null;
  232. /**
  233. * Creates the predefined levels cache and populates it.
  234. * @private
  235. */
  236. goog.debug.Logger.Level.createPredefinedLevelsCache_ = function() {
  237. goog.debug.Logger.Level.predefinedLevelsCache_ = {};
  238. for (var i = 0, level; level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
  239. i++) {
  240. goog.debug.Logger.Level.predefinedLevelsCache_[level.value] = level;
  241. goog.debug.Logger.Level.predefinedLevelsCache_[level.name] = level;
  242. }
  243. };
  244. /**
  245. * Gets the predefined level with the given name.
  246. * @param {string} name The name of the level.
  247. * @return {goog.debug.Logger.Level} The level, or null if none found.
  248. */
  249. goog.debug.Logger.Level.getPredefinedLevel = function(name) {
  250. if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
  251. goog.debug.Logger.Level.createPredefinedLevelsCache_();
  252. }
  253. return goog.debug.Logger.Level.predefinedLevelsCache_[name] || null;
  254. };
  255. /**
  256. * Gets the highest predefined level <= #value.
  257. * @param {number} value Level value.
  258. * @return {goog.debug.Logger.Level} The level, or null if none found.
  259. */
  260. goog.debug.Logger.Level.getPredefinedLevelByValue = function(value) {
  261. if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
  262. goog.debug.Logger.Level.createPredefinedLevelsCache_();
  263. }
  264. if (value in /** @type {!Object} */ (
  265. goog.debug.Logger.Level.predefinedLevelsCache_)) {
  266. return goog.debug.Logger.Level.predefinedLevelsCache_[value];
  267. }
  268. for (var i = 0; i < goog.debug.Logger.Level.PREDEFINED_LEVELS.length; ++i) {
  269. var level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
  270. if (level.value <= value) {
  271. return level;
  272. }
  273. }
  274. return null;
  275. };
  276. /**
  277. * Finds or creates a logger for a named subsystem. If a logger has already been
  278. * created with the given name it is returned. Otherwise a new logger is
  279. * created. If a new logger is created its log level will be configured based
  280. * on the LogManager configuration and it will configured to also send logging
  281. * output to its parent's handlers. It will be registered in the LogManager
  282. * global namespace.
  283. *
  284. * @param {string} name A name for the logger. This should be a dot-separated
  285. * name and should normally be based on the package name or class name of the
  286. * subsystem, such as goog.net.BrowserChannel.
  287. * @return {!goog.debug.Logger} The named logger.
  288. * @deprecated use {@link goog.log} instead.
  289. */
  290. goog.debug.Logger.getLogger = function(name) {
  291. return goog.debug.LogManager.getLogger(name);
  292. };
  293. /**
  294. * Logs a message to profiling tools, if available.
  295. * {@see https://developers.google.com/web-toolkit/speedtracer/logging-api}
  296. * {@see http://msdn.microsoft.com/en-us/library/dd433074(VS.85).aspx}
  297. * @param {string} msg The message to log.
  298. */
  299. goog.debug.Logger.logToProfilers = function(msg) {
  300. // Using goog.global, as loggers might be used in window-less contexts.
  301. if (goog.global['console']) {
  302. if (goog.global['console']['timeStamp']) {
  303. // Logs a message to Firebug, Web Inspector, SpeedTracer, etc.
  304. goog.global['console']['timeStamp'](msg);
  305. } else if (goog.global['console']['markTimeline']) {
  306. // TODO(user): markTimeline is deprecated. Drop this else clause entirely
  307. // after Chrome M14 hits stable.
  308. goog.global['console']['markTimeline'](msg);
  309. }
  310. }
  311. if (goog.global['msWriteProfilerMark']) {
  312. // Logs a message to the Microsoft profiler
  313. goog.global['msWriteProfilerMark'](msg);
  314. }
  315. };
  316. /**
  317. * Gets the name of this logger.
  318. * @return {string} The name of this logger.
  319. */
  320. goog.debug.Logger.prototype.getName = function() {
  321. return this.name_;
  322. };
  323. /**
  324. * Adds a handler to the logger. This doesn't use the event system because
  325. * we want to be able to add logging to the event system.
  326. * @param {Function} handler Handler function to add.
  327. */
  328. goog.debug.Logger.prototype.addHandler = function(handler) {
  329. if (goog.debug.LOGGING_ENABLED) {
  330. if (goog.debug.Logger.ENABLE_HIERARCHY) {
  331. if (!this.handlers_) {
  332. this.handlers_ = [];
  333. }
  334. this.handlers_.push(handler);
  335. } else {
  336. goog.asserts.assert(
  337. !this.name_, 'Cannot call addHandler on a non-root logger when ' +
  338. 'goog.debug.Logger.ENABLE_HIERARCHY is false.');
  339. goog.debug.Logger.rootHandlers_.push(handler);
  340. }
  341. }
  342. };
  343. /**
  344. * Removes a handler from the logger. This doesn't use the event system because
  345. * we want to be able to add logging to the event system.
  346. * @param {Function} handler Handler function to remove.
  347. * @return {boolean} Whether the handler was removed.
  348. */
  349. goog.debug.Logger.prototype.removeHandler = function(handler) {
  350. if (goog.debug.LOGGING_ENABLED) {
  351. var handlers = goog.debug.Logger.ENABLE_HIERARCHY ?
  352. this.handlers_ :
  353. goog.debug.Logger.rootHandlers_;
  354. return !!handlers && goog.array.remove(handlers, handler);
  355. } else {
  356. return false;
  357. }
  358. };
  359. /**
  360. * Returns the parent of this logger.
  361. * @return {goog.debug.Logger} The parent logger or null if this is the root.
  362. */
  363. goog.debug.Logger.prototype.getParent = function() {
  364. return this.parent_;
  365. };
  366. /**
  367. * Returns the children of this logger as a map of the child name to the logger.
  368. * @return {!Object} The map where the keys are the child leaf names and the
  369. * values are the Logger objects.
  370. */
  371. goog.debug.Logger.prototype.getChildren = function() {
  372. if (!this.children_) {
  373. this.children_ = {};
  374. }
  375. return this.children_;
  376. };
  377. /**
  378. * Set the log level specifying which message levels will be logged by this
  379. * logger. Message levels lower than this value will be discarded.
  380. * The level value Level.OFF can be used to turn off logging. If the new level
  381. * is null, it means that this node should inherit its level from its nearest
  382. * ancestor with a specific (non-null) level value.
  383. *
  384. * @param {goog.debug.Logger.Level} level The new level.
  385. */
  386. goog.debug.Logger.prototype.setLevel = function(level) {
  387. if (goog.debug.LOGGING_ENABLED) {
  388. if (goog.debug.Logger.ENABLE_HIERARCHY) {
  389. this.level_ = level;
  390. } else {
  391. goog.asserts.assert(
  392. !this.name_, 'Cannot call setLevel() on a non-root logger when ' +
  393. 'goog.debug.Logger.ENABLE_HIERARCHY is false.');
  394. goog.debug.Logger.rootLevel_ = level;
  395. }
  396. }
  397. };
  398. /**
  399. * Gets the log level specifying which message levels will be logged by this
  400. * logger. Message levels lower than this value will be discarded.
  401. * The level value Level.OFF can be used to turn off logging. If the level
  402. * is null, it means that this node should inherit its level from its nearest
  403. * ancestor with a specific (non-null) level value.
  404. *
  405. * @return {goog.debug.Logger.Level} The level.
  406. */
  407. goog.debug.Logger.prototype.getLevel = function() {
  408. return goog.debug.LOGGING_ENABLED ? this.level_ : goog.debug.Logger.Level.OFF;
  409. };
  410. /**
  411. * Returns the effective level of the logger based on its ancestors' levels.
  412. * @return {goog.debug.Logger.Level} The level.
  413. */
  414. goog.debug.Logger.prototype.getEffectiveLevel = function() {
  415. if (!goog.debug.LOGGING_ENABLED) {
  416. return goog.debug.Logger.Level.OFF;
  417. }
  418. if (!goog.debug.Logger.ENABLE_HIERARCHY) {
  419. return goog.debug.Logger.rootLevel_;
  420. }
  421. if (this.level_) {
  422. return this.level_;
  423. }
  424. if (this.parent_) {
  425. return this.parent_.getEffectiveLevel();
  426. }
  427. goog.asserts.fail('Root logger has no level set.');
  428. return null;
  429. };
  430. /**
  431. * Checks if a message of the given level would actually be logged by this
  432. * logger. This check is based on the Loggers effective level, which may be
  433. * inherited from its parent.
  434. * @param {goog.debug.Logger.Level} level The level to check.
  435. * @return {boolean} Whether the message would be logged.
  436. */
  437. goog.debug.Logger.prototype.isLoggable = function(level) {
  438. return goog.debug.LOGGING_ENABLED &&
  439. level.value >= this.getEffectiveLevel().value;
  440. };
  441. /**
  442. * Logs a message. If the logger is currently enabled for the
  443. * given message level then the given message is forwarded to all the
  444. * registered output Handler objects.
  445. * @param {goog.debug.Logger.Level} level One of the level identifiers.
  446. * @param {goog.debug.Loggable} msg The message to log.
  447. * @param {Error|Object=} opt_exception An exception associated with the
  448. * message.
  449. */
  450. goog.debug.Logger.prototype.log = function(level, msg, opt_exception) {
  451. // java caches the effective level, not sure it's necessary here
  452. if (goog.debug.LOGGING_ENABLED && this.isLoggable(level)) {
  453. // Message callbacks can be useful when a log message is expensive to build.
  454. if (goog.isFunction(msg)) {
  455. msg = msg();
  456. }
  457. this.doLogRecord_(this.getLogRecord(level, msg, opt_exception));
  458. }
  459. };
  460. /**
  461. * Creates a new log record and adds the exception (if present) to it.
  462. * @param {goog.debug.Logger.Level} level One of the level identifiers.
  463. * @param {string} msg The string message.
  464. * @param {Error|Object=} opt_exception An exception associated with the
  465. * message.
  466. * @return {!goog.debug.LogRecord} A log record.
  467. * @suppress {es5Strict}
  468. */
  469. goog.debug.Logger.prototype.getLogRecord = function(level, msg, opt_exception) {
  470. if (goog.debug.LogBuffer.isBufferingEnabled()) {
  471. var logRecord =
  472. goog.debug.LogBuffer.getInstance().addRecord(level, msg, this.name_);
  473. } else {
  474. logRecord = new goog.debug.LogRecord(level, String(msg), this.name_);
  475. }
  476. if (opt_exception) {
  477. logRecord.setException(opt_exception);
  478. }
  479. return logRecord;
  480. };
  481. /**
  482. * Logs a message at the Logger.Level.SHOUT level.
  483. * If the logger is currently enabled for the given message level then the
  484. * given message is forwarded to all the registered output Handler objects.
  485. * @param {goog.debug.Loggable} msg The message to log.
  486. * @param {Error=} opt_exception An exception associated with the message.
  487. */
  488. goog.debug.Logger.prototype.shout = function(msg, opt_exception) {
  489. if (goog.debug.LOGGING_ENABLED) {
  490. this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception);
  491. }
  492. };
  493. /**
  494. * Logs a message at the Logger.Level.SEVERE level.
  495. * If the logger is currently enabled for the given message level then the
  496. * given message is forwarded to all the registered output Handler objects.
  497. * @param {goog.debug.Loggable} msg The message to log.
  498. * @param {Error=} opt_exception An exception associated with the message.
  499. */
  500. goog.debug.Logger.prototype.severe = function(msg, opt_exception) {
  501. if (goog.debug.LOGGING_ENABLED) {
  502. this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception);
  503. }
  504. };
  505. /**
  506. * Logs a message at the Logger.Level.WARNING level.
  507. * If the logger is currently enabled for the given message level then the
  508. * given message is forwarded to all the registered output Handler objects.
  509. * @param {goog.debug.Loggable} msg The message to log.
  510. * @param {Error=} opt_exception An exception associated with the message.
  511. */
  512. goog.debug.Logger.prototype.warning = function(msg, opt_exception) {
  513. if (goog.debug.LOGGING_ENABLED) {
  514. this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception);
  515. }
  516. };
  517. /**
  518. * Logs a message at the Logger.Level.INFO level.
  519. * If the logger is currently enabled for the given message level then the
  520. * given message is forwarded to all the registered output Handler objects.
  521. * @param {goog.debug.Loggable} msg The message to log.
  522. * @param {Error=} opt_exception An exception associated with the message.
  523. */
  524. goog.debug.Logger.prototype.info = function(msg, opt_exception) {
  525. if (goog.debug.LOGGING_ENABLED) {
  526. this.log(goog.debug.Logger.Level.INFO, msg, opt_exception);
  527. }
  528. };
  529. /**
  530. * Logs a message at the Logger.Level.CONFIG level.
  531. * If the logger is currently enabled for the given message level then the
  532. * given message is forwarded to all the registered output Handler objects.
  533. * @param {goog.debug.Loggable} msg The message to log.
  534. * @param {Error=} opt_exception An exception associated with the message.
  535. */
  536. goog.debug.Logger.prototype.config = function(msg, opt_exception) {
  537. if (goog.debug.LOGGING_ENABLED) {
  538. this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception);
  539. }
  540. };
  541. /**
  542. * Logs a message at the Logger.Level.FINE level.
  543. * If the logger is currently enabled for the given message level then the
  544. * given message is forwarded to all the registered output Handler objects.
  545. * @param {goog.debug.Loggable} msg The message to log.
  546. * @param {Error=} opt_exception An exception associated with the message.
  547. */
  548. goog.debug.Logger.prototype.fine = function(msg, opt_exception) {
  549. if (goog.debug.LOGGING_ENABLED) {
  550. this.log(goog.debug.Logger.Level.FINE, msg, opt_exception);
  551. }
  552. };
  553. /**
  554. * Logs a message at the Logger.Level.FINER level.
  555. * If the logger is currently enabled for the given message level then the
  556. * given message is forwarded to all the registered output Handler objects.
  557. * @param {goog.debug.Loggable} msg The message to log.
  558. * @param {Error=} opt_exception An exception associated with the message.
  559. */
  560. goog.debug.Logger.prototype.finer = function(msg, opt_exception) {
  561. if (goog.debug.LOGGING_ENABLED) {
  562. this.log(goog.debug.Logger.Level.FINER, msg, opt_exception);
  563. }
  564. };
  565. /**
  566. * Logs a message at the Logger.Level.FINEST level.
  567. * If the logger is currently enabled for the given message level then the
  568. * given message is forwarded to all the registered output Handler objects.
  569. * @param {goog.debug.Loggable} msg The message to log.
  570. * @param {Error=} opt_exception An exception associated with the message.
  571. */
  572. goog.debug.Logger.prototype.finest = function(msg, opt_exception) {
  573. if (goog.debug.LOGGING_ENABLED) {
  574. this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception);
  575. }
  576. };
  577. /**
  578. * Logs a LogRecord. If the logger is currently enabled for the
  579. * given message level then the given message is forwarded to all the
  580. * registered output Handler objects.
  581. * @param {goog.debug.LogRecord} logRecord A log record to log.
  582. */
  583. goog.debug.Logger.prototype.logRecord = function(logRecord) {
  584. if (goog.debug.LOGGING_ENABLED && this.isLoggable(logRecord.getLevel())) {
  585. this.doLogRecord_(logRecord);
  586. }
  587. };
  588. /**
  589. * Logs a LogRecord.
  590. * @param {goog.debug.LogRecord} logRecord A log record to log.
  591. * @private
  592. */
  593. goog.debug.Logger.prototype.doLogRecord_ = function(logRecord) {
  594. goog.debug.Logger.logToProfilers('log:' + logRecord.getMessage());
  595. if (goog.debug.Logger.ENABLE_HIERARCHY) {
  596. var target = this;
  597. while (target) {
  598. target.callPublish_(logRecord);
  599. target = target.getParent();
  600. }
  601. } else {
  602. for (var i = 0, handler; handler = goog.debug.Logger.rootHandlers_[i++];) {
  603. handler(logRecord);
  604. }
  605. }
  606. };
  607. /**
  608. * Calls the handlers for publish.
  609. * @param {goog.debug.LogRecord} logRecord The log record to publish.
  610. * @private
  611. */
  612. goog.debug.Logger.prototype.callPublish_ = function(logRecord) {
  613. if (this.handlers_) {
  614. for (var i = 0, handler; handler = this.handlers_[i]; i++) {
  615. handler(logRecord);
  616. }
  617. }
  618. };
  619. /**
  620. * Sets the parent of this logger. This is used for setting up the logger tree.
  621. * @param {goog.debug.Logger} parent The parent logger.
  622. * @private
  623. */
  624. goog.debug.Logger.prototype.setParent_ = function(parent) {
  625. this.parent_ = parent;
  626. };
  627. /**
  628. * Adds a child to this logger. This is used for setting up the logger tree.
  629. * @param {string} name The leaf name of the child.
  630. * @param {goog.debug.Logger} logger The child logger.
  631. * @private
  632. */
  633. goog.debug.Logger.prototype.addChild_ = function(name, logger) {
  634. this.getChildren()[name] = logger;
  635. };
  636. /**
  637. * There is a single global LogManager object that is used to maintain a set of
  638. * shared state about Loggers and log services. This is loosely based on the
  639. * java class java.util.logging.LogManager.
  640. * @const
  641. */
  642. goog.debug.LogManager = {};
  643. /**
  644. * Map of logger names to logger objects.
  645. *
  646. * @type {!Object<string, !goog.debug.Logger>}
  647. * @private
  648. */
  649. goog.debug.LogManager.loggers_ = {};
  650. /**
  651. * The root logger which is the root of the logger tree.
  652. * @type {goog.debug.Logger}
  653. * @private
  654. */
  655. goog.debug.LogManager.rootLogger_ = null;
  656. /**
  657. * Initializes the LogManager if not already initialized.
  658. */
  659. goog.debug.LogManager.initialize = function() {
  660. if (!goog.debug.LogManager.rootLogger_) {
  661. goog.debug.LogManager.rootLogger_ =
  662. new goog.debug.Logger(goog.debug.Logger.ROOT_LOGGER_NAME);
  663. goog.debug.LogManager.loggers_[goog.debug.Logger.ROOT_LOGGER_NAME] =
  664. goog.debug.LogManager.rootLogger_;
  665. goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG);
  666. }
  667. };
  668. /**
  669. * Returns all the loggers.
  670. * @return {!Object<string, !goog.debug.Logger>} Map of logger names to logger
  671. * objects.
  672. */
  673. goog.debug.LogManager.getLoggers = function() {
  674. return goog.debug.LogManager.loggers_;
  675. };
  676. /**
  677. * Returns the root of the logger tree namespace, the logger with the empty
  678. * string as its name.
  679. *
  680. * @return {!goog.debug.Logger} The root logger.
  681. */
  682. goog.debug.LogManager.getRoot = function() {
  683. goog.debug.LogManager.initialize();
  684. return /** @type {!goog.debug.Logger} */ (goog.debug.LogManager.rootLogger_);
  685. };
  686. /**
  687. * Finds a named logger.
  688. *
  689. * @param {string} name A name for the logger. This should be a dot-separated
  690. * name and should normally be based on the package name or class name of the
  691. * subsystem, such as goog.net.BrowserChannel.
  692. * @return {!goog.debug.Logger} The named logger.
  693. */
  694. goog.debug.LogManager.getLogger = function(name) {
  695. goog.debug.LogManager.initialize();
  696. var ret = goog.debug.LogManager.loggers_[name];
  697. return ret || goog.debug.LogManager.createLogger_(name);
  698. };
  699. /**
  700. * Creates a function that can be passed to goog.debug.catchErrors. The function
  701. * will log all reported errors using the given logger.
  702. * @param {goog.debug.Logger=} opt_logger The logger to log the errors to.
  703. * Defaults to the root logger.
  704. * @return {function(Object)} The created function.
  705. */
  706. goog.debug.LogManager.createFunctionForCatchErrors = function(opt_logger) {
  707. return function(info) {
  708. var logger = opt_logger || goog.debug.LogManager.getRoot();
  709. logger.severe(
  710. 'Error: ' + info.message + ' (' + info.fileName + ' @ Line: ' +
  711. info.line + ')');
  712. };
  713. };
  714. /**
  715. * Creates the named logger. Will also create the parents of the named logger
  716. * if they don't yet exist.
  717. * @param {string} name The name of the logger.
  718. * @return {!goog.debug.Logger} The named logger.
  719. * @private
  720. */
  721. goog.debug.LogManager.createLogger_ = function(name) {
  722. // find parent logger
  723. var logger = new goog.debug.Logger(name);
  724. if (goog.debug.Logger.ENABLE_HIERARCHY) {
  725. var lastDotIndex = name.lastIndexOf('.');
  726. var parentName = name.substr(0, lastDotIndex);
  727. var leafName = name.substr(lastDotIndex + 1);
  728. var parentLogger = goog.debug.LogManager.getLogger(parentName);
  729. // tell the parent about the child and the child about the parent
  730. parentLogger.addChild_(leafName, logger);
  731. logger.setParent_(parentLogger);
  732. }
  733. goog.debug.LogManager.loggers_[name] = logger;
  734. return logger;
  735. };