Skip to content

Commit

Permalink
DAP: introduce rdbg trace inspector
Browse files Browse the repository at this point in the history
  • Loading branch information
ono-max committed Mar 8, 2023
1 parent 0fcfc28 commit 6d9078d
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
51 changes: 51 additions & 0 deletions lib/debug/server_dap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,10 @@ def process
send_event :terminated unless @sock.closed?
end

def request_rdbgTraceInspector req
@q_msg << req
end

## called by the SESSION thread

def respond req, res
Expand Down Expand Up @@ -655,6 +659,53 @@ def process_protocol_request req
end
end

def request_rdbgTraceInspector(req)
cmd = req.dig('arguments', 'command')
case cmd
when 'enable'
events = req.dig('arguments', 'events')
evts = []
events.each{|evt|
case evt
when 'line'
evts << :line
when 'call'
evts << :call
evts << :c_call
evts << :b_call
when 'return'
evts << :return
evts << :c_return
evts << :b_return
else
raise "unknown trace type #{evt}"
end
}
add_tracer MultiTracer.new @ui, evts
@ui.respond req, {}
when 'disable'
@tracers.values.each{|t|
if t.type == 'multi'
t.disable
break
end
}
@ui.respond req, {}
when 'collect'
logs = []
@tracers.values.each{|t|
if t.type == 'multi'
logs = t.log
break
end
}
@ui.respond req, logs: logs
else
raise "unknown command #{cmd}"
end
return :retry
end

def dap_event args
# puts({dap_event: args}.inspect)
type, req, result = args
Expand Down
72 changes: 72 additions & 0 deletions lib/debug/tracer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,78 @@ def skip_with_pattern?(tp)
end
end

# MultiTracer is designated for DAP.
class MultiTracer < Tracer
MAX_LOG_SIZE = 4000
def initialize ui, evts, **kw
super(ui, **kw)
@log = []
@evts = evts
end

attr_reader :log

def setup
@tracer = TracePoint.new(*@evts){|tp|
next if skip?(tp)

case tp.event
when :call, :c_call, :b_call
append(call_trace_log(tp))
when :return, :c_return, :b_return
return_str = DEBUGGER__.safe_inspect(tp.return_value, short: true, max_length: 120)
append(call_trace_log(tp, return_str: return_str))
when :line
append(line_trace_log(tp))
end
}
end

def call_identifier_str tp
if tp.defined_class
minfo(tp)
else
"block"
end
end

def append log
if @log.size >= MAX_LOG_SIZE
@log.shift
end
@log << log
end

def call_trace_log tp, return_str: nil
log = {
depth: DEBUGGER__.frame_depth,
name: call_identifier_str(tp),
threadId: Thread.current.instance_variable_get(:@__thread_client_id),
location: {
path: tp.path,
line: tp.lineno
}
}
log[:returnValue] = return_str if return_str
log
end

def line_trace_log tp
{
depth: DEBUGGER__.frame_depth,
threadId: Thread.current.instance_variable_get(:@__thread_client_id),
location: {
path: tp.path,
line: tp.lineno
}
}
end

def skip? tp
super || !@evts.include?(tp.event)
end
end

class ExceptionTracer < Tracer
def setup
@tracer = TracePoint.new(:raise) do |tp|
Expand Down

0 comments on commit 6d9078d

Please sign in to comment.