Acornsgrow/optional_logger

View on GitHub
lib/optional_logger/logger.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'logger'

module OptionalLogger
  # Proxy logger to handle making the proxied logger optional
  #
  # The original intent for this optional proxy logger was specifically to be
  # used inside of gems. This would enable them to receive a logger from the
  # parenting application/gem and log within their gem without having to worry
  # about spreading conditionals all over their gem.
  class Logger
    # Construct an instance of the proxy logger
    #
    # @param logger [#add,#info?,#warn?,#debug?,#fatal?,#error?] the ruby logger
    #   to wrap
    # @return the instance of the proxy logger
    def initialize(logger)
      @logger = logger
    end

    # Get the ruby logger instance this proxy logger wraps
    #
    # @return the wrapped ruby logger
    def wrapped_logger
      @logger
    end

    # Log a message at the given level if the logger is present
    #
    # This isn't generally a recommended method to use while logging in your
    # libraries. Instead see {#debug}, {#info}, {#warn}, {#error}, {#fatal}, and
    # {#unknown} as they simplify messaging considerably.
    #
    # If you don't want to use the recommended methods and want more control for
    # some reason. There are a few ways to log a message depending on your usecase.
    #
    # The first is probably the most generally useful, which is logging messages
    # that aren't costly to build. This is accomplished as follows:
    #
    #     add(::Logger::INFO, 'some message', nil)
    #
    # The second is for use cases in which it is costly to build the log message
    # as it avoids executing the block until the logger knows that the message
    # level will be displayed. If the message level would not be displayed then
    # the block is not executed, saving the performance cost of building the
    # message.
    #
    #     add(::Logger::INFO) { 'some expensive message' }
    #
    # The third gives you the benefits of preventing uneeded expensive messages
    # but also allows you to override the program name that will be prefixed on
    # that log message. This is accomplished as follows.
    #
    #     add(::Logger::INFO, nil, 'overridden progname') { 'some expensive message' }
    #
    # It is important to realize that if the wrapped logger is nil then this
    # method will simply do nothing.
    #
    # @param severity ::Logger::DEBUG, ::Logger::INFO, ::Logger::WARN,
    #   ::Logger::ERROR, ::Logger::FATAL, ::Logger::UNKNOWN
    # @param message the optional message to log
    # @param progname_or_message the optional program name or message, if
    #   message is nil, and a block is NOT provided, then progname_or_message is
    #   treated as a message rather than progname
    # @param block the block to evaluate and yield a message, generally useful
    #   preventing building of expensive messages when message of that level
    #   aren't allowed
    def add(severity, message = nil, progname_or_message = nil, &block)
      @logger.add(severity, message, progname_or_message, &block) if @logger
    end
    alias log add

    # Log a message at the info level if the logger is present
    #
    # There are a few ways to log a message depending on your usecase.
    #
    # The first is probably the most generally useful, which is logging messages
    # that aren't costly to build. This is accomplished as follows:
    #
    #     info('some message')
    #
    # The second is for use cases in which it is costly to build the log message
    # as it avoids executing the block until the logger knows that the message
    # level will be displayed. If the message level would not be displayed then
    # the block is not executed, saving the performance cost of building the
    # message.
    #
    #     info { 'some expensive message' }
    #
    # The third gives you the benefits of preventing uneeded expensive messages
    # but also allows you to override the program name that will be prefixed on
    # that log message. This is accomplished as follows.
    #
    #     info('overridden progname') { 'some expensive message' }
    #
    # It is important to realize that if the wrapped logger is nil then this
    # method will simply do nothing.
    #
    # @param progname_or_message the progname or message depending on scenario
    # @param block the optional block depending on scenario
    def info(progname_or_message = nil, &block)
      add(::Logger::INFO, nil, progname_or_message, &block)
    end

    # Log a message at the warn level if the logger is present
    #
    # See {#info} for details on specifics around various scenarios
    def warn(progname_or_message = nil, &block)
      add(::Logger::WARN, nil, progname_or_message, &block)
    end

    # Log a message at the debug level if the logger is present
    #
    # See {#info} for details on specifics around various scenarios
    def debug(progname_or_message = nil, &block)
      add(::Logger::DEBUG, nil, progname_or_message, &block)
    end

    # Log a message at the error level if the logger is present
    #
    # See {#info} for details on specifics around various scenarios
    def error(progname_or_message = nil, &block)
      add(::Logger::ERROR, nil, progname_or_message, &block)
    end

    # Log a message at the fatal level if the logger is present
    #
    # See {#info} for details on specifics around various scenarios
    def fatal(progname_or_message = nil, &block)
      add(::Logger::FATAL, nil, progname_or_message, &block)
    end

    # Log a message at the unknown level if the logger is present
    #
    # See {#info} for details on specifics around various scenarios
    def unknown(progname_or_message = nil, &block)
      add(::Logger::UNKNOWN, nil, progname_or_message, &block)
    end

    # Check if info level messages are allowed by loggers current configuration
    #
    # @return [Boolean] true if the current severity level allows for the
    #   printing of info messages and false otherwise. It will also return false
    #   if there is no logger present.
    def info?
      return @logger.info? if @logger
      false
    end

    # Check if warn level messages are allowed by loggers current configuration
    #
    # @return [Boolean] true if the current severity level allows for the
    #   printing of warn messages and false otherwise. It will also return false
    #   if there is no logger present.
    def warn?
      return @logger.warn? if @logger
      false
    end

    # Check if debug level messages are allowed by loggers current configuration
    #
    # @return [Boolean] true if the current severity level allows for the
    #   printing of debug messages and false otherwise. It will also return false
    #   if there is no logger present.
    def debug?
      return @logger.debug? if @logger
      false
    end

    # Check if fatal level messages are allowed by loggers current configuration
    #
    # @return [Boolean] true if the current severity level allows for the
    #   printing of fatal messages and false otherwise. It will also return false
    #   if there is no logger present.
    def fatal?
      return @logger.fatal? if @logger
      false
    end

    # Check if error level messages are allowed by loggers current configuration
    #
    # @return [Boolean] true if the current severity level allows for the
    #   printing of error messages and false otherwise. It will also return false
    #   if there is no logger present.
    def error?
      return @logger.error? if @logger
      false
    end
  end
end