Logger class
Use a Logger to log debug messages. Loggers are named using a hierarchical dot-separated name convention.
class Logger {
/** Simple name of this logger. */
final String name;
/** The full name of this logger, which includes the parent's full name. */
String get fullName =>
(parent == null || parent.name == '') ? name : '${parent.fullName}.$name';
/** Parent of this logger in the hierarchy of loggers. */
final Logger parent;
/** 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. */
final Map<String, Logger> children;
/** Controller used to notify when log entries are added to this logger. */
StreamController<LogRecord> _controller;
/**
* 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 '.'");
}
// Split hierarchical names (separated with '.').
int dot = name.lastIndexOf('.');
Logger parent = null;
String thisName;
if (dot == -1) {
if (name != '') parent = new Logger('');
thisName = name;
} else {
parent = new Logger(name.substring(0, dot));
thisName = name.substring(dot + 1);
}
return new Logger._internal(thisName, parent, new Map<String, Logger>());
}
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;
}
/**
* Effective level considering the levels established in this logger's parents
* (when [hierarchicalLoggingEnabled] is true).
*/
Level get level {
if (hierarchicalLoggingEnabled) {
if (_level != null) return _level;
if (parent != null) return parent.level;
}
return _rootLevel;
}
/** Override the level for this particular [Logger] and its children. */
void set level(Level value) {
if (hierarchicalLoggingEnabled && parent != null) {
_level = value;
} else {
if (parent != null) {
throw new UnsupportedError(
'Please set "hierarchicalLoggingEnabled" to true if you want to '
'change the level on a non-root logger.');
}
_rootLevel = value;
}
}
/**
* Returns an stream of messages added to this [Logger]. You can listen for
* messages using the standard stream APIs, for instance:
* logger.onRecord.listen((record) { ... });
*/
Stream<LogRecord> get onRecord => _getStream();
void clearListeners() {
if (hierarchicalLoggingEnabled || parent == null) {
if (_controller != null) {
_controller.close();
_controller = null;
}
} else {
root.clearListeners();
}
}
/** Whether a message for [value]'s level is loggable in this logger. */
bool isLoggable(Level value) => (value >= level);
/**
* 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).
*/
void log(Level logLevel, String message, [Object error,
StackTrace stackTrace]) {
if (isLoggable(logLevel)) {
var record = new LogRecord(logLevel, message, fullName, error,
stackTrace);
if (hierarchicalLoggingEnabled) {
var target = this;
while (target != null) {
target._publish(record);
target = target.parent;
}
} else {
root._publish(record);
}
}
}
/** Log message at level [Level.FINEST]. */
void finest(String message, [Object error, StackTrace stackTrace]) =>
log(Level.FINEST, message, error, stackTrace);
/** Log message at level [Level.FINER]. */
void finer(String message, [Object error, StackTrace stackTrace]) =>
log(Level.FINER, message, error, stackTrace);
/** Log message at level [Level.FINE]. */
void fine(String message, [Object error, StackTrace stackTrace]) =>
log(Level.FINE, message, error, stackTrace);
/** Log message at level [Level.CONFIG]. */
void config(String message, [Object error, StackTrace stackTrace]) =>
log(Level.CONFIG, message, error, stackTrace);
/** Log message at level [Level.INFO]. */
void info(String message, [Object error, StackTrace stackTrace]) =>
log(Level.INFO, message, error, stackTrace);
/** Log message at level [Level.WARNING]. */
void warning(String message, [Object error, StackTrace stackTrace]) =>
log(Level.WARNING, message, error, stackTrace);
/** Log message at level [Level.SEVERE]. */
void severe(String message, [Object error, StackTrace stackTrace]) =>
log(Level.SEVERE, message, error, stackTrace);
/** Log message at level [Level.SHOUT]. */
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);
}
return _controller.stream;
} else {
return root._getStream();
}
}
void _publish(LogRecord record) {
if (_controller != null) {
_controller.add(record);
}
}
/** Top-level root [Logger]. */
static Logger get root => new Logger('');
/** All [Logger]s in the system. */
static final Map<String, Logger> _loggers = <String, Logger>{};
}
Static Properties
Constructors
Properties
final Map<String, Logger> children #
Children in the hierarchy of loggers, indexed by their simple names.
final Map<String, Logger> children
final String fullName #
The full name of this logger, which includes the parent's full name.
String get fullName =>
(parent == null || parent.name == '') ? name : '${parent.fullName}.$name';
Level get level #
Effective level considering the levels established in this logger's parents (when hierarchicalLoggingEnabled is true).
Level get level {
if (hierarchicalLoggingEnabled) {
if (_level != null) return _level;
if (parent != null) return parent.level;
}
return _rootLevel;
}
void set level(Level value) #
Override the level for this particular Logger and its children.
void set level(Level value) {
if (hierarchicalLoggingEnabled && parent != null) {
_level = value;
} else {
if (parent != null) {
throw new UnsupportedError(
'Please set "hierarchicalLoggingEnabled" to true if you want to '
'change the level on a non-root logger.');
}
_rootLevel = value;
}
}
Methods
void clearListeners() #
void clearListeners() {
if (hierarchicalLoggingEnabled || parent == null) {
if (_controller != null) {
_controller.close();
_controller = null;
}
} else {
root.clearListeners();
}
}
void config(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.CONFIG.
void config(String message, [Object error, StackTrace stackTrace]) => log(Level.CONFIG, message, error, stackTrace);
void fine(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.FINE.
void fine(String message, [Object error, StackTrace stackTrace]) => log(Level.FINE, message, error, stackTrace);
void finer(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.FINER.
void finer(String message, [Object error, StackTrace stackTrace]) => log(Level.FINER, message, error, stackTrace);
void finest(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.FINEST.
void finest(String message, [Object error, StackTrace stackTrace]) => log(Level.FINEST, message, error, stackTrace);
void info(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.INFO.
void info(String message, [Object error, StackTrace stackTrace]) => log(Level.INFO, message, error, stackTrace);
bool isLoggable(Level value) #
Whether a message for value's level is loggable in this logger.
bool isLoggable(Level value) => (value >= level);
void log(Level logLevel, String message, [Object error, StackTrace stackTrace]) #
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).
void log(Level logLevel, String message, [Object error,
StackTrace stackTrace]) {
if (isLoggable(logLevel)) {
var record = new LogRecord(logLevel, message, fullName, error,
stackTrace);
if (hierarchicalLoggingEnabled) {
var target = this;
while (target != null) {
target._publish(record);
target = target.parent;
}
} else {
root._publish(record);
}
}
}
void severe(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.SEVERE.
void severe(String message, [Object error, StackTrace stackTrace]) => log(Level.SEVERE, message, error, stackTrace);
void shout(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.SHOUT.
void shout(String message, [Object error, StackTrace stackTrace]) => log(Level.SHOUT, message, error, stackTrace);
void warning(String message, [Object error, StackTrace stackTrace]) #
Log message at level Level.WARNING.
void warning(String message, [Object error, StackTrace stackTrace]) => log(Level.WARNING, message, error, stackTrace);