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 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