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:convert'; |
10 import 'dart:io'; | 10 import 'dart:io'; |
(...skipping 30 matching lines...) Expand all Loading... | |
41 | 41 |
42 /// The list of recorded log messages. Will only be recorded if | 42 /// The list of recorded log messages. Will only be recorded if |
43 /// [recordTranscript()] is called. | 43 /// [recordTranscript()] is called. |
44 Transcript<Entry> _transcript; | 44 Transcript<Entry> _transcript; |
45 | 45 |
46 /// The currently-animated progress indicator, if any. | 46 /// The currently-animated progress indicator, if any. |
47 /// | 47 /// |
48 /// This will also be in [_progresses]. | 48 /// This will also be in [_progresses]. |
49 Progress _animatedProgress; | 49 Progress _animatedProgress; |
50 | 50 |
51 /// The Timer used to coalesce a number of collapsible messages. | |
52 /// | |
53 /// This is `null` if no collapsible messages are waiting to be displayed. | |
54 Timer _collapsibleTimer; | |
55 | |
56 /// The queue of collapsible messages waiting to be displayed. | |
57 final _collapsibleMessages = []; | |
58 | |
51 final _cyan = getSpecial('\u001b[36m'); | 59 final _cyan = getSpecial('\u001b[36m'); |
52 final _green = getSpecial('\u001b[32m'); | 60 final _green = getSpecial('\u001b[32m'); |
53 final _magenta = getSpecial('\u001b[35m'); | 61 final _magenta = getSpecial('\u001b[35m'); |
54 final _red = getSpecial('\u001b[31m'); | 62 final _red = getSpecial('\u001b[31m'); |
55 final _yellow = getSpecial('\u001b[33m'); | 63 final _yellow = getSpecial('\u001b[33m'); |
56 final _gray = getSpecial('\u001b[1;30m'); | 64 final _gray = getSpecial('\u001b[1;30m'); |
57 final _none = getSpecial('\u001b[0m'); | 65 final _none = getSpecial('\u001b[0m'); |
58 final _noColor = getSpecial('\u001b[39m'); | 66 final _noColor = getSpecial('\u001b[39m'); |
59 final _bold = getSpecial('\u001b[1m'); | 67 final _bold = getSpecial('\u001b[1m'); |
60 | 68 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 void io(message) => write(Level.IO, message); | 210 void io(message) => write(Level.IO, message); |
203 | 211 |
204 /// Logs [message] at [Level.SOLVER]. | 212 /// Logs [message] at [Level.SOLVER]. |
205 void solver(message) => write(Level.SOLVER, message); | 213 void solver(message) => write(Level.SOLVER, message); |
206 | 214 |
207 /// Logs [message] at [Level.FINE]. | 215 /// Logs [message] at [Level.FINE]. |
208 void fine(message) => write(Level.FINE, message); | 216 void fine(message) => write(Level.FINE, message); |
209 | 217 |
210 /// Logs [message] at [level]. | 218 /// Logs [message] at [level]. |
211 void write(Level level, message) { | 219 void write(Level level, message) { |
220 // Don't allow interleaving collapsible messages with other kinds. | |
221 if (_collapsibleTimer != null) _flushCollapsible(); | |
222 | |
212 message = message.toString(); | 223 message = message.toString(); |
213 var lines = splitLines(message); | 224 var lines = splitLines(message); |
214 | 225 |
215 // Discard a trailing newline. This is useful since StringBuffers often end | 226 // Discard a trailing newline. This is useful since StringBuffers often end |
216 // up with an extra newline at the end from using [writeln]. | 227 // up with an extra newline at the end from using [writeln]. |
217 if (lines.isNotEmpty && lines.last == "") { | 228 if (lines.isNotEmpty && lines.last == "") { |
218 lines.removeLast(); | 229 lines.removeLast(); |
219 } | 230 } |
220 | 231 |
221 var entry = new Entry(level, lines.map(format).toList()); | 232 var entry = new Entry(level, lines.map(format).toList()); |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 _numMutes++; | 413 _numMutes++; |
403 } | 414 } |
404 | 415 |
405 /// Resumes animating any ongoing progress once all calls to [muteProgress] | 416 /// Resumes animating any ongoing progress once all calls to [muteProgress] |
406 /// have made their matching [unmuteProgress]. | 417 /// have made their matching [unmuteProgress]. |
407 void unmuteProgress() { | 418 void unmuteProgress() { |
408 assert(_numMutes > 0); | 419 assert(_numMutes > 0); |
409 _numMutes--; | 420 _numMutes--; |
410 } | 421 } |
411 | 422 |
423 /// Logs a collapsible [message]. | |
424 /// | |
425 /// If a number of collapsible messages are printed in short succession, they | |
426 /// are collapsed to just showing the first one followed by a count of the | |
427 /// elided ones. Avoids spamming the output with not-very-interesting output. | |
428 /// | |
429 /// Internally, every time this is called, a time is set (or reset). When it | |
430 /// fires, any collapsible messages enqueued since the last time it fired are | |
431 /// displayed. | |
432 void collapsible(String message) { | |
nweiz
2015/07/31 22:42:35
Rather than only printing this once the timeout ha
Bob Nystrom
2015/08/03 21:51:02
I thought about that, but the output lines can be
nweiz
2015/08/03 22:11:10
Since this is pub, we should be able to safely use
Bob Nystrom
2015/08/05 21:25:39
Tried a different approach based on our discussion
| |
433 // Only collapse messages when the output is not verbose. | |
434 if (verbosity._loggers[Level.MESSAGE] != _logToStdout) { | |
435 write(Level.MESSAGE, message); | |
436 return; | |
437 } | |
438 | |
439 // Reset the timer. | |
440 if (_collapsibleTimer != null) _collapsibleTimer.cancel(); | |
441 | |
442 _collapsibleMessages.add(message); | |
443 _collapsibleTimer = new Timer(new Duration(milliseconds: 100), | |
nweiz
2015/07/31 22:42:35
Consider making this duration a top-level constant
Bob Nystrom
2015/08/03 21:51:02
Done.
| |
444 _flushCollapsible); | |
445 } | |
446 | |
447 /// Displays any queued collapsible messages. | |
448 void _flushCollapsible() { | |
449 if (_collapsibleMessages.isEmpty) return; | |
450 | |
451 if (_collapsibleTimer != null) { | |
452 _collapsibleTimer.cancel(); | |
453 _collapsibleTimer = null; | |
454 } | |
455 | |
456 if (_collapsibleMessages.length == 1) { | |
457 message(_collapsibleMessages.single); | |
458 } else { | |
459 var trailing = gray("(and ${_collapsibleMessages.length - 1} more...)"); | |
460 message("${_collapsibleMessages.first} $trailing"); | |
461 } | |
462 | |
463 _collapsibleMessages.clear(); | |
464 } | |
465 | |
412 /// Wraps [text] in the ANSI escape codes to make it bold when on a platform | 466 /// Wraps [text] in the ANSI escape codes to make it bold when on a platform |
413 /// that supports that. | 467 /// that supports that. |
414 /// | 468 /// |
415 /// Use this to highlight the most important piece of a long chunk of text. | 469 /// Use this to highlight the most important piece of a long chunk of text. |
416 /// | 470 /// |
417 /// This is disabled under [withPrejudice] since all text is bold with | 471 /// This is disabled under [withPrejudice] since all text is bold with |
418 /// prejudice. | 472 /// prejudice. |
419 String bold(text) => withPrejudice ? text : "$_bold$text$_none"; | 473 String bold(text) => withPrejudice ? text : "$_bold$text$_none"; |
420 | 474 |
421 /// Wraps [text] in the ANSI escape codes to make it gray when on a platform | 475 /// Wraps [text] in the ANSI escape codes to make it gray when on a platform |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 this.message(errorJson); | 592 this.message(errorJson); |
539 } | 593 } |
540 | 594 |
541 /// Encodes [message] to JSON and prints it if JSON output is enabled. | 595 /// Encodes [message] to JSON and prints it if JSON output is enabled. |
542 void message(message) { | 596 void message(message) { |
543 if (!enabled) return; | 597 if (!enabled) return; |
544 | 598 |
545 print(JSON.encode(message)); | 599 print(JSON.encode(message)); |
546 } | 600 } |
547 } | 601 } |
OLD | NEW |