From: "st0012 (Stan Lo) via ruby-core" Date: 2022-12-30T16:38:38+00:00 Subject: [ruby-core:111540] [Ruby master Feature#15778] Expose an API to pry-open the stack frames in Ruby Issue #15778 has been updated by st0012 (Stan Lo). I think such feature has a great potential for production use too, especially for error monitoring. For example, both [Rollbar](https://rollbar.com) and [Sentry](https://sentry.io) tries to support local variables capturing with `TracePoint`: - [Rollbar's implementation](https://github.com/rollbar/rollbar-gem/blob/caa82a97177b946b7f6d3766603483c99b4d5135/lib/rollbar/notifier/trace_with_bindings.rb#L36-L54) (captures all frames' data) - [Sentry's implementation](https://github.com/getsentry/sentry-ruby/blob/3097c49c16de2296e91b9ef1398e66ccf00d86bc/sentry-ruby/lib/sentry-ruby.rb#L50-L62) (captures only the current frame's data) But as we all know, using `TracePoint` in production is usually risky. So this feature in both services remained "experimental" and is disabled by default, even though it'd be super helpful to users. I think in a sense it proves @Eregon's point: > hiding it in the C API is not much of a safety, but it makes it inconvenient to use, inefficient (see above) and not portable (e.g., cannot be implemented on JRuby as a C API). If there can be a bundled gem to power usage like: ```rb caller_locations(1, 1, debug: true).first.binding ``` it'd level up our developer's debugging experience significantly in both development and production. ### Reasons to have a bundled gem then just use [`binding_of_caller`](https://github.com/banister/binding_of_caller) 1. From a business' perspective, it's easier to convince customers adding a language-official library than a community library. 2. We can be confident that it'd work well with Ruby's latest development, especially with YJIT. 3. It'd allow better cross-platform support. (As a side note, [Honeybdger](https://www.honeybadger.io/) supports it via [`binding_of_caller`](https://github.com/banister/binding_of_caller), but also disables it by default). ---------------------------------------- Feature #15778: Expose an API to pry-open the stack frames in Ruby https://bugs.ruby-lang.org/issues/15778#change-100904 * Author: gsamokovarov (Genadi Samokovarov) * Status: Open * Priority: Normal * Assignee: ko1 (Koichi Sasada) ---------------------------------------- Hello, I'm the maintainer of the web-console (https://github.com/rails/web-console/) gem, where one of our features is to jump between the frames in which an error occurred. To accomplish this, I currently use the Debug Inspector CRuby API. I think we should expose this functionality in Rubyland, so tools like web-console don't need to resort to C code for this. This also makes it quite harder for me to support different implementations like JRuby or TruffleRuby as everyone is having a different way to create Ruby Binding objects that represent the frames. Here the API ideas: Add `Thread::Backtrace::Location#binding` method that can create a binding for a specific caller of the current frame. We can reuse the existing `Kernel.caller_locations` method to generate the array of `Thread::Backtrace::Location` objects. We can optionally have the `Kernel.caller_locations(debug: true)` argument if we cannot generate the bindings lazily on the VM that can instruct the VM to do the slower operation. - `Thread::Backtrace::Location#binding` returns `Binding|nil`. Nil result may mean that the current location is a C frame or a JITted/optimized frame and we cannot debug it. We can also expose the DebugInspector API directly, as done in the https://github.com/banister/debug_inspector gem, but for tools like web-console, we'd need to map the bindings with the backtrace, as we cannot generate Bindings for every frame (C frames) and this needs to be done in application code, so I think the `Thread::Backtrace::Location#binding` is the better API for Ruby-land. Such API can help us eventually write most of our debuggers in Ruby as right now we don't have a way to do Post-Mortem debugging without native code or even start our debuggers without monkey-patching `Binding`. I have presented this idea in a RubyKaigi's 2019 talk called "Writing Debuggers in Plain Ruby", you can check-out the slides for more context: http://kaigi-debuggers-in-ruby.herokuapp.com. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/