logging 1.5.2 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == 1.6.0 / 2011-08-
2
+
3
+ Enhancements
4
+ - Adding periodic flushing of buffered messages [issue #10]
5
+ - Accessor for a logger's appenders [issue #9]
6
+ - Better support for capturing log messages in RSpec version 1 & 2
7
+
1
8
  == 1.5.2 / 2011-07-07
2
9
 
3
10
  Bug Fixes
@@ -26,6 +26,47 @@ module Logging::Appenders
26
26
  #
27
27
  attr_reader :auto_flushing
28
28
 
29
+ # When set, the buffer will be flushed at regular intervals defined by the
30
+ # flush_period.
31
+ #
32
+ attr_reader :flush_period
33
+
34
+ # Setup the message buffer and other variables for automatically and
35
+ # periodically flushing the buffer.
36
+ #
37
+ def initialize( *args, &block )
38
+ @buffer = []
39
+ @immediate = []
40
+ @auto_flushing = 1
41
+ @flush_period = @periodic_flusher = nil
42
+
43
+ super(*args, &block)
44
+ end
45
+
46
+ # Close the message buffer by flusing all log events to the appender. If a
47
+ # periodic flusher thread is running, shut it down and allow it to exit.
48
+ #
49
+ def close( *args )
50
+ flush
51
+
52
+ if @periodic_flusher
53
+ @periodic_flusher.stop
54
+ @periodic_flusher = nil
55
+ Thread.pass
56
+ end
57
+
58
+ super(*args)
59
+ end
60
+
61
+ # Reopen the connection to the underlying logging destination. In addtion
62
+ # if the appender is configured for periodic flushing, then the flushing
63
+ # thread will be stopped and restarted.
64
+ #
65
+ def reopen
66
+ _setup_periodic_flusher
67
+ super
68
+ end
69
+
29
70
  # Call +flush+ to force an appender to write out any buffered log events.
30
71
  # Similar to IO#flush, so use in a similar fashion.
31
72
  #
@@ -42,7 +83,7 @@ module Logging::Appenders
42
83
  self
43
84
  end
44
85
 
45
- # Configure the levels that will trigger and immediate flush of the
86
+ # Configure the levels that will trigger an immediate flush of the
46
87
  # logging buffer. When a log event of the given level is seen, the
47
88
  # buffer will be flushed immediately. Only the levels explicitly given
48
89
  # in this assignment will flush the buffer; if an "error" message is
@@ -59,7 +100,6 @@ module Logging::Appenders
59
100
  # immediate_at = "warn, error"
60
101
  #
61
102
  def immediate_at=( level )
62
- @immediate ||= []
63
103
  @immediate.clear
64
104
 
65
105
  # get the immediate levels -- no buffering occurs at these levels, and
@@ -77,8 +117,8 @@ module Logging::Appenders
77
117
  end
78
118
  end
79
119
 
80
- # Configure the auto-flushing period. Auto-flushing is used to flush the
81
- # contents of the logging buffer to the logging destination
120
+ # Configure the auto-flushing threshold. Auto-flushing is used to flush
121
+ # the contents of the logging buffer to the logging destination
82
122
  # automatically when the buffer reaches a certain threshold.
83
123
  #
84
124
  # By default, the auto-flushing will be configured to flush after each
@@ -109,12 +149,50 @@ module Logging::Appenders
109
149
  "unrecognized auto_flushing period: #{period.inspect}"
110
150
  end
111
151
 
112
- if @auto_flushing < 0
152
+ if @auto_flushing <= 0
113
153
  raise ArgumentError,
114
- "auto_flushing period cannot be negative: #{period.inspect}"
154
+ "auto_flushing period must be greater than zero: #{period.inspect}"
115
155
  end
156
+
157
+ @auto_flushing = DEFAULT_BUFFER_SIZE if @flush_period and @auto_flushing <= 1
116
158
  end
117
159
 
160
+ # Configure periodic flushing of the message buffer. Periodic flushing is
161
+ # used to flush the contents of the logging buffer at some regular
162
+ # interval. Periodic flushing is disabled by default.
163
+ #
164
+ # When enabling periodic flushing the flush period should be set using one
165
+ # of the following formats: "HH:MM:SS" or seconds as an numeric or string.
166
+ #
167
+ # "01:00:00" : every hour
168
+ # "00:05:00" : every 5 minutes
169
+ # "00:00:30" : every 30 seconds
170
+ # 60 : every 60 seconds (1 minute)
171
+ # "120" : every 120 seconds (2 minutes)
172
+ #
173
+ # For the periodic flusher to work properly, the auto-flushing threshold
174
+ # will be set to the default value of 500. The auto-flushing threshold can
175
+ # be changed, but it must be greater than 1.
176
+ #
177
+ # To disable the periodic flusher simply set the flush period to +nil+.
178
+ # The auto-flushing threshold will not be changed; it must be disabled
179
+ # manually if so desired.
180
+ #
181
+ def flush_period=( period )
182
+ period =
183
+ case period
184
+ when Integer, Float, nil; period
185
+ when String;
186
+ num = _parse_hours_minutes_seconds(period) || _parse_numeric(period)
187
+ num = ArgumentError.new("unrecognized flush period: #{period.inspect}") if num.nil?
188
+ num
189
+ else ArgumentError.new("unrecognized flush period: #{period.inspect}") end
190
+
191
+ raise period if Exception === period
192
+ @flush_period = period
193
+
194
+ _setup_periodic_flusher
195
+ end
118
196
 
119
197
  protected
120
198
 
@@ -127,9 +205,9 @@ module Logging::Appenders
127
205
  def configure_buffering( opts )
128
206
  ::Logging.init unless ::Logging.const_defined? :MAX_LEVEL_LENGTH
129
207
 
130
- @buffer = []
131
208
  self.immediate_at = opts.getopt(:immediate_at, '')
132
209
  self.auto_flushing = opts.getopt(:auto_flushing, true)
210
+ self.flush_period = opts.getopt(:flush_period, nil)
133
211
  end
134
212
 
135
213
  # Returns true if the _event_ level matches one of the configured
@@ -151,7 +229,7 @@ module Logging::Appenders
151
229
  # formatted using the layout given to the appender when it was created.
152
230
  #
153
231
  # The _event_ will be formatted and then buffered until the
154
- # "auto_flushing" level has been reached. At thsi time the canonical_write
232
+ # "auto_flushing" level has been reached. At this time the canonical_write
155
233
  # method will be used to log all events stored in the buffer.
156
234
  #
157
235
  def write( event )
@@ -163,12 +241,155 @@ module Logging::Appenders
163
241
  canonical_write(str)
164
242
  else
165
243
  sync { @buffer << str }
244
+ @periodic_flusher.signal if @periodic_flusher
166
245
  flush if @buffer.length >= @auto_flushing || immediate?(event)
167
246
  end
168
247
 
169
248
  self
170
249
  end
171
250
 
251
+ # Attempt to parse an hours/minutes/seconds value from the string and return
252
+ # an integer number of seconds.
253
+ #
254
+ # _parse_hours_minutes_seconds("14:12:42") #=> 51162
255
+ # _parse_hours_minutes_seconds("foo") #=> nil
256
+ #
257
+ def _parse_hours_minutes_seconds( str )
258
+ m = %r/^\s*(\d{2,}):(\d{2}):(\d{2}(?:\.\d+)?)\s*$/.match(str)
259
+ return if m.nil?
260
+
261
+ (3600 * m[1].to_i) + (60 * m[2].to_i) + (m[3].to_f)
262
+ end
263
+
264
+ # Convert the string into a numeric value. If the string does not
265
+ # represent a valid Integer or Float then +nil+ is returned.
266
+ #
267
+ # _parse_numeric("10") #=> 10
268
+ # _parse_numeric("1.0") #=> 1.0
269
+ # _parse_numeric("foo") #=> nil
270
+ #
271
+ def _parse_numeric( str )
272
+ Integer(str) rescue (Float(str) rescue nil)
273
+ end
274
+
275
+ # Using the flush_period, create a new PeriodicFlusher attached to this
276
+ # appender. If the flush_period is nil, then no action will be taken. If a
277
+ # PeriodicFlusher alreayd exists, it will be stopped and a new one will be
278
+ # created.
279
+ #
280
+ def _setup_periodic_flusher
281
+ # stop and remove any existing periodic flusher instance
282
+ if @periodic_flusher
283
+ @periodic_flusher.stop
284
+ @periodic_flusher = nil
285
+ Thread.pass
286
+ end
287
+
288
+ # create a new periodic flusher if we have a valid flush period
289
+ if @flush_period
290
+ @auto_flushing = DEFAULT_BUFFER_SIZE unless @auto_flushing > 1
291
+ @periodic_flusher = PeriodicFlusher.new(self, @flush_period)
292
+ @periodic_flusher.start
293
+ end
294
+ end
295
+
296
+ # :stopdoc:
297
+
298
+ # The PeriodicFlusher contains an internal run loop that will periodically
299
+ # wake up and flush any log events contained in the message buffer of the
300
+ # owning appender instance. The PeriodicFlusher relies on a _signal_ from
301
+ # the appender in order to wakeup and perform the flush on the appender.
302
+ #
303
+ class PeriodicFlusher
304
+
305
+ # Create a new PeriodicFlusher instance that will call the +flush+
306
+ # method on the given _appender_. The +flush+ method will be called
307
+ # every _period_ seconds, but only when the message buffer is non-empty.
308
+ #
309
+ def initialize( appender, period )
310
+ @appender = appender
311
+ @period = period
312
+
313
+ @mutex = Mutex.new
314
+ @cv = ConditionVariable.new
315
+ @thread = nil
316
+ @waiting = nil
317
+ @signaled = false
318
+ end
319
+
320
+ # Start the periodic flusher's internal run loop.
321
+ #
322
+ def start
323
+ return if @thread
324
+
325
+ @thread = Thread.new { loop {
326
+ begin
327
+ break if Thread.current[:stop]
328
+ _wait_for_signal
329
+ sleep @period unless Thread.current[:stop]
330
+ @appender.flush
331
+ rescue => err
332
+ ::Logging.log_internal {"PeriodicFlusher for appender #{@appender.inspect} encountered an error"}
333
+ ::Logging.log_internal(-2) {err}
334
+ end
335
+ }; @thread = nil }
336
+
337
+ self
338
+ end
339
+
340
+ # Stop the periodic flusher's internal run loop.
341
+ #
342
+ def stop
343
+ return if @thread.nil?
344
+ @thread[:stop] = true
345
+ signal if waiting?
346
+ self
347
+ end
348
+
349
+ # Signal the periodic flusher. This will wake up the run loop if it is
350
+ # currently waiting for something to do. If the signal method is never
351
+ # called, the periodic flusher will never perform the flush action on
352
+ # the appender.
353
+ #
354
+ def signal
355
+ return if Thread.current == @thread # don't signal ourselves
356
+ return if @signaled # don't need to signal again
357
+
358
+ @mutex.synchronize {
359
+ @signaled = true
360
+ @cv.signal
361
+ }
362
+ self
363
+ end
364
+
365
+ # Returns +true+ if the flusher is waiting for a signal. Returns +false+
366
+ # if the flusher is somewhere in the processing loop.
367
+ #
368
+ def waiting?
369
+ @waiting
370
+ end
371
+
372
+ private
373
+
374
+ def _wait_for_signal
375
+ @mutex.synchronize {
376
+ begin
377
+ # wait on the condition variable only if we have NOT been signaled
378
+ unless @signaled
379
+ @waiting = true
380
+ @cv.wait(@mutex)
381
+ @waiting = false
382
+ end
383
+ ensure
384
+ @signaled = false
385
+ end
386
+ }
387
+ ensure
388
+ @waiting = false
389
+ end
390
+ end # class PeriodicFlusher
391
+ # :startdoc:
392
+
172
393
  end # module Buffering
173
394
  end # module Logging::Appenders
174
395
 
@@ -64,9 +64,9 @@ module Logging::Appenders
64
64
  flush
65
65
  @io.close rescue nil
66
66
  end
67
- @closed = false
68
67
  @io = ::File.new(@fn, @mode)
69
68
  }
