logging 1.4.3 → 1.5.0

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 (50) hide show
  1. data/History.txt +8 -0
  2. data/Rakefile +2 -4
  3. data/examples/colorization.rb +62 -0
  4. data/lib/logging.rb +22 -8
  5. data/lib/logging/appender.rb +7 -7
  6. data/lib/logging/appenders/buffering.rb +30 -24
  7. data/lib/logging/appenders/email.rb +7 -11
  8. data/lib/logging/appenders/file.rb +0 -1
  9. data/lib/logging/appenders/io.rb +8 -14
  10. data/lib/logging/appenders/rolling_file.rb +9 -13
  11. data/lib/logging/appenders/string_io.rb +0 -1
  12. data/lib/logging/appenders/syslog.rb +1 -1
  13. data/lib/logging/color_scheme.rb +249 -0
  14. data/lib/logging/layouts/basic.rb +2 -3
  15. data/lib/logging/layouts/parseable.rb +5 -7
  16. data/lib/logging/layouts/pattern.rb +77 -18
  17. data/lib/logging/log_event.rb +1 -1
  18. data/lib/logging/logger.rb +3 -4
  19. data/lib/logging/proxy.rb +57 -0
  20. data/lib/logging/utils.rb +3 -2
  21. data/test/appenders/test_buffered_io.rb +2 -7
  22. data/test/appenders/test_console.rb +1 -1
  23. data/test/appenders/test_email.rb +1 -1
  24. data/test/appenders/test_file.rb +1 -1
  25. data/test/appenders/test_growl.rb +1 -1
  26. data/test/appenders/test_io.rb +4 -5
  27. data/test/appenders/test_rolling_file.rb +1 -1
  28. data/test/appenders/test_syslog.rb +1 -1
  29. data/test/benchmark.rb +15 -11
  30. data/test/config/test_configurator.rb +1 -1
  31. data/test/config/test_yaml_configurator.rb +1 -1
  32. data/test/layouts/test_basic.rb +1 -1
  33. data/test/layouts/test_color_pattern.rb +90 -0
  34. data/test/layouts/test_json.rb +1 -1
  35. data/test/layouts/test_pattern.rb +4 -5
  36. data/test/layouts/test_yaml.rb +1 -1
  37. data/test/test_appender.rb +1 -1
  38. data/test/test_color_scheme.rb +39 -0
  39. data/test/test_consolidate.rb +1 -1
  40. data/test/test_layout.rb +1 -1
  41. data/test/test_log_event.rb +1 -1
  42. data/test/test_logger.rb +1 -1
  43. data/test/test_logging.rb +1 -1
  44. data/test/test_proxy.rb +67 -0
  45. data/test/test_repository.rb +2 -2
  46. data/test/test_root_logger.rb +1 -1
  47. data/test/test_stats.rb +1 -1
  48. data/test/test_utils.rb +1 -1
  49. data/version.txt +1 -1
  50. metadata +40 -17
@@ -11,7 +11,7 @@ module Logging
11
11
  # * $1 == filename
12
12
  # * $2 == line number
13
13
  # * $3 == method name (might be nil)
