class NewRelic::Agent::AgentLogger

Constants

LOG_LEVELS

Public Class Methods

new(root = '', override_logger = nil) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 16
def initialize(root = '', override_logger = nil)
  @already_logged_lock = Mutex.new
  clear_already_logged
  create_log(root, override_logger)
  set_log_level!
  set_log_format!
  disable_log_instrumentation!

  gather_startup_logs
end

Private Class Methods

format_fatal_error(message) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 182
def self.format_fatal_error(message)
  "** [NewRelic] FATAL : #{message}\n"
end
log_level_for(level) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 161
def self.log_level_for(level)
  LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
end

Public Instance Methods

debug(*msgs, &blk) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 43
def debug(*msgs, &blk)
  format_and_send(:debug, msgs, &blk)
end
error(*msgs, &blk) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 31
def error(*msgs, &blk)
  format_and_send(:error, msgs, &blk)
end
fatal(*msgs, &blk) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 27
def fatal(*msgs, &blk)
  format_and_send(:fatal, msgs, &blk)
end
info(*msgs, &blk) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 39
def info(*msgs, &blk)
  format_and_send(:info, msgs, &blk)
end
is_startup_logger?() click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 47
def is_startup_logger?
  @log.is_a?(NullLogger)
end
log_exception(level, e, backtrace_level = level) click to toggle source

Use this when you want to log an exception with explicit control over the log level that the backtrace is logged at. If you just want the default behavior of backtraces logged at debug, use one of the methods above and pass an Exception as one of the args.

# File lib/new_relic/agent/agent_logger.rb, line 55
def log_exception(level, e, backtrace_level = level)
  @log.send(level, '%p: %s' % [e.class, e.message])
  @log.send(backtrace_level) do
    backtrace = backtrace_from_exception(e)
    if backtrace
      "Debugging backtrace:\n" + backtrace.join("\n  ")
    else
      'No backtrace available.'
    end
  end
end
log_formatter=(formatter) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 67
def log_formatter=(formatter)
  @log.formatter = formatter
end
warn(*msgs, &blk) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 35
def warn(*msgs, &blk)
  format_and_send(:warn, msgs, &blk)
end

Private Instance Methods

backtrace_from_exception(e) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 73
def backtrace_from_exception(e)
  # We've seen that often the backtrace on a SystemStackError is bunk
  # so massage the caller instead at a known depth.
  #
  # Tests keep us honest about minimum method depth our log calls add.
  return caller.drop(5) if e.is_a?(SystemStackError)

  e.backtrace
end
create_log(root, override_logger) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 100
def create_log(root, override_logger)
  if !override_logger.nil?
    @log = override_logger
  elsif ::NewRelic::Agent.config[:agent_enabled] == false
    create_null_logger
  else
    if wants_stdout?
      @log = ::Logger.new(STDOUT)
    else
      create_log_to_file(root)
    end
  end
end
create_log_to_file(root) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 114
def create_log_to_file(root)
  path = find_or_create_file_path(::NewRelic::Agent.config[:log_file_path], root)
  if path.nil?
    @log = ::Logger.new(STDOUT)
    warn("Error creating log directory #{::NewRelic::Agent.config[:log_file_path]}, using standard out for logging.")
  else
    file_path = "#{path}/#{::NewRelic::Agent.config[:log_file_name]}"
    begin
      @log = ::Logger.new(file_path)
    rescue => e
      @log = ::Logger.new(STDOUT)
      warn("Failed creating logger for file #{file_path}, using standard out for logging.", e)
    end
  end
end
create_null_logger() click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 130
def create_null_logger
  @log = ::NewRelic::Agent::NullLogger.new
end
disable_log_instrumentation!() click to toggle source

Don’t allow agent logs into agent log forwarding for now

# File lib/new_relic/agent/agent_logger.rb, line 174
def disable_log_instrumentation!
  NewRelic::Agent::Instrumentation::Logger.mark_skip_instrumenting(@log)
end
find_or_create_file_path(path_setting, root) click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 139
  def find_or_create_file_path(path_setting, root)
    for abs_path in [File.expand_path(path_setting),
      File.expand_path(File.join(root, path_setting))] do
      if File.directory?(abs_path) || (Dir.mkdir(abs_path) rescue nil)
        return abs_path[%r{^(.*?)/?$}]
      end
    end
    nil
  end

  def set_log_level!
    @log.level = AgentLogger.log_level_for(::NewRelic::Agent.config[:log_level])
  end

  LOG_LEVELS = {
    'debug' => ::Logger::DEBUG,
    'info' => ::Logger::INFO,
    'warn' => ::Logger::WARN,
    'error' => ::Logger::ERROR,
    'fatal' => ::Logger::FATAL
  }

  def self.log_level_for(level)
    LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
  end

  def set_log_format!
    @hostname = NewRelic::Agent::Hostname.get
    @prefix = wants_stdout? ? '** [NewRelic]' : ''
    @log.formatter = proc do |severity, timestamp, progname, msg|
      "#{@prefix}[#{timestamp.strftime('%F %H:%M:%S %z')} #{@hostname} (#{$$})] #{severity} : #{msg}\n"
    end
  end

  # Don't allow agent logs into agent log forwarding for now
  def disable_log_instrumentation!
    NewRelic::Agent::Instrumentation::Logger.mark_skip_instrumenting(@log)
  end

  def gather_startup_logs
    StartupLogger.instance.dump(self)
  end

  def self.format_fatal_error(message)
    "** [NewRelic] FATAL : #{message}\n"
  end
end
format_and_send(level, *msgs) { || ... } click to toggle source

Allows for passing exceptions in explicitly, which format with backtrace

# File lib/new_relic/agent/agent_logger.rb, line 84
def format_and_send(level, *msgs, &block)
  if block
    return unless @log.send("#{level}?")

    msgs = Array(yield)
  end

  msgs.flatten.each do |item|
    case item
    when Exception then log_exception(level, item, :debug)
    else @log.send(level, item)
    end
  end
  nil
end
gather_startup_logs() click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 178
def gather_startup_logs
  StartupLogger.instance.dump(self)
end
set_log_format!() click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 165
def set_log_format!
  @hostname = NewRelic::Agent::Hostname.get
  @prefix = wants_stdout? ? '** [NewRelic]' : ''
  @log.formatter = proc do |severity, timestamp, progname, msg|
    "#{@prefix}[#{timestamp.strftime('%F %H:%M:%S %z')} #{@hostname} (#{$$})] #{severity} : #{msg}\n"
  end
end
set_log_level!() click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 149
def set_log_level!
  @log.level = AgentLogger.log_level_for(::NewRelic::Agent.config[:log_level])
end
wants_stdout?() click to toggle source
# File lib/new_relic/agent/agent_logger.rb, line 134
def wants_stdout?
  ::NewRelic::Agent.config[:log_file_path].casecmp(NewRelic::STANDARD_OUT) == 0 ||
    ::NewRelic::Agent.config[:'serverless_mode.enabled']
end