sgeorgi-logging 1.4.2

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