logging 1.4.3 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/Rakefile +2 -4
- data/examples/colorization.rb +62 -0
- data/lib/logging.rb +22 -8
- data/lib/logging/appender.rb +7 -7
- data/lib/logging/appenders/buffering.rb +30 -24
- data/lib/logging/appenders/email.rb +7 -11
- data/lib/logging/appenders/file.rb +0 -1
- data/lib/logging/appenders/io.rb +8 -14
- data/lib/logging/appenders/rolling_file.rb +9 -13
- data/lib/logging/appenders/string_io.rb +0 -1
- data/lib/logging/appenders/syslog.rb +1 -1
- data/lib/logging/color_scheme.rb +249 -0
- data/lib/logging/layouts/basic.rb +2 -3
- data/lib/logging/layouts/parseable.rb +5 -7
- data/lib/logging/layouts/pattern.rb +77 -18
- data/lib/logging/log_event.rb +1 -1
- data/lib/logging/logger.rb +3 -4
- data/lib/logging/proxy.rb +57 -0
- data/lib/logging/utils.rb +3 -2
- data/test/appenders/test_buffered_io.rb +2 -7
- data/test/appenders/test_console.rb +1 -1
- data/test/appenders/test_email.rb +1 -1
- data/test/appenders/test_file.rb +1 -1
- data/test/appenders/test_growl.rb +1 -1
- data/test/appenders/test_io.rb +4 -5
- data/test/appenders/test_rolling_file.rb +1 -1
- data/test/appenders/test_syslog.rb +1 -1
- data/test/benchmark.rb +15 -11
- data/test/config/test_configurator.rb +1 -1
- data/test/config/test_yaml_configurator.rb +1 -1
- data/test/layouts/test_basic.rb +1 -1
- data/test/layouts/test_color_pattern.rb +90 -0
- data/test/layouts/test_json.rb +1 -1
- data/test/layouts/test_pattern.rb +4 -5
- data/test/layouts/test_yaml.rb +1 -1
- data/test/test_appender.rb +1 -1
- data/test/test_color_scheme.rb +39 -0
- data/test/test_consolidate.rb +1 -1
- data/test/test_layout.rb +1 -1
- data/test/test_log_event.rb +1 -1
- data/test/test_logger.rb +1 -1
- data/test/test_logging.rb +1 -1
- data/test/test_proxy.rb +67 -0
- data/test/test_repository.rb +2 -2
- data/test/test_root_logger.rb +1 -1
- data/test/test_stats.rb +1 -1
- data/test/test_utils.rb +1 -1
- data/version.txt +1 -1
- metadata +40 -17
data/lib/logging/log_event.rb
CHANGED
@@ -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/([
|
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:
|
data/lib/logging/logger.rb
CHANGED
@@ -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 #
|
502
|
-
end #
|
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 #
|
201
|
+
end # ReentrantMutex
|
200
202
|
|
201
|
-
# EOF
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
require File.
|
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
|
-
|
161
|
+
private
|
167
162
|
def readline
|
168
163
|
@appender.readline
|
169
164
|
end
|
data/test/appenders/test_file.rb
CHANGED
data/test/appenders/test_io.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
require File.
|
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
|
-
|
107
|
-
@
|
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
|
110
|
+
assert_equal 'flush', @appender.readline
|
112
111
|
end
|
113
112
|
|
114
113
|
def test_initialize
|
data/test/benchmark.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
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
|
data/test/layouts/test_basic.rb
CHANGED
@@ -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
|
+
|
data/test/layouts/test_json.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
require File.
|
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 #
|
195
|
-
end #
|
196
|
-
end #
|
194
|
+
end # TestBasic
|
195
|
+
end # TestLayouts
|
196
|
+
end # TestLogging
|
197
197
|
|
198
|
-
# EOF
|
data/test/layouts/test_yaml.rb
CHANGED
data/test/test_appender.rb
CHANGED
@@ -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
|
+
|