Class: Google::Cloud::Debugger::Tracer

Inherits:
Object
  • Object
show all
Defined in:
lib/google/cloud/debugger/tracer.rb

Overview

Tracer

When active breakpoints are set for the debugger, the tracer monitors the running Ruby application and triggers evaluation when the code is executed at the breakpoint locations.

The tracer tracks the running application using several Ruby TracePoints and C level Ruby debugging API.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#agentGoogle::Cloud::Debugger::Agent (readonly)

The debugger agent this tracer belongs to



35
36
37
# File 'lib/google/cloud/debugger/tracer.rb', line 35

def agent
  @agent
end

#app_rootString

Ruby application root directory, in absolute path form. The Stackdriver Debugger Service only knows the relative application file path. So the tracer needs to combine relative file path with application root directory to get full file path for tracing purpose

Returns:

  • (String)


43
44
45
# File 'lib/google/cloud/debugger/tracer.rb', line 43

def app_root
  @app_root
end

Instance Method Details

#eval_breakpoint(breakpoint, call_stack_bindings) ⇒ Object

Evaluates a hit breakpoint, and signal BreakpointManager and Transmitter if this breakpoint is evaluated successfully.

See Breakpoint#eval_call_stack for evaluation details.

Parameters:

  • breakpoint (Google::Cloud::Debugger::Breakpoint)

    The breakpoint to be evaluated

  • call_stack_bindings (Array<Binding>)

    An array of Ruby Binding objects, from the each frame of the call stack that leads to the triggering of the breakpoints.



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/google/cloud/debugger/tracer.rb', line 117

def eval_breakpoint breakpoint, call_stack_bindings
  return if breakpoint.nil? || breakpoint.complete?

  breakpoint.eval_call_stack call_stack_bindings

  # Take this completed breakpoint off manager's active breakpoints
  # list, submit the breakpoint snapshot, and update Tracer's
  # breakpoints_cache.
  return unless breakpoint.complete?

  # Signal breakpoint_manager that this breakpoint is evaluated
  agent.breakpoint_manager.mark_off breakpoint
  # Signal transmitter to submit this breakpoint
  agent.transmitter.submit breakpoint

  update_breakpoints_cache

  # Disable all trace points and tracing if all breakpoints are complete
  disable_traces if @breakpoints_cache.empty?
end

#startObject

Get the sync the breakpoints cache with BreakpointManager. Start tracing and monitoring if there are any breakpoints.



152
153
154
155
# File 'lib/google/cloud/debugger/tracer.rb', line 152

def start
  update_breakpoints_cache
  enable_traces unless breakpoints_cache.empty?
end

#stopObject

Stops all tracing.



159
160
161
# File 'lib/google/cloud/debugger/tracer.rb', line 159

def stop
  disable_traces
end

#update_breakpoints_cacheObject

Update tracer's private breakpoints cache with the list of active breakpoints from BreakpointManager.

This methood is atomic for thread safety purpose.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/google/cloud/debugger/tracer.rb', line 87

def update_breakpoints_cache
  active_breakpoints = agent.breakpoint_manager.active_breakpoints.dup
  breakpoints_hash = {}

  active_breakpoints.each do |active_breakpoint|
    breakpoint_line = active_breakpoint.line
    breakpoint_path = full_breakpoint_path active_breakpoint.path
    breakpoints_hash[breakpoint_path] ||= {}
    breakpoints_hash[breakpoint_path][breakpoint_line] ||= []
    breakpoints_hash[breakpoint_path][breakpoint_line].push(
      active_breakpoint)
  end

  # Tracer is explicitly designed to not have a lock. This should be the
  # only place writing @breakpoints_cache to ensure thread safety.
  @breakpoints_cache = breakpoints_hash
end