69
+ super
70
70
  self
71
71
  end
72
72
 
@@ -7,6 +7,12 @@ module Logging::Appenders
7
7
  class IO < ::Logging::Appender
8
8
  include Buffering
9
9
 
10
+ # The method that will be used to close the IO stream. Defaults to :close
11
+ # but can be :close_read, :close_write or nil. When nil, the IO stream
12
+ # will not be closed when the appender's close method is called.
13
+ #
14
+ attr_accessor :close_method
15
+
10
16
  # call-seq:
11
17
  # IO.new( name, io )
12
18
  # IO.new( name, io, :layout => layout )
@@ -21,9 +27,10 @@ module Logging::Appenders
21
27
 
22
28
  @io = io
23
29
  @io.sync = true if io.respond_to? :sync= # syswrite complains if the IO stream is buffered
30
+ @close_method = :close
24
31
 
25
- configure_buffering(opts)
26
32
  super(name, opts)
33
+ configure_buffering(opts)
27
34
  end
28
35
 
29
36
  # call-seq:
@@ -37,8 +44,11 @@ module Logging::Appenders
37
44
  def close( *args )
38
45
  return self if @io.nil?
39
46
  super
47
+
40
48
  io, @io = @io, nil
41
- io.close unless [STDIN, STDERR, STDOUT].include?(io)
49
+ unless [STDIN, STDERR, STDOUT].include?(io)
50
+ io.send(@close_method) if @close_method and io.respond_to? @close_method
51
+ end
42
52
  rescue IOError => err
