class Kitchen::Logger

Logging implementation for Kitchen. By default the console/stdout output will be displayed differently than the file log output. Therefor, this class wraps multiple loggers that conform to the stdlib `Logger` class behavior.

@author Fletcher Nichol <fnichol@nichol.ca>

Attributes

log_overwrite[R]

@return [Boolean] whether logger is configured for

overwriting
logdev[R]

@return [IO] the log device

Public Class Methods

new(options = {}) click to toggle source

Constructs a new logger.

@param options [Hash] configuration for a new logger @option options [Symbol] :color color to use when when outputting

messages

@option options [Integer] :level the logging severity threshold

(default: `Kitchen::DEFAULT_LOG_LEVEL`)

@option options [Boolean] whether to overwrite the log

when Test Kitchen runs. Only applies if the :logdev is a String.
(default: `Kitchen::DEFAULT_LOG_OVERWRITE`)

@option options [String,IO] :logdev filepath String or IO object to be

used for logging (default: `nil`)

@option options [String] :progname program name to include in log

messages (default: `"Kitchen"`)

@option options [IO] :stdout a standard out IO object to use

(default: `$stdout`)

@option options [Boolean] :colorize whether to colorize output

when Test Kitchen runs.
(default: `$stdout.tty?`)
# File lib/kitchen/logger.rb, line 57
def initialize(options = {})
  @log_overwrite = if options[:log_overwrite].nil?
                     default_log_overwrite
                   else
                     options[:log_overwrite]
                   end

  @logdev = logdev_logger(options[:logdev], log_overwrite) if options[:logdev]

  populate_loggers(options)

  # These setters cannot be called until @loggers are populated because
  # they are delegated
  self.progname = options[:progname] || "Kitchen"
  self.level = options[:level] || default_log_level
end

Private Class Methods

delegate_to_all_loggers(meth) click to toggle source

@api private @!macro delegate_to_all_loggers

@method $1()
# File lib/kitchen/logger.rb, line 100
def delegate_to_all_loggers(meth)
  define_method(meth) do |*args|
    result = nil
    @loggers.each { |l| result = l.public_send(meth, *args) }
    result
  end
end
delegate_to_first_logger(meth) click to toggle source

@api private @!macro delegate_to_first_logger

@method $1()
# File lib/kitchen/logger.rb, line 93
def delegate_to_first_logger(meth)
  define_method(meth) { |*args| @loggers.first.public_send(meth, *args) }
end

Private Instance Methods

default_log_level() click to toggle source

@return [Integer] the default logger level @api private

# File lib/kitchen/logger.rb, line 275
def default_log_level
  Util.to_logger_level(Kitchen::DEFAULT_LOG_LEVEL)
end
default_log_overwrite() click to toggle source

@return [Boolean] whether to overwrite logs by default @api private

# File lib/kitchen/logger.rb, line 281
def default_log_overwrite
  Kitchen::DEFAULT_LOG_OVERWRITE
end
logdev_logger(filepath_or_logdev, log_overwrite) click to toggle source

Construct a new logdev logger.

@param filepath_or_logdev [String,IO] a filepath String or IO object @param log_overwrite [Boolean] apply log overwriting

if filepath_or_logdev is a file path

@return [LogdevLogger] a new logger @api private

# File lib/kitchen/logger.rb, line 313
def logdev_logger(filepath_or_logdev, log_overwrite)
  LogdevLogger.new(resolve_logdev(filepath_or_logdev, log_overwrite))
end
populate_loggers(options) click to toggle source

Pulled out for Rubocop complexity issues

@api private

# File lib/kitchen/logger.rb, line 77
def populate_loggers(options)
  @loggers = []
  @loggers << logdev unless logdev.nil?
  @loggers << stdout_logger(options[:stdout], options[:color], options[:colorize]) if
    options[:stdout]
  @loggers << stdout_logger($stdout, options[:color], options[:colorize]) if
    @loggers.empty?
end
resolve_logdev(filepath_or_logdev, log_overwrite) click to toggle source

Return an IO object from a filepath String or the IO object itself.

@param filepath_or_logdev [String,IO] a filepath String or IO object @param log_overwrite [Boolean] apply log overwriting

if filepath_or_logdev is a file path

@return [IO] an IO object @api private

# File lib/kitchen/logger.rb, line 324
def resolve_logdev(filepath_or_logdev, log_overwrite)
  if filepath_or_logdev.is_a? String
    mode = log_overwrite ? "wb" : "ab"
    FileUtils.mkdir_p(File.dirname(filepath_or_logdev))
    file = File.open(File.expand_path(filepath_or_logdev), mode)
    file.sync = true
    file
  else
    filepath_or_logdev
  end
end
stdout_logger(stdout, color, colorize) click to toggle source

Construct a new standard out logger.

@param stdout [IO] the IO object that represents stdout (or similar) @param color [Symbol] color to use when outputing messages @param colorize [Boolean] whether to enable color @return [StdoutLogger] a new logger @api private

# File lib/kitchen/logger.rb, line 292
def stdout_logger(stdout, color, colorize)
  logger = StdoutLogger.new(stdout)
  if colorize
    logger.formatter = proc do |_severity, _datetime, _progname, msg|
      Color.colorize(msg.dup.to_s, color).concat("\n")
    end
  else
    logger.formatter = proc do |_severity, _datetime, _progname, msg|
      msg.dup.concat("\n")
    end
  end
  logger
end