Class: Logging::Logger
- Inherits:
-
Object
- Object
- Logging::Logger
- Defined in:
- lib/logging/logger.rb
Overview
The Logger
class is the primary interface to the Logging
framework. It provides the logging methods that will be called from user methods, and it generates logging events that are sent to the appenders (the appenders take care of sending the log events to the logging destinations – files, sockets, etc).
Logger
instances are obtained from the Repository
and should not be directly created by users.
Example:
log = Logging.logger['my logger']
log.add_appenders( Logging.appenders.stdout ) # append to STDOUT
log.level = :info # log 'info' and above
log.info 'starting foo operation'
...
log.info 'finishing foo operation'
...
log.fatal 'unknown exception', exception
Direct Known Subclasses
Instance Attribute Summary collapse
-
#additive ⇒ Object
Returns the value of attribute additive.
-
#caller_tracing ⇒ Object
Returns the value of attribute caller_tracing.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
Class Method Summary collapse
-
.[](name) ⇒ Object
Returns a logger instance for the given name.
-
.define_log_methods(logger) ⇒ Object
This is where the actual logging methods are defined.
-
.instantiate ⇒ Object
‘instantiate` becomes the “real” `new`.
-
.log_methods_for_level(level) ⇒ Object
This generator is used to define the log methods for the given ‘level`.
-
.mutex ⇒ Object
Returns a global ReentrantMutex for use when creating Logger instances and/or updating log levels.
-
.new(*args) ⇒ Object
Overrides the new method such that only one Logger will be created for any given logger name.
-
.root ⇒ Object
Returns the root logger.
Instance Method Summary collapse
-
#<<(msg) ⇒ Object
(also: #write)
call-seq: log << “message”.
-
#<=>(other) ⇒ Object
call-seq: log <=> other.
-
#_dump_configuration(indent = 0) ⇒ Object
call-seq: _dump_configuration( io = STDOUT, indent = 0 ).
-
#_meta_eval(code, file = nil, line = nil) ⇒ Object
call-seq: _meta_eval( code ).
-
#_setup(name, opts = {}) ⇒ Object
call-seq: _setup( name, opts = {} ).
-
#add(lvl, data = nil, progname = nil) ⇒ Object
call-seq: add( severity, message = nil ) block.
-
#add_appenders(*args) ⇒ Object
call-seq: add_appenders( appenders ).
-
#appenders ⇒ Object
Returns the list of appenders.
-
#appenders=(args) ⇒ Object
call-seq: appenders = app.
-
#clear_appenders ⇒ Object
call-seq: clear_appenders.
-
#has_own_level? ⇒ Boolean
Returns ‘true` if the logger has its own level defined.
-
#initialize(name) ⇒ Logger
constructor
call-seq: Logger.new( name ) Logger.
-
#level ⇒ Object
call-seq: level => integer.
-
#level=(level) ⇒ Object
call-seq: level = :all.
-
#remove_appenders(*args) ⇒ Object
call-seq: remove_appenders( appenders ).
Constructor Details
#initialize(name) ⇒ Logger
call-seq:
Logger.new( name )
Logger[name]
Returns the logger identified by name.
When name is a String
or a Symbol
it will be used “as is” to retrieve the logger. When name is a Class
the class name will be used to retrieve the logger. When name is an object the name of the object’s class will be used to retrieve the logger.
Example:
obj = MyClass.new
log1 = Logger.new(obj)
log2 = Logger.new(MyClass)
log3 = Logger['MyClass']
log1.object_id == log2.object_id # => true
log2.object_id == log3.object_id # => true
154 155 156 157 158 159 160 161 162 |
# File 'lib/logging/logger.rb', line 154 def initialize( name ) case name when String raise(ArgumentError, "logger must have a name") if name.empty? else raise(ArgumentError, "logger name must be a String") end repo = ::Logging::Repository.instance _setup(name, :parent => repo.parent(name)) end |
Instance Attribute Details
#additive ⇒ Object
Returns the value of attribute additive.
130 131 132 |
# File 'lib/logging/logger.rb', line 130 def additive @additive end |
#caller_tracing ⇒ Object
Returns the value of attribute caller_tracing.
130 131 132 |
# File 'lib/logging/logger.rb', line 130 def caller_tracing @caller_tracing end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
130 131 132 |
# File 'lib/logging/logger.rb', line 130 def name @name end |
#parent ⇒ Object
Returns the value of attribute parent.
130 131 132 |
# File 'lib/logging/logger.rb', line 130 def parent @parent end |
Class Method Details
.[](name) ⇒ Object
Returns a logger instance for the given name.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/logging/logger.rb', line 43 def self.[]( name ) repo = ::Logging::Repository.instance name = repo.to_key(name) logger = repo[name] return logger unless logger.nil? # Share the same mutex that's used by 'define_log_methods' because # it iterates over the hash of loggers, and adding a new key to a hash # while iterating over it produces an error. ::Logging::Logger.mutex.synchronize do logger = repo[name] return logger unless logger.nil? # thread-safe double checking logger = instantiate(name) repo[name] = logger repo.children(name).each { |child| child.__send__(:parent=, logger) } logger end end |
.define_log_methods(logger) ⇒ Object
This is where the actual logging methods are defined. Two methods are created for each log level. The first is a query method used to determine if that perticular logging level is enabled. The second is the actual logging method that accepts a list of objects to be logged or a block. If a block is given, then the object returned from the block will be logged.
Example
log = Logging::Logger['my logger']
log.level = :warn
log.info? # => false
log.warn? # => true
log.warn 'this is your last warning'
log.fatal 'I die!', exception
log.debug do
# expensive method to construct log message
msg
end
85 86 87 88 89 |
# File 'lib/logging/logger.rb', line 85 def self.define_log_methods( logger ) code = log_methods_for_level(logger.level) logger.(code, __FILE__, __LINE__) logger end |
.instantiate ⇒ Object
‘instantiate` becomes the “real” `new`
33 |
# File 'lib/logging/logger.rb', line 33 alias_method :instantiate, :new |
.log_methods_for_level(level) ⇒ Object
This generator is used to define the log methods for the given ‘level`. This code is evaluated in the context of a Logger instance.
Returns log methods as a String
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/logging/logger.rb', line 95 def self.log_methods_for_level( level ) code = [] ::Logging::LEVELS.each do |name,num| code << <<-CODE undef :#{name} if method_defined? :#{name} undef :#{name}? if method_defined? :#{name}? CODE if level > num code << <<-CODE def #{name}?( ) false end def #{name}( data = nil ) false end CODE else code << <<-CODE def #{name}?( ) true end def #{name}( data = nil ) data = yield if block_given? log_event(::Logging::LogEvent.new(@name, #{num}, data, @caller_tracing)) true end CODE end end code.join("\n") end |
.mutex ⇒ Object
Returns a global ReentrantMutex for use when creating Logger instances and/or updating log levels.
126 127 128 |
# File 'lib/logging/logger.rb', line 126 def self.mutex @mutex end |
.new(*args) ⇒ Object
Overrides the new method such that only one Logger will be created for any given logger name.
38 39 40 |
# File 'lib/logging/logger.rb', line 38 def self.new( *args ) args.empty? ? super : self[args.shift] end |
.root ⇒ Object
Returns the root logger.
28 29 30 |
# File 'lib/logging/logger.rb', line 28 def self.root ::Logging::Repository.instance[:root] end |
Instance Method Details
#<<(msg) ⇒ Object Also known as: write
call-seq:
log << "message"
Log the given message without any formatting and without performing any level checks. The message is logged to all appenders. The message is passed up the logger tree if this logger’s additivity is true
.
185 186 187 188 |
# File 'lib/logging/logger.rb', line 185 def <<( msg ) @appenders.each {|a| a << msg} @parent << msg if @additive end |
#<=>(other) ⇒ Object
call-seq:
log <=> other
Compares this logger by name to another logger. The normal return codes for String
objects apply.
170 171 172 173 174 175 176 |
# File 'lib/logging/logger.rb', line 170 def <=>( other ) case other when self; 0 when ::Logging::RootLogger; 1 when ::Logging::Logger; @name <=> other.name else raise ArgumentError, 'expecting a Logger instance' end end |
#_dump_configuration(indent = 0) ⇒ Object
call-seq:
_dump_configuration( io = STDOUT, indent = 0 )
An internal method that is used to dump this logger’s configuration to the given io stream. The configuration includes the logger’s name, level, additivity, and caller_tracing settings. The configured appenders are also printed to the io stream.
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 |
# File 'lib/logging/logger.rb', line 472 def _dump_configuration( indent = 0 ) str, spacer, base = '', ' ', 50 indent_str = indent == 0 ? '' : ' ' * indent str << indent_str str << self.name.shrink(base - indent) if (str.length + spacer.length) < base str << spacer str << '.' * (base - str.length) end str = str.ljust(base) str << spacer level_str = @level.nil? ? '' : '*' level_str << if level < ::Logging::LEVELS.length ::Logging.levelify(::Logging::LNAMES[level]) else 'off' end level_len = ::Logging::MAX_LEVEL_LENGTH + 1 str << sprintf("%#{level_len}s" % level_str) str << spacer if self.respond_to?(:additive) str << (additive ? '+A' : '-A') else str << ' ' end str << spacer str << (caller_tracing ? '+T' : '-T') str << "\n" @appenders.each do |appender| str << indent_str str << '- ' str << appender.to_s str << "\n" end return str end |
#_meta_eval(code, file = nil, line = nil) ⇒ Object
call-seq:
( code )
Evaluates the given string of code if the singleton class of this Logger object.
441 442 443 444 |
# File 'lib/logging/logger.rb', line 441 def ( code, file = nil, line = nil ) = class << self; self end .class_eval code, file, line end |
#_setup(name, opts = {}) ⇒ Object
call-seq:
_setup( name, opts = {} )
Configures internal variables for the logger. This method can be used to avoid storing the logger in the repository.
452 453 454 455 456 457 458 459 460 461 462 |
# File 'lib/logging/logger.rb', line 452 def _setup( name, opts = {} ) @name = name @parent = opts.fetch(:parent, nil) @appenders = opts.fetch(:appenders, []) @additive = opts.fetch(:additive, true) @level = opts.fetch(:level, nil) @caller_tracing = opts.fetch(:caller_tracing, false) ::Logging::Logger.define_log_methods(self) end |
#add(lvl, data = nil, progname = nil) ⇒ Object
call-seq:
add( severity, = nil ) {block}
Log a message if the given severity is high enough. This is the generic logging method. Users will be more inclined to use #debug, #info, #warn, #error, and #fatal.
Message format: message
can be any object, but it has to be converted to a String in order to log it. The Logging::format_as method is used to determine how objects chould be converted to strings. Generally, inspect
is used.
A special case is an Exception
object, which will be printed in detail, including message, class, and backtrace.
If a message is not given, then the return value from the block is used as the message to log. This is useful when creating the actual message is an expensive operation. This allows the logger to check the severity against the configured level before actually constructing the message.
This method returns true
if the message was logged, and false
is returned if the message was not logged.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/logging/logger.rb', line 215 def add( lvl, data = nil, progname = nil ) lvl = Integer(lvl) return false if lvl < level if data.nil? if block_given? data = yield else data = progname end end log_event(::Logging::LogEvent.new(@name, lvl, data, @caller_tracing)) true end |
#add_appenders(*args) ⇒ Object
call-seq:
add_appenders( appenders )
Add the given appenders to the list of appenders, where appenders can be either a single appender or an array of appenders.
349 350 351 352 353 354 355 356 |
# File 'lib/logging/logger.rb', line 349 def add_appenders( *args ) args.flatten.each do |arg| o = arg.kind_of?(::Logging::Appender) ? arg : ::Logging::Appenders[arg.to_s] raise ArgumentError, "unknown appender #{arg.inspect}" if o.nil? @appenders << o unless @appenders.include?(o) end self end |
#appenders ⇒ Object
Returns the list of appenders.
328 329 330 |
# File 'lib/logging/logger.rb', line 328 def appenders @appenders.dup end |
#appenders=(args) ⇒ Object
call-seq:
appenders = app
Clears the current list of appenders and replaces them with app, where app can be either a single appender or an array of appenders.
338 339 340 341 |
# File 'lib/logging/logger.rb', line 338 def appenders=( args ) @appenders.clear add_appenders(*args) unless args.nil? end |
#clear_appenders ⇒ Object
call-seq:
clear_appenders
Remove all appenders from this logger.
385 |
# File 'lib/logging/logger.rb', line 385 def clear_appenders( ) @appenders.clear end |
#has_own_level? ⇒ Boolean
Returns ‘true` if the logger has its own level defined.
322 323 324 |
# File 'lib/logging/logger.rb', line 322 def has_own_level? !@level.nil? end |
#level ⇒ Object
call-seq:
level => integer
Returns an integer which is the defined log level for this logger.
267 268 269 270 |
# File 'lib/logging/logger.rb', line 267 def level return @level unless @level.nil? @parent.level end |
#level=(level) ⇒ Object
call-seq:
level = :all
Set the level for this logger. The level can be either a String
, a Symbol
, or an Integer
. An ArgumentError
is raised if this is not the case.
There are two special levels – “all” and “off”. The former will enable log messages from this logger. The latter will disable all log messages from this logger.
Setting the logger level to nil
will cause the parent’s logger level to be used.
Example:
log.level = :debug
log.level = "INFO"
log.level = 4
log.level = 'off'
log.level = :all
These produce an ArgumentError
log.level = Object
log.level = -1
log.level = 1_000_000_000_000
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/logging/logger.rb', line 300 def level=( level ) @level = if level.nil? then level else lvl = case level when String, Symbol; ::Logging::level_num(level) when Integer; level else raise ArgumentError, "level must be a String, Symbol, or Integer" end if lvl.nil? or lvl < 0 or lvl > ::Logging::LEVELS.length raise ArgumentError, "unknown level was given '#{level}'" end lvl end define_log_methods(true) self.level end |
#remove_appenders(*args) ⇒ Object
call-seq:
remove_appenders( appenders )
Remove the given appenders from the list of appenders. The appenders to remove can be identified either by name using a String
or by passing the appender instance. appenders can be a single appender or an array of appenders.
366 367 368 369 370 371 372 373 374 375 376 377 378 |
# File 'lib/logging/logger.rb', line 366 def remove_appenders( *args ) args.flatten.each do |arg| @appenders.delete_if do |a| case arg when String; arg == a.name when ::Logging::Appender; arg.object_id == a.object_id else raise ArgumentError, "#{arg.inspect} is not a 'Logging::Appender'" end end end self end |