sgeorgi-logging 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/History.txt +262 -0
  2. data/README.rdoc +115 -0
  3. data/Rakefile +32 -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/examples/appenders.rb +47 -0
  10. data/examples/classes.rb +41 -0
  11. data/examples/consolidation.rb +83 -0
  12. data/examples/fork.rb +37 -0
  13. data/examples/formatting.rb +51 -0
  14. data/examples/hierarchies.rb +73 -0
  15. data/examples/layouts.rb +48 -0
  16. data/examples/loggers.rb +29 -0
  17. data/examples/names.rb +43 -0
  18. data/examples/simple.rb +17 -0
  19. data/lib/logging.rb +528 -0
  20. data/lib/logging/appender.rb +260 -0
  21. data/lib/logging/appenders.rb +137 -0
  22. data/lib/logging/appenders/buffering.rb +178 -0
  23. data/lib/logging/appenders/console.rb +60 -0
  24. data/lib/logging/appenders/email.rb +75 -0
  25. data/lib/logging/appenders/file.rb +75 -0
  26. data/lib/logging/appenders/growl.rb +197 -0
  27. data/lib/logging/appenders/io.rb +69 -0
  28. data/lib/logging/appenders/rolling_file.rb +327 -0
  29. data/lib/logging/appenders/string_io.rb +68 -0
  30. data/lib/logging/appenders/syslog.rb +210 -0
  31. data/lib/logging/config/configurator.rb +188 -0
  32. data/lib/logging/config/yaml_configurator.rb +191 -0
  33. data/lib/logging/layout.rb +117 -0
  34. data/lib/logging/layouts.rb +47 -0
  35. data/lib/logging/layouts/basic.rb +32 -0
  36. data/lib/logging/layouts/parseable.rb +211 -0
  37. data/lib/logging/layouts/pattern.rb +311 -0
  38. data/lib/logging/log_event.rb +45 -0
  39. data/lib/logging/logger.rb +504 -0
  40. data/lib/logging/repository.rb +232 -0
  41. data/lib/logging/root_logger.rb +61 -0
  42. data/lib/logging/stats.rb +278 -0
  43. data/lib/logging/utils.rb +201 -0
  44. data/lib/spec/logging_helper.rb +34 -0
  45. data/test/appenders/test_buffered_io.rb +176 -0
  46. data/test/appenders/test_console.rb +66 -0
  47. data/test/appenders/test_email.rb +170 -0
  48. data/test/appenders/test_file.rb +95 -0
  49. data/test/appenders/test_growl.rb +127 -0
  50. data/test/appenders/test_io.rb +129 -0
  51. data/test/appenders/test_rolling_file.rb +209 -0
  52. data/test/appenders/test_syslog.rb +194 -0
  53. data/test/benchmark.rb +86 -0
  54. data/test/config/test_configurator.rb +70 -0
  55. data/test/config/test_yaml_configurator.rb +40 -0
  56. data/test/layouts/test_basic.rb +42 -0
  57. data/test/layouts/test_json.rb +112 -0
  58. data/test/layouts/test_pattern.rb +198 -0
  59. data/test/layouts/test_yaml.rb +121 -0
  60. data/test/setup.rb +43 -0
  61. data/test/test_appender.rb +152 -0
  62. data/test/test_consolidate.rb +46 -0
  63. data/test/test_layout.rb +110 -0
  64. data/test/test_log_event.rb +80 -0
  65. data/test/test_logger.rb +699 -0
  66. data/test/test_logging.rb +267 -0
  67. data/test/test_repository.rb +158 -0
  68. data/test/test_root_logger.rb +81 -0
  69. data/test/test_stats.rb +274 -0
  70. data/test/test_utils.rb +116 -0
  71. data/version.txt +1 -0
  72. metadata +227 -0
