TwP-logging 0.9.7

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.
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