diff --git a/.agents/codebase-insights.txt b/.agents/codebase-insights.txt index a886c88..8cc4f76 100644 --- a/.agents/codebase-insights.txt +++ b/.agents/codebase-insights.txt @@ -1 +1,5 @@ -No insights yet. Please add content here and remove this line. +When tracing scripts with the pure Ruby recorder, avoid including the +`RubyRecorder` instance (or its `TraceRecord`) among the inspected local +variables. Otherwise the serializer will descend into the tracer's own +state which quickly explodes in size and appears as infinite recursion. +`load_variables` filters these objects out. diff --git a/gems/codetracer-pure-ruby-recorder/lib/trace.rb b/gems/codetracer-pure-ruby-recorder/lib/trace.rb index 9fd4820..1b07920 100644 --- a/gems/codetracer-pure-ruby-recorder/lib/trace.rb +++ b/gems/codetracer-pure-ruby-recorder/lib/trace.rb @@ -215,16 +215,21 @@ def deactivate private + # Collect local variables from the current +binding+. Variables that refer to + # the tracer itself or the trace record are ignored to avoid recursively + # serialising the internal state of the tracer. def load_variables(binding) - if !binding.nil? - # $stdout.write binding.local_variables - binding.local_variables.map do |name| - v = binding.local_variable_get(name) - out = to_value(v) - [name, out] - end - else - [] + return [] if binding.nil? + + binding.local_variables.filter_map do |name| + v = binding.local_variable_get(name) + + next if v.equal?(self) || v.equal?(@record) + next if defined?(RubyRecorder) && v.is_a?(RubyRecorder) + next if defined?(TraceRecord) && v.is_a?(TraceRecord) + + out = to_value(v) + [name, out] end end end