Dart API ReferenceloggingLogger

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;

  /** Children in the hierarchy of loggers, indexed by their simple names. */
  Map<String, Logger> children;

  /** Handlers used to process log entries in this logger. */
  List<LoggerHandler> _handlers;

  /**
   * 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) {
    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;
    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);
    }
    final res = new Logger._internal(thisName, parent);
    _loggers[name] = res;
    return res;
  }

  Logger._internal(this.name, this.parent)
      : children = new Map<String, Logger>() {
    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. */
  set level(value) {
    if (hierarchicalLoggingEnabled && parent != null) {
      _level = value;
    } else {
      if (parent != null) {
        throw new UnsupportedOperationException(
            'Please set "hierarchicalLoggingEnabled" to true if you want to '
            'change the level on a non-root logger.');
      }
      _rootLevel = value;
    }
  }

  /**
   * Returns an event manager for this [Logger]. You can listen for log messages
   * by adding a [LoggerHandler] to an event from the event manager, for
   * instance:
   *    logger.on.record.add((record) { ... });
   */
  LoggerEvents get on => new LoggerEvents(this);

  /** Adds a handler to listen whenever a log record is added to this logger. */
  void _addHandler(LoggerHandler handler) {
    if (hierarchicalLoggingEnabled || parent == null) {
      if (_handlers == null) {
        _handlers = new List<LoggerHandler>();
      }
      _handlers.add(handler);
    } else {
      root._addHandler(handler);
    }
  }

  /** Remove a previously added handler. */
  void _removeHandler(LoggerHandler handler) {
    if (hierarchicalLoggingEnabled || parent == null) {
      if (_handlers == null) return;
      int index = _handlers.indexOf(handler);
      if (index != -1) _handlers.removeRange(index, 1);
    } else {
      root._removeHandler(handler);
    }
  }

  /** Removes all handlers previously added to this logger. */
  void _clearHandlers() {
    if (hierarchicalLoggingEnabled || parent == null) {
      _handlers = null;
    } else {
      root._clearHandlers();
    }
  }

  /** 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).
   */
  // TODO(sigmund): add support for logging exceptions.
  void log(Level logLevel, String message) {
    if (isLoggable(logLevel)) {
      var record = new LogRecord(logLevel, message, fullName);
      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) => log(Level.FINEST, message);

  /** Log message at level [Level.FINER]. */
  void finer(String message) => log(Level.FINER, message);

  /** Log message at level [Level.FINE]. */
  void fine(String message) => log(Level.FINE, message);

  /** Log message at level [Level.CONFIG]. */
  void config(String message) => log(Level.CONFIG, message);

  /** Log message at level [Level.INFO]. */
  void info(String message) => log(Level.INFO, message);

  /** Log message at level [Level.WARNING]. */
  void warning(String message) => log(Level.WARNING, message);

  /** Log message at level [Level.SEVERE]. */
  void severe(String message) => log(Level.SEVERE, message);

  /** Log message at level [Level.SHOUT]. */
  void shout(String message) => log(Level.SHOUT, message);

  void _publish(LogRecord record) {
    if (_handlers != null) {
      _handlers.forEach((h) => h(record));
    }
  }

  /** Top-level root [Logger]. */
  static get root => new Logger('');

  /** All [Logger]s in the system. */
  static Map<String, Logger> _loggers;
}

Static Properties

final root #

Top-level root Logger.

static get root => new Logger('');

Constructors

factory Logger(String name) #

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) {
  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;
  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);
  }
  final res = new Logger._internal(thisName, parent);
  _loggers[name] = res;
  return res;
}

Properties

Map<String, Logger> children #

Children in the hierarchy of loggers, indexed by their simple names.

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;
}

set level(value) #

Override the level for this particular Logger and its children.

set level(value) {
  if (hierarchicalLoggingEnabled && parent != null) {
    _level = value;
  } else {
    if (parent != null) {
      throw new UnsupportedOperationException(
          'Please set "hierarchicalLoggingEnabled" to true if you want to '
          'change the level on a non-root logger.');
    }
    _rootLevel = value;
  }
}

final String name #

Simple name of this logger.

final String name;

final LoggerEvents on #

Returns an event manager for this Logger. You can listen for log messages by adding a LoggerHandler to an event from the event manager, for instance: logger.on.record.add((record) { ... });

LoggerEvents get on => new LoggerEvents(this);

final Logger parent #

Parent of this logger in the hierarchy of loggers.

final Logger parent;

Methods

void config(String message) #

Log message at level Level.CONFIG.

void config(String message) => log(Level.CONFIG, message);

void fine(String message) #

Log message at level Level.FINE.

void fine(String message) => log(Level.FINE, message);

void finer(String message) #

Log message at level Level.FINER.

void finer(String message) => log(Level.FINER, message);

void finest(String message) #

Log message at level Level.FINEST.

void finest(String message) => log(Level.FINEST, message);

void info(String message) #

Log message at level Level.INFO.

void info(String message) => log(Level.INFO, message);

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) #

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) {
  if (isLoggable(logLevel)) {
    var record = new LogRecord(logLevel, message, fullName);
    if (hierarchicalLoggingEnabled) {
      var target = this;
      while (target != null) {
        target._publish(record);
        target = target.parent;
      }
    } else {
      root._publish(record);
    }
  }
}

void severe(String message) #

Log message at level Level.SEVERE.

void severe(String message) => log(Level.SEVERE, message);

void shout(String message) #

Log message at level Level.SHOUT.

void shout(String message) => log(Level.SHOUT, message);

void warning(String message) #

Log message at level Level.WARNING.

void warning(String message) => log(Level.WARNING, message);