filterfish-logging 0.9.8

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 (55) hide show
  1. data/History.txt +176 -0
  2. data/Manifest.txt +54 -0
  3. data/README.txt +93 -0
  4. data/Rakefile +28 -0
  5. data/data/logging.yaml +63 -0
  6. data/lib/logging.rb +288 -0
  7. data/lib/logging/appender.rb +257 -0
  8. data/lib/logging/appenders/console.rb +43 -0
  9. data/lib/logging/appenders/email.rb +131 -0
  10. data/lib/logging/appenders/file.rb +55 -0
  11. data/lib/logging/appenders/growl.rb +182 -0
  12. data/lib/logging/appenders/io.rb +81 -0
  13. data/lib/logging/appenders/rolling_file.rb +293 -0
  14. data/lib/logging/appenders/syslog.rb +202 -0
  15. data/lib/logging/config/yaml_configurator.rb +197 -0
  16. data/lib/logging/layout.rb +103 -0
  17. data/lib/logging/layouts/basic.rb +35 -0
  18. data/lib/logging/layouts/pattern.rb +292 -0
  19. data/lib/logging/log_event.rb +50 -0
  20. data/lib/logging/logger.rb +388 -0
  21. data/lib/logging/repository.rb +151 -0
  22. data/lib/logging/root_logger.rb +60 -0
  23. data/lib/logging/utils.rb +44 -0
  24. data/tasks/ann.rake +78 -0
  25. data/tasks/bones.rake +21 -0
  26. data/tasks/gem.rake +106 -0
  27. data/tasks/manifest.rake +49 -0
  28. data/tasks/notes.rake +22 -0
  29. data/tasks/post_load.rake +37 -0
  30. data/tasks/rdoc.rake +49 -0
  31. data/tasks/rubyforge.rake +57 -0
  32. data/tasks/setup.rb +253 -0
  33. data/tasks/svn.rake +45 -0
  34. data/tasks/test.rake +38 -0
  35. data/test/appenders/test_console.rb +40 -0
  36. data/test/appenders/test_email.rb +167 -0
  37. data/test/appenders/test_file.rb +94 -0
  38. data/test/appenders/test_growl.rb +115 -0
  39. data/test/appenders/test_io.rb +113 -0
  40. data/test/appenders/test_rolling_file.rb +187 -0
  41. data/test/appenders/test_syslog.rb +192 -0
  42. data/test/benchmark.rb +88 -0
  43. data/test/config/test_yaml_configurator.rb +41 -0
  44. data/test/layouts/test_basic.rb +44 -0
  45. data/test/layouts/test_pattern.rb +173 -0
  46. data/test/setup.rb +66 -0
  47. data/test/test_appender.rb +162 -0
  48. data/test/test_layout.rb +85 -0
  49. data/test/test_log_event.rb +81 -0
  50. data/test/test_logger.rb +589 -0
  51. data/test/test_logging.rb +250 -0
  52. data/test/test_repository.rb +123 -0
  53. data/test/test_root_logger.rb +82 -0
  54. data/test/test_utils.rb +48 -0
  55. metadata +126 -0
