Class: Tracer::Base

Inherits:
Object
  • Object
show all
Includes:
Color
Defined in:
lib/ruby_tracer/base.rb

Direct Known Subclasses

CallTracer, ExceptionTracer, LineTracer, ObjectTracer

Defined Under Namespace

Classes: LimitedPP

Constant Summary collapse

DIR =
__dir__
M_OBJECT_ID =
Object.instance_method(:object_id)
M_INSPECT =
Object.instance_method(:inspect)
M_CLASS =
Object.instance_method(:class)
M_IS_A =
Object.instance_method(:is_a?)
HOME =
ENV["HOME"] ? (ENV["HOME"] + "/") : nil

Constants included from Color

Color::BLUE, Color::BOLD, Color::CLEAR, Color::CYAN, Color::GREEN, Color::MAGENTA, Color::RED, Color::REVERSE, Color::UNDERLINE, Color::YELLOW

Instance Method Summary collapse

Methods included from Color

clear, colorize, #colorize, #colorize_blue, #colorize_cyan, #colorize_magenta

Constructor Details

#initialize(output: STDOUT, pattern: nil, colorize: nil, depth_offset: 0) ⇒ Base

Returns a new instance of Base.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/ruby_tracer/base.rb', line 73

def initialize(output: STDOUT, pattern: nil, colorize: nil, depth_offset: 0)
  @name = self.class.name
  @type = @name.sub(/Tracer\z/, "")
  @output = output
  @depth_offset = depth_offset
  @colorize = colorize || colorizable?

  if pattern
    @pattern = Regexp.compile(pattern)
  else
    @pattern = nil
  end

  @tp = setup_tp
end

Instance Method Details

#colorizable?Boolean

Returns:

  • (Boolean)


167
168
169
170
# File 'lib/ruby_tracer/base.rb', line 167

def colorizable?
  no_color = (nc = ENV["NO_COLOR"]).nil? || nc.empty?
  @output.is_a?(IO) && @output.tty? && no_color
end

#descriptionObject



103
104
105
# File 'lib/ruby_tracer/base.rb', line 103

def description
  "(#{@tp.enabled? ? "enabled" : "disabled"})"
end

#headerObject



93
94
95
# File 'lib/ruby_tracer/base.rb', line 93

def header
  ""
end

#keyObject



89
90
91
# File 'lib/ruby_tracer/base.rb', line 89

def key
  [@type, @pattern, @into].freeze
end

#minfo(tp) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/ruby_tracer/base.rb', line 155

def minfo(tp)
  return "block{}" if tp.event == :b_call

  klass = tp.defined_class

  if klass.singleton_class?
    "#{tp.self}.#{tp.method_id}"
  else
    "#{klass}\##{tp.method_id}"
  end
end

#out(tp, msg = nil, depth: caller.size - 1, location: nil) ⇒ Object



142
143
144
145
146
147
148
# File 'lib/ruby_tracer/base.rb', line 142

def out(tp, msg = nil, depth: caller.size - 1, location: nil)
  location ||= "#{tp.path}:#{tp.lineno}"
  buff =
    "#{header} \#depth:#{"%-2d" % depth}#{msg} at #{colorize("#{location}", [:GREEN])}"

  puts buff
end

#pretty_path(path) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/ruby_tracer/base.rb', line 58

def pretty_path(path)
  return "#<none>" unless path

  case
  when path.start_with?(dir = RbConfig::CONFIG["rubylibdir"] + "/")
    path.sub(dir, "$(rubylibdir)/")
  when Gem.path.any? { |gp| path.start_with?(dir = gp + "/gems/") }
    path.sub(dir, "$(Gem)/")
  when HOME && path.start_with?(HOME)
    path.sub(HOME, "~/")
  else
    path
  end
end

#puts(msg) ⇒ Object



150
151
152
153
# File 'lib/ruby_tracer/base.rb', line 150

def puts(msg)
  @output.puts msg
  @output.flush
end

#safe_inspect(obj, max_length: 40) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ruby_tracer/base.rb', line 44

def safe_inspect(obj, max_length: 40)
  LimitedPP.pp(obj, max_length)
rescue NoMethodError => e
  klass, oid = M_CLASS.bind_call(obj), M_OBJECT_ID.bind_call(obj)
  if obj == (r = e.receiver)
    "#<#{klass.name}#{oid} does not have \#inspect>"
  else
    rklass, roid = M_CLASS.bind_call(r), M_OBJECT_ID.bind_call(r)
    "#<#{klass.name}:#{roid} contains #<#{rklass}:#{roid} and it does not have #inspect>"
  end
rescue Exception => e
  "<#inspect raises #{e.inspect}>"
end

#skip?(tp) ⇒ Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/ruby_tracer/base.rb', line 130

def skip?(tp)
  skip_internal?(tp) || skip_with_pattern?(tp)
end

#skip_internal?(tp) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/ruby_tracer/base.rb', line 138

def skip_internal?(tp)
  tp.path.match?(DIR)
end

#skip_with_pattern?(tp) ⇒ Boolean

Returns:

  • (Boolean)


134
135
136
# File 'lib/ruby_tracer/base.rb', line 134

def skip_with_pattern?(tp)
  @pattern && !tp.path.match?(@pattern)
end

#start(&block) ⇒ Object



107
108
109
110
111
112
113
114
115
116
# File 'lib/ruby_tracer/base.rb', line 107

def start(&block)
  puts "PID:#{Process.pid} #{self}" if @output.is_a?(File)

  if block
    @tp.enable(&block)
  else
    @tp.enable
    self
  end
end

#started?Boolean

Returns:

  • (Boolean)


122
123
124
# File 'lib/ruby_tracer/base.rb', line 122

def started?
  @tp.enabled?
end

#stopObject



118
119
120
# File 'lib/ruby_tracer/base.rb', line 118

def stop
  @tp.disable
end

#stopped?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'lib/ruby_tracer/base.rb', line 126

def stopped?
  !started?
end

#to_sObject



97
98
99
100
101
# File 'lib/ruby_tracer/base.rb', line 97

def to_s
  s = "#{@name} #{description}"
  s += " with pattern #{@pattern.inspect}" if @pattern
  s
end