TwP-logging 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/History.txt +169 -0
  2. data/README.rdoc +102 -0
  3. data/Rakefile +42 -0
  4. data/data/bad_logging_1.rb +13 -0
  5. data/data/bad_logging_2.rb +21 -0
  6. data/data/logging.rb +42 -0
  7. data/data/logging.yaml +63 -0
  8. data/data/simple_logging.rb +13 -0
  9. data/lib/logging.rb +408 -0
  10. data/lib/logging/appender.rb +303 -0
  11. data/lib/logging/appenders/buffering.rb +167 -0
  12. data/lib/logging/appenders/console.rb +62 -0
  13. data/lib/logging/appenders/email.rb +75 -0
  14. data/lib/logging/appenders/file.rb +54 -0
  15. data/lib/logging/appenders/growl.rb +197 -0
  16. data/lib/logging/appenders/io.rb +69 -0
  17. data/lib/logging/appenders/rolling_file.rb +291 -0
  18. data/lib/logging/appenders/syslog.rb +201 -0
  19. data/lib/logging/config/configurator.rb +190 -0
  20. data/lib/logging/config/yaml_configurator.rb +195 -0
  21. data/lib/logging/layout.rb +119 -0
  22. data/lib/logging/layouts/basic.rb +34 -0
  23. data/lib/logging/layouts/pattern.rb +296 -0
  24. data/lib/logging/log_event.rb +51 -0
  25. data/lib/logging/logger.rb +490 -0
  26. data/lib/logging/repository.rb +172 -0
  27. data/lib/logging/root_logger.rb +61 -0
  28. data/lib/logging/stats.rb +278 -0
  29. data/lib/logging/utils.rb +130 -0
  30. data/logging.gemspec +41 -0
  31. data/test/appenders/test_buffered_io.rb +183 -0
  32. data/test/appenders/test_console.rb +66 -0
  33. data/test/appenders/test_email.rb +171 -0
  34. data/test/appenders/test_file.rb +93 -0
  35. data/test/appenders/test_growl.rb +128 -0
  36. data/test/appenders/test_io.rb +142 -0
  37. data/test/appenders/test_rolling_file.rb +207 -0
  38. data/test/appenders/test_syslog.rb +194 -0
  39. data/test/benchmark.rb +87 -0
  40. data/test/config/test_configurator.rb +70 -0
  41. data/test/config/test_yaml_configurator.rb +40 -0
  42. data/test/layouts/test_basic.rb +43 -0
  43. data/test/layouts/test_pattern.rb +177 -0
  44. data/test/setup.rb +74 -0
  45. data/test/test_appender.rb +166 -0
  46. data/test/test_layout.rb +110 -0
  47. data/test/test_log_event.rb +80 -0
  48. data/test/test_logger.rb +734 -0
  49. data/test/test_logging.rb +267 -0
  50. data/test/test_repository.rb +126 -0
  51. data/test/test_root_logger.rb +81 -0
  52. data/test/test_stats.rb +274 -0
  53. data/test/test_utils.rb +116 -0
  54. metadata +156 -0