14
- CALLER_RGXP = %r/([\.\/\(\)\w]+):(\d+)(?::in `(\w+)')?/o
14
+ CALLER_RGXP = %r/([-\.\/\(\)\w]+):(\d+)(?::in `(\w+)')?/o
15
15
  CALLER_INDEX = 2
16
16
  #CALLER_INDEX = RUBY_PLATFORM[%r/^java/i] ? 1 : 2
17
17
  # :startdoc:
@@ -434,7 +434,7 @@ module Logging
434
434
  #
435
435
  # Configures internal variables for the logger. This method can be used
436
436
  # to avoid storing the logger in the repository.
437
- #
437
+ #
438
438
  def _setup( name, opts = {} )
439
439
  @name = name
440
440
  @parent = opts.getopt(:parent)
@@ -498,7 +498,6 @@ module Logging
498
498
  end
499
499
  # :startdoc:
500
500
 
501
- end # class Logger
502
- end # module Logging
501
+ end # Logger
502
+ end # Logging
503
503
 
504
- # EOF
@@ -0,0 +1,57 @@
1
+
2
+ module Logging
3
+
4
+ # Defines a Proxy that will log all method calls on the proxied object. This
5
+ # class uses +method_missing+ on a "blank slate" object to intercept all
6
+ # method calls. The method name being called and the arguments are all
7
+ # logged to the proxied object's logger instance. The log level and other
8
+ # settings for the proxied object are honored by the Proxy instance.
9
+ #
10
+ # If you want, you can also supply your own +method_missing+ code as a block
11
+ # to the constructor.
12
+ #
13
+ # Proxy.new(object) do |name, *args, &block|
14
+ # # code to be executed before the proxied method
15
+ # result = @object.send(name, *args, &block)
16
+ # # code to be executed after the proxied method
17
+ # result # <-- always return the result
18
+ # end
19
+ #
20
+ # The proxied object is avaiable as the "@object" variable. The logger is
21
+ # available as the "@logger" variable.
22
+ #
23
+ class Proxy
24
+
25
+ # :stopdoc:
26
+ KEEPERS = %r/^__|^object_id$|^initialize$/
27
+ instance_methods(true).each { |m| undef_method m unless m[KEEPERS] }
28
+ private_instance_methods(true).each { |m| undef_method m unless m[KEEPERS] }
29
+ # :startdoc:
30
+
31
+ # Create a new proxy for the given _object_. If an optional _block_ is
32
+ # given it will be called before the proxied method. This _block_ will
33
+ # replace the +method_missing+ implementation
34
+ #
35
+ def initialize( object, &block )
36
+ @object = object
37
+ @leader = @object.is_a?(Class) ? "#{@object.name}." : "#{@object.class.name}#"
38
+ @logger = Logging.logger[object]
39
+
40
+ if block
41
+ eigenclass = class << self; self; end
42
+ eigenclass.__send__(:define_method, :method_missing, &block)
43
+ end
44
+ end
45
+
46
+ # All hail the magic of method missing. Here is where we are going to log
47
+ # the method call and then forward to the proxied object. The return value
48
+ # from the proxied objet method call is passed back.
49
+ #
50
+ def method_missing( name, *args, &block )
51
+ @logger << "#@leader#{name}(#{args.inspect[1..-2]})\n"
52
+ @object.send(name, *args, &block)
53
+ end
54
+
55
+ end # Proxy
56
+ end # Logging
57
+
data/lib/logging/utils.rb CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ require 'thread'
3
+
2
4
  # --------------------------------------------------------------------------
3
5
  class Hash
4
6
 
@@ -196,6 +198,5 @@ class ReentrantMutex < Mutex
196
198
  }
197
199
  end
198
200
  end
199
- end # class ReentrantMutex
201
+ end # ReentrantMutex
200
202
 
201
- # EOF
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestAppenders
@@ -135,15 +135,10 @@ module TestAppenders
135
135
  end
136
136
 
137
137
  def test_flush
138
- ary = []
139
- @sio.instance_variable_set :@ary, ary
140
- def @sio.flush() @ary << :flush end
141
-
142
138
  @appender << "this is a test message\n"
143
139
  assert_nil(readline)
144
140
 
145
141
  @appender.flush
146
- assert_equal :flush, ary.pop
147
142
  assert_equal "this is a test message\n", readline
148
143
  assert_nil(readline)
149
144
  end
@@ -163,7 +158,7 @@ module TestAppenders
163
158
  assert_nil(readline)
164
159
  end
165
160
 
166
- private
161
+ private
167
162
  def readline
168
163
  @appender.readline
169
164
  end
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestAppenders
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
  require 'flexmock'
4
4
 
5
5
  module TestLogging
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestAppenders
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
  require 'flexmock'
4
4
 
5
5
  module TestLogging
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestAppenders
@@ -103,12 +103,11 @@ module TestAppenders
103
103
  end
104
104
 
105
105
  def test_flush
106
- ary = []
107
- @sio.instance_variable_set :@ary, ary
108
- def @sio.flush() @ary << :flush end
106
+ @appender.buffer << 'flush'
107
+ assert_nil @appender.readline
109
108
 
110
109
  @appender.flush
111
- assert_equal :flush, ary.pop
110
+ assert_equal 'flush', @appender.readline
112
111
  end
113
112
 
114
113
  def test_initialize
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestAppenders
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  if HAVE_SYSLOG
5
5
 
