Chromium Code Reviews| 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 _Collapser _collapser; | |
| 52 | |
| 51 final _cyan = getSpecial('\u001b[36m'); | 53 final _cyan = getSpecial('\u001b[36m'); |
| 52 final _green = getSpecial('\u001b[32m'); | 54 final _green = getSpecial('\u001b[32m'); |
| 53 final _magenta = getSpecial('\u001b[35m'); | 55 final _magenta = getSpecial('\u001b[35m'); |
| 54 final _red = getSpecial('\u001b[31m'); | 56 final _red = getSpecial('\u001b[31m'); |
| 55 final _yellow = getSpecial('\u001b[33m'); | 57 final _yellow = getSpecial('\u001b[33m'); |
| 56 final _gray = getSpecial('\u001b[1;30m'); | 58 final _gray = getSpecial('\u001b[1;30m'); |
| 57 final _none = getSpecial('\u001b[0m'); | 59 final _none = getSpecial('\u001b[0m'); |
| 58 final _noColor = getSpecial('\u001b[39m'); | 60 final _noColor = getSpecial('\u001b[39m'); |
| 59 final _bold = getSpecial('\u001b[1m'); | 61 final _bold = getSpecial('\u001b[1m'); |
| 60 | 62 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 void io(message) => write(Level.IO, message); | 204 void io(message) => write(Level.IO, message); |
| 203 | 205 |
| 204 /// Logs [message] at [Level.SOLVER]. | 206 /// Logs [message] at [Level.SOLVER]. |
| 205 void solver(message) => write(Level.SOLVER, message); | 207 void solver(message) => write(Level.SOLVER, message); |
| 206 | 208 |
| 207 /// Logs [message] at [Level.FINE]. | 209 /// Logs [message] at [Level.FINE]. |
| 208 void fine(message) => write(Level.FINE, message); | 210 void fine(message) => write(Level.FINE, message); |
| 209 | 211 |
| 210 /// Logs [message] at [level]. | 212 /// Logs [message] at [level]. |
| 211 void write(Level level, message) { | 213 void write(Level level, message) { |
| 214 // Don't allow interleaving collapsible messages with other kinds. | |
| 215 if (_collapser != null) _collapser.end(); | |
| 216 | |
| 212 message = message.toString(); | 217 message = message.toString(); |
| 213 var lines = splitLines(message); | 218 var lines = splitLines(message); |
| 214 | 219 |
| 215 // Discard a trailing newline. This is useful since StringBuffers often end | 220 // Discard a trailing newline. This is useful since StringBuffers often end |
| 216 // up with an extra newline at the end from using [writeln]. | 221 // up with an extra newline at the end from using [writeln]. |
| 217 if (lines.isNotEmpty && lines.last == "") { | 222 if (lines.isNotEmpty && lines.last == "") { |
| 218 lines.removeLast(); | 223 lines.removeLast(); |
| 219 } | 224 } |
| 220 | 225 |
| 221 var entry = new Entry(level, lines.map(format).toList()); | 226 var entry = new Entry(level, lines.map(format).toList()); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 _numMutes++; | 407 _numMutes++; |
| 403 } | 408 } |
| 404 | 409 |
| 405 /// Resumes animating any ongoing progress once all calls to [muteProgress] | 410 /// Resumes animating any ongoing progress once all calls to [muteProgress] |
| 406 /// have made their matching [unmuteProgress]. | 411 /// have made their matching [unmuteProgress]. |
| 407 void unmuteProgress() { | 412 void unmuteProgress() { |
| 408 assert(_numMutes > 0); | 413 assert(_numMutes > 0); |
| 409 _numMutes--; | 414 _numMutes--; |
| 410 } | 415 } |
| 411 | 416 |
| 417 /// Logs a collapsible [message]. | |
| 418 /// | |
| 419 /// If a number of collapsible messages are printed in short succession, they | |
| 420 /// are collapsed to just showing [template] with "##" replaced with the number | |
| 421 /// of collapsed messages. Avoids spamming the output with not-very-interesting | |
| 422 /// output. | |
| 423 void collapsible(String message, String template) { | |
| 424 // Only collapse messages when the output is not verbose. | |
| 425 if (verbosity._loggers[Level.MESSAGE] != _logToStdout) { | |
| 426 write(Level.MESSAGE, message); | |
| 427 return; | |
| 428 } | |
| 429 | |
| 430 // If this is a different set of collapsed messages, end the previous ones. | |
| 431 if (_collapser != null && _collapser._template != template) { | |
| 432 _collapser.end(); | |
| 433 } | |
| 434 | |
| 435 if (_collapser != null) { | |
| 436 _collapser.increment(); | |
| 437 } else { | |
| 438 _collapser = new _Collapser(message, template); | |
| 439 } | |
| 440 } | |
| 441 | |
| 412 /// Wraps [text] in the ANSI escape codes to make it bold when on a platform | 442 /// Wraps [text] in the ANSI escape codes to make it bold when on a platform |
| 413 /// that supports that. | 443 /// that supports that. |
| 414 /// | 444 /// |
| 415 /// Use this to highlight the most important piece of a long chunk of text. | 445 /// Use this to highlight the most important piece of a long chunk of text. |
| 416 /// | 446 /// |
| 417 /// This is disabled under [withPrejudice] since all text is bold with | 447 /// This is disabled under [withPrejudice] since all text is bold with |
| 418 /// prejudice. | 448 /// prejudice. |
| 419 String bold(text) => withPrejudice ? text : "$_bold$text$_none"; | 449 String bold(text) => withPrejudice ? text : "$_bold$text$_none"; |
| 420 | 450 |
| 421 /// Wraps [text] in the ANSI escape codes to make it gray when on a platform | 451 /// 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); | 568 this.message(errorJson); |
| 539 } | 569 } |
| 540 | 570 |
| 541 /// Encodes [message] to JSON and prints it if JSON output is enabled. | 571 /// Encodes [message] to JSON and prints it if JSON output is enabled. |
| 542 void message(message) { | 572 void message(message) { |
| 543 if (!enabled) return; | 573 if (!enabled) return; |
| 544 | 574 |
| 545 print(JSON.encode(message)); | 575 print(JSON.encode(message)); |
| 546 } | 576 } |
| 547 } | 577 } |
| 578 | |
| 579 /// Collapses a series of collapsible messages into a single line of output if | |
| 580 /// they happen within a short window of time. | |
| 581 class _Collapser { | |
| 582 /// The window of time where a series of calls to [collapsible] will be | |
| 583 /// collapsed to a single message. | |
| 584 static final _window = new Duration(milliseconds: 100); | |
| 585 | |
| 586 /// The Timer used to coalesce a number of collapsible messages. | |
| 587 /// | |
| 588 /// This is `null` if no collapsible messages are waiting to be displayed. | |
| 589 Timer _timer; | |
| 590 | |
| 591 /// The first collapsible message waiting to be displayed. | |
| 592 String _firstMessage; | |
| 593 | |
| 594 /// The template used to display the number of collapsed messages when more | |
| 595 /// than one collapsible message is logged within the window of time. | |
| 596 /// | |
| 597 /// Inside the template, "##" will be replaced with the number of collapsed | |
| 598 /// messages. | |
| 599 String _template; | |
| 600 | |
| 601 /// The number of collapsible messages that are waiting to be logged. | |
| 602 int _count = 1; | |
| 603 | |
| 604 _Collapser(this._firstMessage, this._template) { | |
| 605 _initTimer(); | |
| 606 } | |
| 607 | |
| 608 void increment() { | |
| 609 // Reset the timer. | |
| 610 _timer.cancel(); | |
| 611 _initTimer(); | |
| 612 | |
| 613 _count++; | |
| 614 } | |
| 615 | |
| 616 void end() { | |
| 617 // Clear this first so we don't stack overflow when we call message() below. | |
| 618 _collapser = null; | |
| 619 | |
| 620 _timer.cancel(); | |
| 621 if (_count == 1) { | |
| 622 message(_firstMessage); | |
| 623 } else { | |
| 624 message(_template.replaceAll("##", _count.toString())); | |
|
nweiz
2015/08/05 22:57:14
I'd still really like to have this dynamically upd
Bob Nystrom
2015/08/05 23:49:23
Leaving as-is per our discussion.
| |
| 625 } | |
| 626 } | |
| 627 | |
| 628 void _initTimer() { | |
| 629 _timer = new Timer(_window, end); | |
| 630 } | |
| 631 } | |
| OLD | NEW |