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 /// Message logging. | 5 /// Message logging. |
6 library pub.log; | 6 library pub.log; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:convert'; | |
9 import 'dart:io'; | 10 import 'dart:io'; |
10 | 11 |
11 import 'package:path/path.dart' as p; | 12 import 'package:path/path.dart' as p; |
12 | 13 |
13 import 'io.dart'; | 14 import 'io.dart'; |
14 import 'transcript.dart'; | 15 import 'transcript.dart'; |
15 import 'utils.dart'; | 16 import 'utils.dart'; |
16 | 17 |
17 typedef LogFn(Entry entry); | 18 typedef LogFn(Entry entry); |
18 final Map<Level, LogFn> _loggers = new Map<Level, LogFn>(); | 19 final Map<Level, LogFn> _loggers = new Map<Level, LogFn>(); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 void recordTranscript() { | 203 void recordTranscript() { |
203 _transcript = new Transcript<Entry>(_MAX_TRANSCRIPT); | 204 _transcript = new Transcript<Entry>(_MAX_TRANSCRIPT); |
204 } | 205 } |
205 | 206 |
206 /// If [recordTranscript()] was called, then prints the previously recorded log | 207 /// If [recordTranscript()] was called, then prints the previously recorded log |
207 /// transcript to stderr. | 208 /// transcript to stderr. |
208 void dumpTranscript() { | 209 void dumpTranscript() { |
209 if (_transcript == null) return; | 210 if (_transcript == null) return; |
210 | 211 |
211 stderr.writeln('---- Log transcript ----'); | 212 stderr.writeln('---- Log transcript ----'); |
212 _transcript.forEach(_logToStderrWithLabel, (discarded) { | 213 _transcript.forEach((entry) { |
214 _printToStream(stderr, entry, showLabel: true); | |
nweiz
2014/03/05 02:36:52
If you're keeping _logToStderrWithLabel, I don't u
Bob Nystrom
2014/03/07 00:42:18
Calling _printToStream() directly skips the if (js
| |
215 }, (discarded) { | |
213 stderr.writeln('---- ($discarded discarded) ----'); | 216 stderr.writeln('---- ($discarded discarded) ----'); |
214 }); | 217 }); |
215 stderr.writeln('---- End log transcript ----'); | 218 stderr.writeln('---- End log transcript ----'); |
216 } | 219 } |
217 | 220 |
218 /// Prints [message] then slowly prints additional "..." after it until the | 221 /// Prints [message] then slowly prints additional "..." after it until the |
219 /// future returned by [callback] completes. If anything else is logged during | 222 /// future returned by [callback] completes. If anything else is logged during |
220 /// this, it cancels the progress. | 223 /// this, it cancels the progress. |
221 Future progress(String message, Future callback()) { | 224 Future progress(String message, Future callback()) { |
225 if (json.enabled) return callback(); | |
226 | |
222 if (_progressTimer != null) throw new StateError("Already in progress."); | 227 if (_progressTimer != null) throw new StateError("Already in progress."); |
223 | 228 |
224 _progressMessage = '$message...'; | 229 _progressMessage = '$message...'; |
225 stdout.write(_progressMessage); | 230 stdout.write(_progressMessage); |
226 | 231 |
227 _progressTimer = new Timer.periodic(new Duration(milliseconds: 500), (_) { | 232 _progressTimer = new Timer.periodic(new Duration(milliseconds: 500), (_) { |
228 stdout.write('.'); | 233 stdout.write('.'); |
229 _progressMessage += '.'; | 234 _progressMessage += '.'; |
230 }); | 235 }); |
231 | 236 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 void _logToStderr(Entry entry) { | 354 void _logToStderr(Entry entry) { |
350 _logToStream(stderr, entry, showLabel: false); | 355 _logToStream(stderr, entry, showLabel: false); |
351 } | 356 } |
352 | 357 |
353 /// Log function that prints the message to stderr with the level name. | 358 /// Log function that prints the message to stderr with the level name. |
354 void _logToStderrWithLabel(Entry entry) { | 359 void _logToStderrWithLabel(Entry entry) { |
355 _logToStream(stderr, entry, showLabel: true); | 360 _logToStream(stderr, entry, showLabel: true); |
356 } | 361 } |
357 | 362 |
358 void _logToStream(IOSink sink, Entry entry, {bool showLabel}) { | 363 void _logToStream(IOSink sink, Entry entry, {bool showLabel}) { |
364 if (json.enabled) return; | |
365 | |
366 _printToStream(sink, entry, showLabel: showLabel); | |
367 } | |
368 | |
369 void _printToStream(IOSink sink, Entry entry, {bool showLabel}) { | |
359 _stopProgress(); | 370 _stopProgress(); |
360 | 371 |
361 bool firstLine = true; | 372 bool firstLine = true; |
362 for (var line in entry.lines) { | 373 for (var line in entry.lines) { |
363 if (showLabel) { | 374 if (showLabel) { |
364 if (firstLine) { | 375 if (firstLine) { |
365 sink.write('${entry.level.name}: '); | 376 sink.write('${entry.level.name}: '); |
366 } else { | 377 } else { |
367 sink.write(' | '); | 378 sink.write(' | '); |
368 } | 379 } |
369 } | 380 } |
370 | 381 |
371 sink.writeln(line); | 382 sink.writeln(line); |
372 | 383 |
373 firstLine = false; | 384 firstLine = false; |
374 } | 385 } |
375 } | 386 } |
387 | |
388 /// Namespace-like class for collecting the methods for JSON logging. | |
389 class _JsonLogger { | |
390 /// Whether logging should use machine-friendl JSON output or human-friendly | |
nweiz
2014/03/05 02:36:52
"friendl" -> "friendly"
Bob Nystrom
2014/03/07 00:42:18
Done.
| |
391 /// text. | |
392 /// | |
393 /// If set to `true`, then all regular logging is not printed. Logged | |
nweiz
2014/03/05 02:36:52
"no regular logging is printed"
Bob Nystrom
2014/03/07 00:42:18
Done.
| |
394 /// messages will still be recorded and displayed if the transcript is | |
395 /// printed. | |
396 bool enabled = false; | |
397 | |
398 /// Creates an error JSON object for [error] and prints it if JSON output | |
399 /// is enabled. | |
nweiz
2014/03/05 02:36:52
Mention that this prints to stdout as opposed to s
Bob Nystrom
2014/03/07 00:42:18
Done.
| |
400 void error(error) { | |
nweiz
2014/03/05 02:36:52
This should take an optional StackTrace as well.
Bob Nystrom
2014/03/07 00:42:18
Done.
| |
401 var errorJson = {"error": error.toString()}; | |
402 | |
403 var trace; | |
404 if (error is Error) trace = error.stackTrace; | |
405 if (trace != null) { | |
406 errorJson["stackTrace"] = trace; | |
nweiz
2014/03/05 02:36:52
We should [new Chain.forTrace] this.
Bob Nystrom
2014/03/07 00:42:18
Done.
| |
407 } | |
408 | |
409 this.message(errorJson); | |
410 } | |
411 | |
412 /// Encodes [message] to JSON and prints it if JSON output is enabled. | |
413 void message(message) { | |
414 if (!enabled) return; | |
415 | |
416 // TODO(rnystrom): Should errors be printed to stderr? | |
nweiz
2014/03/05 02:36:52
I think stdout is fine. Since the errors have iden
Bob Nystrom
2014/03/07 00:42:18
Done.
| |
417 print(JSON.encode(message)); | |
418 } | |
419 } | |
420 | |
421 /// The singleton instance so that we can have a nice api like: | |
422 /// | |
423 /// log.json.error(...); | |
424 final json = new _JsonLogger(); | |
nweiz
2014/03/05 02:36:52
Nit: I'd expect this to be at the top of the file,
Bob Nystrom
2014/03/07 00:42:18
Done.
| |
OLD | NEW |