lib/goog/debug/logger.js

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