class Traceable::Tracer

rubocop:disable Metrics/ClassLength

Attributes

logger[RW]
parent[R]
tags[R]

Public Class Methods

default_logger() click to toggle source
# File lib/traceable/tracer.rb, line 22
def self.default_logger
  Traceable.config.logger
end
default_parent() click to toggle source

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

# File lib/traceable/tracer.rb, line 114
def self.default_parent
  tracer_stack.last # nil if nothing currently on the stack
end
default_tags() click to toggle source
# 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
new(parent_tracer, tags: nil, logger: nil) click to toggle source
# 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
tracer_stack() click to toggle source

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.

# File lib/traceable/tracer.rb, line 125
def self.tracer_stack
  Thread.current[:tracer_stack] ||= []
end

Public Instance Methods

debug(msg, **tags) click to toggle source
# File lib/traceable/tracer.rb, line 74
def debug(msg, **tags)
  emit :debug, msg, **tags
end
do_block(msg, **tags) { |tags| ... } click to toggle source

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

# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# File lib/traceable/tracer.rb, line 62
def error(msg, **tags)
  emit :error, msg, **tags
end
fatal(msg, **tags) click to toggle source
# File lib/traceable/tracer.rb, line 58
def fatal(msg, **tags)
  emit :fatal, msg, **tags
end
format_tags(tags) click to toggle source
# 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) click to toggle source
# File lib/traceable/tracer.rb, line 70
def info(msg, **tags)
  emit :info, msg, **tags
end
make_tags(**tags) click to toggle source
# File lib/traceable/tracer.rb, line 42
def make_tags(**tags)
  format_tags(@tags.merge(tags))
end
warn(msg, **tags) click to toggle source
# File lib/traceable/tracer.rb, line 66
def warn(msg, **tags)
  emit :warn, msg, **tags
end

Private Instance Methods

pop() click to toggle source
# File lib/traceable/tracer.rb, line 148
def pop
  Tracer.tracer_stack.pop
end
push() click to toggle source
# File lib/traceable/tracer.rb, line 144
def push
  Tracer.tracer_stack.push self
end
which_parent(parent_tracer) click to toggle source
# File lib/traceable/tracer.rb, line 131
def which_parent(parent_tracer)
  case parent_tracer
  when nil
    nil
  when Tracer
    parent_tracer
  when Traceable
    parent_tracer.local_tracer
  else
    raise(ArgumentError, "#{parent_tracer} (#{parent_tracer.class})")
  end
end