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( |
548 | level, msg, opt_exception, goog.debug.Logger.prototype.log)); |
549 | } |
550 | }; |
551 | |
552 | |
553 | /** |
554 | * Creates a new log record and adds the exception (if present) to it. |
555 | * @param {goog.debug.Logger.Level} level One of the level identifiers. |
556 | * @param {string} msg The string message. |
557 | * @param {Error|Object=} opt_exception An exception associated with the |
558 | * message. |
559 | * @param {Function=} opt_fnStackContext A function to use as the base |
560 | * of the stack trace used in the log record. |
561 | * @return {!goog.debug.LogRecord} A log record. |
562 | * @suppress {es5Strict} |
563 | */ |
564 | goog.debug.Logger.prototype.getLogRecord = function( |
565 | level, msg, opt_exception, opt_fnStackContext) { |
566 | if (goog.debug.LogBuffer.isBufferingEnabled()) { |
567 | var logRecord = |
568 | goog.debug.LogBuffer.getInstance().addRecord(level, msg, this.name_); |
569 | } else { |
570 | logRecord = new goog.debug.LogRecord(level, String(msg), this.name_); |
571 | } |
572 | if (opt_exception) { |
573 | var context; |
574 | if (goog.STRICT_MODE_COMPATIBLE) { |
575 | context = opt_fnStackContext || goog.debug.Logger.prototype.getLogRecord; |
576 | } else { |
577 | context = opt_fnStackContext || arguments.callee.caller; |
578 | } |
579 | |
580 | logRecord.setException(opt_exception); |
581 | logRecord.setExceptionText( |
582 | goog.debug.exposeException(opt_exception, |
583 | opt_fnStackContext || goog.debug.Logger.prototype.getLogRecord)); |
584 | } |
585 | return logRecord; |
586 | }; |
587 | |
588 | |
589 | /** |
590 | * Logs a message at the Logger.Level.SHOUT level. |
591 | * If the logger is currently enabled for the given message level then the |
592 | * given message is forwarded to all the registered output Handler objects. |
593 | * @param {goog.debug.Loggable} msg The message to log. |
594 | * @param {Error=} opt_exception An exception associated with the message. |
595 | */ |
596 | goog.debug.Logger.prototype.shout = function(msg, opt_exception) { |
597 | if (goog.debug.LOGGING_ENABLED) { |
598 | this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception); |
599 | } |
600 | }; |
601 | |
602 | |
603 | /** |
604 | * Logs a message at the Logger.Level.SEVERE level. |
605 | * If the logger is currently enabled for the given message level then the |
606 | * given message is forwarded to all the registered output Handler objects. |
607 | * @param {goog.debug.Loggable} msg The message to log. |
608 | * @param {Error=} opt_exception An exception associated with the message. |
609 | */ |
610 | goog.debug.Logger.prototype.severe = function(msg, opt_exception) { |
611 | if (goog.debug.LOGGING_ENABLED) { |
612 | this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception); |
613 | } |
614 | }; |
615 | |
616 | |
617 | /** |
618 | * Logs a message at the Logger.Level.WARNING level. |
619 | * If the logger is currently enabled for the given message level then the |
620 | * given message is forwarded to all the registered output Handler objects. |
621 | * @param {goog.debug.Loggable} msg The message to log. |
622 | * @param {Error=} opt_exception An exception associated with the message. |
623 | */ |
624 | goog.debug.Logger.prototype.warning = function(msg, opt_exception) { |
625 | if (goog.debug.LOGGING_ENABLED) { |
626 | this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception); |
627 | } |
628 | }; |
629 | |
630 | |
631 | /** |
632 | * Logs a message at the Logger.Level.INFO level. |
633 | * If the logger is currently enabled for the given message level then the |
634 | * given message is forwarded to all the registered output Handler objects. |
635 | * @param {goog.debug.Loggable} msg The message to log. |
636 | * @param {Error=} opt_exception An exception associated with the message. |
637 | */ |
638 | goog.debug.Logger.prototype.info = function(msg, opt_exception) { |
639 | if (goog.debug.LOGGING_ENABLED) { |
640 | this.log(goog.debug.Logger.Level.INFO, msg, opt_exception); |
641 | } |
642 | }; |
643 | |
644 | |
645 | /** |
646 | * Logs a message at the Logger.Level.CONFIG level. |
647 | * If the logger is currently enabled for the given message level then the |
648 | * given message is forwarded to all the registered output Handler objects. |
649 | * @param {goog.debug.Loggable} msg The message to log. |
650 | * @param {Error=} opt_exception An exception associated with the message. |
651 | */ |
652 | goog.debug.Logger.prototype.config = function(msg, opt_exception) { |
653 | if (goog.debug.LOGGING_ENABLED) { |
654 | this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception); |
655 | } |
656 | }; |
657 | |
658 | |
659 | /** |
660 | * Logs a message at the Logger.Level.FINE level. |
661 | * If the logger is currently enabled for the given message level then the |
662 | * given message is forwarded to all the registered output Handler objects. |
663 | * @param {goog.debug.Loggable} msg The message to log. |
664 | * @param {Error=} opt_exception An exception associated with the message. |
665 | */ |
666 | goog.debug.Logger.prototype.fine = function(msg, opt_exception) { |
667 | if (goog.debug.LOGGING_ENABLED) { |
668 | this.log(goog.debug.Logger.Level.FINE, msg, opt_exception); |
669 | } |
670 | }; |
671 | |
672 | |
673 | /** |
674 | * Logs a message at the Logger.Level.FINER level. |
675 | * If the logger is currently enabled for the given message level then the |
676 | * given message is forwarded to all the registered output Handler objects. |
677 | * @param {goog.debug.Loggable} msg The message to log. |
678 | * @param {Error=} opt_exception An exception associated with the message. |
679 | */ |
680 | goog.debug.Logger.prototype.finer = function(msg, opt_exception) { |
681 | if (goog.debug.LOGGING_ENABLED) { |
682 | this.log(goog.debug.Logger.Level.FINER, msg, opt_exception); |
683 | } |
684 | }; |
685 | |
686 | |
687 | /** |
688 | * Logs a message at the Logger.Level.FINEST level. |
689 | * If the logger is currently enabled for the given message level then the |
690 | * given message is forwarded to all the registered output Handler objects. |
691 | * @param {goog.debug.Loggable} msg The message to log. |
692 | * @param {Error=} opt_exception An exception associated with the message. |
693 | */ |
694 | goog.debug.Logger.prototype.finest = function(msg, opt_exception) { |
695 | if (goog.debug.LOGGING_ENABLED) { |
696 | this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception); |
697 | } |
698 | }; |
699 | |
700 | |
701 | /** |
702 | * Logs a LogRecord. If the logger is currently enabled for the |
703 | * given message level then the given message is forwarded to all the |
704 | * registered output Handler objects. |
705 | * @param {goog.debug.LogRecord} logRecord A log record to log. |
706 | */ |
707 | goog.debug.Logger.prototype.logRecord = function(logRecord) { |
708 | if (goog.debug.LOGGING_ENABLED && this.isLoggable(logRecord.getLevel())) { |
709 | this.doLogRecord_(logRecord); |
710 | } |
711 | }; |
712 | |
713 | |
714 | /** |
715 | * Logs a LogRecord. |
716 | * @param {goog.debug.LogRecord} logRecord A log record to log. |
717 | * @private |
718 | */ |
719 | goog.debug.Logger.prototype.doLogRecord_ = function(logRecord) { |
720 | goog.debug.Logger.logToProfilers('log:' + logRecord.getMessage()); |
721 | if (goog.debug.Logger.ENABLE_HIERARCHY) { |
722 | var target = this; |
723 | while (target) { |
724 | target.callPublish_(logRecord); |
725 | target = target.getParent(); |
726 | } |
727 | } else { |
728 | for (var i = 0, handler; handler = goog.debug.Logger.rootHandlers_[i++]; ) { |
729 | handler(logRecord); |
730 | } |
731 | } |
732 | }; |
733 | |
734 | |
735 | /** |
736 | * Calls the handlers for publish. |
737 | * @param {goog.debug.LogRecord} logRecord The log record to publish. |
738 | * @private |
739 | */ |
740 | goog.debug.Logger.prototype.callPublish_ = function(logRecord) { |
741 | if (this.handlers_) { |
742 | for (var i = 0, handler; handler = this.handlers_[i]; i++) { |
743 | handler(logRecord); |
744 | } |
745 | } |
746 | }; |
747 | |
748 | |
749 | /** |
750 | * Sets the parent of this logger. This is used for setting up the logger tree. |
751 | * @param {goog.debug.Logger} parent The parent logger. |
752 | * @private |
753 | */ |
754 | goog.debug.Logger.prototype.setParent_ = function(parent) { |
755 | this.parent_ = parent; |
756 | }; |
757 | |
758 | |
759 | /** |
760 | * Adds a child to this logger. This is used for setting up the logger tree. |
761 | * @param {string} name The leaf name of the child. |
762 | * @param {goog.debug.Logger} logger The child logger. |
763 | * @private |
764 | */ |
765 | goog.debug.Logger.prototype.addChild_ = function(name, logger) { |
766 | this.getChildren()[name] = logger; |
767 | }; |
768 | |
769 | |
770 | /** |
771 | * There is a single global LogManager object that is used to maintain a set of |
772 | * shared state about Loggers and log services. This is loosely based on the |
773 | * java class java.util.logging.LogManager. |
774 | */ |
775 | goog.debug.LogManager = {}; |
776 | |
777 | |
778 | /** |
779 | * Map of logger names to logger objects. |
780 | * |
781 | * @type {!Object.<string, !goog.debug.Logger>} |
782 | * @private |
783 | */ |
784 | goog.debug.LogManager.loggers_ = {}; |
785 | |
786 | |
787 | /** |
788 | * The root logger which is the root of the logger tree. |
789 | * @type {goog.debug.Logger} |
790 | * @private |
791 | */ |
792 | goog.debug.LogManager.rootLogger_ = null; |
793 | |
794 | |
795 | /** |
796 | * Initializes the LogManager if not already initialized. |
797 | */ |
798 | goog.debug.LogManager.initialize = function() { |
799 | if (!goog.debug.LogManager.rootLogger_) { |
800 | goog.debug.LogManager.rootLogger_ = new goog.debug.Logger( |
801 | goog.debug.Logger.ROOT_LOGGER_NAME); |
802 | goog.debug.LogManager.loggers_[goog.debug.Logger.ROOT_LOGGER_NAME] = |
803 | goog.debug.LogManager.rootLogger_; |
804 | goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG); |
805 | } |
806 | }; |
807 | |
808 | |
809 | /** |
810 | * Returns all the loggers. |
811 | * @return {!Object.<string, !goog.debug.Logger>} Map of logger names to logger |
812 | * objects. |
813 | */ |
814 | goog.debug.LogManager.getLoggers = function() { |
815 | return goog.debug.LogManager.loggers_; |
816 | }; |
817 | |
818 | |
819 | /** |
820 | * Returns the root of the logger tree namespace, the logger with the empty |
821 | * string as its name. |
822 | * |
823 | * @return {!goog.debug.Logger} The root logger. |
824 | */ |
825 | goog.debug.LogManager.getRoot = function() { |
826 | goog.debug.LogManager.initialize(); |
827 | return /** @type {!goog.debug.Logger} */ (goog.debug.LogManager.rootLogger_); |
828 | }; |
829 | |
830 | |
831 | /** |
832 | * Finds a named logger. |
833 | * |
834 | * @param {string} name A name for the logger. This should be a dot-separated |
835 | * name and should normally be based on the package name or class name of the |
836 | * subsystem, such as goog.net.BrowserChannel. |
837 | * @return {!goog.debug.Logger} The named logger. |
838 | */ |
839 | goog.debug.LogManager.getLogger = function(name) { |
840 | goog.debug.LogManager.initialize(); |
841 | var ret = goog.debug.LogManager.loggers_[name]; |
842 | return ret || goog.debug.LogManager.createLogger_(name); |
843 | }; |
844 | |
845 | |
846 | /** |
847 | * Creates a function that can be passed to goog.debug.catchErrors. The function |
848 | * will log all reported errors using the given logger. |
849 | * @param {goog.debug.Logger=} opt_logger The logger to log the errors to. |
850 | * Defaults to the root logger. |
851 | * @return {function(Object)} The created function. |
852 | */ |
853 | goog.debug.LogManager.createFunctionForCatchErrors = function(opt_logger) { |
854 | return function(info) { |
855 | var logger = opt_logger || goog.debug.LogManager.getRoot(); |
856 | logger.severe('Error: ' + info.message + ' (' + info.fileName + |
857 | ' @ Line: ' + info.line + ')'); |
858 | }; |
859 | }; |
860 | |
861 | |
862 | /** |
863 | * Creates the named logger. Will also create the parents of the named logger |
864 | * if they don't yet exist. |
865 | * @param {string} name The name of the logger. |
866 | * @return {!goog.debug.Logger} The named logger. |
867 | * @private |
868 | */ |
869 | goog.debug.LogManager.createLogger_ = function(name) { |
870 | // find parent logger |
871 | var logger = new goog.debug.Logger(name); |
872 | if (goog.debug.Logger.ENABLE_HIERARCHY) { |
873 | var lastDotIndex = name.lastIndexOf('.'); |
874 | var parentName = name.substr(0, lastDotIndex); |
875 | var leafName = name.substr(lastDotIndex + 1); |
876 | var parentLogger = goog.debug.LogManager.getLogger(parentName); |
877 | |
878 | // tell the parent about the child and the child about the parent |
879 | parentLogger.addChild_(leafName, logger); |
880 | logger.setParent_(parentLogger); |
881 | } |
882 | |
883 | goog.debug.LogManager.loggers_[name] = logger; |
884 | return logger; |
885 | }; |