The stack_trace
package https://pub.dartlang.org/packages/stack_trace puts together the whole stack trace.
See also
- this blog post from a developer of the stack_trace package.
- 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!';
}
produces this output which allows trace back to the first line in 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
Even more useful is the terse version
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!';
}
which produces:
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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…