data/test/benchmark.rb CHANGED
@@ -1,15 +1,11 @@
1
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
2
+ require 'rubygems'
3
+
4
+ libpath = File.expand_path('../../lib', __FILE__)
5
+ $:.unshift libpath
6
+ require 'logging'
10
7
 
11
8
  begin
12
- require 'rubygems'
13
9
  gem 'log4r'
14
10
  require 'log4r'
15
11
  $log4r = true
@@ -26,10 +22,18 @@ module Logging
26
22
  def run
27
23
  this_many = 300_000
28
24
 
29
- sio = StringIO.new
25
+ Logging.appenders.string_io(
26
+ 'sio',
27
+ :layout => Logging.layouts.pattern(
28
+ :pattern => '%.1l, [%d] %5l -- %c: %m\n',
29
+ :date_pattern => "%Y-%m-%dT%H:%M:%S.%s"
30
+ )
31
+ )
32
+ sio = Logging.appenders['sio'].sio
30
33
 
31
- logging = ::Logging.logger sio
34
+ logging = ::Logging.logger('benchmark')
32
35
  logging.level = :warn
36
+ logging.appenders = 'sio'
33
37
 
34
38
  logger = ::Logger.new sio
35
39
  logger.level = ::Logger::WARN
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestConfig
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestConfig
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestLayouts
@@ -0,0 +1,90 @@
1
+
2
+ require File.expand_path('../../setup', __FILE__)
3
+
4
+ module TestLogging
5
+ module TestLayouts
6
+
7
+ class TestColorPattern < Test::Unit::TestCase
8
+ include LoggingTestCase
9
+ CS = ::Logging::ColorScheme
10
+
11
+ def setup
12
+ super
13
+
14
+ ::Logging.color_scheme :levels, :levels => {
15
+ :debug => :blue, :info => :green, :warn => :yellow, :error => :red, :fatal => :cyan
16
+ }
17
+
18
+ ::Logging.color_scheme :lines, :lines => {
19
+ :debug => :blue, :info => :green, :warn => :yellow, :error => :red, :fatal => :cyan
20
+ }, :date => :blue, :logger => :cyan
21
+
22
+ ::Logging.color_scheme :tokens, :date => :blue, :logger => :green, :message => :magenta
23
+
24
+ @levels = Logging::LEVELS
25
+ end
26
+
27
+ def test_level_coloring
28
+ layout = Logging.layouts.pattern(:color_scheme => :levels)
29
+ event = Logging::LogEvent.new('ArrayLogger', @levels['info'], 'log message', false)
30
+
31
+ rgxp = Regexp.new(Regexp.escape("#{CS::GREEN}INFO #{CS::RESET}"))
32
+ assert_match rgxp, layout.format(event)
33
+
34
+ event.level = @levels['debug']
35
+ rgxp = Regexp.new(Regexp.escape("#{CS::BLUE}DEBUG#{CS::RESET}"))
36
+ assert_match rgxp, layout.format(event)
37
+
38
+ event.level = @levels['error']
39
+ rgxp = Regexp.new(Regexp.escape("#{CS::RED}ERROR#{CS::RESET}"))
40
+ assert_match rgxp, layout.format(event)
41
+ end
42
+
43
+ def test_multiple_level_coloring
44
+ layout = Logging.layouts.pattern(:pattern => '%.1l, %5l -- %c: %m\n', :color_scheme => :levels)
45
+ event = Logging::LogEvent.new('ArrayLogger', @levels['info'], 'log message', false)
46
+
47
+ rgxp = Regexp.new(Regexp.escape("#{CS::GREEN}I#{CS::RESET}, #{CS::GREEN} INFO#{CS::RESET}"))
48
+ assert_match rgxp, layout.format(event)
49
+
50
+ event.level = @levels['debug']
51
+ rgxp = Regexp.new(Regexp.escape("#{CS::BLUE}D#{CS::RESET}, #{CS::BLUE}DEBUG#{CS::RESET}"))
52
+ assert_match rgxp, layout.format(event)
53
+
54
+ event.level = @levels['error']
55
+ rgxp = Regexp.new(Regexp.escape("#{CS::RED}E#{CS::RESET}, #{CS::RED}ERROR#{CS::RESET}"))
56
+ assert_match rgxp, layout.format(event)
57
+ end
58
+
59
+ def test_line_coloring
60
+ layout = Logging.layouts.pattern(:color_scheme => :lines)
61
+ event = Logging::LogEvent.new('ArrayLogger', @levels['info'], 'log message', false)
62
+
63
+ rgxp = Regexp.new('^'+Regexp.escape(CS::GREEN)+'.*?'+Regexp.escape(CS::RESET)+'$', Regexp::MULTILINE)
64
+ assert_match rgxp, layout.format(event)
65
+
66
+ event.level = @levels['error']
67
+ rgxp = Regexp.new('^'+Regexp.escape(CS::RED)+'.*?'+Regexp.escape(CS::RESET)+'$', Regexp::MULTILINE)
68
+ assert_match rgxp, layout.format(event)
69
+
70
+ event.level = @levels['warn']
71
+ rgxp = Regexp.new('^'+Regexp.escape(CS::YELLOW)+'.*?'+Regexp.escape(CS::RESET)+'$', Regexp::MULTILINE)
72
+ assert_match rgxp, layout.format(event)
73
+ end
74
+
75
+ def test_token_coloring
76
+ layout = Logging.layouts.pattern(:color_scheme => :tokens)
77
+ event = Logging::LogEvent.new('ArrayLogger', @levels['info'], 'log message', false)
78
+
79
+ rgxp = Regexp.new(
80
+ '^\['+Regexp.escape(CS::BLUE)+'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'+Regexp.escape(CS::RESET)+
81
+ '\] INFO -- '+Regexp.escape(CS::GREEN)+'ArrayLogger'+Regexp.escape(CS::RESET)+
82
+ ' : '+Regexp.escape(CS::MAGENTA)+'log message'+Regexp.escape(CS::RESET)
83
+ )
84
+ assert_match rgxp, layout.format(event)
85
+ end
86
+
87
+ end # TestColorPattern
88
+ end # TestLayouts
89
+ end # TestLogging
90
+
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestLayouts
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../../setup', __FILE__)
3
3
 
