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

Side by Side Diff: runtime/observatory/lib/src/elements/debugger.dart

Issue 1258063005: Add log support to debugger (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 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 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 library debugger_page_element; 5 library debugger_page_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'observatory_element.dart'; 9 import 'observatory_element.dart';
10 import 'package:observatory/cli.dart'; 10 import 'package:observatory/cli.dart';
11 import 'package:observatory/debugger.dart'; 11 import 'package:observatory/debugger.dart';
12 import 'package:observatory/service.dart'; 12 import 'package:observatory/service.dart';
13 import 'package:logging/logging.dart';
13 import 'package:polymer/polymer.dart'; 14 import 'package:polymer/polymer.dart';
14 15
15 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library. 16 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library.
16 abstract class DebuggerCommand extends Command { 17 abstract class DebuggerCommand extends Command {
17 ObservatoryDebugger debugger; 18 ObservatoryDebugger debugger;
18 19
19 DebuggerCommand(this.debugger, name, children) 20 DebuggerCommand(this.debugger, name, children)
20 : super(name, children); 21 : super(name, children);
21 22
22 String get helpShort; 23 String get helpShort;
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 String helpShort = 343 String helpShort =
343 'Continue running the isolate until it reaches the next source location'; 344 'Continue running the isolate until it reaches the next source location';
344 345
345 String helpLong = 346 String helpLong =
346 'Continue running the isolate until it reaches the next source ' 347 'Continue running the isolate until it reaches the next source '
347 'location.\n' 348 'location.\n'
348 '\n' 349 '\n'
349 'Syntax: step\n'; 350 'Syntax: step\n';
350 } 351 }
351 352
353 class LogCommand extends DebuggerCommand {
354 LogCommand(Debugger debugger) : super(debugger, 'log', []) {
355
turnidge 2015/08/03 18:16:22 Remove extra blank line here?
Cutch 2015/08/03 19:29:56 Done.
356 }
357
358 Future run(List<String> args) async {
359 if (args.length == 0) {
360 debugger.console.print(
361 'Current log level: '
362 '${debugger._stdioPrinter._minimumLogLevel.name}');
363 return new Future.value(null);
364 }
365 if (args.length > 1) {
366 debugger.console.print('Not implemented.');
turnidge 2015/08/03 18:16:22 Different message here for consistency w/ other co
Cutch 2015/08/03 19:29:56 Done.
367 return new Future.value(null);
368 }
369 var level = _findLevel(args[0]);
370 if (level == null) {
371 debugger.console.print('No such log level: ${args[0]}');
372 return new Future.value(null);
373 }
374 debugger._stdioPrinter._minimumLogLevel = level;
375 debugger.console.print('Set log level to: ${level.name}');
376 return new Future.value(null);
377 }
378
379 Level _findLevel(String levelName) {
380 for (var level in Level.LEVELS) {
381 if (level.name == levelName) {
turnidge 2015/08/03 18:16:22 Consider adding a case-insensitive match so we can
Cutch 2015/08/03 19:29:56 Done.
382 return level;
383 }
384 }
385 return null;
386 }
387
388 Future<List<String>> complete(List<String> args) {
389 if (args.length != 1) {
390 return new Future.value([args.join('')]);
391 }
392 var prefix = args[0];
393 var result = <String>[];
394 for (var level in Level.LEVELS) {
395 if (level.name.startsWith(prefix)) {
turnidge 2015/08/03 18:16:22 Consider either - completing against lowercase ve
Cutch 2015/08/03 19:29:56 case-insensitive prefix match.
396 result.add(level.name);
397 }
398 }
399 return new Future.value(result);
400 }
401
402 String helpShort =
403 'Control which log messages are displayed';
404
405 String helpLong =
406 'Get or set the minimum log level that should be displayed.\n'
407 '\n'
408 'Log levels (in ascending order): ALL, FINEST, FINER, FINE, CONFIG, '
409 'INFO, WARNING, SEVERE, SHOUT, OFF\n'
410 '\n'
411 'Default: OFF\n'
412 '\n'
413 'Syntax: log\n'
414 '- Display the current minimum log level.\n'
415 ' log <level>\n'
416 '- Set the minimum log level to <level>.\n'
417 ' log OFF\n'
418 '- Display no log messages.\n'
419 ' log ALL\n'
420 '- Display all log messages.\n';
turnidge 2015/08/03 18:16:22 The tabbing/layout here is odd - the commands are
Cutch 2015/08/03 19:29:56 Done.
421 }
422
352 class AsyncNextCommand extends DebuggerCommand { 423 class AsyncNextCommand extends DebuggerCommand {
353 AsyncNextCommand(Debugger debugger) : super(debugger, 'anext', []) { 424 AsyncNextCommand(Debugger debugger) : super(debugger, 'anext', []) {
354 } 425 }
355 426
356 Future run(List<String> args) async { 427 Future run(List<String> args) async {
357 if (debugger.isolatePaused()) { 428 if (debugger.isolatePaused()) {
358 var event = debugger.isolate.pauseEvent; 429 var event = debugger.isolate.pauseEvent;
359 if (event.asyncContinuation == null) { 430 if (event.asyncContinuation == null) {
360 debugger.console.print("No async continuation at this location"); 431 debugger.console.print("No async continuation at this location");
361 } else { 432 } else {
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 } 945 }
875 946
876 String helpShort = 'Refresh debugging information of various sorts'; 947 String helpShort = 'Refresh debugging information of various sorts';
877 948
878 String helpLong = 949 String helpLong =
879 'Refresh debugging information of various sorts.\n' 950 'Refresh debugging information of various sorts.\n'
880 '\n' 951 '\n'
881 'Syntax: refresh <subcommand>\n'; 952 'Syntax: refresh <subcommand>\n';
882 } 953 }
883 954
884 class _VMStreamPrinter { 955 class _ConsoleStreamPrinter {
885 ObservatoryDebugger _debugger; 956 ObservatoryDebugger _debugger;
886 957
887 _VMStreamPrinter(this._debugger); 958 _ConsoleStreamPrinter(this._debugger);
888 959 Level _minimumLogLevel = Level.OFF;
turnidge 2015/08/03 18:16:22 OFF is ok. Did you consider a different default,
Cutch 2015/08/03 19:29:56 I'll start with OFF but we might want to reconside
889 String _savedStream; 960 String _savedStream;
890 String _savedIsolate; 961 String _savedIsolate;
891 String _savedLine; 962 String _savedLine;
892 List<String> _buffer = []; 963 List<String> _buffer = [];
893 964
894 void onEvent(String streamName, ServiceEvent event) { 965 void onEvent(String streamName, ServiceEvent event) {
966 if (event.kind == ServiceEvent.kLogging) {
967 // Check if we should print this log message.
968 if (event.logRecord['level'].value < _minimumLogLevel.value) {
969 return;
970 }
971 }
895 String isolateName = event.isolate.name; 972 String isolateName = event.isolate.name;
896 // If we get a line from a different isolate/stream, flush 973 // If we get a line from a different isolate/stream, flush
897 // any pending output, even if it is not newline-terminated. 974 // any pending output, even if it is not newline-terminated.
898 if ((_savedIsolate != null && isolateName != _savedIsolate) || 975 if ((_savedIsolate != null && isolateName != _savedIsolate) ||
899 (_savedStream != null && streamName != _savedStream)) { 976 (_savedStream != null && streamName != _savedStream)) {
900 flush(); 977 flush();
901 } 978 }
902 String data = event.bytesAsString; 979 String data;
903 bool hasNewline = data.endsWith('\n'); 980 bool hasNewline;
981 if (event.kind == ServiceEvent.kLogging) {
982 data = event.logRecord["message"].valueAsString;
turnidge 2015/08/03 18:16:22 I'm wondering why valueAsString is showing up here
Cutch 2015/08/03 19:29:56 The messages are transmitted as instances. I think
983 hasNewline = true;
984 } else {
985 data = event.bytesAsString;
986 hasNewline = data.endsWith('\n');
987 }
904 if (_savedLine != null) { 988 if (_savedLine != null) {
905 data = _savedLine + data; 989 data = _savedLine + data;
906 _savedIsolate = null; 990 _savedIsolate = null;
907 _savedStream = null; 991 _savedStream = null;
908 _savedLine = null; 992 _savedLine = null;
909 } 993 }
910 var lines = data.split('\n').where((line) => line != '').toList(); 994 var lines = data.split('\n').where((line) => line != '').toList();
911 if (lines.isEmpty) { 995 if (lines.isEmpty) {
912 return; 996 return;
913 } 997 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 new StepCommand(this), 1063 new StepCommand(this),
980 new AsyncNextCommand(this), 1064 new AsyncNextCommand(this),
981 new FinishCommand(this), 1065 new FinishCommand(this),
982 new BreakCommand(this), 1066 new BreakCommand(this),
983 new SetCommand(this), 1067 new SetCommand(this),
984 new ClearCommand(this), 1068 new ClearCommand(this),
985 new DeleteCommand(this), 1069 new DeleteCommand(this),
986 new InfoCommand(this), 1070 new InfoCommand(this),
987 new IsolateCommand(this), 1071 new IsolateCommand(this),
988 new RefreshCommand(this), 1072 new RefreshCommand(this),
1073 new LogCommand(this),
989 ]); 1074 ]);
990 _stdioPrinter = new _VMStreamPrinter(this); 1075 _stdioPrinter = new _ConsoleStreamPrinter(this);
991 } 1076 }
992 1077
993 VM get vm => page.app.vm; 1078 VM get vm => page.app.vm;
994 1079
995 void updateIsolate(Isolate iso) { 1080 void updateIsolate(Isolate iso) {
1081 cancelFutureSubscription(_logSubscriptionFuture);
1082 _logSubscriptionFuture = null;
996 _isolate = iso; 1083 _isolate = iso;
997 if (_isolate != null) { 1084 if (_isolate != null) {
998 if ((exceptions != iso.exceptionsPauseInfo) && 1085 if ((exceptions != iso.exceptionsPauseInfo) &&
999 (iso.exceptionsPauseInfo != null)) { 1086 (iso.exceptionsPauseInfo != null)) {
1000 exceptions = iso.exceptionsPauseInfo; 1087 exceptions = iso.exceptionsPauseInfo;
1001 console.print("Now pausing for $exceptions exceptions"); 1088 console.print("Now pausing for $exceptions exceptions");
1002 } 1089 }
1003 1090
1091 _logSubscriptionFuture = vm.listenEventStream(Isolate.kLoggingStream,
1092 onEvent);
turnidge 2015/08/03 18:16:22 Streams are per-vm, not per-isolate, so it is not
Cutch 2015/08/03 19:29:56 Done.
1093
1004 _isolate.reload().then((response) { 1094 _isolate.reload().then((response) {
1005 // TODO(turnidge): Currently the debugger relies on all libs 1095 // TODO(turnidge): Currently the debugger relies on all libs
1006 // being loaded. Fix this. 1096 // being loaded. Fix this.
1007 var pending = []; 1097 var pending = [];
1008 for (var lib in _isolate.libraries) { 1098 for (var lib in _isolate.libraries) {
1009 if (!lib.loaded) { 1099 if (!lib.loaded) {
1010 pending.add(lib.load()); 1100 pending.add(lib.load());
1011 } 1101 }
1012 } 1102 }
1013 Future.wait(pending).then((_) { 1103 Future.wait(pending).then((_) {
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1231 _reportBreakpointEvent(event); 1321 _reportBreakpointEvent(event);
1232 } 1322 }
1233 break; 1323 break;
1234 1324
1235 case ServiceEvent.kIsolateStart: 1325 case ServiceEvent.kIsolateStart:
1236 case ServiceEvent.kGraph: 1326 case ServiceEvent.kGraph:
1237 case ServiceEvent.kGC: 1327 case ServiceEvent.kGC:
1238 case ServiceEvent.kInspect: 1328 case ServiceEvent.kInspect:
1239 break; 1329 break;
1240 1330
1331 case ServiceEvent.kLogging:
1332 _stdioPrinter.onEvent(event.logRecord['level'].name, event);
1333 break;
1334
1241 default: 1335 default:
1242 console.print('Unrecognized event: $event'); 1336 console.print('Unrecognized event: $event');
1243 break; 1337 break;
1244 } 1338 }
1245 } 1339 }
1246 1340
1247 _VMStreamPrinter _stdioPrinter; 1341 Future<StreamSubscription> _logSubscriptionFuture;
turnidge 2015/08/03 18:16:22 Move this with other subscription futures.
Cutch 2015/08/03 19:29:56 Done.
1342
1343 _ConsoleStreamPrinter _stdioPrinter;
turnidge 2015/08/03 18:16:22 Rename _stdioPrinter to _consolePrinter?
Cutch 2015/08/03 19:29:56 Done.
1248 1344
1249 void flushStdio() { 1345 void flushStdio() {
1250 _stdioPrinter.flush(); 1346 _stdioPrinter.flush();
1251 } 1347 }
1252 1348
1253 void onStdout(ServiceEvent event) { 1349 void onStdout(ServiceEvent event) {
1254 _stdioPrinter.onEvent('stdout', event); 1350 _stdioPrinter.onEvent('stdout', event);
1255 } 1351 }
1256 1352
1257 void onStderr(ServiceEvent event) { 1353 void onStderr(ServiceEvent event) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1399 } 1495 }
1400 }); 1496 });
1401 } 1497 }
1402 1498
1403 void onPoll() { 1499 void onPoll() {
1404 debugger.flushStdio(); 1500 debugger.flushStdio();
1405 } 1501 }
1406 1502
1407 @override 1503 @override
1408 void detached() { 1504 void detached() {
1505 debugger.isolate = null;
1409 cancelFutureSubscription(_isolateSubscriptionFuture); 1506 cancelFutureSubscription(_isolateSubscriptionFuture);
1410 _isolateSubscriptionFuture = null; 1507 _isolateSubscriptionFuture = null;
1411 cancelFutureSubscription(_debugSubscriptionFuture); 1508 cancelFutureSubscription(_debugSubscriptionFuture);
1412 _debugSubscriptionFuture = null; 1509 _debugSubscriptionFuture = null;
1413 cancelFutureSubscription(_stdoutSubscriptionFuture); 1510 cancelFutureSubscription(_stdoutSubscriptionFuture);
1414 _stdoutSubscriptionFuture = null; 1511 _stdoutSubscriptionFuture = null;
1415 cancelFutureSubscription(_stderrSubscriptionFuture); 1512 cancelFutureSubscription(_stderrSubscriptionFuture);
1416 _stderrSubscriptionFuture = null; 1513 _stderrSubscriptionFuture = null;
1417 super.detached(); 1514 super.detached();
1418 } 1515 }
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
1882 } 1979 }
1883 }); 1980 });
1884 } 1981 }
1885 1982
1886 void focus() { 1983 void focus() {
1887 $['textBox'].focus(); 1984 $['textBox'].focus();
1888 } 1985 }
1889 1986
1890 DebuggerInputElement.created() : super.created(); 1987 DebuggerInputElement.created() : super.created();
1891 } 1988 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698