Class: Tracia

Inherits:
Object
  • Object
show all
Defined in:
lib/tracia.rb,
lib/tracia/frame.rb,
lib/tracia/version.rb,
lib/tracia/gem_paths.rb,
lib/tracia/default_logger.rb,
lib/tracia/fake_trace_point.rb

Defined Under Namespace

Modules: GemPaths Classes: DefaultLogger, Error, FakeTracePoint, Frame

Constant Summary collapse

INSTANCE_METHOD_SHARP =
'#'
VERSION =
"0.2.16"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**opt) ⇒ Tracia

Returns a new instance of Tracia.



48
49
50
51
52
53
54
55
56
57
# File 'lib/tracia.rb', line 48

def initialize(**opt)
  @frames_to_reject = Array(opt[:reject])
  @non_tail_recursion = opt[:non_tail_recursion]
  @logger = opt[:logger] || DefaultLogger.new

  @backtraces = []
  @level = 0

  enable_trace_point(opt[:trace_point])
end

Instance Attribute Details

#depthObject

Returns the value of attribute depth.



16
17
18
# File 'lib/tracia.rb', line 16

def depth
  @depth
end

#errorObject

Returns the value of attribute error.



16
17
18
# File 'lib/tracia.rb', line 16

def error
  @error
end

#levelObject

Returns the value of attribute level.



16
17
18
# File 'lib/tracia.rb', line 16

def level
  @level
end

Class Method Details

.add(info = nil, &block) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/tracia.rb', line 36

def add(info = nil, &block)
  trc = Thread.current[:_tracia_]
  return unless trc

  backtrace = binding.partial_callers(-trc.depth)
  backtrace.reverse!
  backtrace.pop
  info = block.call if block
  trc.add(backtrace, info)
end

.start(**opt) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/tracia.rb', line 19

def start(**opt)
  trc = (Thread.current[:_tracia_] ||= new(**opt))
  trc.level += 1
  trc.depth = binding.frame_count + 1
  yield
rescue StandardError => e
  trc.error = e
  raise e
ensure
  trc.level -= 1
  if trc.error || trc.level == 0
    Thread.current[:_tracia_] = nil
    trc.disable_trace_point
  end
  trc.log if trc.level == 0
end

Instance Method Details

#add(backtrace, info) ⇒ Object



84
85
86
87
# File 'lib/tracia.rb', line 84

def add(backtrace, info)
  backtrace = convert_to_frames(backtrace)
  @backtraces << [backtrace, info]
end

#disable_trace_pointObject



80
81
82
# File 'lib/tracia.rb', line 80

def disable_trace_point
  @trace_point.disable
end

#enable_trace_point(trace_point_opt) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/tracia.rb', line 59

def enable_trace_point(trace_point_opt)
  return @trace_point = FakeTracePoint.new if trace_point_opt == false

  current_thread = Thread.current
  @trace_point = TracePoint.new(:raise) do |point|
    if Proc === trace_point_opt
      next if trace_point_opt.call(point, self) == false
    end
    bd = point.binding
    next unless current_thread == bd.eval('Thread.current')
    backtrace = bd.eval("binding.partial_callers(-#{depth})")
    raiser = backtrace[0]
    next if raiser.klass == Tracia && raiser.frame_env == 'rescue in start'
    backtrace.reverse!
    backtrace.pop
    backtrace.pop
    add(backtrace, point.raised_exception)
  end
  @trace_point.enable
end

#logObject



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/tracia.rb', line 89

def log
  @stack = []

  @backtraces.each do |backtrace, info|
    build_road_from_root_to_leaf(backtrace)
    @stack.last.children << info
  end

  root = @stack[0]
  if root
    eliminate_tail_recursion!([root]) if @non_tail_recursion
    @logger.call(root)
  end
end