@@ -0,0 +1,209 @@
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.rolling_file(NAME, :filename => @fn)
26
+ assert_equal @fn, ap.filename
27
+ assert File.exist?(@fn)
28
+ assert_equal 0, File.size(@fn)
29
+
30
+ ap << "Just a line of text\n" # 20 bytes
31
+ ap.flush
32
+ assert_equal 20, File.size(@fn)
33
+ cleanup
34
+
35
+ # make sure we append to the current file (not truncate)
36
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn)
37
+ assert_equal @fn, ap.filename
38
+ assert_equal [@fn], Dir.glob(@glob)
39
+ assert_equal 20, File.size(@fn)
40
+
41
+ ap << "Just another line of text\n" # 26 bytes
42
+ ap.flush
43
+ assert_equal 46, File.size(@fn)
44
+ cleanup
45
+
46
+ # setting the truncate option to true should roll the current log file
47
+ # and create a new one
48
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn, :truncate => true)
49
+
50
+ log1 = sprintf(@fn_fmt, 1)
51
+ assert_equal [log1, @fn], Dir.glob(@glob).sort
52
+ assert_equal 0, File.size(@fn)
53
+ assert_equal 46, File.size(log1)
54
+
55
+ ap << "Some more text in the new file\n" # 31 bytes
56
+ ap.flush
57
+ assert_equal 31, File.size(@fn)
58
+ cleanup
59
+ end
60
+
61
+ def test_keep
62
+ assert_equal [], Dir.glob(@glob)
63
+
64
+ (1..12).each do |cnt|
65
+ name = sprintf(@fn_fmt, cnt)
66
+ File.open(name,'w') {|fd| fd.write 'X'*cnt}
67
+ end
68
+ FileUtils.touch(@fn)
69
+
70
+ # keep only five files
71
+ ap = Logging.appenders.rolling_file(NAME, :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 :copy_truncate
79
+ ap.instance_variable_get(:@roller).roll_files
80
+ assert_equal 6, Dir.glob(@glob).length
81
+
82
+ (1..5).each do |cnt|
83
+ name = sprintf(@fn_fmt, cnt)
84
+ assert_equal cnt-1, File.size(name)
85
+ end
86
+ cleanup
87
+ end
88
+
89
+ def test_age
90
+ d_glob = File.join(TMP, 'test.*.log')
91
+ dt_glob = File.join(TMP, 'test.*-*.log')
92
+ age_fn = @fn + '.age'
93
+
94
+ assert_equal [], Dir.glob(@glob)
95
+
96
+ assert_raise(ArgumentError) do
97
+ Logging.appenders.rolling_file(NAME, :filename => @fn, :age => 'bob')
98
+ end
99
+
100
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn, :age => 1)
101
+ ap << "random message\n"
102
+ assert_equal 1, Dir.glob(@glob).length
103
+
104
+ now = ::File.mtime(age_fn)
105
+ start = now - 42
106
+ ::File.utime(start, start, age_fn)
107
+ ap.instance_variable_set(:@age_fn_mtime, nil)
108
+ ap << "another random message\n"
109
+ assert_equal 1, Dir.glob(dt_glob).length
110
+
111
+ Dir.glob(d_glob).each {|fn| ::File.delete fn}
112
+ cleanup
113
+
114
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn, 'age' => 'daily')
115
+ ap << "random message\n"
116
+ assert_equal 1, Dir.glob(@glob).length
117
+
118
+ now = ::File.mtime(age_fn)
119
+ start = now - 3600 * 24
120
+ ::File.utime(start, start, age_fn)
121
+ ap.instance_variable_set(:@age_fn_mtime, nil)
122
+
123
+ sleep 0.250
124
+ ap << "yet another random message\n"
125
+ assert_equal 0, Dir.glob(dt_glob).length
126
+ assert_equal 1, Dir.glob(d_glob).length
127
+
128
+ Dir.glob(d_glob).each {|fn| ::File.delete fn}
129
+ cleanup
130
+
131
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn, :age => 'weekly')
132
+ ap << "random message\n"
133
+ assert_equal 1, Dir.glob(@glob).length
134
+
135
+ start = now - 3600 * 24 * 7
136
+ ::File.utime(start, start, age_fn)
137
+ ap.instance_variable_set(:@age_fn_mtime, nil)
138
+
139
+ sleep 0.250
140
+ ap << "yet another random message\n"
141
+ assert_equal 0, Dir.glob(dt_glob).length
142
+ assert_equal 1, Dir.glob(d_glob).length
143
+
144
+ Dir.glob(d_glob).each {|fn| ::File.delete fn}
145
+ cleanup
146
+
147
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn, :age => 'monthly')
148
+ ap << "random message\n"
149
+ assert_equal 1, Dir.glob(@glob).length
150
+
151
+ start = now - 3600 * 24 * 31
152
+ ::File.utime(start, start, age_fn)
153
+ ap.instance_variable_set(:@age_fn_mtime, nil)
154
+
155
+ sleep 0.250
156
+ ap << "yet another random message\n"
157
+ assert_equal 0, Dir.glob(dt_glob).length
158
+ assert_equal 1, Dir.glob(d_glob).length
159
+ end
160
+
161
+ def test_size
162
+ assert_equal [], Dir.glob(@glob)
163
+
164
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn, :size => 100)
165
+
166
+ ap << 'X' * 100; ap.flush
167
+ assert_equal 1, Dir.glob(@glob).length
168
+ assert_equal 100, File.size(@fn)
169
+
170
+ # this character is appended to the log file (bringing its size to 101)
171
+ # and THEN the file is rolled resulting in a new, empty log file
172
+ ap << 'X'
173
+ assert_equal 2, Dir.glob(@glob).length
174
+ assert_equal 0, File.size(@fn)
175
+
176
+ ap << 'X' * 100; ap.flush
177
+ assert_equal 2, Dir.glob(@glob).length
178
+ assert_equal 100, File.size(@fn)
179
+
180
+ ap << 'X'
181
+ assert_equal 3, Dir.glob(@glob).length
182
+ assert_equal 0, File.size(@fn)
183
+
184
+ cleanup
185
+ end
186
+
187
+ def test_file_removed
188
+ assert_equal [], Dir.glob(@glob)
189
+
190
+ ap = Logging.appenders.rolling_file(NAME, :filename => @fn, :size => 100)
191
+
192
+ ap << 'X' * 100; ap.flush
193
+ assert_equal 1, Dir.glob(@glob).length
194
+ assert_equal 100, File.size(@fn)
195
+ end
196
+
197
+ private
198
+ def cleanup
199
+ unless Logging.appenders[NAME].nil?
200
+ Logging.appenders[NAME].close false
201
+ Logging.appenders[NAME] = nil
202
+ end
203
+ end
204
+
205
+ end # class TestRollingFile
206
+ end # module TestAppenders
207
+ end # module TestLogging
208
+
209
+ # EOF
@@ -0,0 +1,194 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ if HAVE_SYSLOG
5
+
6
+ module TestLogging
7
+ module TestAppenders
8
+
9
+ class TestSyslog < Test::Unit::TestCase
10
+ include LoggingTestCase
11
+ include ::Syslog::Constants
12
+
13
+ def setup
14
+ super
15
+ Logging.init
16
+ @levels = Logging::LEVELS
17
+ @logopt = defined?(::Syslog::LOG_NDELAY) ?
18
+ (::Syslog::LOG_PERROR | ::Syslog::LOG_NDELAY) :
19
+ (::Syslog::LOG_PERROR)
20
+ end
21
+
22
+ def test_append
23
+ return if RUBY_PLATFORM =~ %r/cygwin/
24
+
25
+ stderr = IO::pipe
26
+
27
+ pid = fork do
28
+ stderr[0].close
29
+ STDERR.reopen(stderr[1])
30
+ stderr[1].close
31
+
32
+ appender = create_syslog
33
+ event = Logging::LogEvent.new('TestLogger', @levels['info'],
34
+ [1, 2, 3, 4], false)
35
+ appender.append event
36
+ event.level = @levels['debug']
37
+ event.data = 'the big log message'
38
+ appender.append event
39
+
40
+ appender.level = :warn
41
+ event.level = @levels['info']
42
+ event.data = 'this message should not get logged'
43
+ appender.append event
44
+ event.level = @levels['warn']
45
+ event.data = 'this is your last warning'
46
+ appender.append event
47
+
48
+ exit!
49
+ end
50
+
51
+ stderr[1].close
52
+ Process.waitpid(pid)
53
+
54
+ assert_equal("syslog_test: INFO TestLogger : <Array> #{[1,2,3,4]}\n",
55
+ stderr[0].gets)
56
+ assert_equal("syslog_test: DEBUG TestLogger : the big log message\n",
57
+ stderr[0].gets)
58
+ assert_equal("syslog_test: WARN TestLogger : this is your last warning\n",
59
+ stderr[0].gets)
60
+ end
61
+
62
+ def test_append_error
63
+ appender = create_syslog
64
+ appender.close false
65
+
66
+ event = Logging::LogEvent.new('TestLogger', @levels['warn'],
67
+ [1, 2, 3, 4], false)
68
+ assert_raise(RuntimeError) {appender.append event}
69
+ assert_equal true, appender.closed?
70
+ end
71
+
72
+ def test_close
73
+ appender = create_syslog
74
+ assert_equal false, appender.closed?
75
+
76
+ appender.close false
77
+ assert_equal true, appender.closed?
78
+ end
79
+
80
+ def test_concat
81
+ return if RUBY_PLATFORM =~ %r/cygwin/
82
+
83
+ stderr = IO::pipe
84
+
85
+ pid = fork do
86
+ stderr[0].close
87
+ STDERR.reopen(stderr[1])
88
+ stderr[1].close
89
+
90
+ appender = create_syslog
91
+ appender << 'this is a test message'
92
+ appender << 'this is another message'
93
+ appender << 'some other line'
94
+
95
+ exit!
96
+ end
97
+
98
+ stderr[1].close
99
+ Process.waitpid(pid)
100
+
101
+ assert_equal("syslog_test: this is a test message\n", stderr[0].gets)
102
+ assert_equal("syslog_test: this is another message\n", stderr[0].gets)
103
+ assert_equal("syslog_test: some other line\n", stderr[0].gets)
104
+ end
105
+
106
+ def test_concat_error
107
+ appender = create_syslog
108
+ appender.close false
109
+
110
+ assert_raise(RuntimeError) {appender << 'oopsy'}
111
+ assert_equal true, appender.closed?
112
+ end
113
+
114
+ def test_map_eq
115
+ appender = create_syslog
116
+
117
+ assert_equal(
118
+ [LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, LOG_CRIT],
119
+ get_map_from(appender)
120
+ )
121
+
122
+ appender.map = {
123
+ :debug => LOG_DEBUG,
124
+ :info => 'LOG_NOTICE',
125
+ :warn => :LOG_WARNING,
126
+ :error => 'log_err',
127
+ :fatal => :log_alert
128
+ }
129
+
130
+ assert_equal(
131
+ [LOG_DEBUG, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_ALERT],
132
+ get_map_from(appender)
133
+ )
134
+ end
135
+
136
+ def test_map_eq_error
137
+ appender = create_syslog
138
+
139
+ # Object is not a valid syslog level
140
+ assert_raise(ArgumentError) do
141
+ appender.map = {:debug => Object}
142
+ end
143
+
144
+ # there is no syslog level named "info"
145
+ # it should be "log_info"
146
+ assert_raise(NameError) do
147
+ appender.map = {:info => 'lg_info'}
148
+ end
149
+ end
150
+
151
+ def test_initialize_map
152
+ appender = Logging.appenders.syslog(
153
+ 'syslog_test',
154
+ :logopt => @logopt,
155
+ :map => {
156
+ :debug => :log_debug,
157
+ :info => :log_info,
158
+ :warn => :log_warning,
159
+ :error => :log_err,
160
+ :fatal => :log_alert
161
+ }
162
+ )
163
+
164
+ assert_equal(
165
+ [LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, LOG_ALERT],
166
+ get_map_from(appender)
167
+ )
168
+ end
169
+
170
+
171
+ private
172
+
173
+ def create_syslog
174
+ layout = Logging.layouts.pattern(:pattern => '%5l %c : %m')
175
+ Logging.appenders.syslog(
176
+ 'syslog_test',
177
+ :logopt => @logopt,
178
+ :facility => ::Syslog::LOG_USER,
179
+ :layout => layout
180
+ )
181
+ end
182
+
183
+ def get_map_from( syslog )
184
+ syslog.instance_variable_get :@map
185
+ end
186
+
187
+ end # class TestSyslog
188
+
189
+ end # module TestAppenders
190
+ end # module TestLogging
191
+
192
+ end # HAVE_SYSLOG
193
+
194
+ # EOF
data/test/benchmark.rb ADDED
@@ -0,0 +1,86 @@
1
+
2
+ begin
3
+ require 'logging'
4
+ rescue LoadError
5
+ path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ raise if $:.include? path
7
+ $: << path
8
+ retry
9
+ end
10
+
11
+ begin
12
+ require 'rubygems'
13
+ gem 'log4r'
14
+ require 'log4r'
15
+ $log4r = true
16
+ rescue LoadError
17
+ $log4r = false
18
+ end
19
+
20
+ require 'benchmark'
21
+ require 'logger'
22
+
23
+ module Logging
24
+ class Benchmark
25
+
26
+ def run
27
+ this_many = 300_000
28
+
29
+ sio = StringIO.new
30
+
31
+ logging = ::Logging.logger sio
32
+ logging.level = :warn
33
+
34
+ logger = ::Logger.new sio
35
+ logger.level = ::Logger::WARN
36
+
37
+ log4r = if $log4r
38
+ x = ::Log4r::Logger.new('benchmark')
39
+ x.level = ::Log4r::WARN
40
+ x.add ::Log4r::IOOutputter.new(
41
+ 'benchmark', sio,
42
+ :formatter => ::Log4r::PatternFormatter.new(
43
+ :pattern => "%.1l, [%d #\#{Process.pid}] %5l : %M\n",
44
+ :date_pattern => "%Y-%m-%dT%H:%M:%S.\#{Time.now.usec}"
45
+ )
46
+ )
47
+ x
48
+ end
49
+
50
+ puts "== Debug (not logged) ==\n"
51
+ ::Benchmark.bm(10) do |bm|
52
+ bm.report('Logging:') {this_many.times {logging.debug 'not logged'}}
53
+ bm.report('Logger:') {this_many.times {logger.debug 'not logged'}}
54
+ bm.report('Log4r:') {this_many.times {log4r.debug 'not logged'}} if log4r
55
+ end
56
+
57
+ puts "\n== Warn (logged) ==\n"
58
+ ::Benchmark.bm(10) do |bm|
59
+ sio.seek 0
60
+ bm.report('Logging:') {this_many.times {logging.warn 'logged'}}
61
+ sio.seek 0
62
+ bm.report('Logger:') {this_many.times {logger.warn 'logged'}}
63
+ sio.seek 0
64
+ bm.report('Log4r:') {this_many.times {log4r.warn 'logged'}} if log4r
65
+ end
66
+
67
+ puts "\n== Concat ==\n"
68
+ ::Benchmark.bm(10) do |bm|
69
+ sio.seek 0
70
+ bm.report('Logging:') {this_many.times {logging << 'logged'}}
71
+ sio.seek 0
72
+ bm.report('Logger:') {this_many.times {logger << 'logged'}}
73
+ puts "Log4r: not supported" if log4r
74
+ end
75
+ end
76
+
77
+ end # class Benchmark
78
+ end # module Logging
79
+
80
+
81
+ if __FILE__ == $0
82
+ bm = ::Logging::Benchmark.new
83
+ bm.run
84
+ end
85
+
86
+ # EOF