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 |