logging 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/History.txt +19 -0
- data/Rakefile +1 -1
- data/examples/rails4.rb +21 -0
- data/lib/logging/appender.rb +6 -7
- data/lib/logging/appenders/buffering.rb +127 -56
- data/lib/logging/appenders/console.rb +36 -55
- data/lib/logging/appenders/file.rb +1 -1
- data/lib/logging/appenders/io.rb +10 -7
- data/lib/logging/appenders/rolling_file.rb +2 -2
- data/lib/logging/appenders/syslog.rb +1 -1
- data/lib/logging/diagnostic_context.rb +5 -3
- data/lib/logging/layout.rb +21 -8
- data/lib/logging/layouts/pattern.rb +3 -6
- data/lib/logging/log_event.rb +1 -1
- data/lib/logging/logger.rb +109 -89
- data/lib/logging/version.rb +1 -1
- data/logging.gemspec +1 -0
- data/script/console +8 -0
- data/test/appenders/{test_periodic_flushing.rb → test_async_flushing.rb} +67 -14
- data/test/appenders/test_buffered_io.rb +6 -3
- data/test/appenders/test_console.rb +8 -0
- data/test/appenders/test_file.rb +11 -6
- data/test/appenders/test_rolling_file.rb +6 -0
- data/test/appenders/test_syslog.rb +6 -0
- data/test/benchmark.rb +42 -18
- data/test/performance.rb +66 -0
- data/test/setup.rb +20 -28
- data/test/test_appender.rb +2 -4
- data/test/test_layout.rb +9 -0
- data/test/test_logger.rb +20 -3
- metadata +11 -8
@@ -1,44 +1,55 @@
|
|
1
|
-
|
2
1
|
module Logging::Appenders
|
3
2
|
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
return self['stdout'] || ::Logging::Appenders::Stdout.new
|
9
|
-
end
|
10
|
-
::Logging::Appenders::Stdout.new(*args)
|
11
|
-
end
|
12
|
-
|
13
|
-
# This class provides an Appender that can write to STDOUT.
|
14
|
-
#
|
15
|
-
class Stdout < ::Logging::Appenders::IO
|
3
|
+
# This class is provides an Appender base class for writing to the standard IO
|
4
|
+
# stream - STDOUT and STDERR. This class should not be instantiated directly.
|
5
|
+
# The `Stdout` and `Stderr` subclasses should be used.
|
6
|
+
class Console < ::Logging::Appenders::IO
|
16
7
|
|
17
8
|
# call-seq:
|
18
9
|
# Stdout.new( name = 'stdout' )
|
19
|
-
#
|
10
|
+
# Stderr.new( :layout => layout )
|
20
11
|
# Stdout.new( name = 'stdout', :level => 'info' )
|
21
12
|
#
|
22
|
-
# Creates a new Stdout Appender. The name 'stdout' will be
|
23
|
-
# another is given. Optionally, a layout can be given for the
|
24
|
-
# to use (otherwise a basic appender will be created) and a log
|
25
|
-
# can be specified.
|
13
|
+
# Creates a new Stdout/Stderr Appender. The name 'stdout'/'stderr' will be
|
14
|
+
# used unless another is given. Optionally, a layout can be given for the
|
15
|
+
# appender to use (otherwise a basic appender will be created) and a log
|
16
|
+
# level can be specified.
|
26
17
|
#
|
27
18
|
# Options:
|
28
19
|
#
|
29
|
-
# :layout
|
30
|
-
# :level
|
20
|
+
# :layout => the layout to use when formatting log events
|
21
|
+
# :level => the level at which to log
|
31
22
|
#
|
32
23
|
def initialize( *args )
|
24
|
+
name = self.class.name.split("::").last.downcase
|
25
|
+
io = Object.const_get(name.upcase)
|
26
|
+
|
33
27
|
opts = Hash === args.last ? args.pop : {}
|
34
|
-
name = args.
|
28
|
+
name = args.shift unless args.empty?
|
35
29
|
|
36
|
-
opts[:encoding] =
|
30
|
+
opts[:encoding] = io.external_encoding if io.respond_to? :external_encoding
|
37
31
|
|
38
|
-
super(name,
|
32
|
+
super(name, io, opts)
|
33
|
+
rescue NameError
|
34
|
+
raise RuntimeError, "Please do not use the `Logging::Appenders::Console` class directly - " +
|
35
|
+
"use `Logging::Appenders::Stdout` and `Logging::Appenders::Stderr` instead"
|
39
36
|
end
|
40
|
-
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# This class provides an Appender that can write to STDOUT.
|
40
|
+
Stdout = Class.new(Console)
|
41
41
|
|
42
|
+
# This class provides an Appender that can write to STDERR.
|
43
|
+
Stderr = Class.new(Console)
|
44
|
+
|
45
|
+
# Accessor / Factory for the Stdout appender.
|
46
|
+
#
|
47
|
+
def self.stdout( *args )
|
48
|
+
if args.empty?
|
49
|
+
return self['stdout'] || ::Logging::Appenders::Stdout.new
|
50
|
+
end
|
51
|
+
::Logging::Appenders::Stdout.new(*args)
|
52
|
+
end
|
42
53
|
|
43
54
|
# Accessor / Factory for the Stderr appender.
|
44
55
|
#
|
@@ -48,34 +59,4 @@ module Logging::Appenders
|
|
48
59
|
end
|
49
60
|
::Logging::Appenders::Stderr.new(*args)
|
50
61
|
end
|
51
|
-
|
52
|
-
# This class provides an Appender that can write to STDERR.
|
53
|
-
#
|
54
|
-
class Stderr < ::Logging::Appenders::IO
|
55
|
-
|
56
|
-
# call-seq:
|
57
|
-
# Stderr.new( name = 'stderr' )
|
58
|
-
# Stderr.new( :layout => layout )
|
59
|
-
# Stderr.new( name = 'stderr', :level => 'warn' )
|
60
|
-
#
|
61
|
-
# Creates a new Stderr Appender. The name 'stderr' will be used unless
|
62
|
-
# another is given. Optionally, a layout can be given for the appender
|
63
|
-
# to use (otherwise a basic appender will be created) and a log level
|
64
|
-
# can be specified.
|
65
|
-
#
|
66
|
-
# Options:
|
67
|
-
#
|
68
|
-
# :layout => the layout to use when formatting log events
|
69
|
-
# :level => the level at which to log
|
70
|
-
#
|
71
|
-
def initialize( *args )
|
72
|
-
opts = Hash === args.last ? args.pop : {}
|
73
|
-
name = args.empty? ? 'stderr' : args.shift
|
74
|
-
|
75
|
-
opts[:encoding] = STDERR.external_encoding if STDERR.respond_to? :external_encoding
|
76
|
-
|
77
|
-
super(name, STDERR, opts)
|
78
|
-
end
|
79
|
-
end # Stderr
|
80
|
-
end # Logging::Appenders
|
81
|
-
|
62
|
+
end
|
@@ -4,7 +4,7 @@ module Logging::Appenders
|
|
4
4
|
# Accessor / Factory for the File appender.
|
5
5
|
#
|
6
6
|
def self.file( *args )
|
7
|
-
|
7
|
+
fail ArgumentError, '::Logging::Appenders::File needs a name as first argument.' if args.empty?
|
8
8
|
::Logging::Appenders::File.new(*args)
|
9
9
|
end
|
10
10
|
|
data/lib/logging/appenders/io.rb
CHANGED
@@ -28,13 +28,12 @@ module Logging::Appenders
|
|
28
28
|
# stream as the logging destination.
|
29
29
|
#
|
30
30
|
def initialize( name, io, opts = {} )
|
31
|
-
unless io.respond_to? :
|
31
|
+
unless io.respond_to? :write
|
32
32
|
raise TypeError, "expecting an IO object but got '#{io.class.name}'"
|
33
33
|
end
|
34
34
|
|
35
35
|
@io = io
|
36
|
-
@io.sync = true if io.respond_to? :sync=
|
37
|
-
@io.flush rescue nil # syswrite also complains if in unbuffered mode and buffer isn't empty
|
36
|
+
@io.sync = true if io.respond_to? :sync=
|
38
37
|
@close_method = :close
|
39
38
|
|
40
39
|
super(name, opts)
|
@@ -55,7 +54,7 @@ module Logging::Appenders
|
|
55
54
|
|
56
55
|
io, @io = @io, nil
|
57
56
|
unless [STDIN, STDERR, STDOUT].include?(io)
|
58
|
-
io.send(@close_method) if @close_method
|
57
|
+
io.send(@close_method) if @close_method && io.respond_to?(@close_method)
|
59
58
|
end
|
60
59
|
rescue IOError
|
61
60
|
ensure
|
@@ -70,10 +69,15 @@ module Logging::Appenders
|
|
70
69
|
#
|
71
70
|
def canonical_write( str )
|
72
71
|
return self if @io.nil?
|
73
|
-
str = str.force_encoding(encoding) if encoding
|
74
|
-
@io.
|
72
|
+
str = str.force_encoding(encoding) if encoding && str.encoding != encoding
|
73
|
+
@io.write str
|
75
74
|
self
|
76
75
|
rescue StandardError => err
|
76
|
+
handle_internal_error(err)
|
77
|
+
end
|
78
|
+
|
79
|
+
def handle_internal_error( err )
|
80
|
+
return err if off?
|
77
81
|
self.level = :off
|
78
82
|
::Logging.log_internal {"appender #{name.inspect} has been disabled"}
|
79
83
|
::Logging.log_internal_error(err)
|
@@ -81,4 +85,3 @@ module Logging::Appenders
|
|
81
85
|
|
82
86
|
end # IO
|
83
87
|
end # Logging::Appenders
|
84
|
-
|
@@ -2,7 +2,7 @@ module Logging::Appenders
|
|
2
2
|
|
3
3
|
# Accessor / Factory for the RollingFile appender.
|
4
4
|
def self.rolling_file( *args )
|
5
|
-
|
5
|
+
fail ArgumentError, '::Logging::Appenders::RollingFile needs a name as first argument.' if args.empty?
|
6
6
|
::Logging::Appenders::RollingFile.new(*args)
|
7
7
|
end
|
8
8
|
|
@@ -148,7 +148,7 @@ module Logging::Appenders
|
|
148
148
|
return self if @io.nil?
|
149
149
|
|
150
150
|
str = str.force_encoding(encoding) if encoding && str.encoding != encoding
|
151
|
-
@io.flock_sh { @io.
|
151
|
+
@io.flock_sh { @io.write str }
|
152
152
|
|
153
153
|
if roll_required?
|
154
154
|
@io.flock? {
|
@@ -9,7 +9,7 @@ module Logging::Appenders
|
|
9
9
|
# Accessor / Factory for the Syslog appender.
|
10
10
|
#
|
11
11
|
def self.syslog( *args )
|
12
|
-
|
12
|
+
fail ArgumentError, '::Logging::Appenders::Syslog needs a name as first argument.' if args.empty?
|
13
13
|
::Logging::Appenders::Syslog.new(*args)
|
14
14
|
end
|
15
15
|
|
@@ -143,7 +143,7 @@ module Logging
|
|
143
143
|
Thread.current[STACK_NAME] = [obj.dup]
|
144
144
|
when Thread
|
145
145
|
return if Thread.current == obj
|
146
|
-
|
146
|
+
DIAGNOSTIC_MUTEX.synchronize {
|
147
147
|
if obj[STACK_NAME]
|
148
148
|
hash = flatten(obj[STACK_NAME])
|
149
149
|
Thread.current[STACK_NAME] = [hash]
|
@@ -338,7 +338,7 @@ module Logging
|
|
338
338
|
Thread.current[NAME] = obj.dup
|
339
339
|
when Thread
|
340
340
|
return if Thread.current == obj
|
341
|
-
|
341
|
+
DIAGNOSTIC_MUTEX.synchronize {
|
342
342
|
Thread.current[NAME] = obj[NAME].dup if obj[NAME]
|
343
343
|
}
|
344
344
|
end
|
@@ -381,7 +381,7 @@ module Logging
|
|
381
381
|
#
|
382
382
|
def self.clear_diagnostic_contexts( all = false )
|
383
383
|
if all
|
384
|
-
|
384
|
+
DIAGNOSTIC_MUTEX.synchronize {
|
385
385
|
Thread.list.each { |thread|
|
386
386
|
thread[MappedDiagnosticContext::NAME] = nil if thread[MappedDiagnosticContext::NAME]
|
387
387
|
thread[NestedDiagnosticContext::NAME] = nil if thread[NestedDiagnosticContext::NAME]
|
@@ -396,6 +396,8 @@ module Logging
|
|
396
396
|
self
|
397
397
|
end
|
398
398
|
|
399
|
+
DIAGNOSTIC_MUTEX = Mutex.new
|
400
|
+
|
399
401
|
end # module Logging
|
400
402
|
|
401
403
|
|
data/lib/logging/layout.rb
CHANGED
@@ -41,15 +41,28 @@ class Layout
|
|
41
41
|
when :inspect, :yaml, :json; f
|
42
42
|
else :string end
|
43
43
|
|
44
|
-
|
45
|
-
@backtrace = case b
|
46
|
-
when :on, 'on', true; true
|
47
|
-
when :off, 'off', false; false
|
48
|
-
else
|
49
|
-
raise ArgumentError, "backtrace must be true or false"
|
50
|
-
end
|
44
|
+
self.backtrace = opts.fetch(:backtrace, ::Logging.backtrace)
|
51
45
|
end
|
52
46
|
|
47
|
+
# call-seq:
|
48
|
+
# layout.backtrace = true
|
49
|
+
#
|
50
|
+
# Set the backtrace flag to the given value. This can be set to `true` or
|
51
|
+
# `false`.
|
52
|
+
#
|
53
|
+
def backtrace=( value )
|
54
|
+
@backtrace = case value
|
55
|
+
when :on, 'on', true; true
|
56
|
+
when :off, 'off', false; false
|
57
|
+
else
|
58
|
+
raise ArgumentError, "backtrace must be `true` or `false`"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the backtrace setting.
|
63
|
+
attr_reader :backtrace
|
64
|
+
alias :backtrace? :backtrace
|
65
|
+
|
53
66
|
# call-seq:
|
54
67
|
# format( event )
|
55
68
|
#
|
@@ -85,7 +98,7 @@ class Layout
|
|
85
98
|
when String; obj
|
86
99
|
when Exception
|
87
100
|
str = "<#{obj.class.name}> #{obj.message}"
|
88
|
-
if
|
101
|
+
if backtrace? && !obj.backtrace.nil?
|
89
102
|
str << "\n\t" << obj.backtrace.join("\n\t")
|
90
103
|
end
|
91
104
|
str
|
@@ -83,7 +83,7 @@ module Logging::Layouts
|
|
83
83
|
# events is configured to generate tracing information. If this is not
|
84
84
|
# the case these fields will always be empty.
|
85
85
|
#
|
86
|
-
# The directives for
|
86
|
+
# The directives for including diagnostic context information in the log
|
87
87
|
# messages are X and x. For the Mapped Diagnostic Context the directive must
|
88
88
|
# be accompanied by the key identifying the value to insert into the log
|
89
89
|
# message. The X directive can appear multiple times to include multiple
|
@@ -166,12 +166,9 @@ module Logging::Layouts
|
|
166
166
|
code << "def format_date( time )\n"
|
167
167
|
if pl.date_method.nil?
|
168
168
|
if pl.date_pattern =~ %r/%s/
|
169
|
-
code <<
|
170
|
-
dp = '#{pl.date_pattern}'.gsub('%s','%06d' % time.usec)
|
171
|
-
time.strftime dp
|
172
|
-
CODE
|
169
|
+
code << "time.strftime('#{pl.date_pattern.gsub('%s','%6N')}')\n"
|
173
170
|
else
|
174
|
-
code << "time.strftime
|
171
|
+
code << "time.strftime('#{pl.date_pattern}')\n"
|
175
172
|
end
|
176
173
|
else
|
177
174
|
code << "time.#{pl.date_method}\n"
|
data/lib/logging/log_event.rb
CHANGED
@@ -11,7 +11,7 @@ module Logging
|
|
11
11
|
# * $1 == filename
|
12
12
|
# * $2 == line number
|
13
13
|
# * $3 == method name (might be nil)
|
14
|
-
CALLER_RGXP = %r/([-\.\/\(\)\w]+):(\d+)(?::in `(
|
14
|
+
CALLER_RGXP = %r/([-\.\/\(\)\w]+):(\d+)(?::in `([^']+)')?/o
|
15
15
|
#CALLER_INDEX = 2
|
16
16
|
CALLER_INDEX = ((defined? JRUBY_VERSION and JRUBY_VERSION > '1.6') or (defined? RUBY_ENGINE and RUBY_ENGINE[%r/^rbx/i])) ? 1 : 2
|
17
17
|
# :startdoc:
|
data/lib/logging/logger.rb
CHANGED
@@ -26,87 +26,97 @@ module Logging
|
|
26
26
|
|
27
27
|
@mutex = Mutex.new # :nodoc:
|
28
28
|
|
29
|
-
|
29
|
+
# Returns the root logger.
|
30
|
+
def self.root
|
31
|
+
::Logging::Repository.instance[:root]
|
32
|
+
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
34
|
+
class << self
|
35
|
+
alias_method :instantiate, :new # `instantiate` becomes the "real" `new`
|
36
|
+
end
|
35
37
|
|
36
|
-
|
38
|
+
# Overrides the new method such that only one Logger will be created
|
39
|
+
# for any given logger name.
|
40
|
+
def self.new( *args )
|
41
|
+
args.empty? ? super : self[args.shift]
|
42
|
+
end
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
44
|
+
# Returns a logger instance for the given name.
|
45
|
+
def self.[]( name )
|
46
|
+
repo = ::Logging::Repository.instance
|
47
|
+
name = repo.to_key(name)
|
48
|
+
logger = repo[name]
|
49
|
+
return logger unless logger.nil?
|
43
50
|
|
44
|
-
|
45
|
-
def []( name )
|
46
|
-
repo = ::Logging::Repository.instance
|
47
|
-
name = repo.to_key(name)
|
51
|
+
@mutex.synchronize do
|
48
52
|
logger = repo[name]
|
49
|
-
return logger unless logger.nil?
|
53
|
+
return logger unless logger.nil? # thread-safe double checking
|
50
54
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
logger = instantiate(name)
|
56
|
-
repo[name] = logger
|
57
|
-
repo.children(name).each { |c| c.__send__(:parent=, logger) }
|
58
|
-
logger
|
59
|
-
end
|
55
|
+
logger = instantiate(name)
|
56
|
+
repo[name] = logger
|
57
|
+
repo.children(name).each { |child| child.__send__(:parent=, logger) }
|
58
|
+
logger
|
60
59
|
end
|
60
|
+
end
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
if logger.level > num
|
90
|
-
code << <<-CODE
|
91
|
-
def #{name}?( ) false end
|
92
|
-
def #{name}( data = nil ) false end
|
93
|
-
CODE
|
94
|
-
else
|
95
|
-
code << <<-CODE
|
96
|
-
def #{name}?( ) true end
|
97
|
-
def #{name}( data = nil )
|
98
|
-
data = yield if block_given?
|
99
|
-
log_event(::Logging::LogEvent.new(@name, #{num}, data, @caller_tracing))
|
100
|
-
true
|
101
|
-
end
|
102
|
-
CODE
|
103
|
-
end
|
62
|
+
# This is where the actual logging methods are defined. Two methods
|
63
|
+
# are created for each log level. The first is a query method used to
|
64
|
+
# determine if that perticular logging level is enabled. The second is
|
65
|
+
# the actual logging method that accepts a list of objects to be
|
66
|
+
# logged or a block. If a block is given, then the object returned
|
67
|
+
# from the block will be logged.
|
68
|
+
#
|
69
|
+
# Example
|
70
|
+
#
|
71
|
+
# log = Logging::Logger['my logger']
|
72
|
+
# log.level = :warn
|
73
|
+
#
|
74
|
+
# log.info? # => false
|
75
|
+
# log.warn? # => true
|
76
|
+
# log.warn 'this is your last warning'
|
77
|
+
# log.fatal 'I die!', exception
|
78
|
+
#
|
79
|
+
# log.debug do
|
80
|
+
# # expensive method to construct log message
|
81
|
+
# msg
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
def self.define_log_methods( logger )
|
85
|
+
code = log_methods_for_level(logger.level)
|
86
|
+
logger._meta_eval(code, __FILE__, __LINE__)
|
87
|
+
logger
|
88
|
+
end
|
104
89
|
|
105
|
-
|
90
|
+
# This generator is used to define the log methods for the given `level`.
|
91
|
+
# This code is evaluated in the context of a Logger instance.
|
92
|
+
#
|
93
|
+
# Returns log methods as a String
|
94
|
+
def self.log_methods_for_level( level )
|
95
|
+
code = []
|
96
|
+
::Logging::LEVELS.each do |name,num|
|
97
|
+
code << <<-CODE
|
98
|
+
undef :#{name} if method_defined? :#{name}
|
99
|
+
undef :#{name}? if method_defined? :#{name}?
|
100
|
+
CODE
|
101
|
+
|
102
|
+
if level > num
|
103
|
+
code << <<-CODE
|
104
|
+
def #{name}?( ) false end
|
105
|
+
def #{name}( data = nil ) false end
|
106
|
+
CODE
|
107
|
+
else
|
108
|
+
code << <<-CODE
|
109
|
+
def #{name}?( ) true end
|
110
|
+
def #{name}( data = nil )
|
111
|
+
data = yield if block_given?
|
112
|
+
log_event(::Logging::LogEvent.new(@name, #{num}, data, @caller_tracing))
|
113
|
+
true
|
114
|
+
end
|
115
|
+
CODE
|
106
116
|
end
|
107
|
-
logger
|
108
117
|
end
|
109
|
-
|
118
|
+
code.join("\n")
|
119
|
+
end
|
110
120
|
|
111
121
|
attr_reader :name, :parent, :additive, :caller_tracing
|
112
122
|
|
@@ -197,7 +207,14 @@ module Logging
|
|
197
207
|
lvl = Integer(lvl)
|
198
208
|
return false if lvl < level
|
199
209
|
|
200
|
-
|
210
|
+
if data.nil?
|
211
|
+
if block_given?
|
212
|
+
data = yield
|
213
|
+
else
|
214
|
+
data = progname
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
201
218
|
log_event(::Logging::LogEvent.new(@name, lvl, data, @caller_tracing))
|
202
219
|
true
|
203
220
|
end
|
@@ -292,6 +309,11 @@ module Logging
|
|
292
309
|
self.level
|
293
310
|
end
|
294
311
|
|
312
|
+
# Returns `true` if the logger has its own level defined.
|
313
|
+
def has_own_level?
|
314
|
+
!@level.nil?
|
315
|
+
end
|
316
|
+
|
295
317
|
# Returns the list of appenders.
|
296
318
|
#
|
297
319
|
def appenders
|
@@ -353,17 +375,7 @@ module Logging
|
|
353
375
|
#
|
354
376
|
def clear_appenders( ) @appenders.clear end
|
355
377
|
|
356
|
-
|
357
|
-
# inspect => string
|
358
|
-
#
|
359
|
-
# Returns a string representation of the logger.
|
360
|
-
#
|
361
|
-
def inspect
|
362
|
-
"<%s:0x%x name=\"%s\">" % [self.class.name, self.object_id, self.name]
|
363
|
-
end
|
364
|
-
|
365
|
-
|
366
|
-
protected
|
378
|
+
protected
|
367
379
|
|
368
380
|
# call-seq:
|
369
381
|
# parent = ParentLogger
|
@@ -396,18 +408,26 @@ module Logging
|
|
396
408
|
#
|
397
409
|
# Recursively call this method on all our children loggers.
|
398
410
|
#
|
399
|
-
def define_log_methods( force = false )
|
400
|
-
return if
|
411
|
+
def define_log_methods( force = false, code = nil )
|
412
|
+
return if has_own_level? and !force
|
401
413
|
|
402
|
-
::Logging::Logger.
|
403
|
-
|
404
|
-
|
414
|
+
::Logging::Logger._reentrant_mutex.synchronize do
|
415
|
+
::Logging::Logger.define_log_methods(self)
|
416
|
+
::Logging::Repository.instance.children(name).each do |child|
|
417
|
+
child.define_log_methods
|
418
|
+
end
|
405
419
|
end
|
406
420
|
self
|
407
421
|
end
|
408
422
|
|
409
423
|
# :stopdoc:
|
410
|
-
|
424
|
+
public
|
425
|
+
|
426
|
+
@reentrant_mutex = ReentrantMutex.new
|
427
|
+
|
428
|
+
def self._reentrant_mutex
|
429
|
+
@reentrant_mutex
|
430
|
+
end
|
411
431
|
|
412
432
|
# call-seq:
|
413
433
|
# _meta_eval( code )
|
@@ -483,7 +503,7 @@ module Logging
|
|
483
503
|
@appenders.each do |appender|
|
484
504
|
str << indent_str
|
485
505
|
str << '- '
|
486
|
-
str << appender.
|
506
|
+
str << appender.to_s
|
487
507
|
str << "\n"
|
488
508
|
end
|
489
509
|
|