log4r-exceptionable 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ 0.6.0 (06/18/2012)
2
+ ------------------
3
+
4
+ Add white/black lists for context keys Fix disabling source_logger <cb85b26>
5
+
1
6
  0.5.4 (06/15/2012)
2
7
  ------------------
3
8
 
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 (defaults to true)
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 "Log4rExceptionable::RackFailureHandler"
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.
@@ -1,6 +1,7 @@
1
1
  require "log4r"
2
2
  require "log4r-exceptionable/version"
3
3
  require "log4r-exceptionable/configuration"
4
+ require "log4r-exceptionable/helper"
4
5
 
5
6
  # optional if only using resque
6
7
  begin
@@ -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
- begin
39
- mdc = Log4r::MDC
40
- original_mdc = mdc.get_context
41
+
42
+ log_with_context do |context|
41
43
 
42
- begin
43
-
44
- if env and env.size > 0
45
- env.each do |k, v|
46
- begin
47
- mdc.put("rack_env_#{k}", v)
48
- rescue
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
- mdc.put("rack_controller_name", controller.controller_name)
59
- mdc.put("rack_action_name", controller.action_name)
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
- rescue Exception => e
79
- puts "Log4r Exceptionable could not log rack exception: " + e.message
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
- begin
11
- mdc = Log4r::MDC
12
- original_mdc = mdc.get_context
11
+
12
+ log_with_context do |context|
13
13
 
14
- begin
15
-
16
- data = payload.clone
17
- payload_class_name = data.delete('class')
18
- payload_class = Resque.constantize(payload_class_name) rescue payload_class_name
19
- mdc.put("resque_worker", worker)
20
- mdc.put("resque_queue", queue)
21
- mdc.put("resque_class", payload_class)
22
- mdc.put("resque_args", data.delete('args'))
23
-
24
- # add in any extra payload data, in case resque plugins have
25
- # added to it (e.g. resque-lifecycle)
26
- data.each do |k, v|
27
- mdc.put("resque_payload_#{k}", v)
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
- rescue Exception => e
47
- puts "Log4r Exceptionable could not log resque exception: " + e.message
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
@@ -1,3 +1,3 @@
1
1
  module Log4rExceptionable
2
- VERSION = "0.5.4"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -58,9 +58,12 @@ describe Log4rExceptionable::RackFailureHandler do
58
58
 
59
59
  context "handling rack failures" do
60
60
 
61
- before(:all) do
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(:all) do
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.5.4
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-15 00:00:00.000000000 Z
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