Class: Traceable::Tracer

Inherits:
Object
  • Object
show all
Defined in:
lib/traceable/tracer.rb

Overview

rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent_tracer, tags: nil, logger: nil) ⇒ Tracer

Returns a new instance of Tracer.



15
16
17
18
19
20
# File 'lib/traceable/tracer.rb', line 15

def initialize(parent_tracer, tags: nil, logger: nil)
  @parent = which_parent(parent_tracer)
  @logger = logger || (@parent ? @parent.logger : Tracer.default_logger)
  @tags = @parent ? @parent.tags.dup : Tracer.default_tags
  @tags.merge!(tags) if tags
end

Instance Attribute Details

#loggerObject

Returns the value of attribute logger.



11
12
13
# File 'lib/traceable/tracer.rb', line 11

def logger
  @logger
end

#parentObject (readonly)

Returns the value of attribute parent.



12
13
14
# File 'lib/traceable/tracer.rb', line 12

def parent
  @parent
end

#tagsObject (readonly)

Returns the value of attribute tags.



13
14
15
# File 'lib/traceable/tracer.rb', line 13

def tags
  @tags
end

Class Method Details

.default_loggerObject



22
23
24
# File 'lib/traceable/tracer.rb', line 22

def self.default_logger
  Traceable.config.logger
end

.default_parentObject

rubocop:enable Metrics/AbcSize rubocop:enable Metrics/MethodLength



114
115
116
# File 'lib/traceable/tracer.rb', line 114

def self.default_parent
  tracer_stack.last # nil if nothing currently on the stack
end

.default_tagsObject



26
27
28
29
30
31
32
33
34
35
# File 'lib/traceable/tracer.rb', line 26

def self.default_tags
  tags = Traceable.config.default_tags.merge(
    trace: SecureRandom.uuid
  )
  tags.each_key do |k|
    value = tags[k]
    tags[k] = value.call if value.respond_to?(:call)
  end
  tags
end

.tracer_stackObject

The tracer stack is a thread-local list of tracer instances, allowing the current tracer context to be automatically inherited by any other tracer instances created further down in the stack.

The current tracer is pushed onto the stack when entering a traced block, then popped from the stack when leaving the traced block.



125
126
127
# File 'lib/traceable/tracer.rb', line 125

def self.tracer_stack
  Thread.current[:tracer_stack] ||= []
end

Instance Method Details

#debug(msg, **tags) ⇒ Object



74
75
76
# File 'lib/traceable/tracer.rb', line 74

def debug(msg, **tags)
  emit :debug, msg, **tags
end

#do_block(msg, **tags, &_) ⇒ Object

rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/traceable/tracer.rb', line 80

def do_block(msg, **tags, &_)
  info "START: #{msg}", enter: true, **tags
  block_start_time = Time.now.utc

  begin
    push
    yield tags
  rescue StandardError => ex
    elapsed = Time.now.utc - block_start_time
    if ex.instance_variable_defined?(:@traceable_rescued)
      origin = ex.instance_variable_get(:@traceable_rescued)
      ex_message = " [propagated from #{origin}]"
    else
      ex.instance_variable_set(:@traceable_rescued, msg)
      ex_message = ", #{ex.message}"
      tags[:backtrace] ||= ex.backtrace.join('\n')
    end

    warn "EXCEPTION: #{msg} => #{ex.class.name}#{ex_message}",
         exception: true, elapsed: elapsed, class: ex.class.name, **tags

    raise
  ensure
    pop

    unless ex
      elapsed = Time.now.utc - block_start_time
      info "END: #{msg}", exit: true, elapsed: elapsed, **tags
    end
  end
end

#emit(method, msg, **tags) ⇒ Object



37
38
39
40
# File 'lib/traceable/tracer.rb', line 37

def emit(method, msg, **tags)
  final_tags = make_tags(message: msg, **tags)
  emit_tags(method, final_tags)
end

#emit_tags(method, tags) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/traceable/tracer.rb', line 50

def emit_tags(method, tags)
  logger.send(method, tags)
  nil
rescue StandardError => ex
  warn "EXCEPTION in trace: #{ex}"
  nil
end

#error(msg, **tags) ⇒ Object



62
63
64
# File 'lib/traceable/tracer.rb', line 62

def error(msg, **tags)
  emit :error, msg, **tags
end

#fatal(msg, **tags) ⇒ Object



58
59
60
# File 'lib/traceable/tracer.rb', line 58

def fatal(msg, **tags)
  emit :fatal, msg, **tags
end

#format_tags(tags) ⇒ Object



46
47
48
# File 'lib/traceable/tracer.rb', line 46

def format_tags(tags)
  tags.each_with_object(tags) { |(k, v), t| t[k] = Args.format_value(v) }
end

#info(msg, **tags) ⇒ Object



70
71
72
# File 'lib/traceable/tracer.rb', line 70

def info(msg, **tags)
  emit :info, msg, **tags
end

#make_tags(**tags) ⇒ Object



42
43
44
# File 'lib/traceable/tracer.rb', line 42

def make_tags(**tags)
  format_tags(@tags.merge(tags))
end

#warn(msg, **tags) ⇒ Object



66
67
68
# File 'lib/traceable/tracer.rb', line 66

def warn(msg, **tags)
  emit :warn, msg, **tags
end