hanami-utils/lib/hanami/logger.rb

142 lines
3.8 KiB
Ruby

require 'logger'
require 'hanami/utils/string'
module Hanami
# Hanami logger
#
# Implement with the same interface of Ruby std lib `Logger`.
# It uses `STDOUT` as output device.
#
#
#
# When a Hanami application is initialized, it creates a logger for that specific application.
# For instance for a `Bookshelf::Application` a `Bookshelf::Logger` will be available.
#
# This is useful for auto-tagging the output. Eg (`[Booshelf]`).
#
# When used stand alone (eg. `Hanami::Logger.info`), it tags lines with `[Shared]`.
#
#
#
# The available severity levels are the same of `Logger`:
#
# * debug
# * error
# * fatal
# * info
# * unknown
# * warn
#
# Those levels are available both as class and instance methods.
#
# @since 0.5.0
#
# @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html
# @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger/Severity.html
#
# @example Basic usage
# require 'hanami'
#
# module Bookshelf
# class Application < Hanami::Application
# end
# end
#
# # Initialize the application with the following code:
# Bookshelf::Application.load!
# # or
# Bookshelf::Application.new
#
# Bookshelf::Logger.info('Hello')
# # => I, [2015-01-10T21:55:12.727259 #80487] INFO -- [Bookshelf] : Hello
#
# Bookshelf::Logger.new.info('Hello')
# # => I, [2015-01-10T21:55:12.727259 #80487] INFO -- [Bookshelf] : Hello
#
# @example Standalone usage
# require 'hanami'
#
# Hanami::Logger.info('Hello')
# # => I, [2015-01-10T21:55:12.727259 #80487] INFO -- [Hanami] : Hello
#
# Hanami::Logger.new.info('Hello')
# # => I, [2015-01-10T21:55:12.727259 #80487] INFO -- [Hanami] : Hello
#
# @example Custom tagging
# require 'hanami'
#
# Hanami::Logger.new('FOO').info('Hello')
# # => I, [2015-01-10T21:55:12.727259 #80487] INFO -- [FOO] : Hello
class Logger < ::Logger
# Hanami::Logger default formatter
#
# @since 0.5.0
# @api private
#
# @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger/Formatter.html
class Formatter < ::Logger::Formatter
# @since 0.5.0
# @api private
attr_writer :application_name
# @since 0.5.0
# @api private
#
# @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger/Formatter.html#method-i-call
def call(severity, time, progname, msg)
progname = "[#{@application_name}] #{progname}"
super(severity, time.utc, progname, msg)
end
end
# Default application name.
# This is used as a fallback for tagging purposes.
#
# @since 0.5.0
# @api private
DEFAULT_APPLICATION_NAME = 'Hanami'.freeze
# @since 0.5.0
# @api private
attr_writer :application_name
# Initialize a logger
#
# @param application_name [String] an optional application name used for
# tagging purposes
#
# @since 0.5.0
def initialize(application_name = nil)
super(STDOUT)
@application_name = application_name
@formatter = Hanami::Logger::Formatter.new.tap { |f| f.application_name = self.application_name }
end
# Returns the current application name, this is used for tagging purposes
#
# @return [String] the application name
#
# @since 0.5.0
def application_name
@application_name || _application_name_from_namespace || _default_application_name
end
private
# @since 0.5.0
# @api private
def _application_name_from_namespace
class_name = self.class.name
namespace = Utils::String.new(class_name).namespace
class_name != namespace and return namespace
end
# @since 0.5.0
# @api private
def _default_application_name
DEFAULT_APPLICATION_NAME
end
end
end