OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, 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 library engine.incremental_logger; |
| 6 |
| 7 /** |
| 8 * The shared instance of [Logger] used by several incremental resolution |
| 9 * classes. It is initialized externally by the Analysis Engine client. |
| 10 */ |
| 11 Logger logger = NULL_LOGGER; |
| 12 |
| 13 /** |
| 14 * An instance of [Logger] that does not print anything. |
| 15 */ |
| 16 final Logger NULL_LOGGER = new _NullLogger(); |
| 17 |
| 18 /** |
| 19 * An instance of [Logger] that uses `print` for output. |
| 20 */ |
| 21 final Logger PRINT_LOGGER = new StringSinkLogger(new _PrintStringSink()); |
| 22 |
| 23 /** |
| 24 * A simple hierarchical logger. |
| 25 */ |
| 26 abstract class Logger { |
| 27 /** |
| 28 * Mark an enter to a new section with the given [name]. |
| 29 */ |
| 30 void enter(String name); |
| 31 |
| 32 /** |
| 33 * Mark an exit from the current sections, logs the duration. |
| 34 */ |
| 35 void exit(); |
| 36 |
| 37 /** |
| 38 * Logs the given [obj]. |
| 39 */ |
| 40 void log(Object obj); |
| 41 |
| 42 /** |
| 43 * Starts a new timer. |
| 44 */ |
| 45 LoggingTimer startTimer(); |
| 46 } |
| 47 |
| 48 /** |
| 49 * The handle of a timer. |
| 50 */ |
| 51 class LoggingTimer { |
| 52 final Logger _logger; |
| 53 final Stopwatch _stopwatch = new Stopwatch(); |
| 54 |
| 55 LoggingTimer(this._logger) { |
| 56 _stopwatch.start(); |
| 57 } |
| 58 |
| 59 /** |
| 60 * This methods stop the timer and logs the elapsed time. |
| 61 */ |
| 62 void stop(String message) { |
| 63 _stopwatch.stop(); |
| 64 _logger.log('$message in ${_stopwatch.elapsedMilliseconds} ms'); |
| 65 } |
| 66 } |
| 67 |
| 68 /** |
| 69 * A [Logger] that writes to a [StringSink]. |
| 70 */ |
| 71 class StringSinkLogger implements Logger { |
| 72 static const int _MAX_LINE_LENGTH = 512; |
| 73 final StringSink _sink; |
| 74 final List<_LoggerSection> _sectionStack = <_LoggerSection>[]; |
| 75 _LoggerSection _section = new _LoggerSection('', 'ROOT'); |
| 76 |
| 77 StringSinkLogger(this._sink); |
| 78 |
| 79 @override |
| 80 void enter(String name) { |
| 81 log('+++ $name'); |
| 82 _sectionStack.add(_section); |
| 83 _section = new _LoggerSection(_section.indent + '\t', name); |
| 84 } |
| 85 |
| 86 @override |
| 87 void exit() { |
| 88 DateTime now = new DateTime.now(); |
| 89 Duration duration = now.difference(_section.start); |
| 90 String message = '--- ${_section.name} in ${duration.inMilliseconds} ms'; |
| 91 _section = _sectionStack.removeLast(); |
| 92 log(message); |
| 93 } |
| 94 |
| 95 @override |
| 96 void log(Object obj) { |
| 97 DateTime now = new DateTime.now(); |
| 98 String indent = _section.indent; |
| 99 String objStr = _getObjectString(obj); |
| 100 String line = '[$now] $indent$objStr'; |
| 101 _sink.writeln(line); |
| 102 } |
| 103 |
| 104 @override |
| 105 LoggingTimer startTimer() { |
| 106 return new LoggingTimer(this); |
| 107 } |
| 108 |
| 109 String _getObjectString(Object obj) { |
| 110 if (obj == null) { |
| 111 return 'null'; |
| 112 } |
| 113 if (obj is Function) { |
| 114 obj = obj(); |
| 115 } |
| 116 String str = obj.toString(); |
| 117 if (str.length < _MAX_LINE_LENGTH) { |
| 118 return str; |
| 119 } |
| 120 return str.split('\n').map((String line) { |
| 121 if (line.length > _MAX_LINE_LENGTH) { |
| 122 line = line.substring(0, _MAX_LINE_LENGTH) + '...'; |
| 123 } |
| 124 return line; |
| 125 }).join('\n'); |
| 126 } |
| 127 } |
| 128 |
| 129 class _LoggerSection { |
| 130 final DateTime start = new DateTime.now(); |
| 131 final String indent; |
| 132 final String name; |
| 133 _LoggerSection(this.indent, this.name); |
| 134 } |
| 135 |
| 136 /** |
| 137 * A [Logger] that does nothing. |
| 138 */ |
| 139 class _NullLogger implements Logger { |
| 140 @override |
| 141 void enter(String name) {} |
| 142 |
| 143 @override |
| 144 void exit() {} |
| 145 |
| 146 @override |
| 147 void log(Object obj) {} |
| 148 |
| 149 @override |
| 150 LoggingTimer startTimer() { |
| 151 return new LoggingTimer(this); |
| 152 } |
| 153 } |
| 154 |
| 155 /** |
| 156 * A [StringSink] implementation that uses `print`. |
| 157 */ |
| 158 class _PrintStringSink implements StringSink { |
| 159 String _line = ''; |
| 160 |
| 161 @override |
| 162 void write(Object obj) { |
| 163 if (obj == null) { |
| 164 _line += 'null'; |
| 165 } else { |
| 166 _line += obj.toString(); |
| 167 } |
| 168 } |
| 169 |
| 170 @override |
| 171 void writeAll(Iterable objects, [String separator = '']) { |
| 172 _line += objects.join(separator); |
| 173 } |
| 174 |
| 175 @override |
| 176 void writeCharCode(int charCode) { |
| 177 _line += new String.fromCharCode(charCode); |
| 178 } |
| 179 |
| 180 @override |
| 181 void writeln([Object obj = '']) { |
| 182 _line += obj; |
| 183 print(_line); |
| 184 _line = ''; |
| 185 } |
| 186 } |
OLD | NEW |