logging 2.2.2 → 2.3.1
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 +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +5 -3
- data/History.txt +21 -0
- data/Rakefile +2 -2
- data/examples/appenders.rb +1 -1
- data/examples/mdc.rb +2 -2
- data/lib/logging/appender.rb +5 -25
- data/lib/logging/appenders/buffering.rb +3 -3
- data/lib/logging/appenders/console.rb +27 -7
- data/lib/logging/appenders/file.rb +42 -21
- data/lib/logging/appenders/io.rb +14 -11
- data/lib/logging/appenders/rolling_file.rb +48 -24
- data/lib/logging/appenders/string_io.rb +1 -1
- data/lib/logging/appenders/syslog.rb +2 -3
- data/lib/logging/filter.rb +11 -4
- data/lib/logging/filters/level.rb +10 -7
- data/lib/logging/filters.rb +1 -1
- data/lib/logging/layouts/parseable.rb +1 -1
- data/lib/logging/layouts/pattern.rb +1 -1
- data/lib/logging/log_event.rb +7 -6
- data/lib/logging/logger.rb +15 -13
- data/lib/logging/proxy.rb +1 -1
- data/lib/logging/version.rb +1 -1
- data/lib/logging.rb +21 -6
- data/logging.gemspec +12 -13
- data/test/appenders/test_buffered_io.rb +16 -18
- data/test/appenders/test_console.rb +47 -12
- data/test/appenders/test_file.rb +38 -23
- data/test/appenders/test_rolling_file.rb +12 -12
- data/test/layouts/test_json.rb +1 -1
- data/test/layouts/test_nested_exceptions.rb +6 -6
- data/test/layouts/test_pattern.rb +1 -1
- data/test/layouts/test_yaml.rb +1 -1
- data/test/setup.rb +9 -5
- data/test/test_log_event.rb +2 -2
- data/test/test_logging.rb +29 -4
- metadata +12 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f7bb89dcc5956ebabbf591d8f8d348e0e3cfdc7cb5fa356e9995168278b45a95
|
4
|
+
data.tar.gz: be4ad44cf88417be5abe80fbaf0b1d28a2f4899df2c00d1d4818af78cc440443
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b61a6a3bcda67484ec4334a89adfd6149d2aa91be51ba0ca476514c7c4532d0b4040cc202ce58d30e9d93ba5821e6eedbde77d8bdeaac7a82224731796d79eda
|
7
|
+
data.tar.gz: 55c888af479f8c01eb89f96eda24b2cc9cd92f52cc0b1f21d5fde7fcb7e91e573b6007998c67b00781cf8c5ea3eadcb9462b9df2da26dbcfe0464deb13340d18
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
== 2.3.1 / 2022-05-24
|
2
|
+
|
3
|
+
Bug Fixes
|
4
|
+
- logging hangs on JRuby when the stdout appender is closed [PR #237]
|
5
|
+
- initialize the Logging framework when a Filter is created [PR #238]
|
6
|
+
|
7
|
+
== 2.3.0 / 2020-07-04
|
8
|
+
|
9
|
+
Enhancements
|
10
|
+
- all appender output is now synchronized [PR #219]
|
11
|
+
- renamed the `LogEvent#method` to no longer conflict with `Kernel#method` [PR #218]
|
12
|
+
- @bhuga (not the Fortnite star) added a `raise_errors` method for debugging [PR #203]
|
13
|
+
- thanks to @olleolleolle for keeping on top of Travis and Ruby versions
|
14
|
+
|
15
|
+
Bug Fixes
|
16
|
+
- conosle appenders can be reopened [PR #220]
|
17
|
+
- fixed a race condition in the rolling file appender [PR #216]
|
18
|
+
- fixed a race condition when opening log file destinations [PR #208 #217]
|
19
|
+
- @MikaelSmith fixed a race condition in Logger creation [PR #201]
|
20
|
+
- documentation bug fixes [PR #184 #185 #188 #194 #209]
|
21
|
+
|
1
22
|
== 2.2.2 / 2017-04-11
|
2
23
|
|
3
24
|
Enhancements
|
data/Rakefile
CHANGED
@@ -26,9 +26,9 @@ Bones {
|
|
26
26
|
use_gmail
|
27
27
|
|
28
28
|
depend_on 'little-plugger', '~> 1.1'
|
29
|
-
depend_on 'multi_json', '~> 1.
|
29
|
+
depend_on 'multi_json', '~> 1.14'
|
30
30
|
|
31
|
-
depend_on 'test-unit', '~> 3.
|
31
|
+
depend_on 'test-unit', '~> 3.3', :development => true
|
32
32
|
depend_on 'bones-git', '~> 1.3', :development => true
|
33
33
|
#depend_on 'bones-rcov', :development => true
|
34
34
|
}
|
data/examples/appenders.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# :stopdoc:
|
2
2
|
#
|
3
3
|
# Appenders are used to output log events to some logging destination. The
|
4
|
-
# same log event can be sent to multiple
|
4
|
+
# same log event can be sent to multiple destinations by associating
|
5
5
|
# multiple appenders with the logger.
|
6
6
|
#
|
7
7
|
# The following is a list of all the available appenders and a brief
|
data/examples/mdc.rb
CHANGED
@@ -29,9 +29,9 @@
|
|
29
29
|
Logging.mdc['first'] = 'John'
|
30
30
|
Logging.mdc['last'] = 'Doe'
|
31
31
|
|
32
|
-
# in this first thread we will log some quotes by
|
32
|
+
# in this first thread we will log some quotes by Alan Rickman
|
33
33
|
t1 = Thread.new {
|
34
|
-
Logging.mdc['first'] = '
|
34
|
+
Logging.mdc['first'] = 'Alan'
|
35
35
|
Logging.mdc['last'] = 'Rickman'
|
36
36
|
|
37
37
|
[ %q{I've never been able to plan my life. I just lurch from indecision to indecision.},
|
data/lib/logging/appender.rb
CHANGED
@@ -9,11 +9,6 @@ module Logging
|
|
9
9
|
# Each subclass should provide a +write+ method that will write log
|
10
10
|
# messages to the logging destination.
|
11
11
|
#
|
12
|
-
# A private +sync+ method is provided for use by subclasses. It is used to
|
13
|
-
# synchronize writes to the logging destination, and can be used by
|
14
|
-
# subclasses to synchronize the closing or flushing of the logging
|
15
|
-
# destination.
|
16
|
-
#
|
17
12
|
class Appender
|
18
13
|
|
19
14
|
attr_reader :name, :layout, :level, :filters
|
@@ -263,13 +258,9 @@ class Appender
|
|
263
258
|
"<%s name=\"%s\">" % [self.class.name.sub(%r/^Logging::/, ''), self.name]
|
264
259
|
end
|
265
260
|
|
266
|
-
# Returns the current Encoding for the appender
|
267
|
-
#
|
268
|
-
|
269
|
-
def encoding
|
270
|
-
return @encoding if defined? @encoding
|
271
|
-
@encoding = Object.const_defined?(:Encoding) ? Encoding.default_external : nil
|
272
|
-
end
|
261
|
+
# Returns the current Encoding for the appender. The default external econding
|
262
|
+
# will be used if none is explicitly set.
|
263
|
+
attr_reader :encoding
|
273
264
|
|
274
265
|
# Set the appender encoding to the given value. The value can either be an
|
275
266
|
# Encoding instance or a String or Symbol referring to a valid encoding.
|
@@ -282,9 +273,9 @@ class Appender
|
|
282
273
|
# Raises ArgumentError if the value is not a valid encoding.
|
283
274
|
def encoding=( value )
|
284
275
|
if value.nil?
|
285
|
-
@encoding =
|
276
|
+
@encoding = Encoding.default_external
|
286
277
|
else
|
287
|
-
@encoding =
|
278
|
+
@encoding = Encoding.find(value.to_s)
|
288
279
|
end
|
289
280
|
end
|
290
281
|
|
@@ -328,17 +319,6 @@ private
|
|
328
319
|
nil
|
329
320
|
end
|
330
321
|
|
331
|
-
# call-seq:
|
332
|
-
# sync { block }
|
333
|
-
#
|
334
|
-
# Obtains an exclusive lock, runs the block, and releases the lock when
|
335
|
-
# the block completes. This method is re-entrant so that a single thread
|
336
|
-
# can call +sync+ multiple times without hanging the thread.
|
337
|
-
#
|
338
|
-
def sync( &block )
|
339
|
-
@mutex.synchronize(&block)
|
340
|
-
end
|
341
|
-
|
342
322
|
end # class Appender
|
343
323
|
end # module Logging
|
344
324
|
|
@@ -79,7 +79,7 @@ module Logging::Appenders
|
|
79
79
|
return self if @buffer.empty?
|
80
80
|
|
81
81
|
ary = nil
|
82
|
-
|
82
|
+
@mutex.synchronize {
|
83
83
|
ary = @buffer.dup
|
84
84
|
@buffer.clear
|
85
85
|
}
|
@@ -100,7 +100,7 @@ module Logging::Appenders
|
|
100
100
|
# Clear the underlying buffer of all log events. These events will not be
|
101
101
|
# appended to the logging destination; they will be lost.
|
102
102
|
def clear!
|
103
|
-
|
103
|
+
@mutex.synchronize { @buffer.clear }
|
104
104
|
end
|
105
105
|
|
106
106
|
# Configure the levels that will trigger an immediate flush of the
|
@@ -285,7 +285,7 @@ module Logging::Appenders
|
|
285
285
|
canonical_write(str)
|
286
286
|
else
|
287
287
|
str = str.force_encoding(encoding) if encoding && str.encoding != encoding
|
288
|
-
|
288
|
+
@mutex.synchronize {
|
289
289
|
@buffer << str
|
290
290
|
}
|
291
291
|
flush_now = @buffer.length >= @auto_flushing || immediate?(event)
|
@@ -22,17 +22,39 @@ module Logging::Appenders
|
|
22
22
|
#
|
23
23
|
def initialize( *args )
|
24
24
|
name = self.class.name.split("::").last.downcase
|
25
|
-
io = Object.const_get(name.upcase)
|
26
25
|
|
27
26
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
28
27
|
name = args.shift unless args.empty?
|
29
28
|
|
30
|
-
|
29
|
+
io = open_fd
|
30
|
+
opts[:encoding] = io.external_encoding
|
31
31
|
|
32
32
|
super(name, io, opts)
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
end
|
34
|
+
|
35
|
+
# Reopen the connection to the underlying logging destination. If the
|
36
|
+
# connection is currently closed then it will be opened. If the connection
|
37
|
+
# is currently open then it will be closed and immediately reopened.
|
38
|
+
def reopen
|
39
|
+
@mutex.synchronize {
|
40
|
+
flush if defined? @io && @io
|
41
|
+
@io = open_fd
|
42
|
+
}
|
43
|
+
super
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def open_fd
|
50
|
+
case self.class.name
|
51
|
+
when "Logging::Appenders::Stdout"; STDOUT
|
52
|
+
when "Logging::Appenders::Stderr"; STDERR
|
53
|
+
else
|
54
|
+
raise RuntimeError, "Please do not use the `Logging::Appenders::Console` class directly - " +
|
55
|
+
"use `Logging::Appenders::Stdout` and `Logging::Appenders::Stderr` instead" +
|
56
|
+
" [class #{self.class.name}]"
|
57
|
+
end
|
36
58
|
end
|
37
59
|
end
|
38
60
|
|
@@ -43,7 +65,6 @@ module Logging::Appenders
|
|
43
65
|
Stderr = Class.new(Console)
|
44
66
|
|
45
67
|
# Accessor / Factory for the Stdout appender.
|
46
|
-
#
|
47
68
|
def self.stdout( *args )
|
48
69
|
if args.empty?
|
49
70
|
return self['stdout'] || ::Logging::Appenders::Stdout.new
|
@@ -52,7 +73,6 @@ module Logging::Appenders
|
|
52
73
|
end
|
53
74
|
|
54
75
|
# Accessor / Factory for the Stderr appender.
|
55
|
-
#
|
56
76
|
def self.stderr( *args )
|
57
77
|
if args.empty?
|
58
78
|
return self['stderr'] || ::Logging::Appenders::Stderr.new
|
@@ -2,14 +2,12 @@
|
|
2
2
|
module Logging::Appenders
|
3
3
|
|
4
4
|
# Accessor / Factory for the File appender.
|
5
|
-
#
|
6
5
|
def self.file( *args )
|
7
6
|
fail ArgumentError, '::Logging::Appenders::File needs a name as first argument.' if args.empty?
|
8
7
|
::Logging::Appenders::File.new(*args)
|
9
8
|
end
|
10
9
|
|
11
10
|
# This class provides an Appender that can write to a File.
|
12
|
-
#
|
13
11
|
class File < ::Logging::Appenders::IO
|
14
12
|
|
15
13
|
# call-seq:
|
@@ -21,15 +19,14 @@ module Logging::Appenders
|
|
21
19
|
# writable.
|
22
20
|
#
|
23
21
|
# An +ArgumentError+ is raised if any of these assertions fail.
|
24
|
-
#
|
25
22
|
def self.assert_valid_logfile( fn )
|
26
23
|
if ::File.exist?(fn)
|
27
|
-
if
|
24
|
+
if !::File.file?(fn)
|
28
25
|
raise ArgumentError, "#{fn} is not a regular file"
|
29
|
-
elsif
|
26
|
+
elsif !::File.writable?(fn)
|
30
27
|
raise ArgumentError, "#{fn} is not writeable"
|
31
28
|
end
|
32
|
-
elsif
|
29
|
+
elsif !::File.writable?(::File.dirname(fn))
|
33
30
|
raise ArgumentError, "#{::File.dirname(fn)} is not writable"
|
34
31
|
end
|
35
32
|
true
|
@@ -45,41 +42,65 @@ module Logging::Appenders
|
|
45
42
|
# created. If the :truncate option is set to +true+ then the file will
|
46
43
|
# be truncated before writing begins; otherwise, log messages will be
|
47
44
|
# appended to the file.
|
48
|
-
#
|
49
45
|
def initialize( name, opts = {} )
|
50
|
-
@
|
51
|
-
raise ArgumentError, 'no filename was given' if @
|
46
|
+
@filename = opts.fetch(:filename, name)
|
47
|
+
raise ArgumentError, 'no filename was given' if @filename.nil?
|
52
48
|
|
53
|
-
@
|
54
|
-
self.class.assert_valid_logfile(@
|
55
|
-
@mode = opts.fetch(:truncate, false) ? 'w' : 'a'
|
49
|
+
@filename = ::File.expand_path(@filename).freeze
|
50
|
+
self.class.assert_valid_logfile(@filename)
|
56
51
|
|
57
52
|
self.encoding = opts.fetch(:encoding, self.encoding)
|
58
|
-
@mode = "#{@mode}:#{self.encoding}" if self.encoding
|
59
53
|
|
60
|
-
|
54
|
+
io = open_file
|
55
|
+
super(name, io, opts)
|
56
|
+
|
57
|
+
truncate if opts.fetch(:truncate, false)
|
61
58
|
end
|
62
59
|
|
63
60
|
# Returns the path to the logfile.
|
64
|
-
|
65
|
-
def filename() @fn.dup end
|
61
|
+
attr_reader :filename
|
66
62
|
|
67
63
|
# Reopen the connection to the underlying logging destination. If the
|
68
64
|
# connection is currently closed then it will be opened. If the connection
|
69
65
|
# is currently open then it will be closed and immediately opened.
|
70
|
-
#
|
71
66
|
def reopen
|
72
67
|
@mutex.synchronize {
|
73
|
-
if defined? @io
|
68
|
+
if defined? @io && @io
|
74
69
|
flush
|
75
70
|
@io.close rescue nil
|
76
71
|
end
|
77
|
-
@io =
|
72
|
+
@io = open_file
|
78
73
|
}
|
79
74
|
super
|
80
75
|
self
|
81
76
|
end
|
82
77
|
|
83
|
-
end # FileAppender
|
84
|
-
end # Logging::Appenders
|
85
78
|
|
79
|
+
protected
|
80
|
+
|
81
|
+
def truncate
|
82
|
+
@mutex.synchronize {
|
83
|
+
begin
|
84
|
+
@io.flock(::File::LOCK_EX)
|
85
|
+
@io.truncate(0)
|
86
|
+
ensure
|
87
|
+
@io.flock(::File::LOCK_UN)
|
88
|
+
end
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def open_file
|
93
|
+
mode = ::File::WRONLY | ::File::APPEND
|
94
|
+
::File.open(filename, mode: mode, external_encoding: encoding)
|
95
|
+
rescue Errno::ENOENT
|
96
|
+
create_file
|
97
|
+
end
|
98
|
+
|
99
|
+
def create_file
|
100
|
+
mode = ::File::WRONLY | ::File::APPEND | ::File::CREAT | ::File::EXCL
|
101
|
+
::File.open(filename, mode: mode, external_encoding: encoding)
|
102
|
+
rescue Errno::EEXIST
|
103
|
+
open_file
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/logging/appenders/io.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
module Logging::Appenders
|
3
3
|
|
4
4
|
# Accessor / Factory for the IO appender.
|
5
|
-
#
|
6
5
|
def self.io( *args )
|
7
6
|
return ::Logging::Appenders::IO if args.empty?
|
8
7
|
::Logging::Appenders::IO.new(*args)
|
@@ -10,14 +9,12 @@ module Logging::Appenders
|
|
10
9
|
|
11
10
|
# This class provides an Appender that can write to any IO stream
|
12
11
|
# configured for writing.
|
13
|
-
#
|
14
12
|
class IO < ::Logging::Appender
|
15
13
|
include Buffering
|
16
14
|
|
17
15
|
# The method that will be used to close the IO stream. Defaults to :close
|
18
16
|
# but can be :close_read, :close_write or nil. When nil, the IO stream
|
19
17
|
# will not be closed when the appender's close method is called.
|
20
|
-
#
|
21
18
|
attr_accessor :close_method
|
22
19
|
|
23
20
|
# call-seq:
|
@@ -26,7 +23,6 @@ module Logging::Appenders
|
|
26
23
|
#
|
27
24
|
# Creates a new IO Appender using the given name that will use the _io_
|
28
25
|
# stream as the logging destination.
|
29
|
-
#
|
30
26
|
def initialize( name, io, opts = {} )
|
31
27
|
unless io.respond_to? :write
|
32
28
|
raise TypeError, "expecting an IO object but got '#{io.class.name}'"
|
@@ -47,13 +43,12 @@ module Logging::Appenders
|
|
47
43
|
# destination if the _footer_ flag is set to +true+. Log events will
|
48
44
|
# no longer be written to the logging destination after the appender
|
49
45
|
# is closed.
|
50
|
-
#
|
51
46
|
def close( *args )
|
52
47
|
return self if @io.nil?
|
53
48
|
super
|
54
49
|
|
55
50
|
io, @io = @io, nil
|
56
|
-
|
51
|
+
if ![STDIN, STDERR, STDOUT].include?(io)
|
57
52
|
io.send(@close_method) if @close_method && io.respond_to?(@close_method)
|
58
53
|
end
|
59
54
|
rescue IOError
|
@@ -61,16 +56,25 @@ module Logging::Appenders
|
|
61
56
|
return self
|
62
57
|
end
|
63
58
|
|
59
|
+
# Reopen the connection to the underlying logging destination. If the
|
60
|
+
# connection is currently closed then it will be opened. If the connection
|
61
|
+
# is currently open then it will be closed and immediately opened. If
|
62
|
+
# supported, the IO will have its sync mode set to `true` so that all writes
|
63
|
+
# are immediately flushed to the underlying operating system.
|
64
|
+
def reopen
|
65
|
+
super
|
66
|
+
@io.sync = true if @io.respond_to? :sync=
|
67
|
+
self
|
68
|
+
end
|
64
69
|
|
65
70
|
private
|
66
71
|
|
67
72
|
# This method is called by the buffering code when messages need to be
|
68
73
|
# written to the logging destination.
|
69
|
-
#
|
70
74
|
def canonical_write( str )
|
71
75
|
return self if @io.nil?
|
72
76
|
str = str.force_encoding(encoding) if encoding && str.encoding != encoding
|
73
|
-
@io.write str
|
77
|
+
@mutex.synchronize { @io.write str }
|
74
78
|
self
|
75
79
|
rescue StandardError => err
|
76
80
|
handle_internal_error(err)
|
@@ -82,6 +86,5 @@ module Logging::Appenders
|
|
82
86
|
::Logging.log_internal {"appender #{name.inspect} has been disabled"}
|
83
87
|
::Logging.log_internal_error(err)
|
84
88
|
end
|
85
|
-
|
86
|
-
|
87
|
-
end # Logging::Appenders
|
89
|
+
end
|
90
|
+
end
|
@@ -84,24 +84,32 @@ module Logging::Appenders
|
|
84
84
|
# 'date'.
|
85
85
|
#
|
86
86
|
def initialize( name, opts = {} )
|
87
|
-
@roller = Roller.new
|
87
|
+
@roller = Roller.new(
|
88
|
+
opts.fetch(:filename, name),
|
89
|
+
age: opts.fetch(:age, nil),
|
90
|
+
size: opts.fetch(:size, nil),
|
91
|
+
roll_by: opts.fetch(:roll_by, nil),
|
92
|
+
keep: opts.fetch(:keep, nil)
|
93
|
+
)
|
88
94
|
|
89
95
|
# grab our options
|
90
96
|
@size = opts.fetch(:size, nil)
|
91
97
|
@size = Integer(@size) unless @size.nil?
|
92
98
|
|
93
|
-
@age_fn = filename + '.age'
|
99
|
+
@age_fn = self.filename + '.age'
|
94
100
|
@age_fn_mtime = nil
|
95
101
|
@age = opts.fetch(:age, nil)
|
96
102
|
|
97
103
|
# create our `sufficiently_aged?` method
|
98
104
|
build_singleton_methods
|
99
|
-
FileUtils.touch(@age_fn) if @age &&
|
105
|
+
FileUtils.touch(@age_fn) if @age && !::File.file?(@age_fn)
|
100
106
|
|
101
107
|
# we are opening the file in read/write mode so that a shared lock can
|
102
108
|
# be used on the file descriptor => http://pubs.opengroup.org/onlinepubs/009695399/functions/fcntl.html
|
103
|
-
|
104
|
-
|
109
|
+
self.encoding = opts.fetch(:encoding, self.encoding)
|
110
|
+
|
111
|
+
io = open_file
|
112
|
+
super(name, io, opts)
|
105
113
|
|
106
114
|
# if the truncate flag was set to true, then roll
|
107
115
|
roll_now = opts.fetch(:truncate, false)
|
@@ -121,11 +129,11 @@ module Logging::Appenders
|
|
121
129
|
# is currently open then it will be closed and immediately opened.
|
122
130
|
def reopen
|
123
131
|
@mutex.synchronize {
|
124
|
-
if defined?
|
132
|
+
if defined? @io && @io
|
125
133
|
flush
|
126
134
|
@io.close rescue nil
|
127
135
|
end
|
128
|
-
@io =
|
136
|
+
@io = open_file
|
129
137
|
}
|
130
138
|
super
|
131
139
|
self
|
@@ -134,6 +142,20 @@ module Logging::Appenders
|
|
134
142
|
|
135
143
|
private
|
136
144
|
|
145
|
+
def open_file
|
146
|
+
mode = ::File::RDWR | ::File::APPEND
|
147
|
+
::File.open(filename, mode: mode, external_encoding: encoding)
|
148
|
+
rescue Errno::ENOENT
|
149
|
+
create_file
|
150
|
+
end
|
151
|
+
|
152
|
+
def create_file
|
153
|
+
mode = ::File::RDWR | ::File::APPEND | ::File::CREAT | ::File::EXCL
|
154
|
+
::File.open(filename, mode: mode, external_encoding: encoding)
|
155
|
+
rescue Errno::EEXIST
|
156
|
+
open_file
|
157
|
+
end
|
158
|
+
|
137
159
|
# Returns the file name to use as the temporary copy location. We are
|
138
160
|
# using copy-and-truncate semantics for rolling files so that the IO
|
139
161
|
# file descriptor remains valid during rolling.
|
@@ -157,14 +179,18 @@ module Logging::Appenders
|
|
157
179
|
return self if @io.nil?
|
158
180
|
|
159
181
|
str = str.force_encoding(encoding) if encoding && str.encoding != encoding
|
160
|
-
@
|
182
|
+
@mutex.synchronize {
|
183
|
+
@io.flock_sh { @io.write str }
|
184
|
+
}
|
161
185
|
|
162
186
|
if roll_required?
|
163
|
-
@
|
164
|
-
@
|
165
|
-
|
187
|
+
@mutex.synchronize {
|
188
|
+
@io.flock? {
|
189
|
+
@age_fn_mtime = nil
|
190
|
+
copy_truncate if roll_required?
|
191
|
+
}
|
192
|
+
@roller.roll_files
|
166
193
|
}
|
167
|
-
@roller.roll_files
|
168
194
|
end
|
169
195
|
self
|
170
196
|
rescue StandardError => err
|
@@ -193,7 +219,7 @@ module Logging::Appenders
|
|
193
219
|
def copy_truncate
|
194
220
|
return unless ::File.exist?(filename)
|
195
221
|
FileUtils.concat filename, copy_file
|
196
|
-
@io.truncate
|
222
|
+
@io.truncate(0)
|
197
223
|
|
198
224
|
# touch the age file if needed
|
199
225
|
if @age
|
@@ -255,22 +281,22 @@ module Logging::Appenders
|
|
255
281
|
# Create a new roller. See the RollingFile#initialize documentation for
|
256
282
|
# the list of options.
|
257
283
|
#
|
258
|
-
#
|
259
|
-
#
|
284
|
+
# filename - the name of the file to roll
|
285
|
+
# age - the age of the file at which it should be rolled
|
286
|
+
# size - the size of the file in bytes at which it should be rolled
|
287
|
+
# roll_by - roll either by 'number' or 'date'
|
288
|
+
# keep - the number of log files to keep when rolling
|
260
289
|
#
|
261
|
-
def initialize(
|
290
|
+
def initialize( filename, age: nil, size: nil, roll_by: nil, keep: nil )
|
262
291
|
# raise an error if a filename was not given
|
263
|
-
@fn =
|
292
|
+
@fn = filename
|
264
293
|
raise ArgumentError, 'no filename was given' if @fn.nil?
|
265
294
|
|
266
295
|
if (m = RGXP.match @fn)
|
267
296
|
@roll_by = ("#{m[2]}%d" == m[1]) ? :number : :date
|
268
297
|
else
|
269
|
-
age = opts.fetch(:age, nil)
|
270
|
-
size = opts.fetch(:size, nil)
|
271
|
-
|
272
298
|
@roll_by =
|
273
|
-
case
|
299
|
+
case roll_by
|
274
300
|
when 'number'; :number
|
275
301
|
when 'date'; :date
|
276
302
|
else
|
@@ -293,8 +319,7 @@ module Logging::Appenders
|
|
293
319
|
::Logging::Appenders::File.assert_valid_logfile(filename)
|
294
320
|
|
295
321
|
@roll = false
|
296
|
-
@keep =
|
297
|
-
@keep = Integer(keep) unless keep.nil?
|
322
|
+
@keep = keep.nil? ? nil : Integer(keep)
|
298
323
|
end
|
299
324
|
|
300
325
|
attr_reader :keep, :roll_by
|
@@ -347,7 +372,6 @@ module Logging::Appenders
|
|
347
372
|
files.delete copy_file
|
348
373
|
|
349
374
|
self.send "roll_by_#{roll_by}", files
|
350
|
-
|
351
375
|
nil
|
352
376
|
ensure
|
353
377
|
self.roll = false
|
@@ -188,7 +188,7 @@ module Logging::Appenders
|
|
188
188
|
end
|
189
189
|
return if message.empty?
|
190
190
|
|
191
|
-
@syslog.log(pri, '%s', message)
|
191
|
+
@mutex.synchronize { @syslog.log(pri, '%s', message) }
|
192
192
|
self
|
193
193
|
end
|
194
194
|
|
@@ -205,11 +205,10 @@ module Logging::Appenders
|
|
205
205
|
level = level.to_s.upcase
|
206
206
|
self.class.const_get level
|
207
207
|
else
|
208
|
-
raise ArgumentError, "
|
208
|
+
raise ArgumentError, "unknown level '#{level}'"
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
212
212
|
end # Syslog
|
213
213
|
end # Logging::Appenders
|
214
214
|
end # HAVE_SYSLOG
|
215
|
-
|
data/lib/logging/filter.rb
CHANGED
@@ -8,10 +8,17 @@ module Logging
|
|
8
8
|
# Otherwise the `allow` method should return `nil`.
|
9
9
|
class Filter
|
10
10
|
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
11
|
+
# Creates a new level filter that will pass all log events. Create a
|
12
|
+
# subclass and override the `allow` method to filter log events.
|
13
|
+
def initialize
|
14
|
+
::Logging.init unless ::Logging.initialized?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the event if it should be forwarded to the logging appender.
|
18
|
+
# Returns `nil` if the event should _not_ be forwarded to the logging
|
19
|
+
# appender. Subclasses should override this method and provide their own
|
20
|
+
# filtering semantics.
|
21
|
+
def allow(event)
|
15
22
|
event
|
16
23
|
end
|
17
24
|
end
|
@@ -4,8 +4,7 @@ module Logging
|
|
4
4
|
module Filters
|
5
5
|
|
6
6
|
# The `Level` filter class provides a simple level-based filtering mechanism
|
7
|
-
# that
|
8
|
-
# levels to log.
|
7
|
+
# that allows events whose log level matches a preconfigured list of values.
|
9
8
|
class Level < ::Logging::Filter
|
10
9
|
|
11
10
|
# Creates a new level filter that will only allow the given _levels_ to
|
@@ -15,15 +14,19 @@ module Logging
|
|
15
14
|
# Examples
|
16
15
|
# Logging::Filters::Level.new(:debug, :info)
|
17
16
|
#
|
18
|
-
def initialize(
|
19
|
-
|
20
|
-
|
17
|
+
def initialize(*levels)
|
18
|
+
super()
|
19
|
+
levels = levels.flatten.map {|level| ::Logging::level_num(level)}
|
20
|
+
@levels = Set.new(levels)
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
# Returns the event if it should be forwarded to the logging appender.
|
24
|
+
# Otherwise, `nil` is returned. The log event is allowed if the
|
25
|
+
# `event.level` matches one of the levels provided to the filter when it
|
26
|
+
# was constructred.
|
27
|
+
def allow(event)
|
24
28
|
@levels.include?(event.level) ? event : nil
|
25
29
|
end
|
26
|
-
|
27
30
|
end
|
28
31
|
end
|
29
32
|
end
|