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,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.new(
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.new(:pattern => '%5l %c : %m')
175
+ ::Logging::Appenders::Syslog.new(
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 TestIO
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,87 @@
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 'stringio'
22
+ require 'logger'
23
+
24
+ module Logging
25
+ class Benchmark
26
+
27
+ def run
28
+ this_many = 300_000
29
+
30
+ sio = StringIO.new
31
+
32
+ logging = ::Logging.logger sio
33
+ logging.level = :warn
34
+
35
+ logger = ::Logger.new sio
36
+ logger.level = ::Logger::WARN
37
+
38
+ log4r = if $log4r
39
+ x = ::Log4r::Logger.new('benchmark')
40
+ x.level = ::Log4r::WARN
41
+ x.add ::Log4r::IOOutputter.new(
42
+ 'benchmark', sio,
43
+ :formatter => ::Log4r::PatternFormatter.new(
44
+ :pattern => "%.1l, [%d #\#{Process.pid}] %5l : %M\n",
45
+ :date_pattern => "%Y-%m-%dT%H:%M:%S.\#{Time.now.usec}"
46
+ )
47
+ )
48
+ x
49
+ end
50
+
51
+ puts "== Debug (not logged) ==\n"
52
+ ::Benchmark.bm(10) do |bm|
53
+ bm.report('Logging:') {this_many.times {logging.debug 'not logged'}}
54
+ bm.report('Logger:') {this_many.times {logger.debug 'not logged'}}
55
+ bm.report('Log4r:') {this_many.times {log4r.debug 'not logged'}} if log4r
56
+ end
57
+
58
+ puts "\n== Warn (logged) ==\n"
59
+ ::Benchmark.bm(10) do |bm|
60
+ sio.seek 0
61
+ bm.report('Logging:') {this_many.times {logging.warn 'logged'}}
62
+ sio.seek 0
63
+ bm.report('Logger:') {this_many.times {logger.warn 'logged'}}
64
+ sio.seek 0
65
+ bm.report('Log4r:') {this_many.times {log4r.warn 'logged'}} if log4r
66
+ end
67
+
68
+ puts "\n== Concat ==\n"
69
+ ::Benchmark.bm(10) do |bm|
70
+ sio.seek 0
71
+ bm.report('Logging:') {this_many.times {logging << 'logged'}}
72
+ sio.seek 0
73
+ bm.report('Logger:') {this_many.times {logger << 'logged'}}
74
+ puts "Log4r: not supported" if log4r
75
+ end
76
+ end
77
+
78
+ end # class Benchmark
79
+ end # module Logging
80
+
81
+
82
+ if __FILE__ == $0
83
+ bm = ::Logging::Benchmark.new
84
+ bm.run
85
+ end
86
+
87
+ # EOF
@@ -0,0 +1,70 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ module TestLogging
5
+ module TestConfig
6
+
7
+ class TestConfigurator < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def test_configuration
11
+ begin
12
+ load Logging.path(%w[data logging.rb])
13
+ rescue Exception => err
14
+ flunk err.inspect
15
+ end
16
+
17
+ levels = {
18
+ 'deb' => 0,
19
+ 'inf' => 1,
20
+ 'prt' => 2,
21
+ 'wrn' => 3,
22
+ 'err' => 4,
23
+ 'fat' => 5
24
+ }
25
+ assert_equal levels, Logging::LEVELS
26
+ assert_equal :inspect, Logging::OBJ_FORMAT
27
+
28
+ hash = Logging::Repository.instance.instance_variable_get(:@h)
29
+ assert hash.has_key?('A::B::C')
30
+ assert hash.has_key?('yourlogger')
31
+ end
32
+
33
+ def test_simple_configuration
34
+ begin
35
+ load Logging.path(%w[data simple_logging.rb])
36
+ rescue Exception => err
37
+ flunk err.inspect
38
+ end
39
+
40
+ levels = {
41
+ 'debug' => 0,
42
+ 'info' => 1,
43
+ 'warn' => 2,
44
+ 'error' => 3,
45
+ 'fatal' => 4
46
+ }
47
+ assert_equal levels, Logging::LEVELS
48
+ assert_equal false, Logging.const_defined?('OBJ_FORMAT')
49
+
50
+ root = Logging::Logger.root
51
+ assert_equal 1, root.level
52
+ end
53
+
54
+ def test_bad_appender_configuration
55
+ assert_raise(Logging::Config::Configurator::Error) {
56
+ load Logging.path(%w[data bad_logging_1.rb])
57
+ }
58
+ end
59
+
60
+ def test_bad_layout_configuration
61
+ assert_raise(Logging::Config::Configurator::Error) {
62
+ load Logging.path(%w[data bad_logging_2.rb])
63
+ }
64
+ end
65
+ end
66
+
67
+ end # module TestConfig
68
+ end # module TestLogging
69
+
70
+ # EOF
@@ -0,0 +1,40 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ module TestLogging
5
+ module TestConfig
6
+
7
+ class TestYamlConfigurator < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def test_class_load
11
+ assert_raise(::Logging::Config::YamlConfigurator::Error) {
12
+ ::Logging::Config::YamlConfigurator.load(Object.new)
13
+ }
14
+
15
+ begin
16
+ fd = File.open('data/logging.yaml','r')
17
+ assert_nothing_raised {
18
+ ::Logging::Config::YamlConfigurator.load(fd)
19
+ }
20
+ ensure
21
+ fd.close
22
+ end
23
+ end
24
+
25
+ def test_initialize
26
+ io = StringIO.new
27
+ io << YAML.dump({:one => 1, :two => 2, :three => 3})
28
+ io.seek 0
29
+
30
+ assert_raise(::Logging::Config::YamlConfigurator::Error) {
31
+ ::Logging::Config::YamlConfigurator.new(io, :meh)
32
+ }
33
+ end
34
+
35
+ end # class TestYamlConfigurator
36
+
37
+ end # module TestConfig
38
+ end # module TestLogging
39
+
40
+ # EOF
@@ -0,0 +1,43 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ module TestLogging
5
+ module TestLayouts
6
+
7
+ class TestBasic < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def setup
11
+ super
12
+ ::Logging.init
13
+ @layout = ::Logging::Layouts::Basic.new
14
+ @levels = ::Logging::LEVELS
15
+ end
16
+
17
+ def test_format
18
+ event = ::Logging::LogEvent.new( 'ArrayLogger', @levels['info'],
19
+ 'log message', false)
20
+ assert_equal " INFO ArrayLogger : log message\n", @layout.format(event)
21
+
22
+ event.data = [1, 2, 3, 4]
23
+ assert_equal(" INFO ArrayLogger : <Array> #{[1,2,3,4]}\n",
24
+ @layout.format(event))
25
+
26
+ event.level = @levels['debug']
27
+ event.data = 'and another message'
28
+ log = "DEBUG ArrayLogger : and another message\n"
29
+ assert_equal log, @layout.format(event)
30
+
31
+ event.logger = 'Test'
32
+ event.level = @levels['fatal']
33
+ event.data = Exception.new
34
+ log = "FATAL Test : <Exception> Exception\n"
35
+ assert_equal log, @layout.format(event)
36
+ end
37
+
38
+ end # class TestBasic
39
+
40
+ end # module TestLayouts
41
+ end # module TestLogging
42
+
43
+ # EOF
@@ -0,0 +1,177 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. setup])
3
+
4
+ module TestLogging
5
+ module TestLayouts
6
+
7
+ class TestPattern < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def setup
11
+ super
12
+ ::Logging.init
13
+ @layout = ::Logging::Layouts::Pattern.new
14
+ @levels = ::Logging::LEVELS
15
+ @date_fmt = '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'
16
+ end
17
+
18
+ def test_date_method
19
+ assert_nil @layout.date_method
20
+ end
21
+
22
+ def test_date_method_eq
23
+ @layout.date_method = :to_f
24
+ assert_equal :to_f, @layout.date_method
25
+ assert_instance_of Float, @layout.format_date
26
+
27
+ @layout.date_method = 'usec'
28
+ assert_equal 'usec', @layout.date_method
29
+ assert_instance_of Fixnum, @layout.format_date
30
+
31
+ @layout.date_method = :to_s
32
+ assert_equal :to_s, @layout.date_method
33
+ assert_instance_of String, @layout.format_date
34
+
35
+ # now, even if we have defined a date_pattern, the date_method should
36
+ # supersede the date_pattern
37
+ @layout.date_pattern = '%Y'
38
+
39
+ @layout.date_method = 'usec'
40
+ assert_equal 'usec', @layout.date_method
41
+ assert_instance_of Fixnum, @layout.format_date
42
+ end
43
+
44
+ def test_date_pattern
45
+ assert_equal '%Y-%m-%d %H:%M:%S', @layout.date_pattern
46
+ end
47
+
48
+ def test_date_pattern_eq
49
+ @layout.date_pattern = '%Y'
50
+ assert_equal '%Y', @layout.date_pattern
51
+ assert_match %r/\A\d{4}\z/, @layout.format_date
52
+
53
+ @layout.date_pattern = '%H:%M'
54
+ assert_equal '%H:%M', @layout.date_pattern
55
+ assert_match %r/\A\d{2}:\d{2}\z/, @layout.format_date
56
+ end
57
+
58
+ def test_format
59
+ fmt = '\[' + @date_fmt + '\] %s -- %s : %s\n'
60
+
61
+ event = ::Logging::LogEvent.new('ArrayLogger', @levels['info'],
62
+ 'log message', false)
63
+ rgxp = Regexp.new(sprintf(fmt, 'INFO ', 'ArrayLogger', 'log message'))
64
+ assert_match rgxp, @layout.format(event)
65
+
66
+ event.data = [1, 2, 3, 4]
67
+ rgxp = Regexp.new(sprintf(fmt, 'INFO ', 'ArrayLogger',
68
+ Regexp.escape("<Array> #{[1,2,3,4]}")))
69
+ assert_match rgxp, @layout.format(event)
70
+
71
+ event.level = @levels['debug']
72
+ event.data = 'and another message'
73
+ rgxp = Regexp.new(
74
+ sprintf(fmt, 'DEBUG', 'ArrayLogger', 'and another message'))
75
+ assert_match rgxp, @layout.format(event)
76
+
77
+ event.logger = 'Test'
78
+ event.level = @levels['fatal']
79
+ event.data = Exception.new
80
+ rgxp = Regexp.new(
81
+ sprintf(fmt, 'FATAL', 'Test', '<Exception> Exception'))
82
+ assert_match rgxp, @layout.format(event)
83
+ end
84
+
85
+ def test_format_date
86
+ rgxp = Regexp.new @date_fmt
87
+ assert_match rgxp, @layout.format_date
88
+ end
89
+
90
+ def test_pattern
91
+ assert_equal "[%d] %-5l -- %c : %m\n", @layout.pattern
92
+ end
93
+
94
+ def test_pattern_eq
95
+ event = ::Logging::LogEvent.new('TestLogger', @levels['info'],
96
+ ['log message'], false)
97
+
98
+ @layout.pattern = '%d'
99
+ assert_equal '%d', @layout.pattern
100
+ assert_match Regexp.new(@date_fmt), @layout.format(event)
101
+ end
102
+
103
+ def test_pattern_all
104
+ event = ::Logging::LogEvent.new('TestLogger', @levels['info'],
105
+ 'log message', false)
106
+ event.instance_variable_set :@file, 'test_file.rb'
107
+ event.instance_variable_set :@line, '123'
108
+ event.instance_variable_set :@method, 'method_name'
109
+
110
+ @layout.pattern = '%c'
111
+ assert_equal 'TestLogger', @layout.format(event)
112
+
113
+ @layout.pattern = '%d'
114
+ assert_match Regexp.new(@date_fmt), @layout.format(event)
115
+
116
+ @layout.pattern = '%F'
117
+ assert_equal 'test_file.rb', @layout.format(event)
118
+
119
+ @layout.pattern = '%l'
120
+ assert_equal 'INFO', @layout.format(event)
121
+
122
+ @layout.pattern = '%L'
123
+ assert_equal '123', @layout.format(event)
124
+
125
+ @layout.pattern = '%m'
126
+ assert_equal 'log message', @layout.format(event)
127
+
128
+ @layout.pattern = '%M'
129
+ assert_equal 'method_name', @layout.format(event)
130
+
131
+ @layout.pattern = '%p'
132
+ assert_match %r/\A\d+\z/, @layout.format(event)
133
+
134
+ @layout.pattern = '%r'
135
+ assert_match %r/\A\d+\z/, @layout.format(event)
136
+
137
+ @layout.pattern = '%t'
138
+ assert_match %r/\A-?\d+\z/, @layout.format(event)
139
+
140
+ @layout.pattern = '%T'
141
+ assert_equal "", @layout.format(event)
142
+ Thread.current[:name] = "Main"
143
+ assert_equal "Main", @layout.format(event)
144
+
145
+ @layout.pattern = '%%'
146
+ assert_equal '%', @layout.format(event)
147
+
148
+ # 'z' is not a recognized format character
149
+ assert_raise(ArgumentError) {
150
+ @layout.pattern = '[%d] %% %c - %l %z blah'
151
+ }
152
+ assert_equal '%', @layout.format(event)
153
+
154
+ @layout.pattern = '%5l'
155
+ assert_equal ' INFO', @layout.format(event)
156
+
157
+ @layout.pattern = '%-5l'
158
+ assert_equal 'INFO ', @layout.format(event)
159
+
160
+ @layout.pattern = '%.1l, %c'
161
+ assert_equal 'I, TestLogger', @layout.format(event)
162
+
163
+ @layout.pattern = '%7.7m'
164
+ assert_equal 'log mes', @layout.format(event)
165
+
166
+ event.data = 'tim'
167
+ assert_equal ' tim', @layout.format(event)
168
+
169
+ @layout.pattern = '%-7.7m'
170
+ assert_equal 'tim ', @layout.format(event)
171
+ end
172
+
173
+ end # class TestBasic
174
+ end # module TestLayouts
175
+ end # module TestLogging
176
+
177
+ # EOF