logging 1.8.2 → 2.0.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 +3 -3
- data/History.txt +20 -0
- data/README.md +159 -0
- data/Rakefile +9 -5
- data/examples/appenders.rb +0 -4
- data/examples/layouts.rb +1 -8
- data/examples/names.rb +4 -4
- data/lib/logging.rb +24 -76
- data/lib/logging/appender.rb +71 -16
- data/lib/logging/appenders.rb +0 -2
- data/lib/logging/appenders/buffering.rb +32 -16
- data/lib/logging/appenders/file.rb +2 -2
- data/lib/logging/appenders/io.rb +1 -1
- data/lib/logging/appenders/rolling_file.rb +228 -165
- data/lib/logging/appenders/string_io.rb +1 -1
- data/lib/logging/appenders/syslog.rb +4 -4
- data/lib/logging/color_scheme.rb +20 -3
- data/lib/logging/diagnostic_context.rb +142 -17
- data/lib/logging/filter.rb +18 -0
- data/lib/logging/filters.rb +4 -0
- data/lib/logging/filters/level.rb +29 -0
- data/lib/logging/layout.rb +2 -2
- data/lib/logging/layouts/parseable.rb +5 -2
- data/lib/logging/layouts/pattern.rb +309 -168
- data/lib/logging/log_event.rb +5 -5
- data/lib/logging/logger.rb +55 -68
- data/lib/logging/repository.rb +24 -39
- data/lib/logging/root_logger.rb +1 -1
- data/lib/logging/utils.rb +4 -65
- data/lib/logging/version.rb +8 -0
- data/lib/rspec/logging_helper.rb +3 -3
- data/logging.gemspec +46 -0
- data/test/appenders/test_buffered_io.rb +29 -0
- data/test/appenders/test_file.rb +2 -2
- data/test/appenders/test_rolling_file.rb +62 -1
- data/test/layouts/test_color_pattern.rb +1 -1
- data/test/layouts/test_json.rb +3 -0
- data/test/layouts/test_pattern.rb +6 -2
- data/test/layouts/test_yaml.rb +4 -1
- data/test/test_appender.rb +56 -0
- data/test/test_filter.rb +33 -0
- data/test/test_layout.rb +4 -8
- data/test/test_log_event.rb +3 -3
- data/test/test_logger.rb +81 -57
- data/test/test_logging.rb +0 -59
- data/test/test_mapped_diagnostic_context.rb +49 -1
- data/test/test_nested_diagnostic_context.rb +16 -1
- data/test/test_repository.rb +24 -32
- data/test/test_utils.rb +14 -50
- metadata +35 -53
- data/README.rdoc +0 -143
- data/data/bad_logging_1.rb +0 -13
- data/data/bad_logging_2.rb +0 -21
- data/data/logging.rb +0 -42
- data/data/logging.yaml +0 -63
- data/data/simple_logging.rb +0 -13
- data/examples/consolidation.rb +0 -83
- data/lib/logging/appenders/email.rb +0 -178
- data/lib/logging/appenders/growl.rb +0 -200
- data/lib/logging/config/configurator.rb +0 -187
- data/lib/logging/config/yaml_configurator.rb +0 -190
- data/lib/logging/stats.rb +0 -277
- data/test/appenders/test_email.rb +0 -170
- data/test/appenders/test_growl.rb +0 -138
- data/test/config/test_configurator.rb +0 -69
- data/test/config/test_yaml_configurator.rb +0 -39
- data/test/test_consolidate.rb +0 -45
- data/test/test_stats.rb +0 -273
- data/version.txt +0 -1
data/lib/logging/stats.rb
DELETED
@@ -1,277 +0,0 @@
|
|
1
|
-
# Simple statistics collection and logging module.
|
2
|
-
#
|
3
|
-
module Logging::Stats
|
4
|
-
|
5
|
-
# A very simple little class for doing some basic fast statistics
|
6
|
-
# sampling. You feed it either samples of numeric data you want measured
|
7
|
-
# or you call Sampler#tick to get it to add a time delta between the last
|
8
|
-
# time you called it. When you're done either call sum, sumsq, num, min,
|
9
|
-
# max, mean or sd to get the information. The other option is to just
|
10
|
-
# call to_s and see everything.
|
11
|
-
#
|
12
|
-
# It does all of this very fast and doesn't take up any memory since the
|
13
|
-
# samples are not stored but instead all the values are calculated on the
|
14
|
-
# fly.
|
15
|
-
#
|
16
|
-
class Sampler
|
17
|
-
|
18
|
-
attr_reader :name, :sum, :sumsq, :num, :min, :max, :last
|
19
|
-
|
20
|
-
# Create a new sampler.
|
21
|
-
#
|
22
|
-
def initialize( name )
|
23
|
-
@name = name
|
24
|
-
reset
|
25
|
-
end
|
26
|
-
|
27
|
-
# Resets the internal counters so you can start sampling again.
|
28
|
-
#
|
29
|
-
def reset
|
30
|
-
@sum = 0.0
|
31
|
-
@sumsq = 0.0
|
32
|
-
@num = 0
|
33
|
-
@min = 0.0
|
34
|
-
@max = 0.0
|
35
|
-
@last = nil
|
36
|
-
@last_time = Time.now.to_f
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
# Coalesce the statistics from the _other_ sampler into this one. The
|
41
|
-
# _other_ sampler is not modified by this method.
|
42
|
-
#
|
43
|
-
# Coalescing the same two samplers multiple times should only be done if
|
44
|
-
# one of the samplers is reset between calls to this method. Otherwise
|
45
|
-
# statistics will be counted multiple times.
|
46
|
-
#
|
47
|
-
def coalesce( other )
|
48
|
-
@sum += other.sum
|
49
|
-
@sumsq += other.sumsq
|
50
|
-
if other.num > 0
|
51
|
-
@min = other.min if @min > other.min
|
52
|
-
@max = other.max if @max < other.max
|
53
|
-
@last = other.last
|
54
|
-
end
|
55
|
-
@num += other.num
|
56
|
-
end
|
57
|
-
|
58
|
-
# Adds a sampling to the calculations.
|
59
|
-
#
|
60
|
-
def sample( s )
|
61
|
-
@sum += s
|
62
|
-
@sumsq += s * s
|
63
|
-
if @num == 0
|
64
|
-
@min = @max = s
|
65
|
-
else
|
66
|
-
@min = s if @min > s
|
67
|
-
@max = s if @max < s
|
68
|
-
end
|
69
|
-
@num += 1
|
70
|
-
@last = s
|
71
|
-
end
|
72
|
-
|
73
|
-
# Returns statistics in a common format.
|
74
|
-
#
|
75
|
-
def to_s
|
76
|
-
"[%s]: SUM=%0.6f, SUMSQ=%0.6f, NUM=%d, MEAN=%0.6f, SD=%0.6f, MIN=%0.6f, MAX=%0.6f" % to_a
|
77
|
-
end
|
78
|
-
|
79
|
-
# An array of the values: [name,sum,sumsq,num,mean,sd,min,max]
|
80
|
-
#
|
81
|
-
def to_a
|
82
|
-
[name, sum, sumsq, num, mean, sd, min, max]
|
83
|
-
end
|
84
|
-
|
85
|
-
# Class method that returns the headers that a CSV file would have for the
|
86
|
-
# values that this stats object is using.
|
87
|
-
#
|
88
|
-
def self.keys
|
89
|
-
%w[name sum sumsq num mean sd min max]
|
90
|
-
end
|
91
|
-
|
92
|
-
def to_hash
|
93
|
-
{:name => name, :sum => sum, :sumsq => sumsq, :num => num,
|
94
|
-
:mean => mean, :sd => sd, :min => min, :max => max}
|
95
|
-
end
|
96
|
-
|
97
|
-
# Calculates and returns the mean for the data passed so far.
|
98
|
-
#
|
99
|
-
def mean
|
100
|
-
return 0.0 if num < 1
|
101
|
-
sum / num
|
102
|
-
end
|
103
|
-
|
104
|
-
# Calculates the standard deviation of the data so far.
|
105
|
-
#
|
106
|
-
def sd
|
107
|
-
return 0.0 if num < 2
|
108
|
-
|
109
|
-
# (sqrt( ((s).sumsq - ( (s).sum * (s).sum / (s).num)) / ((s).num-1) ))
|
110
|
-
begin
|
111
|
-
return Math.sqrt( (sumsq - ( sum * sum / num)) / (num-1) )
|
112
|
-
rescue Errno::EDOM
|
113
|
-
return 0.0
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# You can just call tick repeatedly if you need the delta times
|
118
|
-
# between a set of sample periods, but many times you actually want
|
119
|
-
# to sample how long something takes between a start/end period.
|
120
|
-
# Call mark at the beginning and then tick at the end you'll get this
|
121
|
-
# kind of measurement. Don't mix mark/tick and tick sampling together
|
122
|
-
# or the measurement will be meaningless.
|
123
|
-
#
|
124
|
-
def mark
|
125
|
-
@last_time = Time.now.to_f
|
126
|
-
end
|
127
|
-
|
128
|
-
# Adds a time delta between now and the last time you called this. This
|
129
|
-
# will give you the average time between two activities.
|
130
|
-
#
|
131
|
-
# An example is:
|
132
|
-
#
|
133
|
-
# t = Sampler.new("do_stuff")
|
134
|
-
# 10000.times { do_stuff(); t.tick }
|
135
|
-
# t.dump("time")
|
136
|
-
#
|
137
|
-
def tick
|
138
|
-
now = Time.now.to_f
|
139
|
-
sample(now - @last_time)
|
140
|
-
@last_time = now
|
141
|
-
end
|
142
|
-
end # class Sampler
|
143
|
-
|
144
|
-
# The Tracker class provides synchronized access to a collection of
|
145
|
-
# related samplers.
|
146
|
-
#
|
147
|
-
class Tracker
|
148
|
-
|
149
|
-
attr_reader :stats
|
150
|
-
|
151
|
-
# Create a new Tracker instance. An optional boolean can be passed in to
|
152
|
-
# change the "threadsafe" value of the tracker. By default all trackers
|
153
|
-
# are created to be threadsafe.
|
154
|
-
#
|
155
|
-
def initialize( threadsafe = true )
|
156
|
-
@stats = Hash.new do |h,name|
|
157
|
-
h[name] = ::Logging::Stats::Sampler.new(name)
|
158
|
-
end
|
159
|
-
@mutex = threadsafe ? ReentrantMutex.new : nil
|
160
|
-
@runner = nil
|
161
|
-
end
|
162
|
-
|
163
|
-
# Coalesce the samplers from the _other_ tracker into this one. The
|
164
|
-
# _other_ tracker is not modified by this method.
|
165
|
-
#
|
166
|
-
# Coalescing the same two trackers multiple times should only be done if
|
167
|
-
# one of the trackers is reset between calls to this method. Otherwise
|
168
|
-
# statistics will be counted multiple times.
|
169
|
-
#
|
170
|
-
# Only this tracker is locked when the coalescing is happening. It is
|
171
|
-
# left to the user to lock the other tracker if that is the desired
|
172
|
-
# behavior. This is a deliberate choice in order to prevent deadlock
|
173
|
-
# situations where two threads are contending on the same mutex.
|
174
|
-
#
|
175
|
-
def coalesce( other )
|
176
|
-
sync {
|
177
|
-
other.stats.each do |name,sampler|
|
178
|
-
stats[name].coalesce(sampler)
|
179
|
-
end
|
180
|
-
}
|
181
|
-
end
|
182
|
-
|
183
|
-
# Add the given _value_ to the named _event_ sampler. The sampler will
|
184
|
-
# be created if it does not exist.
|
185
|
-
#
|
186
|
-
def sample( event, value )
|
187
|
-
sync {stats[event].sample(value)}
|
188
|
-
end
|
189
|
-
|
190
|
-
# Mark the named _event_ sampler. The sampler will be created if it does
|
191
|
-
# not exist.
|
192
|
-
#
|
193
|
-
def mark( event )
|
194
|
-
sync {stats[event].mark}
|
195
|
-
end
|
196
|
-
|
197
|
-
# Tick the named _event_ sampler. The sampler will be created if it does
|
198
|
-
# not exist.
|
199
|
-
#
|
200
|
-
def tick( event )
|
201
|
-
sync {stats[event].tick}
|
202
|
-
end
|
203
|
-
|
204
|
-
# Time the execution of the given block and store the results in the
|
205
|
-
# named _event_ sampler. The sampler will be created if it does not
|
206
|
-
# exist.
|
207
|
-
#
|
208
|
-
def time( event )
|
209
|
-
sync {stats[event].mark}
|
210
|
-
yield
|
211
|
-
ensure
|
212
|
-
sync {stats[event].tick}
|
213
|
-
end
|
214
|
-
|
215
|
-
# Reset all the samplers managed by this tracker.
|
216
|
-
#
|
217
|
-
def reset
|
218
|
-
sync {stats.each_value {|sampler| sampler.reset}}
|
219
|
-
self
|
220
|
-
end
|
221
|
-
|
222
|
-
# Periodically execute the given _block_ at the given _period_. The
|
223
|
-
# tracker will be locked while the block is executing.
|
224
|
-
#
|
225
|
-
# This method is useful for logging statistics at given interval.
|
226
|
-
#
|
227
|
-
# Example
|
228
|
-
#
|
229
|
-
# periodically_run( 300 ) {
|
230
|
-
# logger = Logging::Logger['stats']
|
231
|
-
# tracker.each {|sampler| logger << sampler.to_s}
|
232
|
-
# tracker.reset
|
233
|
-
# }
|
234
|
-
#
|
235
|
-
def periodically_run( period, &block )
|
236
|
-
raise ArgumentError, 'a runner already exists' unless @runner.nil?
|
237
|
-
|
238
|
-
@runner = Thread.new do
|
239
|
-
start = stop = Time.now.to_f
|
240
|
-
loop do
|
241
|
-
seconds = period - (stop-start)
|
242
|
-
seconds = period if seconds <= 0
|
243
|
-
sleep seconds
|
244
|
-
|
245
|
-
start = Time.now.to_f
|
246
|
-
break if Thread.current[:stop] == true
|
247
|
-
if @mutex then @mutex.synchronize(&block)
|
248
|
-
else block.call end
|
249
|
-
stop = Time.now.to_f
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
# Stop the current periodic runner if present.
|
255
|
-
#
|
256
|
-
def stop
|
257
|
-
return if @runner.nil?
|
258
|
-
@runner[:stop] = true
|
259
|
-
@runner.wakeup if @runner.status
|
260
|
-
@runner = nil
|
261
|
-
end
|
262
|
-
|
263
|
-
# call-seq:
|
264
|
-
# sync { block }
|
265
|
-
#
|
266
|
-
# Obtains an exclusive lock, runs the block, and releases the lock when
|
267
|
-
# the block completes. This method is re-entrant so that a single thread
|
268
|
-
# can call +sync+ multiple times without hanging the thread.
|
269
|
-
#
|
270
|
-
def sync
|
271
|
-
return yield if @mutex.nil?
|
272
|
-
@mutex.synchronize {yield}
|
273
|
-
end
|
274
|
-
end # class Tracker
|
275
|
-
|
276
|
-
end # module Logging::Stats
|
277
|
-
|
@@ -1,170 +0,0 @@
|
|
1
|
-
|
2
|
-
require File.expand_path('../setup', File.dirname(__FILE__))
|
3
|
-
require 'flexmock'
|
4
|
-
|
5
|
-
module TestLogging
|
6
|
-
module TestAppenders
|
7
|
-
|
8
|
-
class TestEmail < Test::Unit::TestCase
|
9
|
-
include FlexMock::TestCase
|
10
|
-
include LoggingTestCase
|
11
|
-
|
12
|
-
def setup
|
13
|
-
super
|
14
|
-
|
15
|
-
flexmock(Net::SMTP).new_instances do |m|
|
16
|
-
m.should_receive(:start).at_least.once.with(
|
17
|
-
'test.logging', 'test', 'test', :plain, Proc).and_yield(m)
|
18
|
-
m.should_receive(:sendmail).at_least.once.with(String, 'me', ['you'])
|
19
|
-
end
|
20
|
-
|
21
|
-
@appender = Logging.appenders.email('email',
|
22
|
-
'from' => 'me', 'to' => 'you',
|
23
|
-
:buffer_size => '3', :immediate_at => 'error, fatal',
|
24
|
-
:domain => 'test.logging', :user_name => 'test', :password => 'test'
|
25
|
-
)
|
26
|
-
@levels = Logging::LEVELS
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_initialize
|
30
|
-
assert_raise(ArgumentError, 'Must specify from address') {
|
31
|
-
Logging.appenders.email('email')
|
32
|
-
}
|
33
|
-
assert_raise(ArgumentError, 'Must specify to address') {
|
34
|
-
Logging.appenders.email('email', :from => 'me')
|
35
|
-
}
|
36
|
-
assert_nothing_raised {
|
37
|
-
Logging.appenders.email('email', :from => 'me', :to => 'you')
|
38
|
-
}
|
39
|
-
|
40
|
-
appender = Logging.appenders.email('email',
|
41
|
-
'from' => 'me', 'to' => 'you'
|
42
|
-
)
|
43
|
-
|
44
|
-
assert_equal(100, appender.auto_flushing)
|
45
|
-
assert_equal([], appender.instance_variable_get(:@immediate))
|
46
|
-
assert_equal('localhost', appender.address)
|
47
|
-
assert_equal(25, appender.port)
|
48
|
-
|
49
|
-
domain = ENV['HOSTNAME'] || 'localhost.localdomain'
|
50
|
-
assert_equal(domain, appender.domain)
|
51
|
-
assert_equal(nil, appender.user_name)
|
52
|
-
assert_equal(:plain, appender.authentication)
|
53
|
-
assert_equal("Message from #{$0}", appender.subject)
|
54
|
-
|
55
|
-
appender = Logging.appenders.email('email',
|
56
|
-
'from' => 'lbrinn@gmail.com', 'to' => 'everyone',
|
57
|
-
:buffsize => '1000', :immediate_at => 'error, fatal',
|
58
|
-
:address => 'smtp.google.com', :port => '443',
|
59
|
-
:domain => 'google.com', :user_name => 'lbrinn',
|
60
|
-
:password => '1234', :authentication => 'plain', :enable_starttls_auto => true,
|
61
|
-
:subject => "I'm rich and you're not"
|
62
|
-
)
|
63
|
-
|
64
|
-
assert_equal('lbrinn@gmail.com', appender.instance_variable_get(:@from))
|
65
|
-
assert_equal(['everyone'], appender.instance_variable_get(:@to))
|
66
|
-
assert_equal(1000, appender.auto_flushing)
|
67
|
-
assert_equal('1234', appender.password)
|
68
|
-
assert_equal([nil, nil, nil, true, true],
|
69
|
-
appender.instance_variable_get(:@immediate))
|
70
|
-
assert_equal('smtp.google.com', appender.address)
|
71
|
-
assert_equal(443, appender.port)
|
72
|
-
assert_equal('google.com', appender.domain)
|
73
|
-
assert_equal('lbrinn', appender.user_name)
|
74
|
-
assert_equal(:plain, appender.authentication)
|
75
|
-
assert(appender.enable_starttls_auto)
|
76
|
-
assert_equal("I'm rich and you're not", appender.subject)
|
77
|
-
|
78
|
-
appender = Logging.appenders.email('email',
|
79
|
-
'from' => 'me', 'to' => 'you', :auto_flushing => 42
|
80
|
-
)
|
81
|
-
assert_equal(42, appender.auto_flushing)
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_append
|
85
|
-
# with auto_flushing enabled, mail will be sent each time a log event
|
86
|
-
# occurs
|
87
|
-
@appender.auto_flushing = true
|
88
|
-
event = Logging::LogEvent.new('TestLogger', @levels['warn'],
|
89
|
-
[1, 2, 3, 4], false)
|
90
|
-
@appender.append event
|
91
|
-
assert_not_equal(@levels.length, @appender.level)
|
92
|
-
assert_equal(0, @appender.buffer.length)
|
93
|
-
|
94
|
-
# increase the buffer size and log a few events
|
95
|
-
@appender.auto_flushing = 3
|
96
|
-
@appender.append event
|
97
|
-
@appender.append event
|
98
|
-
assert_equal(2, @appender.buffer.length)
|
99
|
-
|
100
|
-
@appender.append event
|
101
|
-
assert_not_equal(@levels.length, @appender.level)
|
102
|
-
assert_equal(0, @appender.buffer.length)
|
103
|
-
|
104
|
-
# error and fatal messages should be send immediately (no buffering)
|
105
|
-
error = Logging::LogEvent.new('ErrLogger', @levels['error'],
|
106
|
-
'error message', false)
|
107
|
-
fatal = Logging::LogEvent.new('FatalLogger', @levels['fatal'],
|
108
|
-
'fatal message', false)
|
109
|
-
|
110
|
-
@appender.append event
|
111
|
-
@appender.append fatal
|
112
|
-
assert_not_equal(@levels.length, @appender.level)
|
113
|
-
assert_equal(0, @appender.buffer.length)
|
114
|
-
|
115
|
-
@appender.append error
|
116
|
-
assert_not_equal(@levels.length, @appender.level)
|
117
|
-
assert_equal(0, @appender.buffer.length)
|
118
|
-
|
119
|
-
@appender.append event
|
120
|
-
assert_equal(1, @appender.buffer.length)
|
121
|
-
end
|
122
|
-
|
123
|
-
def test_concat
|
124
|
-
# with auto_flushing enabled, mail will be sent each time a log event
|
125
|
-
# occurs
|
126
|
-
@appender.auto_flushing = true
|
127
|
-
@appender << 'test message'
|
128
|
-
assert_not_equal(@levels.length, @appender.level)
|
129
|
-
assert_equal(0, @appender.buffer.length)
|
130
|
-
|
131
|
-
# increase the buffer size and log a few events
|
132
|
-
@appender.auto_flushing = 3
|
133
|
-
@appender << 'another test message'
|
134
|
-
@appender << 'a second test message'
|
135
|
-
assert_equal(2, @appender.buffer.length)
|
136
|
-
|
137
|
-
@appender << 'a third test message'
|
138
|
-
assert_not_equal(@levels.length, @appender.level)
|
139
|
-
assert_equal(0, @appender.buffer.length)
|
140
|
-
end
|
141
|
-
|
142
|
-
def test_flush
|
143
|
-
event = Logging::LogEvent.new('TestLogger', @levels['info'],
|
144
|
-
[1, 2, 3, 4], false)
|
145
|
-
@appender.append event
|
146
|
-
@appender << 'test message'
|
147
|
-
assert_equal(2, @appender.buffer.length)
|
148
|
-
|
149
|
-
@appender.flush
|
150
|
-
assert_not_equal(@levels.length, @appender.level)
|
151
|
-
assert_equal(0, @appender.buffer.length)
|
152
|
-
end
|
153
|
-
|
154
|
-
def test_close
|
155
|
-
event = Logging::LogEvent.new('TestLogger', @levels['info'],
|
156
|
-
[1, 2, 3, 4], false)
|
157
|
-
@appender.append event
|
158
|
-
@appender << 'test message'
|
159
|
-
assert_equal(2, @appender.buffer.length)
|
160
|
-
|
161
|
-
@appender.close
|
162
|
-
assert_not_equal(@levels.length, @appender.level)
|
163
|
-
assert_equal(0, @appender.buffer.length)
|
164
|
-
assert(@appender.closed?)
|
165
|
-
end
|
166
|
-
|
167
|
-
end # class TestEmail
|
168
|
-
end # module TestLogging
|
169
|
-
end # module TestAppenders
|
170
|
-
|
@@ -1,138 +0,0 @@
|
|
1
|
-
|
2
|
-
require File.expand_path('../setup', File.dirname(__FILE__))
|
3
|
-
require 'flexmock'
|
4
|
-
|
5
|
-
module TestLogging
|
6
|
-
module TestAppenders
|
7
|
-
|
8
|
-
class TestGrowl < Test::Unit::TestCase
|
9
|
-
include FlexMock::TestCase
|
10
|
-
include LoggingTestCase
|
11
|
-
|
12
|
-
def setup
|
13
|
-
super
|
14
|
-
|
15
|
-
@appender = Logging.appenders.growl('growl',
|
16
|
-
:coalesce => true, :separator => "\000",
|
17
|
-
:layout => Logging.layouts.pattern(:pattern => "%5l - Test\000%m")
|
18
|
-
)
|
19
|
-
@appender.level = :all
|
20
|
-
@growl = @appender.instance_variable_get(:@growl).dup
|
21
|
-
@levels = Logging::LEVELS
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_initialize
|
25
|
-
assert_equal('growlnotify -w -n "growl" -t "%s" -m "%s" -p %d &', @growl)
|
26
|
-
assert_equal(true, @appender.instance_variable_get(:@coalesce))
|
27
|
-
assert_equal("\000", @appender.instance_variable_get(:@title_sep))
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_append
|
31
|
-
info = Logging::LogEvent.new('TestLogger', @levels['info'],
|
32
|
-
'info message', false)
|
33
|
-
warn = Logging::LogEvent.new('TestLogger', @levels['warn'],
|
34
|
-
'warning message', false)
|
35
|
-
|
36
|
-
flexmock(@appender).should_receive(:system => true).once.with(
|
37
|
-
@growl % ['WARN - Test', "warning message\nwarning message\nwarning message", 0])
|
38
|
-
|
39
|
-
flexmock(@appender).should_receive(:system => true).once.with(
|
40
|
-
@growl % ['INFO - Test', "info message\ninfo message", -1])
|
41
|
-
|
42
|
-
flexmock(@appender).should_receive(:system => true).once.with(
|
43
|
-
@growl % ['WARN - Test', "warning message", 0])
|
44
|
-
|
45
|
-
@appender.append warn
|
46
|
-
@appender.append warn
|
47
|
-
@appender.append warn
|
48
|
-
@appender.append info
|
49
|
-
@appender.append info
|
50
|
-
@appender.append warn
|
51
|
-
ensure_queue_is_empty
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_append_without_coalescing
|
55
|
-
@appender.instance_variable_set(:@coalesce, false)
|
56
|
-
event = Logging::LogEvent.new('TestLogger', @levels['warn'],
|
57
|
-
'warning message', false)
|
58
|
-
|
59
|
-
flexmock(@appender).should_receive(:system => true).twice.with(
|
60
|
-
@growl % ['WARN - Test', 'warning message', 0])
|
61
|
-
|
62
|
-
@appender.append event
|
63
|
-
@appender.append event
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_concat
|
67
|
-
flexmock(@appender).should_receive(:system => true).once.with(
|
68
|
-
@growl % ['', "first message\nsecond message\nthird message", 0])
|
69
|
-
|
70
|
-
@appender << 'first message'
|
71
|
-
@appender << 'second message'
|
72
|
-
@appender << 'third message'
|
73
|
-
ensure_queue_is_empty
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_concat_without_coalescing
|
77
|
-
@appender.instance_variable_set(:@coalesce, false)
|
78
|
-
|
79
|
-
flexmock(@appender).should_receive(:system => true).twice.with(
|
80
|
-
@growl % ['', 'concat message', 0])
|
81
|
-
|
82
|
-
@appender << 'concat message'
|
83
|
-
@appender << 'concat message'
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_map_eq
|
87
|
-
get_map = lambda {@appender.instance_variable_get(:@map)}
|
88
|
-
assert_equal([-2,-1,0,1,2], get_map.call)
|
89
|
-
|
90
|
-
@appender.map = {
|
91
|
-
'fatal' => '0',
|
92
|
-
:error => -2,
|
93
|
-
:warn => '2',
|
94
|
-
'INFO' => 1,
|
95
|
-
'Debug' => -1
|
96
|
-
}
|
97
|
-
assert_equal([-1,1,2,-2,0], get_map.call)
|
98
|
-
|
99
|
-
assert_raise(ArgumentError) do
|
100
|
-
@appender.map = {:fatal => 'not a number', :error => 2}
|
101
|
-
end
|
102
|
-
|
103
|
-
assert_raise(ArgumentError) do
|
104
|
-
@appender.map = {:fatal => -3, :error => 3}
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_disabling
|
109
|
-
@appender.instance_variable_set(:@coalesce, false)
|
110
|
-
event = Logging::LogEvent.new('TestLogger', @levels['warn'],
|
111
|
-
'warning message', false)
|
112
|
-
|
113
|
-
flexmock(@appender).should_receive(:system => false).once.with(
|
114
|
-
@growl % ['WARN - Test', 'warning message', 0])
|
115
|
-
|
116
|
-
assert_equal 0, @appender.level
|
117
|
-
@appender.append event
|
118
|
-
assert_equal 5, @appender.level
|
119
|
-
@appender.append event
|
120
|
-
@appender.append event
|
121
|
-
end
|
122
|
-
|
123
|
-
private
|
124
|
-
|
125
|
-
def ensure_queue_is_empty
|
126
|
-
start = Time.now
|
127
|
-
|
128
|
-
queue = @appender.instance_variable_get :@c_queue
|
129
|
-
sleep 0.2 until queue.empty? or (Time.now - start > 10)
|
130
|
-
|
131
|
-
thread = @appender.instance_variable_get :@c_thread
|
132
|
-
sleep 0.2 until thread.status == 'sleep' or (Time.now - start > 10)
|
133
|
-
end
|
134
|
-
|
135
|
-
end # class TestGrowl
|
136
|
-
end # module TestLogging
|
137
|
-
end # module TestAppenders
|
138
|
-
|