Index: pkg/logging/lib/logging.dart |
diff --git a/pkg/logging/lib/logging.dart b/pkg/logging/lib/logging.dart |
index 33761453f720310ec71ec477f6780ce2b0ee464b..071b496c2f9977a7ee06354eae05fd22e9431975 100644 |
--- a/pkg/logging/lib/logging.dart |
+++ b/pkg/logging/lib/logging.dart |
@@ -5,9 +5,8 @@ |
/** |
* Support for debugging and error logging. |
* |
- * This library introduces abstractions similar to |
- * those used in other languages, such as the Closure JS |
- * Logger and java.util.logging.Logger. |
+ * This library introduces abstractions similar to those used in other |
+ * languages, such as the Closure JS Logger and java.util.logging.Logger. |
* |
* For information on installing and importing this library, see the |
* [logging package on pub.dartlang.org] |
@@ -16,6 +15,8 @@ |
library logging; |
import 'dart:async'; |
+import 'package:meta/meta.dart'; |
+import 'package:unmodifiable_collection/unmodifiable_collection.dart'; |
/** |
* Whether to allow fine-grain logging and configuration of loggers in a |
@@ -48,26 +49,26 @@ class Logger { |
/** Logging [Level] used for entries generated on this logger. */ |
Level _level; |
+ final Map<String, Logger> _children; |
+ |
/** Children in the hierarchy of loggers, indexed by their simple names. */ |
- Map<String, Logger> children; |
+ final Map<String, Logger> children; |
/** Controller used to notify when log entries are added to this logger. */ |
StreamController<LogRecord> _controller; |
- /** The broadcast stream associated with the controller. */ |
- Stream _stream; |
- |
/** |
* Singleton constructor. Calling `new Logger(name)` will return the same |
* actual instance whenever it is called with the same string name. |
*/ |
factory Logger(String name) { |
+ return _loggers.putIfAbsent(name, () => new Logger._named(name)); |
+ } |
+ |
+ factory Logger._named(String name) { |
if (name.startsWith('.')) { |
throw new ArgumentError("name shouldn't start with a '.'"); |
} |
- if (_loggers == null) _loggers = <String, Logger>{}; |
- if (_loggers.containsKey(name)) return _loggers[name]; |
- |
// Split hierarchical names (separated with '.'). |
int dot = name.lastIndexOf('.'); |
Logger parent = null; |
@@ -79,14 +80,13 @@ class Logger { |
parent = new Logger(name.substring(0, dot)); |
thisName = name.substring(dot + 1); |
} |
- final res = new Logger._internal(thisName, parent); |
- _loggers[name] = res; |
- return res; |
+ return new Logger._internal(thisName, parent, new Map<String, Logger>()); |
} |
- Logger._internal(this.name, this.parent) |
- : children = new Map<String, Logger>() { |
- if (parent != null) parent.children[name] = this; |
+ Logger._internal(this.name, this.parent, Map<String, Logger> children) : |
+ this._children = children, |
+ this.children = new UnmodifiableMapView(children) { |
+ if (parent != null) parent._children[name] = this; |
} |
/** |
@@ -102,7 +102,7 @@ class Logger { |
} |
/** Override the level for this particular [Logger] and its children. */ |
- set level(Level value) { |
+ void set level(Level value) { |
if (hierarchicalLoggingEnabled && parent != null) { |
_level = value; |
} else { |
@@ -138,14 +138,18 @@ class Logger { |
/** |
* Adds a log record for a [message] at a particular [logLevel] if |
- * `isLoggable(logLevel)` is true. Use this method to create log entries for |
- * user-defined levels. To record a message at a predefined level (e.g. |
- * [Level.INFO], [Level.WARNING], etc) you can use their specialized methods |
- * instead (e.g. [info], [warning], etc). |
+ * `isLoggable(logLevel)` is true. |
+ * |
+ * Use this method to create log entries for user-defined levels. To record a |
+ * message at a predefined level (e.g. [Level.INFO], [Level.WARNING], etc) you |
+ * can use their specialized methods instead (e.g. [info], [warning], etc). |
*/ |
- void log(Level logLevel, String message, [exception]) { |
+ void log(Level logLevel, String message, [Object error, |
+ StackTrace stackTrace]) { |
if (isLoggable(logLevel)) { |
- var record = new LogRecord(logLevel, message, fullName, exception); |
+ var record = new LogRecord(logLevel, message, fullName, error, |
+ stackTrace); |
+ |
if (hierarchicalLoggingEnabled) { |
var target = this; |
while (target != null) { |
@@ -159,44 +163,43 @@ class Logger { |
} |
/** Log message at level [Level.FINEST]. */ |
- void finest(String message, [exception]) => |
- log(Level.FINEST, message, exception); |
+ void finest(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.FINEST, message, error, stackTrace); |
/** Log message at level [Level.FINER]. */ |
- void finer(String message, [exception]) => |
- log(Level.FINER, message, exception); |
+ void finer(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.FINER, message, error, stackTrace); |
/** Log message at level [Level.FINE]. */ |
- void fine(String message, [exception]) => |
- log(Level.FINE, message, exception); |
+ void fine(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.FINE, message, error, stackTrace); |
/** Log message at level [Level.CONFIG]. */ |
- void config(String message, [exception]) => |
- log(Level.CONFIG, message, exception); |
+ void config(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.CONFIG, message, error, stackTrace); |
/** Log message at level [Level.INFO]. */ |
- void info(String message, [exception]) => |
- log(Level.INFO, message, exception); |
+ void info(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.INFO, message, error, stackTrace); |
/** Log message at level [Level.WARNING]. */ |
- void warning(String message, [exception]) => |
- log(Level.WARNING, message, exception); |
+ void warning(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.WARNING, message, error, stackTrace); |
/** Log message at level [Level.SEVERE]. */ |
- void severe(String message, [exception]) => |
- log(Level.SEVERE, message, exception); |
+ void severe(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.SEVERE, message, error, stackTrace); |
/** Log message at level [Level.SHOUT]. */ |
- void shout(String message, [exception]) => |
- log(Level.SHOUT, message, exception); |
+ void shout(String message, [Object error, StackTrace stackTrace]) => |
+ log(Level.SHOUT, message, error, stackTrace); |
Stream<LogRecord> _getStream() { |
if (hierarchicalLoggingEnabled || parent == null) { |
if (_controller == null) { |
_controller = new StreamController<LogRecord>.broadcast(sync: true); |
- _stream = _controller.stream; |
} |
- return _stream; |
+ return _controller.stream; |
} else { |
return root._getStream(); |
} |
@@ -212,7 +215,7 @@ class Logger { |
static Logger get root => new Logger(''); |
/** All [Logger]s in the system. */ |
- static Map<String, Logger> _loggers; |
+ static final Map<String, Logger> _loggers = <String, Logger>{}; |
} |
@@ -233,7 +236,6 @@ typedef void LoggerHandler(LogRecord); |
*/ |
class Level implements Comparable<Level> { |
- // TODO(sigmund): mark name/value as 'const' when the language supports it. |
final String name; |
/** |
@@ -274,7 +276,7 @@ class Level implements Comparable<Level> { |
/** Key for extra debugging loudness ([value] = 1200). */ |
static const Level SHOUT = const Level('SHOUT', 1200); |
- bool operator ==(Level other) => other != null && value == other.value; |
+ bool operator ==(Object other) => other is Level && value == other.value; |
bool operator <(Level other) => value < other.value; |
bool operator <=(Level other) => value <= other.value; |
bool operator >(Level other) => value > other.value; |
@@ -304,10 +306,21 @@ class LogRecord { |
static int _nextNumber = 0; |
- /** Associated exception (if any) when recording errors messages. */ |
- var exception; |
+ /** Associated error (if any) when recording errors messages. */ |
+ final Object error; |
+ |
+ // TODO(kevmoo) - remove before V1 |
+ /** |
+ * DEPRECATED. Use [error] instead. |
+ */ |
+ @deprecated |
+ Object get exception => error; |
+ |
+ /** Associated stackTrace (if any) when recording errors messages. */ |
+ final StackTrace stackTrace; |
- LogRecord(this.level, this.message, this.loggerName, [this.exception]) |
+ LogRecord(this.level, this.message, this.loggerName, [this.error, |
+ this.stackTrace]) |
: time = new DateTime.now(), |
sequenceNumber = LogRecord._nextNumber++; |