Better runtime backtraces

crystal has the ability to generate very descriptive backtraces at compile time:

$ cat go2.cr
def go1
go3
end

go1
$ crystal build --error-trace go2.cr
In go2.cr:5:1

5 | go1
^–
Error: instantiating ‘go1()’

In go2.cr:2:3

2 | go3
^–
Error: undefined local variable or method ‘go3’ for top-level

Did you mean ‘go1’?

I had a thought that maybe runtime exception traces, like this one:

$ cat go.cr
raise “BOOM”

$ crystal go.cr
Unhandled exception: BOOM (Exception)
from go.cr:1:1 in ‘__crystal_main’
from /usr/share/crystal/src/crystal/main.cr:97:5 in ‘main_user_code’
from /usr/share/crystal/src/crystal/main.cr:86:7 in ‘main’
from /usr/share/crystal/src/crystal/main.cr:106:3 in ‘main’
from __libc_start_main
from _start
from ???

could possibly be aumented so that they show more information, like looking up the source code on the lines of the backtrace, at runtime. Thoughts?
Thanks!

This might help debugging during development, but it wouldn’t be useful in production. The additional verbosity would fill up logs and provide no benefit. Often source code wouldn’t be available anyway in the runtime environment. And these enhancements for runtime errors would add a bunch of additional code to every Crystal program, again with often no real gain.

It would be possible though to have enhanced backtraces for development. This should be pretty easy to implement, and could even go entirely into user code. Essentially, you just need to override Callstack.print_frame and enhance the frame output.

An alternative solution would be to pipe stderr through a program that enhances the backtraces. That might actually be easier to implement and it’s more flexible because it doesn’t need to be activated at compile time and you can even enhance backtraces from logs.

1 Like

Raven.cr’s crash handler would be an example for parsing the error output from a Crystal program and enhancing it: https://github.com/Sija/raven.cr/blob/master/src/crash_handler.cr

2 Likes

Thanks. I’ll try making one a shard and if I really like it propose it for the stdlib (in non release compiles only perhaps? :)