43
53
  ensure
44
54
  return self
@@ -170,9 +170,9 @@ module Logging::Appenders
170
170
  flush
171
171
  @io.close rescue nil
172
172
  end
173
- @closed = false
174
173
  @io = ::File.new(@fn, 'a+')
175
174
  }
175
+ super
176
176
  self
177
177
  end
178
178
 
@@ -22,11 +22,29 @@ module Logging::Appenders
22
22
  super(name, @sio, opts)
23
23
  end
24
24
 
25
+ # Reopen the underlying StringIO instance. If the instance is currently
26
+ # closed then it will be opened. If the instance is currently open then it
27
+ # will be closed and immediately opened.
28
+ #
29
+ def reopen
30
+ @mutex.synchronize {
31
+ if defined? @io and @io
32
+ flush
33
+ @io.close rescue nil
34
+ end
35
+ @io = @sio = StringIO.new
36
+ @sio.extend IoToS
37
+ @pos = 0
38
+ }
39
+ super
40
+ self
41
+ end
42
+
25
43
  # Clears the internal StringIO instance. All log messages are removed
26
44
  # from the buffer.
27
45
  #
28
46
  def clear
29
- sync {
47
+ @mutex.synchronize {
30
48
  @pos = 0
31
49
  @sio.seek 0
32
50
  @sio.truncate 0
@@ -156,8 +156,8 @@ module Logging::Appenders
156
156
  @syslog.close
157
157
  end
158
158
  @syslog = ::Syslog.open(@ident, @logopt, @facility)
159
- @closed = false
160
159
  }
160
+ super
161
161
  self
162
162
  end
163
163
 
@@ -307,6 +307,12 @@ module Logging
307
307
  self.level
308
308
  end
309
309
 
310
+ # Returns the list of appenders.
311
+ #
312
+ def appenders
313
+ @appenders.dup
314
+ end
315
+
310
316
  # call-seq:
311
317
  # appenders = app
312
318
  #
@@ -0,0 +1,39 @@
1
+
2
+ module RSpec
3
+ module LoggingHelper
4
+
5
+ # Capture log messages from the Logging framework and make them
6
+ # available via a @log_output instance variable. The @log_output
7
+ # supports a readline method to access the log messags.
8
+ #
9
+ def capture_log_messages( opts = {} )
10
+ from = opts.getopt(:from, 'root')
11
+ to = opts.getopt(:to, '__rspec__')
12
+ exclusive = opts.getopt(:exclusive, true)
13
+
14
+ appender = Logging::Appenders[to] || Logging::Appenders::StringIo.new(to)
15
+ logger = Logging::Logger[from]
16
+ if exclusive
17
+ logger.appenders = appender
18
+ else
19
+ logger.add_appenders(appender)
20
+ end
21
+
22
+ before(:all) do
23
+ @log_output = Logging::Appenders[to]
24
+ end
25
+
26
+ before(:each) do
27
+ @log_output.reset
28
+ end
29
+ end
30
+
31
+ end # module LoggingHelper
32
+ end # module RSpec
33
+
34
+ if defined? RSpec::Core::Configuration
35
+ class RSpec::Core::Configuration
36
+ include RSpec::LoggingHelper
37
+ end
38
+ end
39
+
@@ -1,34 +1,10 @@
1
1
 
2
- module Spec
3
- module LoggingHelper
2
+ require File.expand_path('../../rspec/logging_helper', __FILE__)
3
+ Spec::LoggingHelper = RSpec::LoggingHelper
4
4
 
5
- # Capture log messages from the Logging framework and make them
6
- # available via a @log_output instance variable. The @log_output
7
- # supports a readline method to access the log messags.
8
- #
9
- def capture_log_messages( opts = {} )
10
- from = opts.getopt(:from, 'root')
11
- to = opts.getopt(:to, '__rspec__')
12
- exclusive = opts.getopt(:exclusive, true)
5
+ if defined? Spec::Runner::Configuration
6
+ class Spec::Runner::Configuration
7
+ include Spec::LoggingHelper
8
+ end
9
+ end
13
10
 
14
- appender = Logging::Appenders[to] || Logging::Appenders::StringIo.new(to)
15
- logger = Logging::Logger[from]
16
- if exclusive
17
- logger.appenders = appender
18
- else
19
- logger.add_appenders(appender)
20
- end
21
-
22
- before(:all) do
23
- @log_output = Logging::Appenders[to]
24
- end
25
-
26
- before(:each) do
27
- @log_output.reset
28
- end
29
- end
30
-
31
- end # module LoggingHelper
32
- end # module Spec
33
-
34
- # EOF
@@ -74,6 +74,9 @@ module TestAppenders
74
74
  assert_raise(ArgumentError) {
75
75
  @appender.auto_flushing = -1
76
76
  }
77
+
78
+ @appender.auto_flushing = 0
79
+ assert_equal Logging::Appenders::Buffering::DEFAULT_BUFFER_SIZE, @appender.auto_flushing
77
80
  end
78
81
 
79
82
  def test_close
@@ -0,0 +1,140 @@
1
+
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
+
4
+ module TestLogging
5
+ module TestAppenders
6
+
7
+ class TestPeriodicFlushing < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def setup
11
+ super
12
+ @appender = Logging.appenders.string_io(
13
+ 'test_appender', :flush_period => 2
14
+ )
15
+ @appender.clear
16
+ @sio = @appender.sio
17
+ @levels = Logging::LEVELS
18
+ begin readline rescue EOFError end
19
+ Thread.pass # give the flusher thread a moment to start
20
+ end
21
+
22
+ def teardown
23
+ @appender.close
24
+ @appender = nil
25
+ super
26
+ end
27
+
28
+ def test_flush_period_set
29
+ assert_equal 2, @appender.flush_period
30
+ assert_equal Logging::Appenders::Buffering::DEFAULT_BUFFER_SIZE, @appender.auto_flushing
31
+
32
+ @appender.flush_period = '01:30:45'
33
+ assert_equal 5445, @appender.flush_period
34
+
35
+ @appender.flush_period = '245'
36
+ assert_equal 245, @appender.flush_period
37
+
38
+ @appender.auto_flushing = true
39
+ assert_equal Logging::Appenders::Buffering::DEFAULT_BUFFER_SIZE, @appender.auto_flushing
40
+
41
+ @appender.auto_flushing = 200
42
+ assert_equal 200, @appender.auto_flushing
43
+ end
44
+
45
+ def test_periodic_flusher_running
46
+ flusher = @appender.instance_variable_get(:@periodic_flusher)
47
+
48
+ assert_instance_of Logging::Appenders::Buffering::PeriodicFlusher, flusher
49
+ assert flusher.waiting?, 'the periodic flusher should be waiting for a signal'
50
+ end
51
+
52
+ def test_append
53
+ event = Logging::LogEvent.new('TestLogger', @levels['warn'],
54
+ [1, 2, 3, 4], false)
55
+ @appender.append event
56
+ @appender.append event
57
+ event.level = @levels['debug']
58
+ event.data = 'the big log message'
59
+ @appender.append event
60
+
61
+ assert_nil(readline)
62
+ sleep 3
63
+
64
+ assert_equal " WARN TestLogger : <Array> #{[1, 2, 3, 4]}\n", readline
65
+ assert_equal " WARN TestLogger : <Array> #{[1, 2, 3, 4]}\n", readline
66
+ assert_equal "DEBUG TestLogger : the big log message\n", readline
67
+ assert_nil(readline)
68
+
69
+ @appender.close
70
+ assert_raise(RuntimeError) {@appender.append event}
71
+ end
72
+
73
+ def test_flush_on_close
74
+ assert_equal false, @sio.closed?
75
+ assert_equal false, @appender.closed?
76
+
77
+ event = Logging::LogEvent.new('TestLogger', @levels['warn'],
78
+ [1, 2, 3, 4], false)
79
+
80
+ @appender.flush_period = "24:00:00"
81
+ @appender.append event
82
+ event.level = @levels['debug']
83
+ event.data = 'the big log message'
84
+ @appender.append event
85
+
86
+ assert_nil(readline)
87
+
88
+ @appender.close_method = :close_write
89
+ @appender.close
90
+ assert_equal false, @sio.closed?
91
+ assert_equal true, @appender.closed?
92
+
93
+ assert_equal " WARN TestLogger : <Array> #{[1, 2, 3, 4]}\n", readline
94
+ assert_equal "DEBUG TestLogger : the big log message\n", readline
95
+ assert_nil(readline)
96
+
97
+ @sio.close
98
+ assert_equal true, @sio.closed?
99
+ end
100
+
101
+ def test_auto_flushing
102
+ @appender.auto_flushing = 3
103
+
104
+ event = Logging::LogEvent.new('TestLogger', @levels['warn'],
105
+ [1, 2, 3, 4], false)
106
+
107
+ @appender.append event
108
+ @appender.append event
109
+ event.level = @levels['debug']
110
+ event.data = 'the big log message'
111
+ @appender.append event
112
+ event.level = @levels['info']
113
+ event.data = 'just FYI'
114
+ @appender.append event
115
+ event.level = @levels['warn']
116
+ event.data = 'this is your last warning!'
117
+ @appender.append event
118
+
119
+ assert_equal " WARN TestLogger : <Array> #{[1, 2, 3, 4]}\n", readline
120
+ assert_equal " WARN TestLogger : <Array> #{[1, 2, 3, 4]}\n", readline
121
+ assert_equal "DEBUG TestLogger : the big log message\n", readline
122
+
123
+ assert_nil(readline)
124
+ sleep 3
125
+
126
+ assert_equal " INFO TestLogger : just FYI\n", readline
127
+ assert_equal " WARN TestLogger : this is your last warning!\n", readline
128
+ assert_nil(readline)
129
+ end
130
+
131
+ private
132
+ def readline
133
+ @appender.readline
134
+ end
135
+
136
+ end # class TestPeriodicFlushing
137
+
138
+ end # module TestAppenders
139
+ end # module TestLogging
140
+
@@ -0,0 +1,36 @@
1
+
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
+
4
+ module TestLogging
5
+ module TestAppenders
6
+
7
+ class TestStringIO < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def setup
11
+ super
12
+
13
+ @appender = Logging.appenders.string_io('test_appender')
14
+ @sio = @appender.sio
15
+ @levels = Logging::LEVELS
16
+ end
17
+
18
+ def teardown
19
+ @appender.close
20
+ @appender = nil
21
+ super
22
+ end
23
+
24
+ def test_reopen
25
+ assert_equal @sio.object_id, @appender.sio.object_id
26
+
27
+ @appender.reopen
28
+ assert @sio.closed?, 'StringIO instance is closed'
29
+ assert_not_equal @sio.object_id, @appender.sio.object_id
30
+ end
31
+
32
+ end # class TestStringIO
33
+
34
+ end # module TestAppenders
35
+ end # module TestLogging
36
+
data/version.txt CHANGED
@@ -1 +1 @@
1
- 1.5.2
1
+ 1.6.0
metadata CHANGED
@@ -1,117 +1,86 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: logging
3
- version: !ruby/object:Gem::Version
4
- hash: 7
5
- prerelease: false
6
- segments:
7
- - 1
8
- - 5
9
- - 2
10
- version: 1.5.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.6.0
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Tim Pease
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-07-07 00:00:00 -06:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2011-08-22 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: little-plugger
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &2161856200 !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 23
30
- segments:
31
- - 1
32
- - 1
33
- - 2
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
34
21
  version: 1.1.2
35
22
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: flexmock
39
23
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *2161856200
25
+ - !ruby/object:Gem::Dependency
26
+ name: flexmock
27
+ requirement: &2161855660 !ruby/object:Gem::Requirement
41
28
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 41
46
- segments:
47
- - 0
48
- - 8
49
- - 11
50
- version: 0.8.11
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.0
51
33
  type: :development
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: bones-git
55
34
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *2161855660
36
+ - !ruby/object:Gem::Dependency
37
+ name: bones-git
38
+ requirement: &2161855040 !ruby/object:Gem::Requirement
57
39
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 23
62
- segments:
63
- - 1
64
- - 2
65
- - 4
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
66
43
  version: 1.2.4
67
44
  type: :development
68
- version_requirements: *id003
69
- - !ruby/object:Gem::Dependency
70
- name: bones-rcov
71
45
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *2161855040
47
+ - !ruby/object:Gem::Dependency
48
+ name: bones-rcov
49
+ requirement: &2161854480 !ruby/object:Gem::Requirement
73
50
  none: false
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- hash: 21
78
- segments:
79
- - 1
80
- - 0
81
- - 1
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
82
54
  version: 1.0.1
83
55
  type: :development
84
- version_requirements: *id004
85
- - !ruby/object:Gem::Dependency
86
- name: bones
87
56
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *2161854480
58
+ - !ruby/object:Gem::Dependency
59
+ name: bones
60
+ requirement: &2161853900 !ruby/object:Gem::Requirement
89
61
  none: false
90
- requirements:
91
- - - ">="
92
- - !ruby/object:Gem::Version
93
- hash: 27
94
- segments:
95
- - 3
96
- - 7
97
- - 0
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
98
65
  version: 3.7.0
99
66
  type: :development
100
- version_requirements: *id005
101
- description: |-
102
- Logging is a flexible logging library for use in Ruby programs based on the
103
- design of Java's log4j library. It features a hierarchical logging system,
67
+ prerelease: false
68
+ version_requirements: *2161853900
69
+ description: ! 'Logging is a flexible logging library for use in Ruby programs based
70
+ on the
71
+
72
+ design of Java''s log4j library. It features a hierarchical logging system,
73
+
104
74
  custom level names, multiple output destinations per log event, custom
105
- formatting, and more.
75
+
76
+ formatting, and more.'
106
77
  email: tim.pease@gmail.com
107
78
  executables: []
108
-
109
79
  extensions: []
110
-
111
- extra_rdoc_files:
80
+ extra_rdoc_files:
112
81
  - History.txt
113
82
  - README.rdoc
114
- files:
83
+ files:
115
84
  - History.txt
116
85
  - README.rdoc
117
86
  - Rakefile
@@ -158,6 +127,7 @@ files:
158
127
  - lib/logging/root_logger.rb
159
128
  - lib/logging/stats.rb
160
129
  - lib/logging/utils.rb
130
+ - lib/rspec/logging_helper.rb
161
131
  - lib/spec/logging_helper.rb
162
132
  - test/appenders/test_buffered_io.rb
163
133
  - test/appenders/test_console.rb
@@ -165,7 +135,9 @@ files:
165
135
  - test/appenders/test_file.rb
166
136
  - test/appenders/test_growl.rb
167
137
  - test/appenders/test_io.rb
138
+ - test/appenders/test_periodic_flushing.rb
168
139
  - test/appenders/test_rolling_file.rb
140
+ - test/appenders/test_string_io.rb
169
141
  - test/appenders/test_syslog.rb
170
142
  - test/benchmark.rb
171
143
  - test/config/test_configurator.rb
@@ -189,49 +161,42 @@ files:
189
161
  - test/test_stats.rb
190
162
  - test/test_utils.rb
191
163
  - version.txt
192
- has_rdoc: true
193
164
  homepage: http://rubygems.org/gems/logging
194
165
  licenses: []
195
-
196
166
  post_install_message:
197
- rdoc_options:
167
+ rdoc_options:
198
168
  - --main
199
169
  - README.rdoc
200
- require_paths:
170
+ require_paths:
201
171
  - lib
202
- required_ruby_version: !ruby/object:Gem::Requirement
172
+ required_ruby_version: !ruby/object:Gem::Requirement
203
173
  none: false
204
- requirements:
205
- - - ">="
206
- - !ruby/object:Gem::Version
207
- hash: 3
208
- segments:
209
- - 0
210
- version: "0"
211
- required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ! '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
212
179
  none: false
213
- requirements:
214
- - - ">="
215
- - !ruby/object:Gem::Version
216
- hash: 3
217
- segments:
218
- - 0
219
- version: "0"
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
220
184
  requirements: []
221
-
222
185
  rubyforge_project: logging
223
- rubygems_version: 1.3.7
186
+ rubygems_version: 1.8.6
224
187
  signing_key:
225
188
  specification_version: 3
226
189
  summary: A flexible and extendable logging library for Ruby
227
- test_files:
190
+ test_files:
228
191
  - test/appenders/test_buffered_io.rb
229
192
  - test/appenders/test_console.rb
230
193
  - test/appenders/test_email.rb
231
194
  - test/appenders/test_file.rb
232
195
  - test/appenders/test_growl.rb
233
196
  - test/appenders/test_io.rb
197
+ - test/appenders/test_periodic_flushing.rb
234
198
  - test/appenders/test_rolling_file.rb
199
+ - test/appenders/test_string_io.rb
235
200
  - test/appenders/test_syslog.rb
236
201
  - test/config/test_configurator.rb
237
202
  - test/config/test_yaml_configurator.rb