@@ -0,0 +1,93 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ module TestLogging
5
+ module TestAppenders
6
+
7
+ class TestFile < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ NAME = 'logfile'
11
+
12
+ def setup
13
+ super
14
+ ::Logging.init
15
+
16
+ FileUtils.mkdir [File.join(TMP, 'dir'), File.join(TMP, 'uw_dir')]
17
+ FileUtils.chmod 0555, File.join(TMP, 'uw_dir')
18
+ FileUtils.touch File.join(TMP, 'uw_file')
19
+ FileUtils.chmod 0444, File.join(TMP, 'uw_file')
20
+ end
21
+
22
+ def test_class_assert_valid_logfile
23
+ log = File.join(TMP, 'uw_dir', 'file.log')
24
+ assert_raise(ArgumentError) do
25
+ ::Logging::Appenders::File.assert_valid_logfile(log)
26
+ end
27
+
28
+ log = File.join(TMP, 'dir')
29
+ assert_raise(ArgumentError) do
30
+ ::Logging::Appenders::File.assert_valid_logfile(log)
31
+ end
32
+
33
+ log = File.join(TMP, 'uw_file')
34
+ assert_raise(ArgumentError) do
35
+ ::Logging::Appenders::File.assert_valid_logfile(log)
36
+ end
37
+
38
+ log = File.join(TMP, 'file.log')
39
+ assert ::Logging::Appenders::File.assert_valid_logfile(log)
40
+ end
41
+
42
+ def test_initialize
43
+ log = File.join(TMP, 'file.log')
44
+ appender = ::Logging::Appenders::File.new(NAME, 'filename' => log)
45
+ assert_equal 'logfile', appender.name
46
+ appender << "This will be the first line\n"
47
+ appender << "This will be the second line\n"
48
+ appender.flush
49
+ File.open(log, 'r') do |file|
50
+ assert_equal "This will be the first line\n", file.readline
51
+ assert_equal "This will be the second line\n", file.readline
52
+ assert_raise(EOFError) {file.readline}
53
+ end
54
+ cleanup
55
+
56
+ appender = ::Logging::Appenders::File.new NAME, :filename => log
57
+ assert_equal 'logfile', appender.name
58
+ appender << "This will be the third line\n"
59
+ appender.flush
60
+ File.open(log, 'r') do |file|
61
+ assert_equal "This will be the first line\n", file.readline
62
+ assert_equal "This will be the second line\n", file.readline
63
+ assert_equal "This will be the third line\n", file.readline
64
+ assert_raise(EOFError) {file.readline}
65
+ end
66
+ cleanup
67
+
68
+ appender = ::Logging::Appenders::File.new NAME, :filename => log,
69
+ :truncate => true
70
+ assert_equal 'logfile', appender.name
71
+ appender << "The file was truncated\n"
72
+ appender.flush
73
+ File.open(log, 'r') do |file|
74
+ assert_equal "The file was truncated\n", file.readline
75
+ assert_raise(EOFError) {file.readline}
76
+ end
77
+ cleanup
78
+ end
79
+
80
+ private
81
+ def cleanup
82
+ unless ::Logging::Appender[NAME].nil?
83
+ ::Logging::Appender[NAME].close false
84
+ ::Logging::Appender[NAME] = nil
85
+ end
86
+ end
87
+
88
+ end # class TestFile
89
+
90
+ end # module TestAppenders
91
+ end # module TestLogging
92
+
93
+ # EOF
@@ -0,0 +1,128 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
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
+ ::Logging.init
15
+ @levels = ::Logging::LEVELS
16
+
17
+ @appender = ::Logging::Appenders::Growl.new('growl',
18
+ :coalesce => true, :separator => "\000",
19
+ :layout => Logging::Layouts::Pattern.new(:pattern => "%5l - Test\000%m")
20
+ )
21
+ @appender.level = :all
22
+ @growl = @appender.instance_variable_get(:@growl).dup
23
+ end
24
+
25
+ def test_initialize
26
+ assert_equal('growlnotify -w -n "growl" -t "%s" -m "%s" -p %d &', @growl)
27
+ assert_equal(true, @appender.instance_variable_get(:@coalesce))
28
+ assert_equal("\000", @appender.instance_variable_get(:@title_sep))
29
+ end
30
+
31
+ def test_append
32
+ info = ::Logging::LogEvent.new('TestLogger', @levels['info'],
33
+ 'info message', false)
34
+ warn = ::Logging::LogEvent.new('TestLogger', @levels['warn'],
35
+ 'warning message', false)
36
+
37
+ flexmock(@appender).should_receive(:system => true).once.with(
38
+ @growl % ['WARN - Test', "warning message\nwarning message\nwarning message", 0])
39
+
40
+ flexmock(@appender).should_receive(:system => true).once.with(
41
+ @growl % ['INFO - Test', "info message\ninfo message", -1])
42
+
43
+ flexmock(@appender).should_receive(:system => true).once.with(
44
+ @growl % ['WARN - Test', "warning message", 0])
45
+
46
+ @appender.append warn
47
+ @appender.append warn
48
+ @appender.append warn
49
+ @appender.append info
50
+ @appender.append info
51
+ @appender.append warn
52
+ sleep 0.7 # give the coalescing thread time to run
53
+ end
54
+
55
+ def test_append_without_coalescing
56
+ @appender.instance_variable_set(:@coalesce, false)
57
+ event = ::Logging::LogEvent.new('TestLogger', @levels['warn'],
58
+ 'warning message', false)
59
+
60
+ flexmock(@appender).should_receive(:system => true).twice.with(
61
+ @growl % ['WARN - Test', 'warning message', 0])
62
+
63
+ @appender.append event
64
+ @appender.append event
65
+ end
66
+
67
+ def test_concat
68
+ flexmock(@appender).should_receive(:system => true).once.with(
69
+ @growl % ['', "first message\nsecond message\nthird message", 0])
70
+
71
+ @appender << 'first message'
72
+ @appender << 'second message'
73
+ @appender << 'third message'
74
+ sleep 0.7 # give the coalescing thread time to run
75
+ end
76
+
77
+ def test_concat_without_coalescing
78
+ @appender.instance_variable_set(:@coalesce, false)
79
+
80
+ flexmock(@appender).should_receive(:system => true).twice.with(
81
+ @growl % ['', 'concat message', 0])
82
+
83
+ @appender << 'concat message'
84
+ @appender << 'concat message'
85
+ end
86
+
87
+ def test_map_eq
88
+ get_map = lambda {@appender.instance_variable_get(:@map)}
89
+ assert_equal([-2,-1,0,1,2], get_map.call)
90
+
91
+ @appender.map = {
92
+ 'fatal' => '0',
93
+ :error => -2,
94
+ :warn => '2',
95
+ 'INFO' => 1,
96
+ 'Debug' => -1
97
+ }
98
+ assert_equal([-1,1,2,-2,0], get_map.call)
99
+
100
+ assert_raise(ArgumentError) do
101
+ @appender.map = {:fatal => 'not a number', :error => 2}
102
+ end
103
+
104
+ assert_raise(ArgumentError) do
105
+ @appender.map = {:fatal => -3, :error => 3}
106
+ end
107
+ end
108
+
109
+ def test_disabling
110
+ @appender.instance_variable_set(:@coalesce, false)
111
+ event = ::Logging::LogEvent.new('TestLogger', @levels['warn'],
112
+ 'warning message', false)
113
+
114
+ flexmock(@appender).should_receive(:system => false).once.with(
115
+ @growl % ['WARN - Test', 'warning message', 0])
116
+
117
+ assert_equal 0, @appender.level
118
+ @appender.append event
119
+ assert_equal 5, @appender.level
120
+ @appender.append event
121
+ @appender.append event
122
+ end
123
+
124
+ end # class TestGrowl
125
+ end # module TestLogging
126
+ end # module TestAppenders
127
+
128
+ # EOF
@@ -0,0 +1,142 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ module TestLogging
5
+ module TestAppenders
6
+
7
+ class TestIO < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def setup
11
+ super
12
+ ::Logging.init
13
+ @levels = ::Logging::LEVELS
14
+
15
+ @sio = StringIO.new
16
+ @appender = ::Logging::Appenders::IO.new 'test_appender', @sio
17
+ begin readline rescue EOFError end
18
+ end
19
+
20
+ def test_append
21
+ event = ::Logging::LogEvent.new('TestLogger', @levels['warn'],
22
+ [1, 2, 3, 4], false)
23
+ @appender.append event
24
+ assert_equal " WARN TestLogger : <Array> #{[1, 2, 3, 4]}\n", readline
25
+ assert_raise(EOFError) {readline}
26
+
27
+ event.level = @levels['debug']
28
+ event.data = 'the big log message'
29
+ @appender.append event
30
+ assert_equal "DEBUG TestLogger : the big log message\n", readline
31
+ assert_raise(EOFError) {readline}
32
+
33
+ @appender.close
34
+ assert_raise(RuntimeError) {@appender.append event}
35
+ end
36
+
37
+ def test_append_error
38
+ # setup an internal logger to capture error messages from the IO
39
+ # appender
40
+ log = StringIO.new
41
+ Logging::Logger[Logging].add_appenders(
42
+ Logging::Appenders::IO.new('__internal_io', log)
43
+ )
44
+ Logging::Logger[Logging].level = 'all'
45
+
46
+
47
+ # close the string IO object so we get an error
48
+ @sio.close
49
+ event = ::Logging::LogEvent.new('TestLogger', @levels['warn'],
50
+ [1, 2, 3, 4], false)
51
+ @appender.append event
52
+
53
+ log.seek 0
54
+ assert_equal "INFO Logging : appender \"test_appender\" has been disabled", log.readline.strip
55
+ assert_equal "ERROR Logging : <IOError> not opened for writing", log.readline.strip
56
+
57
+ assert_equal false, @appender.closed?
58
+ assert_equal 5, @appender.level
59
+ end
60
+
61
+ def test_close
62
+ assert_equal false, @sio.closed?
63
+ assert_equal false, @appender.closed?
64
+
65
+ @appender.close
66
+ assert_equal true, @sio.closed?
67
+ assert_equal true, @appender.closed?
68
+
69
+ [STDIN, STDERR, STDOUT].each do |io|
70
+ @appender = ::Logging::Appenders::IO.new 'test', io
71
+ @appender.close
72
+ assert_equal false, io.closed?
73
+ assert_equal true, @appender.closed?
74
+ end
75
+ end
76
+
77
+ def test_concat
78
+ @appender << "this is a test message\n"
79
+ assert_equal "this is a test message\n", readline
80
+ assert_raise(EOFError) {readline}
81
+
82
+ @appender << "this is another message\n"
83
+ @appender << "some other line\n"
84
+ assert_equal "this is another message\n", readline
85
+ assert_equal "some other line\n", readline
86
+ assert_raise(EOFError) {readline}
87
+
88
+ @appender.close
89
+ assert_raise(RuntimeError) {@appender << 'message'}
90
+ end
91
+
92
+ def test_concat_error
93
+ # setup an internal logger to capture error messages from the IO
94
+ # appender
95
+ log = StringIO.new
96
+ Logging::Logger[Logging].add_appenders(
97
+ Logging::Appenders::IO.new('__internal_io', log)
98
+ )
99
+ Logging::Logger[Logging].level = 'all'
100
+
101
+ # close the string IO object so we get an error
102
+ @sio.close
103
+ @appender << 'oopsy'
104
+
105
+ log.seek 0
106
+ assert_equal "INFO Logging : appender \"test_appender\" has been disabled", log.readline.strip
107
+ assert_equal "ERROR Logging : <IOError> not opened for writing", log.readline.strip
108
+
109
+ # and the appender does not close itself
110
+ assert_equal false, @appender.closed?
111
+ assert_equal 5, @appender.level
112
+ end
113
+
114
+ def test_flush
115
+ ary = []
116
+ @sio.instance_variable_set :@ary, ary
117
+ def @sio.flush() @ary << :flush end
118
+
119
+ @appender.flush
120
+ assert_equal :flush, ary.pop
121
+ end
122
+
123
+ def test_initialize
124
+ assert_raise(EOFError) {@sio.readline}
125
+ assert_raise(TypeError) {::Logging::Appenders::IO.new 'test', []}
126
+ end
127
+
128
+ private
129
+ def readline
130
+ @pos ||= 0
131
+ @sio.seek @pos
132
+ line = @sio.readline
133
+ @pos = @sio.tell
134
+ line
135
+ end
136
+
137
+ end # class TestIO
138
+
139
+ end # module TestAppenders
140
+ end # module TestLogging
141
+
142
+ # EOF
@@ -0,0 +1,207 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ module TestLogging
5
+ module TestAppenders
6
+
7
+ class TestRollingFile < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ NAME = 'roller'
11
+
12
+ def setup
13
+ super
14
+ ::Logging.init
15
+
16
+ @fn = File.join(TMP, 'test.log')
17
+ @fn_fmt = File.join(TMP, 'test.%d.log')
18
+ @glob = File.join(TMP, '*.log')
19
+ end
20
+
21
+ def test_initialize
22
+ assert_equal [], Dir.glob(@glob)
23
+
24
+ # create a new appender
25
+ ap = ::Logging::Appenders::RollingFile.new(NAME, :filename => @fn)
26
+ assert File.exist?(@fn)
27
+ assert_equal 0, File.size(@fn)
28
+
29
+ ap << "Just a line of text\n" # 20 bytes
30
+ ap.flush
31
+ assert_equal 20, File.size(@fn)
32
+ cleanup
33
+
34
+ # make sure we append to the current file (not truncate)
35
+ ap = ::Logging::Appenders::RollingFile.new(NAME, :filename => @fn)
36
+ assert_equal [@fn], Dir.glob(@glob)
37
+ assert_equal 20, File.size(@fn)
38
+
39
+ ap << "Just another line of text\n" # 26 bytes
40
+ ap.flush
41
+ assert_equal 46, File.size(@fn)
42
+ cleanup
43
+
44
+ # setting the truncate option to true should roll the current log file
45
+ # and create a new one
46
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
47
+ :filename => @fn, :truncate => true)
48
+
49
+ log1 = sprintf(@fn_fmt, 1)
50
+ assert_equal [log1, @fn], Dir.glob(@glob).sort
51
+ assert_equal 0, File.size(@fn)
52
+ assert_equal 46, File.size(log1)
53
+
54
+ ap << "Some more text in the new file\n" # 31 bytes
55
+ ap.flush
56
+ assert_equal 31, File.size(@fn)
57
+ cleanup
58
+ end
59
+
60
+ def test_keep
61
+ assert_equal [], Dir.glob(@glob)
62
+
63
+ (1..12).each do |cnt|
64
+ name = sprintf(@fn_fmt, cnt)
65
+ File.open(name,'w') {|fd| fd.write 'X'*cnt}
66
+ end
67
+ FileUtils.touch(@fn)
68
+
69
+ # keep only five files
70
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
71
+ :filename => @fn, :keep => 5)
72
+
73
+ # we still have 13 files because we did not truncate the log file,
74
+ # and hence, we did not roll all the log files
75
+ assert_equal 13, Dir.glob(@glob).length
76
+
77
+ # force the appender to roll the files
78
+ ap.send :roll
79
+ assert_equal 6, Dir.glob(@glob).length
80
+
81
+ (1..5).each do |cnt|
82
+ name = sprintf(@fn_fmt, cnt)
83
+ assert_equal cnt-1, File.size(name)
84
+ end
85
+ cleanup
86
+ end
87
+
88
+ def test_age
89
+ assert_equal [], Dir.glob(@glob)
90
+
91
+ assert_raise(ArgumentError) do
92
+ ::Logging::Appenders::RollingFile.new(
93
+ NAME, :filename => @fn, :age => 'bob')
94
+ end
95
+
96
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
97
+ :filename => @fn, :age => 1)
98
+ ap << "random message\n"
99
+ assert_equal 1, Dir.glob(@glob).length
100
+
101
+ sleep 1.250
102
+ ap << "another random message\n"
103
+ assert_equal 2, Dir.glob(@glob).length
104
+
105
+ cleanup
106
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
107
+ :filename => @fn, 'age' => 'daily')
108
+ ap << "random message\n"
109
+ assert_equal 2, Dir.glob(@glob).length
110
+
111
+ age_fn = @fn + '.age'
112
+ now = ::File.mtime(age_fn)
113
+ start = now - 3600 * 24
114
+ ::File.utime(start, start, age_fn)
115
+
116
+ sleep 0.250
117
+ ap << "yet another random message\n"
118
+ assert_equal 3, Dir.glob(@glob).length
119
+
120
+ cleanup
121
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
122
+ :filename => @fn, :age => 'weekly')
123
+ ap << "random message\n"
124
+ assert_equal 3, Dir.glob(@glob).length
125
+
126
+ start = now - 3600 * 24 * 7
127
+ ::File.utime(start, start, age_fn)
128
+
129
+ sleep 0.250
130
+ ap << "yet another random message\n"
131
+ assert_equal 4, Dir.glob(@glob).length
132
+
133
+ cleanup
134
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
135
+ :filename => @fn, :age => 'monthly')
136
+ ap << "random message\n"
137
+ assert_equal 4, Dir.glob(@glob).length
138
+
139
+ start = now - 3600 * 24 * 31
140
+ ::File.utime(start, start, age_fn)
141
+
142
+ sleep 0.250
143
+ ap << "yet another random message\n"
144
+ assert_equal 5, Dir.glob(@glob).length
145
+ end
146
+
147
+ def test_size
148
+ assert_equal [], Dir.glob(@glob)
149
+
150
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
151
+ :filename => @fn, :size => 100)
152
+
153
+ ap << 'X' * 100; ap.flush
154
+ assert_equal 1, Dir.glob(@glob).length
155
+ assert_equal 100, File.size(@fn)
156
+
157
+ # this character is appended to the log file (bringing its size to 101)
158
+ # and THEN the file is rolled resulting in a new, empty log file
159
+ ap << 'X'
160
+ assert_equal 2, Dir.glob(@glob).length
161
+ assert_equal 0, File.size(@fn)
162
+
163
+ ap << 'X' * 100; ap.flush
164
+ assert_equal 2, Dir.glob(@glob).length
165
+ assert_equal 100, File.size(@fn)
166
+
167
+ ap << 'X'
168
+ assert_equal 3, Dir.glob(@glob).length
169
+ assert_equal 0, File.size(@fn)
170
+
171
+ cleanup
172
+ end
173
+
174
+ def test_file_removed
175
+ assert_equal [], Dir.glob(@glob)
176
+
177
+ ap = ::Logging::Appenders::RollingFile.new(NAME,
178
+ :filename => @fn, :size => 100)
179
+
180
+ ap << 'X' * 100; ap.flush
181
+ assert_equal 1, Dir.glob(@glob).length
182
+ assert_equal 100, File.size(@fn)
183
+
184
+ # Now remove @fn and make sure that the log file is written to
185
+ # again
186
+ File.unlink(@fn)
187
+ assert_equal 0, Dir.glob(@glob).length
188
+
189
+ ap << 'X' * 50; ap.flush
190
+ assert_equal 1, Dir.glob(@glob).length
191
+ assert_equal 50, File.size(@fn)
192
+
193
+ end
194
+
195
+ private
196
+ def cleanup
197
+ unless ::Logging::Appender[NAME].nil?
198
+ ::Logging::Appender[NAME].close false
199
+ ::Logging::Appender[NAME] = nil
200
+ end
201
+ end
202
+
203
+ end # class TestRollingFile
204
+ end # module TestAppenders
205
+ end # module TestLogging
206
+
207
+ # EOF