4
4
  module TestLogging
5
5
  module TestLayouts
@@ -191,8 +191,7 @@ module TestLayouts
191
191
  assert_equal 'message{42}', @layout.format(event)
192
192
  end
193
193
 
194
- end # class TestBasic
195
- end # module TestLayouts
196
- end # module TestLogging
194
+ end # TestBasic
195
+ end # TestLayouts
196
+ end # TestLogging
197
197
 
198
- # EOF
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[.. setup])
2
+ require File.expand_path('../setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
  module TestLayouts
@@ -1,5 +1,5 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), %w[setup])
2
+ require File.expand_path('setup', File.dirname(__FILE__))
3
3
 
4
4
  module TestLogging
5
5
 
@@ -0,0 +1,39 @@
1
+
2
+ require File.expand_path('../setup', __FILE__)
3
+
4
+ module TestLogging
5
+
6
+ class TestColorScheme < Test::Unit::TestCase
7
+ include LoggingTestCase
8
+
9
+ def setup
10
+ super
11
+ ::Logging.init
12
+ end
13
+
14
+ def test_default_color_scheme
15
+ scheme = Logging.color_scheme :default
16
+ assert_instance_of ::Logging::ColorScheme, scheme
17
+
18
+ assert_equal false, scheme.include?(:debug)
19
+ assert scheme.include?(:info)
20
+ assert scheme.include?(:warn)
21
+ assert scheme.include?(:error)
22
+ assert scheme.include?(:fatal)
23
+ end
24
+
25
+ def test_lines_levels_exclusivity
26
+ assert_raise(ArgumentError) { Logging.color_scheme(:error, :lines => {}, :levels => {}) }
27
+ end
28
+
29
+ def test_colorization
30
+ scheme = Logging.color_scheme :default
31
+
32
+ assert_equal "no change", scheme.color('no change', :debug)
33
+ assert_equal "\e[32minfo is green\e[0m", scheme.color('info is green', :info)
34
+ assert_equal "\e[37m\e[41mfatal has multiple color codes\e[0m", scheme.color('fatal has multiple color codes', :fatal)
35
+ end
36
+
37
+ end # TestColorScheme
38
+ end # TestLogging
39
+