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

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

Issue 10693042: first version of a logging library. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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 | « no previous file | tests/lib/logging/logging_test.dart » ('j') | tests/lib/logging/logging_test.dart » ('J')
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 * library and java.util.logging.
Jennifer Messerly 2012/06/29 03:47:45 did you mean: "such as the Closure JS Logger"
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done :)
9 */
10 #library('logging');
11
12 /** A handler that process log entries in of a [Logger]. */
gram 2012/06/29 16:38:25 Grammar? I can't parse this sentence.
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done (also moved further down...)
13 typedef void LoggerHandler(LogRecord);
14
15 /** Default level when none is set on a logger. */
16 Level _rootLevel = Level.INFO;
gram 2012/06/29 16:38:25 Shouldn't this be called _defaultLevel then?
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 rephrased doc
17
18
19 /**
20 * Use a [Logger] to log debug messages. [Logger]s are named using a
21 * hierarchical dot-separated name convention.
22 */
23 class Logger {
24 /** Simple name of this logger. */
25 String name;
Jennifer Messerly 2012/06/29 03:47:45 should this be final? It seems like changing the n
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Good point. Done.
26
27 /* The full name of this logger, which includes also the parent's names. */
Jennifer Messerly 2012/06/29 03:47:45 /**
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done.
28 String get fullName() =>
29 (parent == null || parent.name == '') ? name : '${parent.fullName}.$name';
Jennifer Messerly 2012/06/29 03:47:45 If I'm understanding this correctly: every logger
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Correct.
30
31 /** Parent of this logger in the hierarchy of loggers. */
32 Logger parent;
Jennifer Messerly 2012/06/29 03:47:45 should this be final too? as well as the other fie
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done. _handlers and children are not final so we a
33
34 /** Logging [Level] used for entries generated on this logger. */
35 Level _level;
36
37 /** Children in the hierarchy of loggers, indexed by their simple names. */
38 Map<String, Logger> children;
39
40 /** Handlers used to process log entries in this logger. */
41 List<LoggerHandler> _handlers;
42
43
44 /**
45 * Singleton constructor. Calling [:new Logger(name) :] will return the same
Jennifer Messerly 2012/06/29 03:47:45 nit, use backticks: `new Logger(name)` http://dari
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 done, but [: :] is the dart doc way :)
46 * actual instance whenever it is called with the same string name.
47 */
48 factory Logger(String name) {
49 if (_loggers == null) _loggers = new Map<String, Logger>();
Jennifer Messerly 2012/06/29 03:47:45 you could use "<Logger>{}" instead of "new Map<Str
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done.
50 if (_loggers.containsKey(name)) return _loggers[name];
51
52 // Split hierarchical names (separated with '.').
53 int dot = name.lastIndexOf('.');
54 String parentName;
Jennifer Messerly 2012/06/29 03:47:45 I think I would've understood this quicker if the
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 I like it, very nice suggestion. Done.
55 String thisName;
56 if (dot == -1) {
57 parentName = name == '' ? null : '';
58 thisName = name;
59 } else {
60 parentName = name.substring(0, dot);
61 thisName = name.substring(dot + 1);
62 }
63 final res = new Logger._internal(thisName,
64 parentName == null ? null : new Logger(parentName));
65 _loggers[name] = res;
66 return res;
67 }
68
69 Logger._internal(this.name, this.parent) :
70 children = new Map<String, Logger>() {
Jennifer Messerly 2012/06/29 03:47:45 nit: indent 4 from Logger then ": children = " ...
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Nice - I had forgotten, the style guide has the st
71 if (parent != null) parent.children[name] = this;
72 }
73
74 /**
75 * Effective level considering the levels established in this logger's parents
76 * (when [enableHierarchyLogging] is true).
77 */
78 Level get level() {
79 if (enableHierarchyLogging) {
80 if (_level != null) return _level;
81 if (parent != null) return parent.level;
82 }
83 return _rootLevel;
84 }
85
86 /** Override the level for this particular [Logger] and its children. */
87 Level set level(value) {
88 if (enableHierarchyLogging && parent != null) {
89 _level = value;
90 } else {
91 if (parent != null) throw new Exception(
Jennifer Messerly 2012/06/29 03:47:45 UnsupportedOperationException
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done
92 'Cannot set level on a non-root logger when hierarchycal logging '
Jennifer Messerly 2012/06/29 03:47:45 typo: should be "hierarchical"
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done, thanks!
93 'is not enabled');
Jennifer Messerly 2012/06/29 03:47:45 Maybe reword this message as: "Please set Logger.e
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done.
94 _rootLevel = value;
95 }
96 }
97
98 /** Adds a handler to listen whenever a log record is added to this logger. */
99 void addHandler(LoggerHandler handler) {
Jennifer Messerly 2012/06/29 03:47:45 hmmm. This is just begging to use an event pattern
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done - added the pattern, yippie! Used 'on.record'
100 if (enableHierarchyLogging || parent == null) {
101 if (_handlers == null) {
102 _handlers = new List<LoggerHandler>();
103 }
104 _handlers.add(handler);
105 } else {
106 root.addHandler(handler);
107 }
108 }
109
110 /** Remove an previously added handler. */
gram 2012/06/29 16:38:25 Remove a ...
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 thx. done
111 void removeHandler(LoggerHandler handler) {
112 if (enableHierarchyLogging || parent == null) {
113 if (_handlers == null) return;
114 int index = _handlers.indexOf(handler);
115 if (index != -1) _handlers.removeRange(index, 1);
116 } else {
117 root.removeHandler(handler);
118 }
119 }
120
121 /** Removes all handlers previously added to this logger. */
122 void clearHandlers() {
123 if (enableHierarchyLogging || parent == null) {
gram 2012/06/29 16:38:25 Can this be called 'hierarchicalLoggingEnabled' in
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done.
124 _handlers = null;
125 } else {
126 root.removeHandler(handler);
127 }
128 }
129
130 /** Whether a message for [value]'s level is loggable in this logger. */
131 bool isLoggable(Level value) => (value >= level);
Jennifer Messerly 2012/06/29 03:47:45 nit: redundant parens.
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 I actually did this on purpose, it just looks real
132
133 // TODO(sigmund): add support for logging exceptions.
134 void log(Level logLevel, String message) {
Jennifer Messerly 2012/06/29 03:47:45 This could use a doc comment too, like the other e
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done.
135 if (isLoggable(logLevel)) {
136 var record = new LogRecord(logLevel, message, fullName);
137 if (enableHierarchyLogging) {
138 var target = this;
139 while (target != null) {
140 target._publish(record);
141 target = target.parent;
142 }
143 } else {
144 root._publish(record);
145 }
146 }
147 }
148
149 /** Log message at level [Level.FINEST]. */
150 void finest(Strnig message) => log(Level.FINEST, message);
gram 2012/06/29 16:38:25 Typo, here and elsewhere: Strnig
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 wow! running tests in checked mode -- checked!
151
152 /** Log message at level [Level.FINER]. */
153 void finer(Strnig message) => log(Level.FINER, message);
154
155 /** Log message at level [Level.FINE]. */
156 void fine(Strnig message) => log(Level.FINE, message);
157
158 /** Log message at level [Level.CONFIG]. */
159 void config(Strnig message) => log(Level.CONFIG, message);
160
161 /** Log message at level [Level.INFO]. */
162 void info(Strnig message) => log(Level.INFO, message);
163
164 /** Log message at level [Level.WARNING]. */
165 void warning(Strnig message) => log(Level.WARNING, message);
166
167 /** Log message at level [Level.SEVERE]. */
168 void severe(Strnig message) => log(Level.SEVERE, message);
169
170 /** Log message at level [Level.SHOUT]. */
171 void shout(Strnig message) => log(Level.SHOUT, message);
172
173 void _publish(LogRecord record) {
174 if (_handlers != null) {
175 _handlers.forEach((h) => h(record));
176 }
177 }
178
179 /** Top-level root [Logger]. */
180 static get root() => new Logger('');
181
182 /**
183 * Whether to allow fine-grain logging and configuration of loggers in a
184 * hierarchy. When false, all logging is merged in the root logger.
185 */
186 static bool enableHierarchyLogging = false;
Jennifer Messerly 2012/06/29 03:47:45 does this need to be configurable? might be worth
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Not sure - I was inclined to always have it enable
187
188 /** All [Logger]s in the system. */
189 static Map<String, Logger> _loggers;
190 }
191
192
193 /**
194 * [Level]s to control logging output. Logging can be enabled to include all
195 * levels above certain [Level]. [Level]s are ordered using an integer
196 * value [Level.value]. The predefined [Level] constants below are sorted as
197 * follows (in descending order): [Level.SHOUT], [Level.SEVERE],
198 * [Level.WARNING], [Level.INFO], [Level.CONFIG], [Level.FINE], [Level.FINER],
199 * [Level.FINEST], and [Level.ALL].
200 *
201 * We recommend using one of the predefined logging levels. If you define your
202 * own level, make sure you use a value between those used in [Level.ALL] and
203 * [Level.OFF].
204 */
205 class Level {
Jennifer Messerly 2012/06/29 03:47:45 implements Comparable, Hashable and add methods:
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done.
206 final String name;
207
208 /**
209 * Unique value for this level. Used to order levels, so filtering can exclude
210 * messages whose level is under certain value.
211 */
212 final int value;
Jennifer Messerly 2012/06/29 03:47:45 TODO: this should be "const" when that modifier is
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Done
213
214 const Level(this.name, this.value);
215
216 /** Special key to turn on logging for all levels ([value] = 0). */
217 static final Level ALL = const Level('ALL', 0);
218
219 /** Special key to turn off all logging ([value] = 2000). */
220 static final Level OFF = const Level('OFF', 2000);
221
222 /** Key for highly detailed tracing ([value] = 300). */
223 static final Level FINEST = const Level('FINEST', 300);
224
225 /** Key for fairly detailed tracing ([value] = 400). */
226 static final Level FINER = const Level('FINER', 400);
227
228 /** Key for tracing information ([value] = 500). */
229 static final Level FINE = const Level('FINE', 500);
230
231 /** Key for static configuration messages ([value] = 700). */
232 static final Level CONFIG = const Level('CONFIG', 700);
233
234 /** Key for informational messages ([value] = 800). */
235 static final Level INFO = const Level('INFO', 800);
236
237 /** Key for potential problems ([value] = 900). */
238 static final Level WARNING = const Level('WARNING', 900);
239
240 /** Key for serious failures ([value] = 1000). */
241 static final Level SEVERE = const Level('SEVERE', 1000);
242
243 /** Key for extra debugging loudness ([value] = 1200). */
244 static final Level SHOUT = const Level('SHOUT', 1200);
245
246 bool operator ==(Level other) => this === other;
Jennifer Messerly 2012/06/29 03:47:45 do you need to define this?
Jennifer Messerly 2012/06/29 17:37:13 as gram mentioned later, maybe this should be "val
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 gone
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 agreed - done.
247 bool operator <(Level other) => value < other.value;
248 bool operator <=(Level other) => value <= other.value;
249 bool operator >(Level other) => value > other.value;
250 bool operator >=(Level other) => value >= other.value;
251
252 String toString() => name;
253 }
254
255
256 /**
257 * A log entry representation used to propagate information from [Logger] to
258 * individual [Handler]s.
259 */
260 class LogRecord {
261 final Level level;
262 final String message;
263
264 /** Logger where this record is stored. */
265 final String loggerName;
266
267 /** Time when this record was created. */
268 final Date time;
269
270 /** Unique sequence number greater than all log records created before it. */
271 final int sequenceNumber;
272
273 static int _nextNumber = 0;
274
275 /** Associated exception (if any) when recording errors messages. */
276 Exception exception;
277
278 /** Associated exception message (if any) when recording errors messages. */
279 String exceptionText;
280
281 LogRecord(
282 this.level, this.message, this.loggerName,
283 [time, sequenceNumber, this.exception, this.exceptionText]) :
gram 2012/06/29 16:38:25 Is it really necessary to support passing in an ex
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 Removed from now. Just made this as similar as pos
284 this.time = time == null ? new Date.now() : time,
Jennifer Messerly 2012/06/29 03:47:45 nit, put ":" on next line and indent everything 4
gram 2012/06/29 16:38:25 If find the this.time= time == null scans very poo
Siggi Cherem (dart-lang) 2012/06/29 18:34:48 agreed. same motivation I had for the other extra
285 this.sequenceNumber =
286 sequenceNumber == null ? LogRecord._nextNumber++ : sequenceNumber;
287 }
OLDNEW
« no previous file with comments | « no previous file | tests/lib/logging/logging_test.dart » ('j') | tests/lib/logging/logging_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698