data/test/benchmark.rb ADDED
@@ -0,0 +1,88 @@
1
+ # $Id$
2
+
3
+ begin
4
+ require 'logging'
5
+ rescue LoadError
6
+ path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ raise if $:.include? path
8
+ $: << path
9
+ retry
10
+ end
11
+
12
+ begin
13
+ require 'rubygems'
14
+ gem 'log4r'
15
+ require 'log4r'
16
+ $log4r = true
17
+ rescue LoadError
18
+ $log4r = false
19
+ end
20
+
21
+ require 'benchmark'
22
+ require 'stringio'
23
+ require 'logger'
24
+
25
+ module Logging
26
+ class Benchmark
27
+
28
+ def run
29
+ this_many = 300_000
30
+
31
+ sio = StringIO.new
32
+
33
+ logging = ::Logging.logger sio
34
+ logging.level = :warn
35
+
36
+ logger = ::Logger.new sio
37
+ logger.level = ::Logger::WARN
38
+
39
+ log4r = if $log4r
40
+ x = ::Log4r::Logger.new('benchmark')
41
+ x.level = ::Log4r::WARN
42
+ x.add ::Log4r::IOOutputter.new(
43
+ 'benchmark', sio,
44
+ :formatter => ::Log4r::PatternFormatter.new(
45
+ :pattern => "%.1l, [%d #\#{Process.pid}] %5l : %M\n",
46
+ :date_pattern => "%Y-%m-%dT%H:%M:%S.\#{Time.now.usec}"
47
+ )
48
+ )
49
+ x
50
+ end
51
+
52
+ puts "== Debug (not logged) ==\n"
53
+ ::Benchmark.bm(10) do |bm|
54
+ bm.report('Logging:') {this_many.times {logging.debug 'not logged'}}
55
+ bm.report('Logger:') {this_many.times {logger.debug 'not logged'}}
56
+ bm.report('Log4r:') {this_many.times {log4r.debug 'not logged'}} if log4r
57
+ end
58
+
59
+ puts "\n== Warn (logged) ==\n"
60
+ ::Benchmark.bm(10) do |bm|
61
+ sio.seek 0
62
+ bm.report('Logging:') {this_many.times {logging.warn 'logged'}}
63
+ sio.seek 0
64
+ bm.report('Logger:') {this_many.times {logger.warn 'logged'}}
65
+ sio.seek 0
66
+ bm.report('Log4r:') {this_many.times {log4r.warn 'logged'}} if log4r
67
+ end
68
+
69
+ puts "\n== Concat ==\n"
70
+ ::Benchmark.bm(10) do |bm|
71
+ sio.seek 0
72
+ bm.report('Logging:') {this_many.times {logging << 'logged'}}
73
+ sio.seek 0
74
+ bm.report('Logger:') {this_many.times {logger << 'logged'}}
75
+ puts "Log4r: not supported" if log4r
76
+ end
77
+ end
78
+
79
+ end # class Benchmark
80
+ end # module Logging
81
+
82
+
83
+ if __FILE__ == $0
84
+ bm = ::Logging::Benchmark.new
85
+ bm.run
86
+ end
87
+
88
+ # EOF
@@ -0,0 +1,41 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[.. setup])
4
+
5
+ module TestLogging
6
+ module TestConfig
7
+
8
+ class TestYamlConfigurator < Test::Unit::TestCase
9
+ include LoggingTestCase
10
+
11
+ def test_class_load
12
+ assert_raise(::Logging::Config::YamlConfigurator::Error) {
13
+ ::Logging::Config::YamlConfigurator.load(Object.new)
14
+ }
15
+
16
+ begin
17
+ fd = File.open('data/logging.yaml','r')
18
+ assert_nothing_raised {
19
+ ::Logging::Config::YamlConfigurator.load(fd)
20
+ }
21
+ ensure
22
+ fd.close
23
+ end
24
+ end
25
+
26
+ def test_initialize
27
+ io = StringIO.new
28
+ io << YAML.dump({:one => 1, :two => 2, :three => 3})
29
+ io.seek 0
30
+
31
+ assert_raise(::Logging::Config::YamlConfigurator::Error) {
32
+ ::Logging::Config::YamlConfigurator.new(io, :meh)
33
+ }
34
+ end
35
+
36
+ end # class TestYamlConfigurator
37
+
38
+ end # module TestConfig
39
+ end # module TestLogging
40
+
41
+ # EOF
@@ -0,0 +1,44 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[.. setup])
4
+
5
+ module TestLogging
6
+ module TestLayouts
7
+
8
+ class TestBasic < Test::Unit::TestCase
9
+ include LoggingTestCase
10
+
11
+ def setup
12
+ super
13
+ ::Logging.init
14
+ @layout = ::Logging::Layouts::Basic.new
15
+ @levels = ::Logging::LEVELS
16
+ end
17
+
18
+ def test_format
19
+ event = ::Logging::LogEvent.new( 'ArrayLogger', @levels['info'],
20
+ 'log message', false)
21
+ assert_equal " INFO ArrayLogger : log message\n", @layout.format(event)
22
+
23
+ event.data = [1, 2, 3, 4]
24
+ assert_equal(" INFO ArrayLogger : <Array> #{[1,2,3,4]}\n",
25
+ @layout.format(event))
26
+
27
+ event.level = @levels['debug']
28
+ event.data = 'and another message'
29
+ log = "DEBUG ArrayLogger : and another message\n"
30
+ assert_equal log, @layout.format(event)
31
+
32
+ event.logger = 'Test'
33
+ event.level = @levels['fatal']
34
+ event.data = Exception.new
35
+ log = "FATAL Test : <Exception> Exception\n"
36
+ assert_equal log, @layout.format(event)
37
+ end
38
+
39
+ end # class TestBasic
40
+
41
+ end # module TestLayouts
42
+ end # module TestLogging
43
+
44
+ # EOF
@@ -0,0 +1,173 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[.. setup])
4
+
5
+ module TestLogging
6
+ module TestLayouts
7
+
8
+ class TestPattern < Test::Unit::TestCase
9
+ include LoggingTestCase
10
+
11
+ def setup
12
+ super
13
+ ::Logging.init
14
+ @layout = ::Logging::Layouts::Pattern.new
15
+ @levels = ::Logging::LEVELS
16
+ @date_fmt = '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'
17
+ end
18
+
19
+ def test_date_method
20
+ assert_nil @layout.date_method
21
+ end
22
+
23
+ def test_date_method_eq
24
+ @layout.date_method = :to_f
25
+ assert_equal :to_f, @layout.date_method
26
+ assert_instance_of Float, @layout.format_date
27
+
28
+ @layout.date_method = 'usec'
29
+ assert_equal 'usec', @layout.date_method
30
+ assert_instance_of Fixnum, @layout.format_date
31
+
32
+ @layout.date_method = :to_s
33
+ assert_equal :to_s, @layout.date_method
34
+ assert_instance_of String, @layout.format_date
35
+
36
+ # now, even if we have defined a date_pattern, the date_method should
37
+ # supersede the date_pattern
38
+ @layout.date_pattern = '%Y'
39
+
40
+ @layout.date_method = 'usec'
41
+ assert_equal 'usec', @layout.date_method
42
+ assert_instance_of Fixnum, @layout.format_date
43
+ end
44
+
45
+ def test_date_pattern
46
+ assert_equal '%Y-%m-%d %H:%M:%S', @layout.date_pattern
47
+ end
48
+
49
+ def test_date_pattern_eq
50
+ @layout.date_pattern = '%Y'
51
+ assert_equal '%Y', @layout.date_pattern
52
+ assert_match %r/\A\d{4}\z/, @layout.format_date
53
+
54
+ @layout.date_pattern = '%H:%M'
55
+ assert_equal '%H:%M', @layout.date_pattern
56
+ assert_match %r/\A\d{2}:\d{2}\z/, @layout.format_date
57
+ end
58
+
59
+ def test_format
60
+ fmt = '\[' + @date_fmt + '\] %s -- %s : %s\n'
61
+
62
+ event = ::Logging::LogEvent.new('ArrayLogger', @levels['info'],
63
+ 'log message', false)
64
+ rgxp = Regexp.new(sprintf(fmt, 'INFO ', 'ArrayLogger', 'log message'))
65
+ assert_match rgxp, @layout.format(event)
66
+
67
+ event.data = [1, 2, 3, 4]
68
+ rgxp = Regexp.new(sprintf(fmt, 'INFO ', 'ArrayLogger',
69
+ Regexp.escape("<Array> #{[1,2,3,4]}")))
70
+ assert_match rgxp, @layout.format(event)
71
+
72
+ event.level = @levels['debug']
73
+ event.data = 'and another message'
74
+ rgxp = Regexp.new(
75
+ sprintf(fmt, 'DEBUG', 'ArrayLogger', 'and another message'))
76
+ assert_match rgxp, @layout.format(event)
77
+
78
+ event.logger = 'Test'
79
+ event.level = @levels['fatal']
80
+ event.data = Exception.new
81
+ rgxp = Regexp.new(
82
+ sprintf(fmt, 'FATAL', 'Test', '<Exception> Exception'))
83
+ assert_match rgxp, @layout.format(event)
84
+ end
85
+
86
+ def test_format_date
87
+ rgxp = Regexp.new @date_fmt
88
+ assert_match rgxp, @layout.format_date
89
+ end
90
+
91
+ def test_pattern
92
+ assert_equal "[%d] %-5l -- %c : %m\n", @layout.pattern
93
+ end
94
+
95
+ def test_pattern_eq
96
+ event = ::Logging::LogEvent.new('TestLogger', @levels['info'],
97
+ ['log message'], false)
98
+
99
+ @layout.pattern = '%d'
100
+ assert_equal '%d', @layout.pattern
101
+ assert_match Regexp.new(@date_fmt), @layout.format(event)
102
+ end
103
+
104
+ def test_pattern_all
105
+ event = ::Logging::LogEvent.new('TestLogger', @levels['info'],
106
+ 'log message', false)
107
+ event.instance_variable_set :@file, 'test_file.rb'
108
+ event.instance_variable_set :@line, '123'
109
+ event.instance_variable_set :@method, 'method_name'
110
+
111
+ @layout.pattern = '%c'
112
+ assert_equal 'TestLogger', @layout.format(event)
113
+
114
+ @layout.pattern = '%d'
115
+ assert_match Regexp.new(@date_fmt), @layout.format(event)
116
+
117
+ @layout.pattern = '%F'
118
+ assert_equal 'test_file.rb', @layout.format(event)
119
+
120
+ @layout.pattern = '%l'
121
+ assert_equal 'INFO', @layout.format(event)
122
+
123
+ @layout.pattern = '%L'
124
+ assert_equal '123', @layout.format(event)
125
+
126
+ @layout.pattern = '%m'
127
+ assert_equal 'log message', @layout.format(event)
128
+
129
+ @layout.pattern = '%M'
130
+ assert_equal 'method_name', @layout.format(event)
131
+
132
+ @layout.pattern = '%p'
133
+ assert_match %r/\A\d+\z/, @layout.format(event)
134
+
135
+ @layout.pattern = '%r'
136
+ assert_match %r/\A\d+\z/, @layout.format(event)
137
+
138
+ @layout.pattern = '%t'
139
+ assert_match %r/\A-?\d+\z/, @layout.format(event)
140
+
141
+ @layout.pattern = '%%'
142
+ assert_equal '%', @layout.format(event)
143
+
144
+ # 'z' is not a recognized format character
145
+ assert_raise(ArgumentError) {
146
+ @layout.pattern = '[%d] %% %c - %l %z blah'
147
+ }
148
+ assert_equal '%', @layout.format(event)
149
+
150
+ @layout.pattern = '%5l'
151
+ assert_equal ' INFO', @layout.format(event)
152
+
153
+ @layout.pattern = '%-5l'
154
+ assert_equal 'INFO ', @layout.format(event)
155
+
156
+ @layout.pattern = '%.1l, %c'
157
+ assert_equal 'I, TestLogger', @layout.format(event)
158
+
159
+ @layout.pattern = '%7.7m'
160
+ assert_equal 'log mes', @layout.format(event)
161
+
162
+ event.data = 'tim'
163
+ assert_equal ' tim', @layout.format(event)
164
+
165
+ @layout.pattern = '%-7.7m'
166
+ assert_equal 'tim ', @layout.format(event)
167
+ end
168
+
169
+ end # class TestBasic
170
+ end # module TestLayouts
171
+ end # module TestLogging
172
+
173
+ # EOF
data/test/setup.rb ADDED
@@ -0,0 +1,66 @@
1
+ # $Id$
2
+
3
+ # Equivalent to a header guard in C/C++
4
+ # Used to prevent the class/module from being loaded more than once
5
+ unless defined? LOGGING_TEST_SETUP
6
+ LOGGING_TEST_SETUP = true
7
+
8
+ require 'rubygems'
9
+ require 'test/unit'
10
+ require 'fileutils'
11
+ require 'stringio'
12
+ require 'turn' rescue nil
13
+
14
+ # This line is needed for Ruby 1.9 -- hashes throw a "KeyError" in 1.9
15
+ # whereas they throw an "IndexError" in 1.8
16
+ #
17
+ KeyError = IndexError if not defined? KeyError
18
+
19
+ require File.join(File.dirname(__FILE__), %w[.. lib logging])
20
+
21
+
22
+ module TestLogging
23
+ module LoggingTestCase
24
+
25
+ TMP = 'tmp'
26
+
27
+ def setup
28
+ super
29
+
30
+ FileUtils.rm_rf TMP
31
+ FileUtils.mkdir TMP
32
+
33
+ ::Logging.module_eval do
34
+ ::Logging::LEVELS.clear
35
+ ::Logging::LNAMES.clear
36
+ remove_const :MAX_LEVEL_LENGTH if const_defined? :MAX_LEVEL_LENGTH
37
+ remove_const :OBJ_FORMAT if const_defined? :OBJ_FORMAT
38
+ end
39
+
40
+ ::Logging::Repository.class_eval do
41
+ if defined?(@singleton__instance__)
42
+ @singleton__instance__ = nil
43
+ else
44
+ @__instance__ = nil
45
+ class << self
46
+ nonce = class << Singleton; self; end
47
+ define_method(:instance, nonce::FirstInstanceCall)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def teardown
54
+ super
55
+ h = ::Logging::Appender.instance_variable_get(:@appenders)
56
+ h.each_value {|a| a.close(false) unless a.nil? || a.closed?}
57
+ h.clear
58
+ FileUtils.rm_rf TMP
59
+ end
60
+
61
+ end # module LoggingTestCase
62
+ end # module TestLogging
63
+
64
+ end # unless defined?
65
+
66
+ # EOF
@@ -0,0 +1,162 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[setup])
4
+
5
+ module TestLogging
6
+
7
+ class TestAppender < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+
10
+ def setup
11
+ super
12
+
13
+ ::Logging.init
14
+ @levels = ::Logging::LEVELS
15
+ @event = ::Logging::LogEvent.new('logger', @levels['debug'],
16
+ 'message', false)
17
+ @appender = ::Logging::Appender.new 'test_appender'
18
+ end
19
+
20
+ def test_append
21
+ ary = []
22
+ @appender.instance_variable_set :@ary, ary
23
+ def @appender.write( event )
24
+ str = event.instance_of?(::Logging::LogEvent) ?
25
+ @layout.format(event) : event.to_s
26
+ @ary << str
27
+ end
28
+
29
+ assert_nothing_raised {@appender.append @event}
30
+ assert_equal "DEBUG logger : message\n", ary.pop
31
+
32
+ @appender.level = :info
33
+ @appender.append @event
34
+ assert_nil ary.pop
35
+
36
+ @event.level = @levels['info']
37
+ @appender.append @event
38
+ assert_equal " INFO logger : message\n", ary.pop
39
+
40
+ @appender.close
41
+ assert_raise(RuntimeError) {@appender.append @event}
42
+ end
43
+
44
+ def test_class_stderr
45
+ stderr = ::Logging::Appender.stderr
46
+ assert_instance_of ::Logging::Appenders::Stderr, stderr
47
+ assert_equal 'stderr', stderr.name
48
+ assert_same stderr, ::Logging::Appender.stderr
49
+ end
50
+
51
+ def test_class_stdout
52
+ stdout = ::Logging::Appender.stdout
53
+ assert_instance_of ::Logging::Appenders::Stdout, stdout
54
+ assert_equal 'stdout', stdout.name
55
+ assert_same stdout, ::Logging::Appender.stdout
56
+ end
57
+
58
+ def test_close
59
+ assert_equal false, @appender.closed?
60
+
61
+ @appender.close
62
+ assert_equal true, @appender.closed?
63
+ end
64
+
65
+ def test_closed_eh
66
+ assert_equal false, @appender.closed?
67
+
68
+ @appender.close
69
+ assert_equal true, @appender.closed?
70
+ end
71
+
72
+ def test_concat
73
+ ary = []
74
+ @appender.instance_variable_set :@ary, ary
75
+ def @appender.write( event )
76
+ str = event.instance_of?(::Logging::LogEvent) ?
77
+ @layout.format(event) : event.to_s
78
+ @ary << str
79
+ end
80
+
81
+ assert_nothing_raised {@appender << 'log message'}
82
+ assert_equal 'log message', ary.pop
83
+
84
+ @appender.level = :off
85
+ @appender << 'another log message'
86
+ assert_nil ary.pop
87
+
88
+ layout = @appender.layout
89
+ def layout.footer() 'this is the footer' end
90
+
91
+ @appender.close
92
+ assert_raise(RuntimeError) {@appender << 'log message'}
93
+ assert_equal 'this is the footer', ary.pop
94
+ end
95
+
96
+ def test_flush
97
+ assert_same @appender, @appender.flush
98
+ end
99
+
100
+ def test_initialize
101
+ assert_raise(TypeError) {::Logging::Appender.new 'test', :layout => []}
102
+
103
+ layout = ::Logging::Layouts::Basic.new
104
+ @appender = ::Logging::Appender.new 'test', :layout => layout
105
+ assert_same layout, @appender.instance_variable_get(:@layout)
106
+ end
107
+
108
+ def test_layout
109
+ assert_instance_of ::Logging::Layouts::Basic, @appender.layout
110
+ end
111
+
112
+ def test_layout_eq
113
+ layout = ::Logging::Layouts::Basic.new
114
+ assert_not_equal layout, @appender.layout
115
+
116
+ assert_raise(TypeError) {@appender.layout = Object.new}
117
+ assert_raise(TypeError) {@appender.layout = 'not a layout'}
118
+
119
+ @appender.layout = layout
120
+ assert_same layout, @appender.layout
121
+ end
122
+
123
+ def test_level
124
+ assert_equal 0, @appender.level
125
+ end
126
+
127
+ def test_level_eq
128
+ assert_equal 0, @appender.level
129
+
130
+ assert_raise(ArgumentError) {@appender.level = -1}
131
+ assert_raise(ArgumentError) {@appender.level = 6}
132
+ assert_raise(ArgumentError) {@appender.level = Object}
133
+ assert_raise(ArgumentError) {@appender.level = 'bob'}
134
+ assert_raise(ArgumentError) {@appender.level = :wtf}
135
+
136
+ @appender.level = 'INFO'
137
+ assert_equal 1, @appender.level
138
+
139
+ @appender.level = :warn
140
+ assert_equal 2, @appender.level
141
+
142
+ @appender.level = 'error'
143
+ assert_equal 3, @appender.level
144
+
145
+ @appender.level = 4
146
+ assert_equal 4, @appender.level
147
+
148
+ @appender.level = 'off'
149
+ assert_equal 5, @appender.level
150
+
151
+ @appender.level = :all
152
+ assert_equal 0, @appender.level
153
+ end
154
+
155
+ def test_name
156
+ assert_equal 'test_appender', @appender.name
157
+ end
158
+
159
+ end # class TestAppender
160
+ end # module TestLogging
161
+
162
+ # EOF