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.
- ._reentrant_mutex ⇒ Object
-
.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`.
-
.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
145 146 147 148 149 150 151 152 153 |
# File 'lib/logging/logger.rb', line 145 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.
121 122 123 |
# File 'lib/logging/logger.rb', line 121 def additive @additive end |
#caller_tracing ⇒ Object
Returns the value of attribute caller_tracing.
121 122 123 |
# File 'lib/logging/logger.rb', line 121 def caller_tracing @caller_tracing end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
121 122 123 |
# File 'lib/logging/logger.rb', line 121 def name @name end |
#parent ⇒ Object
Returns the value of attribute parent.
121 122 123 |
# File 'lib/logging/logger.rb', line 121 def parent @parent end |
Class Method Details
.[](name) ⇒ Object
Returns a logger instance for the given name.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/logging/logger.rb', line 45 def self.[]( name ) repo = ::Logging::Repository.instance name = repo.to_key(name) logger = repo[name] return logger unless logger.nil? @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 |
._reentrant_mutex ⇒ Object
428 429 430 |
# File 'lib/logging/logger.rb', line 428 def self._reentrant_mutex @reentrant_mutex 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
84 85 86 87 88 |
# File 'lib/logging/logger.rb', line 84 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`
35 |
# File 'lib/logging/logger.rb', line 35 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
94 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 |
# File 'lib/logging/logger.rb', line 94 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 |
.new(*args) ⇒ Object
Overrides the new method such that only one Logger will be created for any given logger name.
40 41 42 |
# File 'lib/logging/logger.rb', line 40 def self.new( *args ) args.empty? ? super : self[args.shift] end |
.root ⇒ Object
Returns the root logger.
30 31 32 |
# File 'lib/logging/logger.rb', line 30 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
.
176 177 178 179 |
# File 'lib/logging/logger.rb', line 176 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.
161 162 163 164 165 166 167 |
# File 'lib/logging/logger.rb', line 161 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.
469 470 471 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 |
# File 'lib/logging/logger.rb', line 469 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.
438 439 440 441 |
# File 'lib/logging/logger.rb', line 438 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.
449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/logging/logger.rb', line 449 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.
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/logging/logger.rb', line 206 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.
340 341 342 343 344 345 346 347 |
# File 'lib/logging/logger.rb', line 340 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.
319 320 321 |
# File 'lib/logging/logger.rb', line 319 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.
329 330 331 332 |
# File 'lib/logging/logger.rb', line 329 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.
376 |
# File 'lib/logging/logger.rb', line 376 def clear_appenders( ) @appenders.clear end |
#has_own_level? ⇒ Boolean
Returns ‘true` if the logger has its own level defined.
313 314 315 |
# File 'lib/logging/logger.rb', line 313 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.
258 259 260 261 |
# File 'lib/logging/logger.rb', line 258 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
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/logging/logger.rb', line 291 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.
357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/logging/logger.rb', line 357 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 |