threadedlogger 1.1.0 → 1.2.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.
- data/History.txt +5 -0
- data/Manifest.txt +5 -0
- data/README.txt +49 -15
- data/Rakefile +1 -1
- data/lib/threadedlogger.rb +3 -133
- data/lib/threadedlogger/core.rb +138 -0
- data/lib/threadedlogger/logger.rb +15 -0
- data/lib/threadedlogger/version.rb +5 -0
- data/test/minitest_helper.rb +16 -0
- data/test/test_clear.rb +11 -0
- data/test/test_inheritable.rb +67 -0
- data/test/test_logging.rb +3 -17
- data/test/test_methods.rb +4 -19
- data/test/test_shutdown.rb +10 -0
- data/test/test_threadedlogger.rb +7 -22
- data/threadedlogger.gemspec +0 -1
- metadata +12 -3
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -4,8 +4,13 @@ README.txt
|
|
4
4
|
LICENSE.txt
|
5
5
|
Rakefile
|
6
6
|
lib/threadedlogger.rb
|
7
|
+
lib/threadedlogger/core.rb
|
8
|
+
lib/threadedlogger/version.rb
|
9
|
+
lib/threadedlogger/logger.rb
|
7
10
|
test/minitest_helper.rb
|
8
11
|
test/test_logging.rb
|
9
12
|
test/test_methods.rb
|
10
13
|
test/test_threadedlogger.rb
|
14
|
+
test/test_shutdown.rb
|
15
|
+
test/test_clear.rb
|
11
16
|
threadedlogger.gemspec
|
data/README.txt
CHANGED
@@ -13,24 +13,46 @@ to ensure that multiple threads don't step on each other's toes.
|
|
13
13
|
|
14
14
|
## SYNOPSIS:
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
log
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
log.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
16
|
+
require 'threadedlogger'
|
17
|
+
|
18
|
+
log = ThreadedLogger.instance(logfname, 'daily', 'debug')
|
19
|
+
log.info('START')
|
20
|
+
...
|
21
|
+
log.debug('super important stuff')
|
22
|
+
...
|
23
|
+
log.info("STOP")
|
24
|
+
log.shutdown
|
25
|
+
|
26
|
+
or if you have multiple loggers
|
27
|
+
|
28
|
+
require 'threadedlogger'
|
29
|
+
|
30
|
+
class Log1 < ThreadedLogger
|
31
|
+
end
|
32
|
+
|
33
|
+
class Log2 < ThreadedLogger
|
34
|
+
end
|
35
|
+
|
36
|
+
log1 = Log1.instance(logfname1, 'daily', 'debug')
|
37
|
+
log2 = Log2.instance(logfname2, 'daily', 'debug')
|
38
|
+
log1.info('START')
|
39
|
+
...
|
40
|
+
log1.debug('super important stuff')
|
41
|
+
log2.info('something that only goes to the second log')
|
42
|
+
...
|
43
|
+
log1.info("STOP")
|
44
|
+
log2.shutdown
|
45
|
+
log1.shutdown
|
46
|
+
|
47
|
+
ThreadedLogger can be subclassed if you need to have multiple logs in a
|
48
|
+
program. Each subclass has one logger instance, accessed via the ::instance
|
31
49
|
class method. You can only provide arguments the first time - trying to
|
32
50
|
're-construct' the object will throw an ArgumentError.
|
33
51
|
|
52
|
+
If you only need one logger, you can just use ThreadedLogger without
|
53
|
+
subclassing it. Instances are stored keyed on class name, and the base
|
54
|
+
class is a valid key.
|
55
|
+
|
34
56
|
Under the covers, the dedicated thread uses the standard Ruby Logger
|
35
57
|
library. Refer to [Logger](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html)
|
36
58
|
for further detail.
|
@@ -46,9 +68,21 @@ instance method before your program exits. On a clean shutdown this should
|
|
46
68
|
happen automatically, but if you exit in a funky way it might not capture
|
47
69
|
the last message.
|
48
70
|
|
71
|
+
The catalog of instances can be cleared using the ::clear and ::clear_all
|
72
|
+
class methods. Each takes an optional boolean argument indicating whether
|
73
|
+
::shutdown should be called on any active loggers before clearing them.
|
74
|
+
|
49
75
|
This library also overrides Logger.LogDevice.add_log_header to prevent it
|
50
76
|
from putting a header line at the top of a logfile when it is first opened.
|
51
77
|
|
78
|
+
## CONSTRUCTION THREAD SAFETY
|
79
|
+
|
80
|
+
ThreadedLogger does not mutex construction, as the typical use case is for
|
81
|
+
the logger to be initialized for the first time outside of threaded code.
|
82
|
+
If you call the constructor for the first time from threaded code, you will
|
83
|
+
need to protect ::instance with some kind of synchronization to avoid a race
|
84
|
+
condition.
|
85
|
+
|
52
86
|
## LICENSE:
|
53
87
|
|
54
88
|
The MIT License (MIT)
|
data/Rakefile
CHANGED
data/lib/threadedlogger.rb
CHANGED
@@ -1,133 +1,3 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
|
4
|
-
class ThreadedLogger
|
5
|
-
|
6
|
-
VERSION = '1.1.0'
|
7
|
-
|
8
|
-
@@instance = nil
|
9
|
-
|
10
|
-
LOGLEVELS = {
|
11
|
-
'debug' => Logger::DEBUG,
|
12
|
-
'info' => Logger::INFO,
|
13
|
-
'warn' => Logger::WARN,
|
14
|
-
'error' => Logger::ERROR,
|
15
|
-
'fatal' => Logger::FATAL,
|
16
|
-
}
|
17
|
-
|
18
|
-
private_class_method :new
|
19
|
-
|
20
|
-
# create the logging methods
|
21
|
-
LOGLEVELS.each do |k,v|
|
22
|
-
log_method = k.to_sym
|
23
|
-
test_method = "#{k}?".to_sym
|
24
|
-
define_method(log_method) { |msg=nil|
|
25
|
-
enqueue(v, msg)
|
26
|
-
}
|
27
|
-
define_method(test_method) {
|
28
|
-
@log.send(test_method)
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
def ThreadedLogger.instance(*args)
|
33
|
-
|
34
|
-
if @@instance.nil?
|
35
|
-
@@instance = new(*args)
|
36
|
-
else
|
37
|
-
if ! args.empty?
|
38
|
-
raise ArgumentError, "instance already constructed"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
return @@instance
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def initialize(file, rotation = 'daily', level = 'info', formatter = nil)
|
47
|
-
|
48
|
-
if file.nil?
|
49
|
-
raise ArgumentError, "log file name is required"
|
50
|
-
end
|
51
|
-
|
52
|
-
# create a logger
|
53
|
-
@log = Logger.new(file, rotation)
|
54
|
-
|
55
|
-
# set the min threshold
|
56
|
-
send(:level=, level)
|
57
|
-
|
58
|
-
# apply a formatter if one was given
|
59
|
-
if ! formatter.nil?
|
60
|
-
@log.formatter = formatter
|
61
|
-
end
|
62
|
-
|
63
|
-
# set up a queue and spawn a thread to do the logging
|
64
|
-
@queue = Queue.new
|
65
|
-
@shutdown = nil
|
66
|
-
@t = Thread.new { runlogger }
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
def level=(level)
|
71
|
-
if LOGLEVELS.has_key?(level)
|
72
|
-
@log.level = LOGLEVELS[level]
|
73
|
-
else
|
74
|
-
raise ArgumentError, "invalid log level #{level}"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def shutdown
|
79
|
-
|
80
|
-
# stops new messages from being enqueued and tells thread
|
81
|
-
# to drain what's in the queue
|
82
|
-
@shutdown = true
|
83
|
-
@t.join
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
def enqueue(severity, msg=nil)
|
88
|
-
|
89
|
-
# don't enqueue if we're in shutdown
|
90
|
-
if( @shutdown )
|
91
|
-
return
|
92
|
-
end
|
93
|
-
|
94
|
-
# put the message on the queue
|
95
|
-
@queue.push( [severity, msg] )
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
def runlogger
|
102
|
-
|
103
|
-
# do blocking pops off the queue until the shutdown flag is set
|
104
|
-
while @shutdown.nil?
|
105
|
-
msg = @queue.pop(false)
|
106
|
-
@log.add(msg[0], msg[1])
|
107
|
-
end
|
108
|
-
|
109
|
-
# pop anything left on the queue off
|
110
|
-
while ! @queue.empty?
|
111
|
-
msg = @queue.pop(true)
|
112
|
-
@log.add(msg[0], msg[1])
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
# supress the "Logfile created at" header line that logger.rb provides
|
120
|
-
class Logger
|
121
|
-
|
122
|
-
private
|
123
|
-
|
124
|
-
class LogDevice
|
125
|
-
|
126
|
-
private
|
127
|
-
|
128
|
-
def add_log_header(file)
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
1
|
+
require 'threadedlogger/version'
|
2
|
+
require 'threadedlogger/core'
|
3
|
+
require 'threadedlogger/logger'
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
class ThreadedLogger
|
5
|
+
|
6
|
+
LOGLEVELS = {
|
7
|
+
'debug' => Logger::DEBUG,
|
8
|
+
'info' => Logger::INFO,
|
9
|
+
'warn' => Logger::WARN,
|
10
|
+
'error' => Logger::ERROR,
|
11
|
+
'fatal' => Logger::FATAL,
|
12
|
+
}
|
13
|
+
|
14
|
+
@@instances = nil
|
15
|
+
|
16
|
+
private_class_method :new
|
17
|
+
|
18
|
+
# create the logging methods
|
19
|
+
LOGLEVELS.each do |k,v|
|
20
|
+
log_method = k.to_sym
|
21
|
+
test_method = "#{k}?".to_sym
|
22
|
+
define_method(log_method) { |msg=nil|
|
23
|
+
enqueue(v, msg)
|
24
|
+
}
|
25
|
+
define_method(test_method) {
|
26
|
+
@log.send(test_method)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.instance(*args)
|
31
|
+
if @@instances[self].nil?
|
32
|
+
@@instances[self] = new(*args)
|
33
|
+
else
|
34
|
+
if ! args.empty?
|
35
|
+
raise ArgumentError, "instance for #{self} already constructed"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
return @@instances[self]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.clear(shutdown = false)
|
42
|
+
if shutdown and ! @@instances[self].nil?
|
43
|
+
@@instances[self].shutdown
|
44
|
+
end
|
45
|
+
@@instances[self] = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.clear_all(shutdown = false)
|
49
|
+
if shutdown and ! @@instances.nil?
|
50
|
+
@@instances.each_value do |obj|
|
51
|
+
if ! obj.nil?
|
52
|
+
obj.shutdown
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@@instances = Hash.new
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(file, rotation = 'daily', level = 'info', formatter = nil)
|
60
|
+
if file.nil?
|
61
|
+
raise ArgumentError, "log file name is required"
|
62
|
+
end
|
63
|
+
|
64
|
+
# create a logger
|
65
|
+
@log = Logger.new(file, rotation)
|
66
|
+
|
67
|
+
# set the min threshold
|
68
|
+
send(:level=, level)
|
69
|
+
|
70
|
+
# apply a formatter if one was given
|
71
|
+
if ! formatter.nil?
|
72
|
+
@log.formatter = formatter
|
73
|
+
end
|
74
|
+
|
75
|
+
# set up a queue and spawn a thread to do the logging
|
76
|
+
@queue = Queue.new
|
77
|
+
@shutdown = false
|
78
|
+
@t = Thread.new {
|
79
|
+
runlogger
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def level=(level)
|
84
|
+
if LOGLEVELS.has_key?(level)
|
85
|
+
@log.level = LOGLEVELS[level]
|
86
|
+
else
|
87
|
+
raise ArgumentError, "invalid log level #{level}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def shutdown
|
92
|
+
|
93
|
+
# stops new messages from being enqueued and tells thread
|
94
|
+
# to drain what's in the queue
|
95
|
+
if ! @shutdown
|
96
|
+
@shutdown = true
|
97
|
+
@queue.push(nil)
|
98
|
+
@t.join
|
99
|
+
@t = nil
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def enqueue(severity, msg=nil)
|
105
|
+
# don't enqueue if we're in shutdown
|
106
|
+
if( @shutdown )
|
107
|
+
return
|
108
|
+
end
|
109
|
+
|
110
|
+
# put the message on the queue
|
111
|
+
@queue.push( [severity, msg] )
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def runlogger
|
117
|
+
# do blocking pops off the queue until the shutdown flag is set
|
118
|
+
while ! @shutdown
|
119
|
+
msg = @queue.pop(false)
|
120
|
+
if ! msg.nil?
|
121
|
+
@log.add(msg[0], msg[1])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# pop anything left on the queue off
|
126
|
+
while ! @queue.empty?
|
127
|
+
msg = @queue.pop(true)
|
128
|
+
if ! msg.nil?
|
129
|
+
@log.add(msg[0], msg[1])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# create catalog of per-subclass instances
|
135
|
+
self.clear_all
|
136
|
+
|
137
|
+
end
|
138
|
+
|
data/test/minitest_helper.rb
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
require 'simplecov'
|
2
|
+
require 'simplecov-console'
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
5
|
+
SimpleCov::Formatter::HTMLFormatter,
|
6
|
+
SimpleCov::Formatter::Console,
|
7
|
+
]
|
2
8
|
SimpleCov.start do
|
3
9
|
add_filter '/vendor/'
|
4
10
|
add_filter '/test/'
|
5
11
|
end
|
12
|
+
|
13
|
+
require 'minitest/autorun'
|
14
|
+
require 'minitest/debugger' if ENV['DEBUG']
|
15
|
+
require 'threadedlogger'
|
16
|
+
|
17
|
+
class ThreadedLoggerTest < Minitest::Test
|
18
|
+
def teardown
|
19
|
+
ThreadedLogger.clear_all(true)
|
20
|
+
end
|
21
|
+
end
|
data/test/test_clear.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
require 'threadedlogger'
|
3
|
+
|
4
|
+
class TestClear < ThreadedLoggerTest
|
5
|
+
def test_clear_without_shutdown
|
6
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily')
|
7
|
+
ThreadedLogger.clear
|
8
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily')
|
9
|
+
ThreadedLogger.clear(true)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
require 'threadedlogger'
|
3
|
+
|
4
|
+
class OurLog1 < ThreadedLogger
|
5
|
+
end
|
6
|
+
|
7
|
+
class OurLog2 < ThreadedLogger
|
8
|
+
end
|
9
|
+
|
10
|
+
class TestInheritable < ThreadedLoggerTest
|
11
|
+
def test_construct_subclass
|
12
|
+
logger = OurLog1.instance('test/foo.log', 'daily')
|
13
|
+
assert_instance_of(OurLog1, logger)
|
14
|
+
logger.info 'foo'
|
15
|
+
File.exists?('test/foo.log')
|
16
|
+
logger.shutdown
|
17
|
+
end
|
18
|
+
def test_construct_two_subclasses
|
19
|
+
logger1 = OurLog1.instance('test/foo.log', 'daily')
|
20
|
+
logger2 = OurLog2.instance('test/bar.log', 'daily')
|
21
|
+
assert_instance_of(OurLog1, logger1)
|
22
|
+
assert_instance_of(OurLog2, logger2)
|
23
|
+
logger1.info 'foo'
|
24
|
+
logger2.info 'bar'
|
25
|
+
File.exists?('test/foo.log')
|
26
|
+
File.exists?('test/bar.log')
|
27
|
+
logger1.shutdown
|
28
|
+
logger2.shutdown
|
29
|
+
end
|
30
|
+
def test_reconstruct_subclass
|
31
|
+
logger1 = OurLog1.instance('test/foo.log', 'daily')
|
32
|
+
logger2 = OurLog2.instance('test/bar.log', 'daily')
|
33
|
+
assert_instance_of(OurLog1, logger1)
|
34
|
+
assert_instance_of(OurLog2, logger2)
|
35
|
+
assert_raises(ArgumentError) {
|
36
|
+
OurLog1.instance('test/foo.log', 'daily')
|
37
|
+
}
|
38
|
+
assert_raises(ArgumentError) {
|
39
|
+
OurLog2.instance('test/bar.log', 'daily')
|
40
|
+
}
|
41
|
+
end
|
42
|
+
def test_clear
|
43
|
+
logger1 = OurLog1.instance('test/foo.log', 'daily')
|
44
|
+
logger2 = OurLog2.instance('test/bar.log', 'daily')
|
45
|
+
assert_instance_of(OurLog1, logger1)
|
46
|
+
assert_instance_of(OurLog2, logger2)
|
47
|
+
assert_raises(ArgumentError) {
|
48
|
+
OurLog1.instance('test/foo.log', 'daily')
|
49
|
+
}
|
50
|
+
OurLog1.clear
|
51
|
+
logger2b = OurLog2.instance
|
52
|
+
assert_instance_of(OurLog2, logger2b)
|
53
|
+
assert_equal logger2b, logger2
|
54
|
+
logger1 = OurLog1.instance('test/foo.log', 'daily')
|
55
|
+
assert_instance_of(OurLog1, logger1)
|
56
|
+
end
|
57
|
+
def test_clear_all
|
58
|
+
logger1 = OurLog1.instance('test/foo.log', 'daily')
|
59
|
+
assert_instance_of(OurLog1, logger1)
|
60
|
+
assert_raises(ArgumentError) {
|
61
|
+
OurLog1.instance('test/foo.log', 'daily')
|
62
|
+
}
|
63
|
+
ThreadedLogger.clear_all
|
64
|
+
logger1 = OurLog1.instance('test/foo.log', 'daily')
|
65
|
+
assert_instance_of(OurLog1, logger1)
|
66
|
+
end
|
67
|
+
end
|
data/test/test_logging.rb
CHANGED
@@ -1,25 +1,11 @@
|
|
1
1
|
require 'minitest_helper'
|
2
|
-
require 'minitest/autorun'
|
3
2
|
require 'threadedlogger'
|
4
|
-
require 'fakefs'
|
5
3
|
|
6
|
-
class
|
7
|
-
def ThreadedLogger.clear
|
8
|
-
if ! @@instance.nil?
|
9
|
-
@@instance.shutdown
|
10
|
-
@@instance = nil
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class TestLogging < Minitest::Test
|
16
|
-
def setup
|
17
|
-
ThreadedLogger.clear
|
18
|
-
end
|
4
|
+
class TestLogging < ThreadedLoggerTest
|
19
5
|
def test_logging
|
20
|
-
logger = ThreadedLogger.instance('foo.log', 'daily')
|
6
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily')
|
21
7
|
logger.info 'foo'
|
22
|
-
File.exists?('foo.log')
|
8
|
+
File.exists?('test/foo.log')
|
23
9
|
logger.shutdown
|
24
10
|
end
|
25
11
|
end
|
data/test/test_methods.rb
CHANGED
@@ -1,23 +1,8 @@
|
|
1
1
|
require 'minitest_helper'
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'threadedlogger'
|
4
|
-
require 'fakefs'
|
5
2
|
|
6
|
-
class
|
7
|
-
def ThreadedLogger.clear
|
8
|
-
if ! @@instance.nil?
|
9
|
-
@@instance.shutdown
|
10
|
-
@@instance = nil
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class TestMethods < Minitest::Test
|
16
|
-
def setup
|
17
|
-
ThreadedLogger.clear
|
18
|
-
end
|
3
|
+
class TestMethods < ThreadedLoggerTest
|
19
4
|
def test_levels
|
20
|
-
logger = ThreadedLogger.instance('test/
|
5
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily')
|
21
6
|
assert_instance_of ThreadedLogger, logger, "constructor works with 2 args"
|
22
7
|
%w(debug info warn error fatal).each do |level|
|
23
8
|
assert_respond_to(logger, level.to_sym, "logger responds to level #{level}")
|
@@ -27,14 +12,14 @@ class TestMethods < Minitest::Test
|
|
27
12
|
}
|
28
13
|
end
|
29
14
|
def test_level_predicates
|
30
|
-
logger = ThreadedLogger.instance('test/
|
15
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily', 'info')
|
31
16
|
assert_instance_of ThreadedLogger, logger, "constructor works with 3 args"
|
32
17
|
%w(debug info warn error fatal).each do |level|
|
33
18
|
assert_respond_to(logger, "#{level}?".to_sym, "logger responds to predicate #{level}?")
|
34
19
|
end
|
35
20
|
end
|
36
21
|
def test_setlevel
|
37
|
-
logger = ThreadedLogger.instance('test/
|
22
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily', 'info')
|
38
23
|
assert_instance_of ThreadedLogger, logger, "constructor works with 3 args"
|
39
24
|
assert_equal(false, logger.debug?, 'debug is not on when contstructed at level info')
|
40
25
|
logger.level = 'debug'
|
data/test/test_threadedlogger.rb
CHANGED
@@ -1,31 +1,16 @@
|
|
1
1
|
require 'minitest_helper'
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'threadedlogger'
|
4
|
-
require 'fakefs'
|
5
2
|
|
6
|
-
class
|
7
|
-
def ThreadedLogger.clear
|
8
|
-
if ! @@instance.nil?
|
9
|
-
@@instance.shutdown
|
10
|
-
@@instance = nil
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class TestThreadedLogger < Minitest::Test
|
16
|
-
def setup
|
17
|
-
ThreadedLogger.clear
|
18
|
-
end
|
3
|
+
class TestThreadedLogger < ThreadedLoggerTest
|
19
4
|
def test_constructor
|
20
|
-
logger = ThreadedLogger.instance('test/
|
5
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily')
|
21
6
|
assert_instance_of ThreadedLogger, logger, "constructor works with 2 args"
|
22
7
|
end
|
23
8
|
def test_constructor_with_level
|
24
|
-
logger = ThreadedLogger.instance('test/
|
9
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily', 'info')
|
25
10
|
assert_instance_of ThreadedLogger, logger, "constructor works with 3 args"
|
26
11
|
end
|
27
12
|
def test_constructor_with_level_and_formatter
|
28
|
-
logger = ThreadedLogger.instance('test/
|
13
|
+
logger = ThreadedLogger.instance('test/foo.log', 'daily', 'info', proc { |l| l } )
|
29
14
|
assert_instance_of ThreadedLogger, logger, "constructor works with 4 args"
|
30
15
|
end
|
31
16
|
def test_constructor_noargs
|
@@ -34,14 +19,14 @@ class TestThreadedLogger < Minitest::Test
|
|
34
19
|
end
|
35
20
|
end
|
36
21
|
def test_singleton
|
37
|
-
loggera = ThreadedLogger.instance('test/
|
22
|
+
loggera = ThreadedLogger.instance('test/foo.log')
|
38
23
|
loggerb = ThreadedLogger.instance
|
39
24
|
assert_same loggera, loggerb, "two instances are the same object"
|
40
25
|
end
|
41
26
|
def test_construct_twice
|
42
27
|
assert_raises ArgumentError, "cannot call instance a second time with args" do
|
43
|
-
ThreadedLogger.instance('test/
|
44
|
-
ThreadedLogger.instance('test/
|
28
|
+
ThreadedLogger.instance('test/foo.log')
|
29
|
+
ThreadedLogger.instance('test/bar.log')
|
45
30
|
end
|
46
31
|
end
|
47
32
|
end
|
data/threadedlogger.gemspec
CHANGED
@@ -4,7 +4,6 @@ require 'threadedlogger'
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'threadedlogger'
|
6
6
|
s.version = ThreadedLogger::VERSION
|
7
|
-
s.date = '2013-03-23'
|
8
7
|
s.summary = 'Simple logging library with a dedicated logging thread'
|
9
8
|
s.homepage = 'https://github.com/jf647/ThreadedLogger'
|
10
9
|
s.authors = ['James FitzGibbon']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: threadedlogger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -63,11 +63,17 @@ files:
|
|
63
63
|
- LICENSE.txt
|
64
64
|
- Rakefile
|
65
65
|
- lib/threadedlogger.rb
|
66
|
+
- lib/threadedlogger/core.rb
|
67
|
+
- lib/threadedlogger/version.rb
|
68
|
+
- lib/threadedlogger/logger.rb
|
66
69
|
- test/minitest_helper.rb
|
67
70
|
- test/test_logging.rb
|
68
71
|
- test/test_methods.rb
|
69
72
|
- test/test_threadedlogger.rb
|
73
|
+
- test/test_shutdown.rb
|
74
|
+
- test/test_clear.rb
|
70
75
|
- threadedlogger.gemspec
|
76
|
+
- test/test_inheritable.rb
|
71
77
|
- .gemtest
|
72
78
|
homepage: https://github.com/jf647/ThreadedLogger
|
73
79
|
licenses:
|
@@ -86,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
92
|
version: '0'
|
87
93
|
segments:
|
88
94
|
- 0
|
89
|
-
hash: -
|
95
|
+
hash: -484491560591714406
|
90
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
97
|
none: false
|
92
98
|
requirements:
|
@@ -95,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
101
|
version: '0'
|
96
102
|
segments:
|
97
103
|
- 0
|
98
|
-
hash: -
|
104
|
+
hash: -484491560591714406
|
99
105
|
requirements: []
|
100
106
|
rubyforge_project: threadedlogger
|
101
107
|
rubygems_version: 1.8.23
|
@@ -104,6 +110,9 @@ specification_version: 3
|
|
104
110
|
summary: ThreadedLogger runs a dedicated logging thread around Ruby's Logger library
|
105
111
|
to ensure that multiple threads don't step on each other's toes.
|
106
112
|
test_files:
|
113
|
+
- test/test_clear.rb
|
114
|
+
- test/test_inheritable.rb
|
107
115
|
- test/test_logging.rb
|
108
116
|
- test/test_methods.rb
|
117
|
+
- test/test_shutdown.rb
|
109
118
|
- test/test_threadedlogger.rb
|