Class: RailsErrorDashboard::Services::LocalVariableCapturer

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_error_dashboard/services/local_variable_capturer.rb

Overview

TracePoint lifecycle manager for capturing local variables and instance variables at raise time.

Uses TracePoint(:raise) which only fires when exceptions are raised (rare in normal request flow). Sentry ships this in production (proven safe).

Safety contract:

  • Default OFF (opt-in via config.enable_local_variables / enable_instance_variables)

  • Never stores Binding objects or object references — extracts vars immediately in callback

  • Every callback wrapped in rescue => e (never raises)

  • Per-variable rescue in extraction

  • Skips SystemExit, SignalException, Interrupt

  • Skips non-app-code paths (gems, vendor, stdlib, this gem)

  • Re-raise guard: skips if exception already has @_red_locals / @_red_instance_vars

Constant Summary collapse

LOCALS_IVAR =

Instance variable names used to attach captured data to the exception

:@_red_locals
INSTANCE_VARS_IVAR =
:@_red_instance_vars

Class Method Summary collapse

Class Method Details

.disable!Object

Disable the TracePoint hook



42
43
44
45
# File 'lib/rails_error_dashboard/services/local_variable_capturer.rb', line 42

def disable!
  @tracepoint&.disable
  @tracepoint = nil
end

.enable!Object

Enable the TracePoint(:raise) hook globally



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rails_error_dashboard/services/local_variable_capturer.rb', line 26

def enable!
  return if enabled?

  @tracepoint = TracePoint.new(:raise) do |tp|
    on_raise(tp)
  rescue => e
    # CRITICAL: never let the callback crash the app
    RailsErrorDashboard::Logger.debug(
      "[RailsErrorDashboard] LocalVariableCapturer callback error: #{e.class} - #{e.message}"
    )
  end

  @tracepoint.enable
end

.enabled?Boolean

Check if currently enabled

Returns:

  • (Boolean)


48
49
50
# File 'lib/rails_error_dashboard/services/local_variable_capturer.rb', line 48

def enabled?
  @tracepoint&.enabled? == true
end

.extract(exception) ⇒ Hash?

Extract captured locals from an exception (if any)

Parameters:

  • exception (Exception)

    The exception to check

Returns:

  • (Hash, nil)

    Raw locals hash or nil



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rails_error_dashboard/services/local_variable_capturer.rb', line 55

def extract(exception)
  return nil unless exception.is_a?(Exception)
  return nil unless exception.instance_variable_defined?(LOCALS_IVAR)

  exception.instance_variable_get(LOCALS_IVAR)
rescue => e
  RailsErrorDashboard::Logger.debug(
    "[RailsErrorDashboard] LocalVariableCapturer.extract failed: #{e.message}"
  )
  nil
end

.extract_instance_vars(exception) ⇒ Hash?

Extract captured instance variables from an exception (if any)

Parameters:

  • exception (Exception)

    The exception to check

Returns:

  • (Hash, nil)

    Raw instance vars hash or nil



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rails_error_dashboard/services/local_variable_capturer.rb', line 70

def extract_instance_vars(exception)
  return nil unless exception.is_a?(Exception)
  return nil unless exception.instance_variable_defined?(INSTANCE_VARS_IVAR)

  exception.instance_variable_get(INSTANCE_VARS_IVAR)
rescue => e
  RailsErrorDashboard::Logger.debug(
    "[RailsErrorDashboard] LocalVariableCapturer.extract_instance_vars failed: #{e.message}"
  )
  nil
end