Class: Bulldogger::Capture

Inherits:
Object
  • Object
show all
Defined in:
lib/bulldogger/capture.rb

Overview

Subscribes to :raise globally and turns every raised exception into a bounded, already-serialized snapshot before the hook returns.

Serialization happens here, inside the hook, rather than later from whatever holds the frame data: a DEBUGGER__::FrameInfo keeps its frame's Binding alive, and a live Binding keeps every object reachable from that frame alive too (measured: the TracePoint block's own captured-array local was still reachable through a retained Binding). Rendering every value to a String and dropping the FrameInfo/Binding before this method returns is what makes the Pending ring's size an actual memory bound, not just a count of references to unbounded object graphs.

Instance Method Summary collapse

Constructor Details

#initialize(config:) ⇒ Capture

Returns a new instance of Capture.



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/bulldogger/capture.rb', line 22

def initialize(config:)
  @config = config
  @redactor = Redactor.new(config.redact_patterns)
  @formatter = Formatter.new(config: config, redactor: @redactor)
  @frame_source = FrameSource.new(config: config, formatter: @formatter, redactor: @redactor)
  @pending = Pending.new(config.max_pending)
  @trace_point = nil
  @start_mutex = Mutex.new
  @raise_count = 0
  @checkpoint = nil
end

Instance Method Details

#begin_testObject



62
63
64
65
# File 'lib/bulldogger/capture.rb', line 62

def begin_test
  @checkpoint = @raise_count
  self
end

#end_testObject



67
68
69
70
# File 'lib/bulldogger/capture.rb', line 67

def end_test
  @checkpoint = nil
  self
end

#reason_for_missing(exception) ⇒ Object



72
73
74
75
76
77
# File 'lib/bulldogger/capture.rb', line 72

def reason_for_missing(exception)
  return "capture_disabled" unless running?
  return "evicted" if @pending.evicted?(exception)

  "not_captured"
end

#running?Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/bulldogger/capture.rb', line 54

def running?
  !@trace_point.nil?
end

#snapshot_for(exception) ⇒ Object



58
59
60
# File 'lib/bulldogger/capture.rb', line 58

def snapshot_for(exception)
  @pending.get(exception)
end

#startObject



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/bulldogger/capture.rb', line 34

def start
  @start_mutex.synchronize do
    return self if @trace_point

    @frame_source.resolve!
    trace_point = TracePoint.new(:raise) { |tp| handle_raise(tp) }
    trace_point.enable
    @trace_point = trace_point
  end
  self
end

#stopObject



46
47
48
49
50
51
52
# File 'lib/bulldogger/capture.rb', line 46

def stop
  @start_mutex.synchronize do
    @trace_point&.disable
    @trace_point = nil
  end
  self
end