# 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 |
23 | goog.provide('goog.debug.LogManager');
24 | goog.provide('goog.debug.Loggable');
25 | goog.provide('goog.debug.Logger');
26 | goog.provide('goog.debug.Logger.Level');
27 |
28 | goog.require('goog.array');
29 | goog.require('goog.asserts');
30 | goog.require('goog.debug');
31 | goog.require('goog.debug.LogBuffer');
32 | goog.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 | */
44 | goog.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 | */
65 | goog.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 */
101 | goog.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 | */
109 | goog.define('goog.debug.Logger.ENABLE_HIERARCHY', true);
110 |
111 |
112 | if (!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 | */
157 | goog.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 | */
176 | goog.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 | */
186 | goog.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 | */
195 | goog.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 | */
203 | goog.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 | */
211 | goog.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 | */
219 | goog.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 | */
227 | goog.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 | */
235 | goog.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 | */
243 | goog.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 |
251 | goog.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 | */
259 | goog.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 | */
267 | goog.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 | */
286 | goog.debug.Logger.Level.predefinedLevelsCache_ = null;
287 |
288 |
289 | /**
290 | * Creates the predefined levels cache and populates it.
291 | * @private
292 | */
293 | goog.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 | */
308 | goog.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 | */
322 | goog.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 | */
355 | goog.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 | */
366 | goog.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 | */
390 | goog.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 | */
400 | goog.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 | */
423 | goog.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 | */
438 | goog.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 | */
448 | goog.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 | */
465 | goog.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 | */
488 | goog.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 | */
498 | goog.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 | */
524 | goog.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 | */
539 | goog.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 | */
561 | goog.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 | */
583 | goog.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 | */
597 | goog.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 | */
611 | goog.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 | */
625 | goog.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 | */
639 | goog.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 | */
653 | goog.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 | */
667 | goog.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 | */
681 | goog.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 | */
694 | goog.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 | */
706 | goog.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 | */
727 | goog.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 | */
741 | goog.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 | */
752 | goog.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 | */
763 | goog.debug.LogManager = {};
764 |
765 |
766 | /**
767 | * Map of logger names to logger objects.
768 | *
769 | * @type {!Object<string, !goog.debug.Logger>}
770 | * @private
771 | */
772 | goog.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 | */
780 | goog.debug.LogManager.rootLogger_ = null;
781 |
782 |
783 | /**
784 | * Initializes the LogManager if not already initialized.
785 | */
786 | goog.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 | */
802 | goog.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 | */
813 | goog.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 | */
827 | goog.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 | */
841 | goog.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 | */
857 | goog.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 | };