Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(896)

Side by Side Diff: lib/logging/logging.dart

Issue 10827227: Start moving non-platform libraries from lib/ to pkg/ . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Start moving non-platform libraries from lib/ to pkg/ Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « lib/i18n/lib/date_format_helpers.dart ('k') | tests/lib/i18n/bidi_format_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
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
8 * Logger and java.util.logging.Logger.
9 */
10 #library('logging');
11
12 /**
13 * Whether to allow fine-grain logging and configuration of loggers in a
14 * hierarchy. When false, all logging is merged in the root logger.
15 */
16 bool hierarchicalLoggingEnabled = false;
17
18 /**
19 * Level for the root-logger. This will be the level of all loggers if
20 * [hierarchicalLoggingEnabled] is false.
21 */
22 Level _rootLevel = Level.INFO;
23
24
25 /**
26 * Use a [Logger] to log debug messages. [Logger]s are named using a
27 * hierarchical dot-separated name convention.
28 */
29 class Logger {
30 /** Simple name of this logger. */
31 final String name;
32
33 /** The full name of this logger, which includes the parent's full name. */
34 String get fullName() =>
35 (parent == null || parent.name == '') ? name : '${parent.fullName}.$name';
36
37 /** Parent of this logger in the hierarchy of loggers. */
38 final Logger parent;
39
40 /** Logging [Level] used for entries generated on this logger. */
41 Level _level;
42
43 /** Children in the hierarchy of loggers, indexed by their simple names. */
44 Map<String, Logger> children;
45
46 /** Handlers used to process log entries in this logger. */
47 List<LoggerHandler> _handlers;
48
49 /**
50 * Singleton constructor. Calling `new Logger(name)` will return the same
51 * actual instance whenever it is called with the same string name.
52 */
53 factory Logger(String name) {
54 if (name.startsWith('.')) {
55 throw new IllegalArgumentException("name shouldn't start with a '.'");
56 }
57 if (_loggers == null) _loggers = <Logger>{};
58 if (_loggers.containsKey(name)) return _loggers[name];
59
60 // Split hierarchical names (separated with '.').
61 int dot = name.lastIndexOf('.');
62 Logger parent = null;
63 String thisName;
64 if (dot == -1) {
65 if (name != '') parent = new Logger('');
66 thisName = name;
67 } else {
68 parent = new Logger(name.substring(0, dot));
69 thisName = name.substring(dot + 1);
70 }
71 final res = new Logger._internal(thisName, parent);
72 _loggers[name] = res;
73 return res;
74 }
75
76 Logger._internal(this.name, this.parent)
77 : children = new Map<String, Logger>() {
78 if (parent != null) parent.children[name] = this;
79 }
80
81 /**
82 * Effective level considering the levels established in this logger's parents
83 * (when [hierarchicalLoggingEnabled] is true).
84 */
85 Level get level() {
86 if (hierarchicalLoggingEnabled) {
87 if (_level != null) return _level;
88 if (parent != null) return parent.level;
89 }
90 return _rootLevel;
91 }
92
93 /** Override the level for this particular [Logger] and its children. */
94 Level set level(value) {
95 if (hierarchicalLoggingEnabled && parent != null) {
96 _level = value;
97 } else {
98 if (parent != null) {
99 throw new UnsupportedOperationException(
100 'Please set "hierarchicalLoggingEnabled" to true if you want to '
101 'change the level on a non-root logger.');
102 }
103 _rootLevel = value;
104 }
105 }
106
107 /**
108 * Returns an event manager for this [Logger]. You can listen for log messages
109 * by adding a [LoggerHandler] to an event from the event manager, for
110 * instance:
111 * logger.on.record.add((record) { ... });
112 */
113 LoggerEvents get on() => new LoggerEvents(this);
114
115 /** Adds a handler to listen whenever a log record is added to this logger. */
116 void _addHandler(LoggerHandler handler) {
117 if (hierarchicalLoggingEnabled || parent == null) {
118 if (_handlers == null) {
119 _handlers = new List<LoggerHandler>();
120 }
121 _handlers.add(handler);
122 } else {
123 root._addHandler(handler);
124 }
125 }
126
127 /** Remove a previously added handler. */
128 void _removeHandler(LoggerHandler handler) {
129 if (hierarchicalLoggingEnabled || parent == null) {
130 if (_handlers == null) return;
131 int index = _handlers.indexOf(handler);
132 if (index != -1) _handlers.removeRange(index, 1);
133 } else {
134 root._removeHandler(handler);
135 }
136 }
137
138 /** Removes all handlers previously added to this logger. */
139 void _clearHandlers() {
140 if (hierarchicalLoggingEnabled || parent == null) {
141 _handlers = null;
142 } else {
143 root._clearHandlers();
144 }
145 }
146
147 /** Whether a message for [value]'s level is loggable in this logger. */
148 bool isLoggable(Level value) => (value >= level);
149
150 /**
151 * Adds a log record for a [message] at a particular [logLevel] if
152 * `isLoggable(logLevel)` is true. Use this method to create log entries for
153 * user-defined levels. To record a message at a predefined level (e.g.
154 * [Level.INFO], [Level.WARNING], etc) you can use their specialized methods
155 * instead (e.g. [info], [warning], etc).
156 */
157 // TODO(sigmund): add support for logging exceptions.
158 void log(Level logLevel, String message) {
159 if (isLoggable(logLevel)) {
160 var record = new LogRecord(logLevel, message, fullName);
161 if (hierarchicalLoggingEnabled) {
162 var target = this;
163 while (target != null) {
164 target._publish(record);
165 target = target.parent;
166 }
167 } else {
168 root._publish(record);
169 }
170 }
171 }
172
173 /** Log message at level [Level.FINEST]. */
174 void finest(String message) => log(Level.FINEST, message);
175
176 /** Log message at level [Level.FINER]. */
177 void finer(String message) => log(Level.FINER, message);
178
179 /** Log message at level [Level.FINE]. */
180 void fine(String message) => log(Level.FINE, message);
181
182 /** Log message at level [Level.CONFIG]. */
183 void config(String message) => log(Level.CONFIG, message);
184
185 /** Log message at level [Level.INFO]. */
186 void info(String message) => log(Level.INFO, message);
187
188 /** Log message at level [Level.WARNING]. */
189 void warning(String message) => log(Level.WARNING, message);
190
191 /** Log message at level [Level.SEVERE]. */
192 void severe(String message) => log(Level.SEVERE, message);
193
194 /** Log message at level [Level.SHOUT]. */
195 void shout(String message) => log(Level.SHOUT, message);
196
197 void _publish(LogRecord record) {
198 if (_handlers != null) {
199 _handlers.forEach((h) => h(record));
200 }
201 }
202
203 /** Top-level root [Logger]. */
204 static get root() => new Logger('');
205
206 /** All [Logger]s in the system. */
207 static Map<String, Logger> _loggers;
208 }
209
210
211 /** Handler callback to process log entries as they are added to a [Logger]. */
212 typedef void LoggerHandler(LogRecord);
213
214
215 /** Event manager for a [Logger] (holds events that a [Logger] can fire). */
216 class LoggerEvents {
217 final Logger _logger;
218
219 LoggerEvents(this._logger);
220
221 /** Event fired when a log record is added to a [Logger]. */
222 LoggerHandlerList get record() => new LoggerHandlerList(_logger);
223 }
224
225
226 /** List of handlers that will be called on a logger event. */
227 class LoggerHandlerList {
228 Logger _logger;
229
230 LoggerHandlerList(this._logger);
231
232 void add(LoggerHandler handler) => _logger._addHandler(handler);
233 void remove(LoggerHandler handler) => _logger._removeHandler(handler);
234 void clear() => _logger._clearHandlers();
235 }
236
237
238 /**
239 * [Level]s to control logging output. Logging can be enabled to include all
240 * levels above certain [Level]. [Level]s are ordered using an integer
241 * value [Level.value]. The predefined [Level] constants below are sorted as
242 * follows (in descending order): [Level.SHOUT], [Level.SEVERE],
243 * [Level.WARNING], [Level.INFO], [Level.CONFIG], [Level.FINE], [Level.FINER],
244 * [Level.FINEST], and [Level.ALL].
245 *
246 * We recommend using one of the predefined logging levels. If you define your
247 * own level, make sure you use a value between those used in [Level.ALL] and
248 * [Level.OFF].
249 */
250 class Level implements Comparable, Hashable {
251
252 // TODO(sigmund): mark name/value as 'const' when the language supports it.
253 final String name;
254
255 /**
256 * Unique value for this level. Used to order levels, so filtering can exclude
257 * messages whose level is under certain value.
258 */
259 final int value;
260
261 const Level(this.name, this.value);
262
263 /** Special key to turn on logging for all levels ([value] = 0). */
264 static final Level ALL = const Level('ALL', 0);
265
266 /** Special key to turn off all logging ([value] = 2000). */
267 static final Level OFF = const Level('OFF', 2000);
268
269 /** Key for highly detailed tracing ([value] = 300). */
270 static final Level FINEST = const Level('FINEST', 300);
271
272 /** Key for fairly detailed tracing ([value] = 400). */
273 static final Level FINER = const Level('FINER', 400);
274
275 /** Key for tracing information ([value] = 500). */
276 static final Level FINE = const Level('FINE', 500);
277
278 /** Key for static configuration messages ([value] = 700). */
279 static final Level CONFIG = const Level('CONFIG', 700);
280
281 /** Key for informational messages ([value] = 800). */
282 static final Level INFO = const Level('INFO', 800);
283
284 /** Key for potential problems ([value] = 900). */
285 static final Level WARNING = const Level('WARNING', 900);
286
287 /** Key for serious failures ([value] = 1000). */
288 static final Level SEVERE = const Level('SEVERE', 1000);
289
290 /** Key for extra debugging loudness ([value] = 1200). */
291 static final Level SHOUT = const Level('SHOUT', 1200);
292
293 bool operator ==(Level other) => other != null && value == other.value;
294 bool operator <(Level other) => value < other.value;
295 bool operator <=(Level other) => value <= other.value;
296 bool operator >(Level other) => value > other.value;
297 bool operator >=(Level other) => value >= other.value;
298 int compareTo(Level other) => value - other.value;
299 int hashCode() => value;
300 String toString() => name;
301 }
302
303
304 /**
305 * A log entry representation used to propagate information from [Logger] to
306 * individual [Handler]s.
307 */
308 class LogRecord {
309 final Level level;
310 final String message;
311
312 /** Logger where this record is stored. */
313 final String loggerName;
314
315 /** Time when this record was created. */
316 final Date time;
317
318 /** Unique sequence number greater than all log records created before it. */
319 final int sequenceNumber;
320
321 static int _nextNumber = 0;
322
323 /** Associated exception (if any) when recording errors messages. */
324 Exception exception;
325
326 /** Associated exception message (if any) when recording errors messages. */
327 String exceptionText;
328
329 LogRecord(
330 this.level, this.message, this.loggerName,
331 [time, this.exception, this.exceptionText]) :
332 this.time = (time == null) ? new Date.now() : time,
333 this.sequenceNumber = LogRecord._nextNumber++;
334 }
OLDNEW
« no previous file with comments | « lib/i18n/lib/date_format_helpers.dart ('k') | tests/lib/i18n/bidi_format_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698