Module: Google::Cloud::Debugger::Breakpoint::Evaluator

Defined in:
lib/google/cloud/debugger/breakpoint/evaluator.rb

Overview

Helps to evaluate program state at the location of breakpoint during executing. The program state, such as local variables and call stack, are retrieved using Ruby Binding objects.

The breakpoints may consist of conditional expression and other code expressions. The Evaluator helps evaluates these expression in a read-only context. Meaning if the expressions trigger any write operations in middle of the evaluation, the evaluator is able to abort the operation and prevent the program state from being altered.

The evaluated results are saved onto the breakpoints fields. See Stackdriver Breakpoints Doc for details.

Constant Summary collapse

STACK_EVAL_DEPTH =

Max number of top stacks to collect local variables information

5

Class Method Summary collapse

Class Method Details

.eval_call_stack(call_stack_bindings) ⇒ Array<Google::Cloud::Debugger::Breakpoint::StackFrame>

Evaluates call stack. Collects function name and location of each frame from given binding objects. Collects local variable information from top frames.

Parameters:

  • call_stack_bindings (Array<Binding>)

    A list of binding objects that come from each of the call stack frames.

Returns:



788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
# File 'lib/google/cloud/debugger/breakpoint/evaluator.rb', line 788

def eval_call_stack call_stack_bindings
  result = []
  call_stack_bindings.each_with_index do |frame_binding, i|
    frame_info = StackFrame.new.tap do |sf|
      sf.function = frame_binding.eval("__method__").to_s
      sf.location = SourceLocation.new.tap do |l|
        l.path =
          frame_binding.eval("::File.absolute_path(__FILE__)")
        l.line = frame_binding.eval("__LINE__")
      end
    end

    if i < STACK_EVAL_DEPTH
      frame_info.locals = eval_frame_variables frame_binding
    end

    result << frame_info
  end

  result
end

.eval_condition(binding, condition) ⇒ Boolean

Evaluates a boolean conditional expression in the given context binding. The evaluation subjects to the read-only rules. If the expression does any write operation, the evaluation aborts and returns false.

Parameters:

  • binding (Binding)

    The binding object from the context

  • condition (String)

    A string of code to be evaluates

Returns:

  • (Boolean)

    True if condition expression read-only evaluates to true. Otherwise false.



822
823
824
825
826
827
828
829
830
831
# File 'lib/google/cloud/debugger/breakpoint/evaluator.rb', line 822

def eval_condition binding, condition
  result = readonly_eval_expression_exec binding, condition

  if result.is_a?(Exception) &&
     result.instance_variable_get(:@mutation_cause)
    return false
  end

  result ? true : false
end

.eval_expressions(binding, expressions) ⇒ Array<Google::Cloud::Debugger::Breakpoint::Variable>

Evaluates the breakpoint expressions at the point that triggered the breakpoint. The expressions subject to the read-only rules. If the expressions do any write operations, the evaluations abort and show an error message in place of the real result.

Parameters:

  • binding (Binding)

    The binding object from the context

  • expressions (Array<String>)

    A list of code strings to be evaluated

Returns:



846
847
848
849
850
851
852
853
# File 'lib/google/cloud/debugger/breakpoint/evaluator.rb', line 846

def eval_expressions binding, expressions
  expressions.map do |expression|
    eval_result = readonly_eval_expression binding, expression
    evaluated_var = Variable.from_rb_var eval_result
    evaluated_var.name = expression
    evaluated_var
  end
end

.format_message(message_format, expressions) ⇒ String

Format log message by interpolate expressions.

Examples:

Evaluator.format_log_message("Hello $0",
                             ["World"]) #=> "Hello World"

Parameters:

  • message_format (String)

    The message with with expression placeholders such as $0, $1, etc.

  • expressions (Array<Google::Cloud::Debugger::Breakpoint::Variable>)

    An array of evaluated expression variables to be placed into message_format's placeholders. The variables need to have type equal String.

Returns:

  • (String)

    The formatted message string



897
898
899
900
901
902
903
904
905
906
# File 'lib/google/cloud/debugger/breakpoint/evaluator.rb', line 897

def format_message message_format, expressions
  # Substitute placeholders with expressions
  message = message_format.gsub(/(?<!\$)\$\d+/) do |placeholder|
    index = placeholder.match(/\$(\d+)/)[1].to_i
    index < expressions.size ? expressions[index].inspect : ""
  end

  # Unescape "$" charactors
  message.gsub(/\$\$/, "$")
end