如何获取异步执行的完整堆栈跟踪

时间:2015-03-12 15:17:26

标签: dart dart-async

对于像

这样的小例子
import 'dart:async';
import 'package:stack_trace/stack_trace.dart';

void main() {
  scheduleAsync();
}

void scheduleAsync() {
  new Future.delayed(new Duration(seconds: 1))
      .then((_) => runAsync());
}

void runAsync() {
  throw 'oh no!';
}

我得到了这个堆栈跟踪。我可以跟踪回调最远的是runAsync()中的scheduleAsync()来电。 没有留下任何信息,scheduleAsync来自main

Unhandled exception:
Uncaught Error: oh no!
Stack Trace:
#0      runAsync (file:///home/myuser/dart/playground/bin/stack_trace/main.dart:14:3)
#1      scheduleAsync. (file:///home/myuser/dart/playground/bin/stack_trace/main.dart:10:28)
#2      _RootZone.runUnary (dart:async/zone.dart:1155)
#3      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#4      _Future._propagateToListeners (dart:async/future_impl.dart:567)
#5      _Future._complete (dart:async/future_impl.dart:348)
#6      Future.Future.delayed. (dart:async/future.dart:228)
#7      Timer._createTimer. (dart:async-patch/timer_patch.dart:16)
#8      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:385)
#9      _handleMessage (dart:isolate-patch/timer_impl.dart:411)
#10     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:142)

#0      _rootHandleUncaughtError. (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)
#4      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:392)
#5      _handleMessage (dart:isolate-patch/timer_impl.dart:411)
#6      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:142)

Process finished with exit code 255

有没有办法获得完整的堆栈跟踪?

1 个答案:

答案 0 :(得分:6)

stack_tracehttps://pub.dartlang.org/packages/stack_trace将整个堆栈跟踪放在一起。

另见
- 来自stack_trace包的开发者的this blog post - http://news.dartlang.org/2016/01/unboxing-packages-stacktrace.html?m=1

import 'dart:async';
import 'package:stack_trace/stack_trace.dart';

void main() {
  Chain.capture(() {
    scheduleAsync(); // <= pass my code in Chain.capture
    }, onError: (error, stack) {
      print(error);
      print(stack);
    });
}

void scheduleAsync() {
  new Future.delayed(new Duration(seconds: 1))
      .then((_) => runAsync());
}

void runAsync() {
  throw 'oh no!';
}

产生此输出,允许追溯到main中的第一行。

oh no!
main.dart 19:3                                                runAsync
main.dart 15:28                                               scheduleAsync.
package:stack_trace/src/stack_zone_specification.dart 134:26  registerUnaryCallback..
package:stack_trace/src/stack_zone_specification.dart 210:15  StackZoneSpecification._run
package:stack_trace/src/stack_zone_specification.dart 134:18  registerUnaryCallback.
dart:async/zone.dart 902                                      _rootRunUnary
dart:async/zone.dart 804                                      _CustomZone.runUnary
dart:async/future_impl.dart 484                               _Future._propagateToListeners.handleValueCallback
dart:async/future_impl.dart 567                               _Future._propagateToListeners
dart:async/future_impl.dart 348                               _Future._complete
dart:async/future.dart 228                                    Future.Future.delayed.
package:stack_trace/src/stack_zone_specification.dart 210:15  StackZoneSpecification._run
package:stack_trace/src/stack_zone_specification.dart 124:52  registerCallback.
dart:async/zone.dart 891                                      _rootRun
dart:async/zone.dart 796                                      _CustomZone.run
dart:async/zone.dart 704                                      _CustomZone.runGuarded
dart:async/zone.dart 729                                      _CustomZone.bindCallback.
package:stack_trace/src/stack_zone_specification.dart 210:15  StackZoneSpecification._run
package:stack_trace/src/stack_zone_specification.dart 124:52  registerCallback.
dart:async/zone.dart 895                                      _rootRun
dart:async/zone.dart 796                                      _CustomZone.run
dart:async/zone.dart 704                                      _CustomZone.runGuarded
dart:async/zone.dart 729                                      _CustomZone.bindCallback.
dart:async-patch/timer_patch.dart 16                          Timer._createTimer.
dart:isolate-patch/timer_impl.dart 385                        _Timer._runTimers
dart:isolate-patch/timer_impl.dart 411                        _handleMessage
dart:isolate-patch/isolate_patch.dart 142                     _RawReceivePortImpl._handleMessage
===== asynchronous gap ===========================
dart:async/zone.dart 828                                      _CustomZone.registerUnaryCallback
dart:async/future_impl.dart 208                               _Future.then
main.dart 15:12                                               scheduleAsync
main.dart 6:18                                                main.
package:stack_trace/src/chain.dart 82:24                      Chain.capture.
dart:async/zone.dart 895                                      _rootRun
dart:async/zone.dart 796                                      _CustomZone.run
dart:async/zone.dart 1251                                     runZoned
package:stack_trace/src/chain.dart 80:20                      Chain.capture
main.dart 5:16                                                main
dart:isolate-patch/isolate_patch.dart 255                     _startIsolate.
dart:isolate-patch/isolate_patch.dart 142                     _RawReceivePortImpl._handleMessage


Process finished with exit code 0

更简单的是简洁版

import 'dart:async';
import 'package:stack_trace/stack_trace.dart';

void main() {
  Chain.capture(() {
    scheduleAsync();
    }, onError: (error, stack) {
      print(error);
      print(new Trace.from(stack).terse);
    });
}

void scheduleAsync() {
  new Future.delayed(new Duration(seconds: 1))
      .then((_) => runAsync());
}

void runAsync() {
  throw 'oh no!';
}

产生:

oh no!
main.dart 19:3       runAsync
main.dart 15:28      scheduleAsync.
===== asynchronous gap ===========================
dart:async           _Future.then
main.dart 15:12      scheduleAsync
main.dart 6:18       main.
package:stack_trace  Chain.capture
main.dart 5:16       main


Process finished with exit code 0