如何获取异步执行的完整堆栈跟踪
How to get the full stack trace for async execution
举个小例子
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!';
}
我得到了这个堆栈跟踪。我能追踪到的最远的回调是 scheduleAsync()
中的 runAsync()
调用。
没有留下任何信息,scheduleAsync
是从 main
.
调用的
未处理的异常:
未捕获的错误:哦不!
堆栈跟踪:
#0 runAsync (文件:///home/myuser/dart/playground/bin/stack_trace/main.dart:14:3)
#1 scheduleAsync。 (文件:///home/myuser/dart/playground/bin/stack_trace/main.dart:10:28)
#2 _RootZone.runUnary(飞镖:async/zone.飞镖:1155)
#3 _Future._propagateToListeners.handleValueCallback(飞镖:async/future_impl.飞镖:484)
#4 _Future._propagateToListeners(飞镖:async/future_impl.飞镖:567)
#5 _Future._complete(飞镖:async/future_impl.飞镖:348)
#6 Future.Future.delayed。 (飞镖:async/future.飞镖:228)
#7 Timer._createTimer。 (飞镖:async-patch/timer_patch.飞镖:16)
#8 _Timer._runTimers(飞镖:isolate-patch/timer_impl.飞镖:385)
#9 _handleMessage (飞镖:isolate-patch/timer_impl.飞镖:411)
#10 _RawReceivePortImpl._handleMessage(飞镖:isolate-patch/isolate_patch.飞镖:142)
#0 _rootHandleUncaughtError。 (飞镖:async/zone.飞镖:886)
#1 _asyncRunCallbackLoop (飞镖:async/schedule_microtask.飞镖:41)
#2 _asyncRunCallback (飞镖:async/schedule_microtask.飞镖:48)
#3 _runPendingImmediateCallback(飞镖:isolate-patch/isolate_patch.飞镖:96)
#4 _Timer._runTimers(飞镖:isolate-patch/timer_impl.飞镖:392)
#5 _handleMessage (飞镖:isolate-patch/timer_impl.飞镖:411)
#6 _RawReceivePortImpl._handleMessage(飞镖:isolate-patch/isolate_patch.飞镖:142)
进程结束,退出代码为 255
有没有办法获得完整的堆栈跟踪?
stack_trace
包 https://pub.dartlang.org/packages/stack_trace 将整个堆栈跟踪放在一起。
另见
- this blog post 来自 stack_trace 包的开发者。
- 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
举个小例子
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!';
}
我得到了这个堆栈跟踪。我能追踪到的最远的回调是 scheduleAsync()
中的 runAsync()
调用。
没有留下任何信息,scheduleAsync
是从 main
.
未处理的异常: 未捕获的错误:哦不! 堆栈跟踪: #0 runAsync (文件:///home/myuser/dart/playground/bin/stack_trace/main.dart:14:3) #1 scheduleAsync。 (文件:///home/myuser/dart/playground/bin/stack_trace/main.dart:10:28) #2 _RootZone.runUnary(飞镖:async/zone.飞镖:1155) #3 _Future._propagateToListeners.handleValueCallback(飞镖:async/future_impl.飞镖:484) #4 _Future._propagateToListeners(飞镖:async/future_impl.飞镖:567) #5 _Future._complete(飞镖:async/future_impl.飞镖:348) #6 Future.Future.delayed。 (飞镖:async/future.飞镖:228) #7 Timer._createTimer。 (飞镖:async-patch/timer_patch.飞镖:16) #8 _Timer._runTimers(飞镖:isolate-patch/timer_impl.飞镖:385) #9 _handleMessage (飞镖:isolate-patch/timer_impl.飞镖:411) #10 _RawReceivePortImpl._handleMessage(飞镖:isolate-patch/isolate_patch.飞镖:142) #0 _rootHandleUncaughtError。 (飞镖:async/zone.飞镖:886) #1 _asyncRunCallbackLoop (飞镖:async/schedule_microtask.飞镖:41) #2 _asyncRunCallback (飞镖:async/schedule_microtask.飞镖:48) #3 _runPendingImmediateCallback(飞镖:isolate-patch/isolate_patch.飞镖:96) #4 _Timer._runTimers(飞镖:isolate-patch/timer_impl.飞镖:392) #5 _handleMessage (飞镖:isolate-patch/timer_impl.飞镖:411) #6 _RawReceivePortImpl._handleMessage(飞镖:isolate-patch/isolate_patch.飞镖:142) 进程结束,退出代码为 255
有没有办法获得完整的堆栈跟踪?
stack_trace
包 https://pub.dartlang.org/packages/stack_trace 将整个堆栈跟踪放在一起。
另见
- this blog post 来自 stack_trace 包的开发者。
- 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