Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: utils/pub/log.dart

Issue 11474046: Make sure to drain stderr in tests so that spawned process doesn't hang. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 log; 6 library log;
7 7
8 import 'dart:io'; 8 import 'dart:io';
9 import 'io.dart'; 9 import 'io.dart';
10 10
11 typedef LogFn(Level level, message); 11 typedef LogFn(Entry entry);
12 final Map<Level, LogFn> _loggers = new Map<Level, LogFn>(); 12 final Map<Level, LogFn> _loggers = new Map<Level, LogFn>();
13 13
14 /// The list of recorded log messages. Will only be recorded if 14 /// The list of recorded log messages. Will only be recorded if
15 /// [recordTranscript()] is called. 15 /// [recordTranscript()] is called.
16 List<Entry> _transcript; 16 List<Entry> _transcript;
17 17
18 /// An enum type for defining the different logging levels. By default, [ERROR] 18 /// An enum type for defining the different logging levels. By default, [ERROR]
19 /// and [WARNING] messages are printed to sterr. [MESSAGE] messages are printed 19 /// and [WARNING] messages are printed to sterr. [MESSAGE] messages are printed
20 /// to stdout, and others are ignored. 20 /// to stdout, and others are ignored.
21 class Level { 21 class Level {
(...skipping 20 matching lines...) Expand all
42 const Level._(this.name); 42 const Level._(this.name);
43 final String name; 43 final String name;
44 44
45 String toString() => name; 45 String toString() => name;
46 int get hashCode => name.hashCode; 46 int get hashCode => name.hashCode;
47 } 47 }
48 48
49 /// A single log entry. 49 /// A single log entry.
50 class Entry { 50 class Entry {
51 final Level level; 51 final Level level;
52 final String message; 52 final List<String> lines;
53 53
54 Entry(this.level, this.message); 54 Entry(this.level, this.lines);
55 } 55 }
56 56
57 /// Logs [message] at [Level.ERROR]. 57 /// Logs [message] at [Level.ERROR].
58 void error(message) => write(Level.ERROR, message); 58 void error(message) => write(Level.ERROR, message);
59 59
60 /// Logs [message] at [Level.WARNING]. 60 /// Logs [message] at [Level.WARNING].
61 void warning(message) => write(Level.WARNING, message); 61 void warning(message) => write(Level.WARNING, message);
62 62
63 /// Logs [message] at [Level.MESSAGE]. 63 /// Logs [message] at [Level.MESSAGE].
64 void message(message) => write(Level.MESSAGE, message); 64 void message(message) => write(Level.MESSAGE, message);
65 65
66 /// Logs [message] at [Level.IO]. 66 /// Logs [message] at [Level.IO].
67 void io(message) => write(Level.IO, message); 67 void io(message) => write(Level.IO, message);
68 68
69 /// Logs [message] at [Level.FINE]. 69 /// Logs [message] at [Level.FINE].
70 void fine(message) => write(Level.FINE, message); 70 void fine(message) => write(Level.FINE, message);
71 71
72 /// Logs [message] at [level]. 72 /// Logs [message] at [level].
73 void write(Level level, message) { 73 void write(Level level, message) {
74 if (_loggers.isEmpty) showNormal(); 74 if (_loggers.isEmpty) showNormal();
75 75
76 var lines = message.toString().split(NEWLINE_PATTERN);
77 var entry = new Entry(level, lines);
78
76 var logFn = _loggers[level]; 79 var logFn = _loggers[level];
77 if (logFn != null) logFn(level, message); 80 if (logFn != null) logFn(entry);
78 81
79 if (_transcript != null) { 82 if (_transcript != null) _transcript.add(entry);
80 _transcript.add(new Entry(level, '$message'));
81 }
82 } 83 }
83 84
84 /// Logs an asynchronous IO operation. Logs [startMessage] before the operation 85 /// Logs an asynchronous IO operation. Logs [startMessage] before the operation
85 /// starts, then when [operation] completes, invokes [endMessage] with the 86 /// starts, then when [operation] completes, invokes [endMessage] with the
86 /// completion value and logs the result of that. Returns a future that 87 /// completion value and logs the result of that. Returns a future that
87 /// completes after the logging is done. 88 /// completes after the logging is done.
88 /// 89 ///
89 /// If [endMessage] is omitted, then logs "Begin [startMessage]" before the 90 /// If [endMessage] is omitted, then logs "Begin [startMessage]" before the
90 /// operation and "End [startMessage]" after it. 91 /// operation and "End [startMessage]" after it.
91 Future ioAsync(String startMessage, Future operation, 92 Future ioAsync(String startMessage, Future operation,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 _transcript = <Entry>[]; 148 _transcript = <Entry>[];
148 } 149 }
149 150
150 /// If [recordTranscript()] was called, then prints the previously recorded log 151 /// If [recordTranscript()] was called, then prints the previously recorded log
151 /// transcript to stderr. 152 /// transcript to stderr.
152 void dumpTranscript() { 153 void dumpTranscript() {
153 if (_transcript == null) return; 154 if (_transcript == null) return;
154 155
155 stderr.writeString('---- Log transcript ----\n'); 156 stderr.writeString('---- Log transcript ----\n');
156 for (var entry in _transcript) { 157 for (var entry in _transcript) {
157 _logToStderrWithLabel(entry.level, entry.message); 158 _logToStderrWithLabel(entry);
158 } 159 }
159 stderr.writeString('---- End log transcript ----\n'); 160 stderr.writeString('---- End log transcript ----\n');
160 } 161 }
161 162
162 /// Sets the verbosity to "normal", which shows errors, warnings, and messages. 163 /// Sets the verbosity to "normal", which shows errors, warnings, and messages.
163 void showNormal() { 164 void showNormal() {
164 _loggers[Level.ERROR] = _logToStderr; 165 _loggers[Level.ERROR] = _logToStderr;
165 _loggers[Level.WARNING] = _logToStderr; 166 _loggers[Level.WARNING] = _logToStderr;
166 _loggers[Level.MESSAGE] = _logToStdout; 167 _loggers[Level.MESSAGE] = _logToStdout;
167 _loggers[Level.IO] = null; 168 _loggers[Level.IO] = null;
(...skipping 13 matching lines...) Expand all
181 /// Sets the verbosity to "all", which logs ALL the things. 182 /// Sets the verbosity to "all", which logs ALL the things.
182 void showAll() { 183 void showAll() {
183 _loggers[Level.ERROR] = _logToStderrWithLabel; 184 _loggers[Level.ERROR] = _logToStderrWithLabel;
184 _loggers[Level.WARNING] = _logToStderrWithLabel; 185 _loggers[Level.WARNING] = _logToStderrWithLabel;
185 _loggers[Level.MESSAGE] = _logToStdoutWithLabel; 186 _loggers[Level.MESSAGE] = _logToStdoutWithLabel;
186 _loggers[Level.IO] = _logToStderrWithLabel; 187 _loggers[Level.IO] = _logToStderrWithLabel;
187 _loggers[Level.FINE] = _logToStderrWithLabel; 188 _loggers[Level.FINE] = _logToStderrWithLabel;
188 } 189 }
189 190
190 /// Log function that prints the message to stdout. 191 /// Log function that prints the message to stdout.
191 void _logToStdout(Level level, message) { 192 void _logToStdout(Entry entry) {
192 print('$message'); 193 _logToStream(stdout, entry, showLabel: false);
193 } 194 }
194 195
195 /// Log function that prints the message to stdout with the level name. 196 /// Log function that prints the message to stdout with the level name.
196 void _logToStdoutWithLabel(Level level, message) { 197 void _logToStdoutWithLabel(Entry entry) {
197 print(_splitAndPrefix(level, message)); 198 _logToStream(stdout, entry, showLabel: true);
198 } 199 }
199 200
200 /// Log function that prints the message to stderr. 201 /// Log function that prints the message to stderr.
201 void _logToStderr(Level level, message) { 202 void _logToStderr(Entry entry) {
202 stderr.writeString('$message\n'); 203 _logToStream(stderr, entry, showLabel: false);
203 } 204 }
204 205
205 /// Log function that prints the message to stderr with the level name. 206 /// Log function that prints the message to stderr with the level name.
206 void _logToStderrWithLabel(Level level, message) { 207 void _logToStderrWithLabel(Entry entry) {
207 stderr.writeString(_splitAndPrefix(level, message)); 208 _logToStream(stderr, entry, showLabel: true);
208 stderr.writeString('\n');
209 } 209 }
210 210
211 /// Add the level prefix to the first line of [message] and prefix subsequent 211 void _logToStream(OutputStream stream, Entry entry, {bool showLabel}) {
212 /// lines with "|". 212 bool firstLine = true;
213 String _splitAndPrefix(Level level, message) { 213 for (var line in entry.lines) {
214 // TODO(rnystrom): We're doing lots of splitting and joining in here. If that 214 if (showLabel) {
215 // becomes a performance problem, we can optimize this to write directly to 215 if (firstLine) {
216 // stdout/stderr a line at a time. 216 stream.writeString(entry.level.name);
217 return "$level: ${Strings.join(message.toString().split('\n'), '\n | ')}"; 217 stream.writeString(': ');
218 } else {
219 stream.writeString(' | ');
220 }
221 }
222
223 stream.writeString(line);
224 stream.writeString('\n');
225
226 firstLine = false;
227 }
218 } 228 }
OLDNEW
« utils/pub/io.dart ('K') | « utils/pub/io.dart ('k') | utils/tests/pub/test_pub.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698