Class: RubyMethodTracer::SimpleTracer
- Inherits:
-
Object
- Object
- RubyMethodTracer::SimpleTracer
- Defined in:
- lib/ruby_method_tracer/simple_tracer.rb
Overview
SimpleTracer wraps instance methods on a target class and records execution metrics for each invocation. It measures wall-clock duration, captures success or error status, stores results in-memory, and can optionally print each trace as it happens.
Options:
-
:threshold (Float): Minimum duration in seconds to record; defaults to 0.001 (1ms).
-
:auto_output (Boolean): When true, prints each call summary; defaults to false.
-
:max_calls (Integer): Maximum number of calls to store; defaults to 1000. When exceeded, oldest calls are removed.
-
:logger (Logger): Custom logger instance; defaults to Logger.new($stdout).
Usage:
tracer = RubyMethodTracer::SimpleTracer.new(MyClass, threshold: 0.005)
tracer.trace_method(:expensive_call)
results = tracer.fetch_results
Direct Known Subclasses
Instance Method Summary collapse
- #clear_results ⇒ Object
- #fetch_results ⇒ Object
-
#initialize(target_class, **options) ⇒ SimpleTracer
constructor
A new instance of SimpleTracer.
- #record_call(method_name, execution_time, status, error = nil) ⇒ Object
- #trace_method(name) ⇒ Object
Constructor Details
#initialize(target_class, **options) ⇒ SimpleTracer
Returns a new instance of SimpleTracer.
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/ruby_method_tracer/simple_tracer.rb', line 24 def initialize(target_class, **) @target_class = target_class @options = .merge() @calls = [] @lock = Mutex.new # Mutex to make writes to @calls thread safe. @wrapped_methods = Set.new @logger = @options[:logger] || Logger.new($stdout) # Unique per instance so separate tracers don't interfere with each other. @tracer_key = :"__ruby_method_tracer_in_trace_#{object_id}" @formatter = Formatters::BaseFormatter.new end |
Instance Method Details
#clear_results ⇒ Object
85 86 87 |
# File 'lib/ruby_method_tracer/simple_tracer.rb', line 85 def clear_results @lock.synchronize { @calls.clear } end |
#fetch_results ⇒ Object
74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ruby_method_tracer/simple_tracer.rb', line 74 def fetch_results snapshot = nil @lock.synchronize { snapshot = @calls.dup } # Copies under lock to prevent races while reading. { total_calls: snapshot.size, total_time: snapshot.sum { |call| call[:execution_time] }, calls: snapshot } end |
#record_call(method_name, execution_time, status, error = nil) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/ruby_method_tracer/simple_tracer.rb', line 54 def record_call(method_name, execution_time, status, error = nil) return if execution_time < @options[:threshold] call_details = { method_name: "#{@target_class}##{method_name}", execution_time: execution_time, status: status, error: error, timestamp: Time.now } @lock.synchronize do @calls << call_details # Enforce max_calls limit by removing oldest entries @calls.shift if @calls.size > @options[:max_calls] end output_call(call_details) if @options[:auto_output] end |
#trace_method(name) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/ruby_method_tracer/simple_tracer.rb', line 36 def trace_method(name) method_name = name.to_sym visibility = method_visibility(method_name) return unless visibility return unless mark_wrapped?(method_name) aliased = alias_for(method_name) @target_class.send(:alias_method, aliased, method_name) # Aliases original implementation to our private name. tracer = self key = @tracer_key # unique per tracer instance; prevents cross-tracer interference # Defines a new method with the original name that delegates to our wrapper. @target_class.define_method(method_name, &build_wrapper(aliased, method_name, key, tracer)) @target_class.send(visibility, method_name) # Restores the original visibility after redefine. end |