OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Provides APIs for debugging and error logging. This library introduces | 6 * Provides APIs for debugging and error logging. This library introduces |
7 * abstractions similar to those used in other languages, such as the Closure JS | 7 * abstractions similar to those used in other languages, such as the Closure JS |
8 * Logger and java.util.logging.Logger. | 8 * Logger and java.util.logging.Logger. |
9 */ | 9 */ |
10 library logging; | 10 library logging; |
11 | 11 |
12 import 'dart:async'; | 12 import 'dart:async'; |
13 | 13 |
14 import '../../meta/lib/meta.dart'; | |
15 | |
16 /** | 14 /** |
17 * Whether to allow fine-grain logging and configuration of loggers in a | 15 * Whether to allow fine-grain logging and configuration of loggers in a |
18 * hierarchy. When false, all logging is merged in the root logger. | 16 * hierarchy. When false, all logging is merged in the root logger. |
19 */ | 17 */ |
20 bool hierarchicalLoggingEnabled = false; | 18 bool hierarchicalLoggingEnabled = false; |
21 | 19 |
22 /** | 20 /** |
23 * Level for the root-logger. This will be the level of all loggers if | 21 * Level for the root-logger. This will be the level of all loggers if |
24 * [hierarchicalLoggingEnabled] is false. | 22 * [hierarchicalLoggingEnabled] is false. |
25 */ | 23 */ |
(...skipping 17 matching lines...) Expand all Loading... |
43 | 41 |
44 /** Logging [Level] used for entries generated on this logger. */ | 42 /** Logging [Level] used for entries generated on this logger. */ |
45 Level _level; | 43 Level _level; |
46 | 44 |
47 /** Children in the hierarchy of loggers, indexed by their simple names. */ | 45 /** Children in the hierarchy of loggers, indexed by their simple names. */ |
48 Map<String, Logger> children; | 46 Map<String, Logger> children; |
49 | 47 |
50 /** Controller used to notify when log entries are added to this logger. */ | 48 /** Controller used to notify when log entries are added to this logger. */ |
51 StreamController<LogRecord> _controller; | 49 StreamController<LogRecord> _controller; |
52 | 50 |
53 // TODO(sigmund): remove together with the deprecated [on] API. | |
54 Map<LoggerHandler, StreamSubscription> _deprecatedSubscriptions; | |
55 | |
56 /** | 51 /** |
57 * Singleton constructor. Calling `new Logger(name)` will return the same | 52 * Singleton constructor. Calling `new Logger(name)` will return the same |
58 * actual instance whenever it is called with the same string name. | 53 * actual instance whenever it is called with the same string name. |
59 */ | 54 */ |
60 factory Logger(String name) { | 55 factory Logger(String name) { |
61 if (name.startsWith('.')) { | 56 if (name.startsWith('.')) { |
62 throw new ArgumentError("name shouldn't start with a '.'"); | 57 throw new ArgumentError("name shouldn't start with a '.'"); |
63 } | 58 } |
64 if (_loggers == null) _loggers = <String, Logger>{}; | 59 if (_loggers == null) _loggers = <String, Logger>{}; |
65 if (_loggers.containsKey(name)) return _loggers[name]; | 60 if (_loggers.containsKey(name)) return _loggers[name]; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 if (parent != null) { | 100 if (parent != null) { |
106 throw new UnsupportedError( | 101 throw new UnsupportedError( |
107 'Please set "hierarchicalLoggingEnabled" to true if you want to ' | 102 'Please set "hierarchicalLoggingEnabled" to true if you want to ' |
108 'change the level on a non-root logger.'); | 103 'change the level on a non-root logger.'); |
109 } | 104 } |
110 _rootLevel = value; | 105 _rootLevel = value; |
111 } | 106 } |
112 } | 107 } |
113 | 108 |
114 /** | 109 /** |
115 * Returns an event manager for this [Logger]. You can listen for log messages | |
116 * by adding a [LoggerHandler] to an event from the event manager, for | |
117 * instance: | |
118 * logger.on.record.add((record) { ... }); | |
119 * | |
120 * This API is Deprecated. Use [onRecord] instead. | |
121 */ | |
122 @deprecated | |
123 LoggerEvents get on => new LoggerEvents(this); | |
124 | |
125 /** | |
126 * Returns an stream of messages added to this [Logger]. You can listen for | 110 * Returns an stream of messages added to this [Logger]. You can listen for |
127 * messages using the standard stream APIs, for instance: | 111 * messages using the standard stream APIs, for instance: |
128 * logger.onRecord.listen((record) { ... }); | 112 * logger.onRecord.listen((record) { ... }); |
129 */ | 113 */ |
130 Stream<LogRecord> get onRecord => _getStream(); | 114 Stream<LogRecord> get onRecord => _getStream(); |
131 | 115 |
132 void clearListeners() { | 116 void clearListeners() { |
133 if (hierarchicalLoggingEnabled || parent == null) { | 117 if (hierarchicalLoggingEnabled || parent == null) { |
134 if (_controller != null) { | 118 if (_controller != null) { |
135 _controller.close(); | 119 _controller.close(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 if (hierarchicalLoggingEnabled || parent == null) { | 178 if (hierarchicalLoggingEnabled || parent == null) { |
195 if (_controller == null) { | 179 if (_controller == null) { |
196 _controller = new StreamController<LogRecord>.broadcast(); | 180 _controller = new StreamController<LogRecord>.broadcast(); |
197 } | 181 } |
198 return _controller.stream; | 182 return _controller.stream; |
199 } else { | 183 } else { |
200 return root._getStream(); | 184 return root._getStream(); |
201 } | 185 } |
202 } | 186 } |
203 | 187 |
204 /** Adds a handler to listen whenever a log record is added to this logger. */ | |
205 void _addHandler(LoggerHandler handler) { | |
206 if (_deprecatedSubscriptions == null) { | |
207 _deprecatedSubscriptions = new Map<LoggerHandler, StreamSubscription>(); | |
208 } | |
209 | |
210 _deprecatedSubscriptions[handler] = onRecord.listen(handler); | |
211 } | |
212 | |
213 void _removeHandler(LoggerHandler handler) { | |
214 if (_deprecatedSubscriptions != null) { | |
215 var sub = _deprecatedSubscriptions.remove(handler); | |
216 if (sub != null) { | |
217 sub.cancel(); | |
218 } | |
219 if (_deprecatedSubscriptions.isEmpty) { | |
220 _deprecatedSubscriptions = null; | |
221 } | |
222 } | |
223 } | |
224 | |
225 void _publish(LogRecord record) { | 188 void _publish(LogRecord record) { |
226 if (_controller != null) { | 189 if (_controller != null) { |
227 _controller.add(record); | 190 _controller.add(record); |
228 } | 191 } |
229 } | 192 } |
230 | 193 |
231 /** Top-level root [Logger]. */ | 194 /** Top-level root [Logger]. */ |
232 static Logger get root => new Logger(''); | 195 static Logger get root => new Logger(''); |
233 | 196 |
234 /** All [Logger]s in the system. */ | 197 /** All [Logger]s in the system. */ |
235 static Map<String, Logger> _loggers; | 198 static Map<String, Logger> _loggers; |
236 } | 199 } |
237 | 200 |
238 | 201 |
239 /** Handler callback to process log entries as they are added to a [Logger]. */ | 202 /** Handler callback to process log entries as they are added to a [Logger]. */ |
240 typedef void LoggerHandler(LogRecord); | 203 typedef void LoggerHandler(LogRecord); |
241 | 204 |
242 | |
243 /** Event manager for a [Logger] (holds events that a [Logger] can fire). */ | |
244 class LoggerEvents { | |
245 final Logger _logger; | |
246 | |
247 LoggerEvents(this._logger); | |
248 | |
249 /** Event fired when a log record is added to a [Logger]. */ | |
250 LoggerHandlerList get record => new LoggerHandlerList(_logger); | |
251 } | |
252 | |
253 | |
254 /** List of handlers that will be called on a logger event. */ | |
255 class LoggerHandlerList { | |
256 Logger _logger; | |
257 | |
258 LoggerHandlerList(this._logger); | |
259 | |
260 void add(LoggerHandler handler) => _logger._addHandler(handler); | |
261 void remove(LoggerHandler handler) => _logger._removeHandler(handler); | |
262 void clear() => _logger.clearListeners(); | |
263 } | |
264 | |
265 | |
266 /** | 205 /** |
267 * [Level]s to control logging output. Logging can be enabled to include all | 206 * [Level]s to control logging output. Logging can be enabled to include all |
268 * levels above certain [Level]. [Level]s are ordered using an integer | 207 * levels above certain [Level]. [Level]s are ordered using an integer |
269 * value [Level.value]. The predefined [Level] constants below are sorted as | 208 * value [Level.value]. The predefined [Level] constants below are sorted as |
270 * follows (in descending order): [Level.SHOUT], [Level.SEVERE], | 209 * follows (in descending order): [Level.SHOUT], [Level.SEVERE], |
271 * [Level.WARNING], [Level.INFO], [Level.CONFIG], [Level.FINE], [Level.FINER], | 210 * [Level.WARNING], [Level.INFO], [Level.CONFIG], [Level.FINE], [Level.FINER], |
272 * [Level.FINEST], and [Level.ALL]. | 211 * [Level.FINEST], and [Level.ALL]. |
273 * | 212 * |
274 * We recommend using one of the predefined logging levels. If you define your | 213 * We recommend using one of the predefined logging levels. If you define your |
275 * own level, make sure you use a value between those used in [Level.ALL] and | 214 * own level, make sure you use a value between those used in [Level.ALL] and |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 | 292 |
354 /** Associated exception message (if any) when recording errors messages. */ | 293 /** Associated exception message (if any) when recording errors messages. */ |
355 String exceptionText; | 294 String exceptionText; |
356 | 295 |
357 LogRecord( | 296 LogRecord( |
358 this.level, this.message, this.loggerName, | 297 this.level, this.message, this.loggerName, |
359 [time, this.exception, this.exceptionText]) : | 298 [time, this.exception, this.exceptionText]) : |
360 this.time = (time == null) ? new DateTime.now() : time, | 299 this.time = (time == null) ? new DateTime.now() : time, |
361 this.sequenceNumber = LogRecord._nextNumber++; | 300 this.sequenceNumber = LogRecord._nextNumber++; |
362 } | 301 } |
OLD | NEW |