log4r-exceptionable 0.5.4 → 0.6.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.
- data/CHANGELOG +5 -0
- data/README.md +14 -2
- data/lib/log4r-exceptionable.rb +1 -0
- data/lib/log4r-exceptionable/configuration.rb +10 -1
- data/lib/log4r-exceptionable/helper.rb +44 -0
- data/lib/log4r-exceptionable/rack_failure_handler.rb +26 -29
- data/lib/log4r-exceptionable/resque_failure_handler.rb +24 -31
- data/lib/log4r-exceptionable/version.rb +1 -1
- data/spec/rack_failure_handler_spec.rb +48 -2
- data/spec/resque_failure_handler_spec.rb +42 -1
- metadata +3 -2
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -29,13 +29,25 @@ Add to some initializer code:
|
|
29
29
|
# The source logger is taken from the resque class raising
|
30
30
|
# the exception, rails controller raising the exception,
|
31
31
|
# or rack_env['rack.logger']
|
32
|
-
# optional
|
32
|
+
# optional - defaults to true
|
33
33
|
#
|
34
34
|
# config.use_source_logger = false
|
35
35
|
|
36
|
+
# A whitelist of the context keys to include when logging.
|
37
|
+
# If this is set, _only_these keys will show up.
|
38
|
+
# optional - defaults to nil, so all keys get included
|
39
|
+
#
|
40
|
+
# config.context_inclusions = ['rack_env.rack.version']
|
41
|
+
|
42
|
+
# A blacklist of the context keys to exclude when logging.
|
43
|
+
# If this is set, the keys in here will not show up.
|
44
|
+
# optional - defaults to nil, so no keys get excluded
|
45
|
+
#
|
46
|
+
# config.context_exclusions = ['resque_args']
|
47
|
+
|
36
48
|
end
|
37
49
|
|
38
|
-
Rails.application.config.middleware.use
|
50
|
+
Rails.application.config.middleware.use Log4rExceptionable::RackFailureHandler
|
39
51
|
Resque::Failure.backend = Log4rExceptionable::ResqueFailureHandler
|
40
52
|
|
41
53
|
All failures will be logged using the source logger or the given logger if a source is not available. The logger can be set using their log4r fullname or a log4r logger instance.
|
data/lib/log4r-exceptionable.rb
CHANGED
@@ -7,7 +7,12 @@ module Log4rExceptionable
|
|
7
7
|
class << self
|
8
8
|
# required - default loggers used if source logger not available
|
9
9
|
attr_accessor :rack_failure_logger, :resque_failure_logger
|
10
|
+
# Allows one to force use of default loggers by setting to false
|
10
11
|
attr_accessor :use_source_logger
|
12
|
+
# whitelist of context keys (e.g. keys in rack env) to include in log4r context when logging
|
13
|
+
attr_accessor :context_inclusions
|
14
|
+
# blacklist of context keys (e.g. keys in rack env) to exclude in log4r context when logging
|
15
|
+
attr_accessor :context_exclusions
|
11
16
|
end
|
12
17
|
|
13
18
|
# default values
|
@@ -27,6 +32,10 @@ module Log4rExceptionable
|
|
27
32
|
if self.resque_failure_logger
|
28
33
|
self.set_logger(:resque_failure_logger)
|
29
34
|
end
|
35
|
+
|
36
|
+
self.context_inclusions = Set.new(self.context_inclusions) if self.context_inclusions
|
37
|
+
self.context_exclusions = Set.new(self.context_exclusions) if self.context_exclusions
|
38
|
+
|
30
39
|
end
|
31
40
|
|
32
41
|
def self.set_logger(accessor)
|
@@ -35,7 +44,7 @@ module Log4rExceptionable
|
|
35
44
|
self.send("#{accessor}=", Log4r::Logger[name] || Log4r::Logger.new(name))
|
36
45
|
end
|
37
46
|
end
|
38
|
-
|
47
|
+
|
39
48
|
end
|
40
49
|
|
41
50
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Log4rExceptionable
|
2
|
+
|
3
|
+
# Configuration for the failure backends that log exceptions with log4r
|
4
|
+
#
|
5
|
+
module Helper
|
6
|
+
|
7
|
+
def log_with_context
|
8
|
+
begin
|
9
|
+
mdc = Log4r::MDC
|
10
|
+
original_mdc = mdc.get_context
|
11
|
+
|
12
|
+
begin
|
13
|
+
yield mdc
|
14
|
+
ensure
|
15
|
+
# Since this is somewhat of a global map, clean the keys
|
16
|
+
# we put in so other log messages don't see them
|
17
|
+
mdc.get_context.keys.each do |k|
|
18
|
+
mdc.remove(k) unless original_mdc.has_key?(k)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
rescue => e
|
23
|
+
$stderr.puts "Log4r Exceptionable could not log exception: " + e.message
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_context(context, key, value)
|
28
|
+
inclusions = Log4rExceptionable::Configuration.context_inclusions
|
29
|
+
exclusions = Log4rExceptionable::Configuration.context_exclusions
|
30
|
+
|
31
|
+
return if inclusions && ! inclusions.include?(key)
|
32
|
+
|
33
|
+
if exclusions
|
34
|
+
if ! exclusions.include?(key)
|
35
|
+
context.put(key, value)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
context.put(key, value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -4,6 +4,9 @@ module Log4rExceptionable
|
|
4
4
|
# A rack middleware handler that logs exceptions with log4r
|
5
5
|
#
|
6
6
|
class RackFailureHandler
|
7
|
+
|
8
|
+
include Log4rExceptionable::Helper
|
9
|
+
|
7
10
|
attr_reader :args
|
8
11
|
|
9
12
|
def initialize(app, opts = {})
|
@@ -35,51 +38,45 @@ module Log4rExceptionable
|
|
35
38
|
end
|
36
39
|
|
37
40
|
def send_to_log4r(exception, env=nil)
|
38
|
-
|
39
|
-
|
40
|
-
original_mdc = mdc.get_context
|
41
|
+
|
42
|
+
log_with_context do |context|
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
puts "Log4r Exceptionable could not extract a rack env item: " + e.message
|
50
|
-
end
|
44
|
+
# add rack env to context so our logger can report with that data
|
45
|
+
if env and env.size > 0
|
46
|
+
env.each do |k, v|
|
47
|
+
begin
|
48
|
+
add_context(context, "rack_env_#{k}", v)
|
49
|
+
rescue => e
|
50
|
+
$stderr.puts "Log4r Exceptionable could not extract a rack env item: " + e.message
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
end
|
54
|
+
|
55
|
+
# Determine exception source class if possible, and use its logger if configured to do so.
|
56
|
+
error_logger = nil
|
57
|
+
if Log4rExceptionable::Configuration.use_source_logger
|
54
58
|
controller = env['action_controller.instance']
|
55
59
|
if controller && controller.respond_to?(:logger) && controller.logger.instance_of?(Log4r::Logger)
|
56
60
|
error_logger = controller.logger
|
57
61
|
begin
|
58
|
-
|
59
|
-
|
62
|
+
add_context(context, "rack_controller_name", controller.controller_name)
|
63
|
+
add_context(context, "rack_action_name", controller.action_name)
|
60
64
|
rescue => e
|
61
|
-
puts "Log4r Exceptionable could not extract controller names: " + e.message
|
65
|
+
$stderr.puts "Log4r Exceptionable could not extract controller names: " + e.message
|
62
66
|
end
|
63
67
|
elsif env['rack.logger'] && env['rack.logger'].instance_of?(Log4r::Logger)
|
64
68
|
error_logger = env['rack.logger']
|
65
|
-
else
|
66
|
-
error_logger = Log4rExceptionable::Configuration.rack_failure_logger
|
67
|
-
end
|
68
|
-
|
69
|
-
error_logger.error(exception)
|
70
|
-
ensure
|
71
|
-
# Since this is somewhat of a global map, clean the keys
|
72
|
-
# we put in so other log messages don't see them
|
73
|
-
mdc.get_context.keys.each do |k|
|
74
|
-
mdc.remove(k) unless original_mdc.has_key?(k)
|
75
69
|
end
|
76
70
|
end
|
77
71
|
|
78
|
-
|
79
|
-
|
72
|
+
error_logger ||= Log4rExceptionable::Configuration.rack_failure_logger
|
73
|
+
|
74
|
+
error_logger.error(exception)
|
75
|
+
|
80
76
|
end
|
77
|
+
|
81
78
|
end
|
82
|
-
|
79
|
+
|
83
80
|
end
|
84
81
|
|
85
82
|
end
|
@@ -5,47 +5,40 @@ module Log4rExceptionable
|
|
5
5
|
# A Resque Failure backend that logs exceptions with log4r
|
6
6
|
#
|
7
7
|
class ResqueFailureHandler < ::Resque::Failure::Base
|
8
|
-
|
8
|
+
include Log4rExceptionable::Helper
|
9
|
+
|
9
10
|
def save
|
10
|
-
|
11
|
-
|
12
|
-
original_mdc = mdc.get_context
|
11
|
+
|
12
|
+
log_with_context do |context|
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
14
|
+
data = payload.clone
|
15
|
+
payload_class_name = data.delete('class')
|
16
|
+
payload_class = Resque.constantize(payload_class_name) rescue payload_class_name
|
17
|
+
|
18
|
+
add_context(context, "resque_worker", worker)
|
19
|
+
add_context(context, "resque_queue", queue)
|
20
|
+
add_context(context, "resque_class", payload_class)
|
21
|
+
add_context(context, "resque_args", data.delete('args'))
|
22
|
+
|
23
|
+
# add in any extra payload data, in case resque plugins have
|
24
|
+
# added to it (e.g. resque-lifecycle)
|
25
|
+
data.each do |k, v|
|
26
|
+
add_context(context, "resque_payload_#{k}", v)
|
27
|
+
end
|
29
28
|
|
29
|
+
error_logger = nil
|
30
|
+
if Log4rExceptionable::Configuration.use_source_logger
|
30
31
|
payload_class = Resque.constantize(payload['class']) rescue nil
|
31
32
|
if payload_class && payload_class.respond_to?(:logger) && payload_class.logger.instance_of?(Log4r::Logger)
|
32
33
|
error_logger = payload_class.logger
|
33
|
-
else
|
34
|
-
error_logger = Log4rExceptionable::Configuration.resque_failure_logger
|
35
|
-
end
|
36
|
-
|
37
|
-
error_logger.error(exception)
|
38
|
-
ensure
|
39
|
-
# Since this is somewhat of a global map, clean the keys
|
40
|
-
# we put in so other log messages don't see them
|
41
|
-
mdc.get_context.keys.each do |k|
|
42
|
-
mdc.remove(k) unless original_mdc.has_key?(k)
|
43
34
|
end
|
44
35
|
end
|
45
36
|
|
46
|
-
|
47
|
-
|
37
|
+
error_logger ||= Log4rExceptionable::Configuration.resque_failure_logger
|
38
|
+
|
39
|
+
error_logger.error(exception)
|
48
40
|
end
|
41
|
+
|
49
42
|
end
|
50
43
|
|
51
44
|
def self.count
|
@@ -58,9 +58,12 @@ describe Log4rExceptionable::RackFailureHandler do
|
|
58
58
|
|
59
59
|
context "handling rack failures" do
|
60
60
|
|
61
|
-
before(:
|
61
|
+
before(:each) do
|
62
62
|
Log4rExceptionable::Configuration.configure do |config|
|
63
63
|
config.rack_failure_logger = 'racklogger'
|
64
|
+
config.use_source_logger = true
|
65
|
+
config.context_inclusions = nil
|
66
|
+
config.context_exclusions = nil
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
@@ -119,6 +122,20 @@ describe Log4rExceptionable::RackFailureHandler do
|
|
119
122
|
}.should raise_error("I failed")
|
120
123
|
end
|
121
124
|
|
125
|
+
it "uses default logger if source logger disabled" do
|
126
|
+
Log4rExceptionable::Configuration.use_source_logger = false
|
127
|
+
Log4r::Logger.new('ControllerLogger')
|
128
|
+
Log4r::Logger['ControllerLogger'].should_not_receive(:error)
|
129
|
+
Log4r::Logger['racklogger'].should_receive(:error) do |msg|
|
130
|
+
msg.should be_instance_of RuntimeError
|
131
|
+
msg.message.should == "I failed"
|
132
|
+
end
|
133
|
+
|
134
|
+
lambda {
|
135
|
+
get "/controller_logger"
|
136
|
+
}.should raise_error("I failed")
|
137
|
+
end
|
138
|
+
|
122
139
|
it "adds controller names if set" do
|
123
140
|
Log4r::Logger.new('ControllerLogger')
|
124
141
|
Log4r::Logger['ControllerLogger'].should_receive(:error) do |msg|
|
@@ -146,7 +163,6 @@ describe Log4rExceptionable::RackFailureHandler do
|
|
146
163
|
end
|
147
164
|
|
148
165
|
it "uses default logger if rack logger is not log4r" do
|
149
|
-
|
150
166
|
Log4r::Logger['racklogger'].should_receive(:error) do |msg|
|
151
167
|
msg.should be_instance_of RuntimeError
|
152
168
|
msg.message.should == "I failed"
|
@@ -170,6 +186,36 @@ describe Log4rExceptionable::RackFailureHandler do
|
|
170
186
|
}.should raise_error("I failed")
|
171
187
|
end
|
172
188
|
|
189
|
+
it "only includes inclusions if set" do
|
190
|
+
Log4rExceptionable::Configuration.context_inclusions = ['rack_env_rack.version']
|
191
|
+
|
192
|
+
Log4r::Logger['racklogger'].should_receive(:error) do |msg|
|
193
|
+
msg.should be_instance_of RuntimeError
|
194
|
+
msg.message.should == "I failed"
|
195
|
+
Log4r::MDC.get_context.keys.should == ['rack_env_rack.version']
|
196
|
+
end
|
197
|
+
|
198
|
+
lambda {
|
199
|
+
get "/other_rack_logger"
|
200
|
+
}.should raise_error("I failed")
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
it "excludes exclusions if set" do
|
205
|
+
Log4rExceptionable::Configuration.context_exclusions = ['rack_env_rack.version']
|
206
|
+
|
207
|
+
Log4r::Logger['racklogger'].should_receive(:error) do |msg|
|
208
|
+
msg.should be_instance_of RuntimeError
|
209
|
+
msg.message.should == "I failed"
|
210
|
+
Log4r::MDC.get_context.keys.should_not include 'rack_env_rack.version'
|
211
|
+
end
|
212
|
+
|
213
|
+
lambda {
|
214
|
+
get "/other_rack_logger"
|
215
|
+
}.should raise_error("I failed")
|
216
|
+
|
217
|
+
end
|
218
|
+
|
173
219
|
end
|
174
220
|
|
175
221
|
end
|
@@ -41,9 +41,12 @@ describe Log4rExceptionable::ResqueFailureHandler do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
before(:
|
44
|
+
before(:each) do
|
45
45
|
Log4rExceptionable::Configuration.configure do |config|
|
46
46
|
config.resque_failure_logger = 'resquelogger'
|
47
|
+
config.use_source_logger = true
|
48
|
+
config.context_inclusions = nil
|
49
|
+
config.context_exclusions = nil
|
47
50
|
end
|
48
51
|
|
49
52
|
Resque::Failure.backend = Log4rExceptionable::ResqueFailureHandler
|
@@ -98,6 +101,44 @@ describe Log4rExceptionable::ResqueFailureHandler do
|
|
98
101
|
run_resque_job(SomeJobWithLogger, 'foo', :queue => :somequeue, :inline => true)
|
99
102
|
end
|
100
103
|
|
104
|
+
it "uses default logger if source logger disabled" do
|
105
|
+
Log4rExceptionable::Configuration.use_source_logger = false
|
106
|
+
|
107
|
+
Log4r::Logger.new('SomeJobWithLogger')
|
108
|
+
Log4r::Logger['SomeJobWithLogger'].should_not_receive(:error)
|
109
|
+
Log4r::Logger['resquelogger'].should_receive(:error) do |msg|
|
110
|
+
msg.should be_instance_of RuntimeError
|
111
|
+
msg.message.should == "I failed"
|
112
|
+
Log4r::MDC.get('resque_class').should == SomeJobWithLogger
|
113
|
+
end
|
114
|
+
|
115
|
+
run_resque_job(SomeJobWithLogger, 'foo', :queue => :somequeue, :inline => true)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "only includes inclusions if set" do
|
119
|
+
Log4rExceptionable::Configuration.context_inclusions = ['resque_queue']
|
120
|
+
|
121
|
+
Log4r::Logger['resquelogger'].should_receive(:error) do |msg|
|
122
|
+
msg.should be_instance_of RuntimeError
|
123
|
+
msg.message.should == "I failed"
|
124
|
+
Log4r::MDC.get_context.keys.should == ['resque_queue']
|
125
|
+
end
|
126
|
+
|
127
|
+
run_resque_job(SomeJob, 'foo', :queue => :somequeue, :inline => true)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "excludes exclusions if set" do
|
131
|
+
Log4rExceptionable::Configuration.context_exclusions = ['resque_queue']
|
132
|
+
|
133
|
+
Log4r::Logger['resquelogger'].should_receive(:error) do |msg|
|
134
|
+
msg.should be_instance_of RuntimeError
|
135
|
+
msg.message.should == "I failed"
|
136
|
+
Log4r::MDC.get_context.keys.should_not include 'resque_queue'
|
137
|
+
end
|
138
|
+
|
139
|
+
run_resque_job(SomeJob, 'foo', :queue => :somequeue, :inline => true)
|
140
|
+
end
|
141
|
+
|
101
142
|
end
|
102
143
|
|
103
144
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: log4r-exceptionable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- graylog2-resque.gemspec
|
127
127
|
- lib/log4r-exceptionable.rb
|
128
128
|
- lib/log4r-exceptionable/configuration.rb
|
129
|
+
- lib/log4r-exceptionable/helper.rb
|
129
130
|
- lib/log4r-exceptionable/rack_failure_handler.rb
|
130
131
|
- lib/log4r-exceptionable/resque_failure_handler.rb
|
131
132
|
- lib/log4r-exceptionable/version.rb
|