bugsnag 2.8.1 → 2.8.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/VERSION +1 -1
- data/lib/bugsnag.rb +3 -1
- data/lib/bugsnag/delivery/thread_queue.rb +17 -19
- data/lib/bugsnag/helpers.rb +1 -1
- data/lib/bugsnag/middleware_stack.rb +36 -24
- data/lib/bugsnag/notification.rb +43 -37
- data/spec/helper_spec.rb +11 -0
- data/spec/integration_spec.rb +13 -0
- data/spec/rack_spec.rb +11 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43df7800cf5b29766a8eb2ee1574eea6549f9e0a
|
4
|
+
data.tar.gz: 6c9478cd0c3dcf185b30e6266fbbe7bffc1ab26d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e961861ba8a71814253994d8c011166fa2b95c3c086ab795aa6ee4a0086f6affb09655426256684ccd0010033f3df1f32ef38353e49cfd693ef4b86c66e04849
|
7
|
+
data.tar.gz: ca3916340b2c8d937481204bf36f1f6b523d0ebaf30ab48e1440107ba36d83dbbe9c35670bb1341bd95dce1f656cd2451fd7a05ff4f7eaa434d9ce074ddddd7a
|
data/CHANGELOG.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.8.
|
1
|
+
2.8.2
|
data/lib/bugsnag.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "rubygems"
|
2
|
+
require "thread"
|
2
3
|
|
3
4
|
require "bugsnag/version"
|
4
5
|
require "bugsnag/configuration"
|
@@ -25,6 +26,7 @@ require "bugsnag/middleware/callbacks"
|
|
25
26
|
|
26
27
|
module Bugsnag
|
27
28
|
LOG_PREFIX = "** [Bugsnag] "
|
29
|
+
LOCK = Mutex.new
|
28
30
|
|
29
31
|
class << self
|
30
32
|
# Configure the Bugsnag notifier application-wide settings.
|
@@ -92,7 +94,7 @@ module Bugsnag
|
|
92
94
|
|
93
95
|
# Configuration getters
|
94
96
|
def configuration
|
95
|
-
@configuration ||= Bugsnag::Configuration.new
|
97
|
+
@configuration || LOCK.synchronize { @configuration ||= Bugsnag::Configuration.new }
|
96
98
|
end
|
97
99
|
|
98
100
|
# Set "per-request" data, temporal data for use in bugsnag middleware
|
@@ -6,6 +6,7 @@ module Bugsnag
|
|
6
6
|
MAX_OUTSTANDING_REQUESTS = 100
|
7
7
|
STOP = Object.new
|
8
8
|
|
9
|
+
|
9
10
|
class << self
|
10
11
|
def deliver(url, body, configuration)
|
11
12
|
if queue.length > MAX_OUTSTANDING_REQUESTS
|
@@ -15,35 +16,32 @@ module Bugsnag
|
|
15
16
|
|
16
17
|
# Add delivery to the worker thread
|
17
18
|
queue.push proc { super(url, body, configuration) }
|
18
|
-
|
19
|
-
# Make sure the worker thread is started
|
20
|
-
ensure_worker_thread_started
|
21
19
|
end
|
22
20
|
|
23
21
|
private
|
24
|
-
def queue
|
25
|
-
@queue ||= Queue.new
|
26
|
-
end
|
27
22
|
|
28
|
-
|
29
|
-
unless @worker_thread
|
30
|
-
@worker_thread = Thread.new do
|
31
|
-
while x = queue.pop
|
32
|
-
break if x == STOP
|
33
|
-
x.call
|
34
|
-
end
|
35
|
-
end
|
23
|
+
attr_reader :queue
|
36
24
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
25
|
+
def start!
|
26
|
+
@queue = Queue.new
|
27
|
+
|
28
|
+
worker_thread = Thread.new do
|
29
|
+
while x = queue.pop
|
30
|
+
break if x == STOP
|
31
|
+
x.call
|
41
32
|
end
|
42
33
|
end
|
43
34
|
|
44
|
-
|
35
|
+
at_exit do
|
36
|
+
Bugsnag.warn("Waiting for #{queue.length} outstanding request(s)") unless queue.empty?
|
37
|
+
queue.push STOP
|
38
|
+
worker_thread.join
|
39
|
+
end
|
45
40
|
end
|
46
41
|
end
|
42
|
+
|
43
|
+
# do this once at require time to avoid race conditions
|
44
|
+
start!
|
47
45
|
end
|
48
46
|
end
|
49
47
|
end
|
data/lib/bugsnag/helpers.rb
CHANGED
@@ -3,46 +3,58 @@ module Bugsnag
|
|
3
3
|
def initialize
|
4
4
|
@middlewares = []
|
5
5
|
@disabled_middleware = []
|
6
|
+
@mutex = Mutex.new
|
6
7
|
end
|
7
8
|
|
8
9
|
def use(new_middleware)
|
9
|
-
|
10
|
+
@mutex.synchronize do
|
11
|
+
return if @disabled_middleware.include?(new_middleware)
|
12
|
+
return if @middlewares.include?(new_middleware)
|
10
13
|
|
11
|
-
|
14
|
+
@middlewares << new_middleware
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
def insert_after(after, new_middleware)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
@mutex.synchronize do
|
20
|
+
return if @disabled_middleware.include?(new_middleware)
|
21
|
+
return if @middlewares.include?(new_middleware)
|
22
|
+
|
23
|
+
if after.is_a? Array
|
24
|
+
index = @middlewares.rindex {|el| after.include?(el)}
|
25
|
+
else
|
26
|
+
index = @middlewares.rindex(after)
|
27
|
+
end
|
28
|
+
|
29
|
+
if index.nil?
|
30
|
+
@middlewares << new_middleware
|
31
|
+
else
|
32
|
+
@middlewares.insert index + 1, new_middleware
|
33
|
+
end
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
37
|
def insert_before(before, new_middleware)
|
31
|
-
|
38
|
+
@mutex.synchronize do
|
39
|
+
return if @disabled_middleware.include?(new_middleware)
|
40
|
+
return if @middlewares.include?(new_middleware)
|
32
41
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
42
|
+
if before.is_a? Array
|
43
|
+
index = @middlewares.index {|el| before.include?(el)}
|
44
|
+
else
|
45
|
+
index = @middlewares.index(before)
|
46
|
+
end
|
38
47
|
|
39
|
-
|
48
|
+
@middlewares.insert index || @middlewares.length, new_middleware
|
49
|
+
end
|
40
50
|
end
|
41
51
|
|
42
52
|
def disable(*middlewares)
|
43
|
-
@
|
53
|
+
@mutex.synchronize do
|
54
|
+
@disabled_middleware += middlewares
|
44
55
|
|
45
|
-
|
56
|
+
@middlewares.delete_if {|m| @disabled_middleware.include?(m)}
|
57
|
+
end
|
46
58
|
end
|
47
59
|
|
48
60
|
# This allows people to proxy methods to the array if they want to do more complex stuff
|
@@ -56,7 +68,7 @@ module Bugsnag
|
|
56
68
|
lambda_has_run = false
|
57
69
|
notify_lambda = lambda do |notif|
|
58
70
|
lambda_has_run = true
|
59
|
-
yield
|
71
|
+
yield if block_given?
|
60
72
|
end
|
61
73
|
|
62
74
|
begin
|
data/lib/bugsnag/notification.rb
CHANGED
@@ -191,7 +191,7 @@ module Bugsnag
|
|
191
191
|
# Warn if no release_stage is set
|
192
192
|
Bugsnag.warn "You should set your app's release_stage (see https://bugsnag.com/docs/notifiers/ruby#release_stage)." unless @configuration.release_stage
|
193
193
|
|
194
|
-
@configuration.internal_middleware.run(self)
|
194
|
+
@configuration.internal_middleware.run(self)
|
195
195
|
|
196
196
|
exceptions.each do |exception|
|
197
197
|
if exception.class.include?(Bugsnag::MetaData)
|
@@ -224,46 +224,49 @@ module Bugsnag
|
|
224
224
|
endpoint = (@configuration.use_ssl ? "https://" : "http://") + @configuration.endpoint
|
225
225
|
Bugsnag.log("Notifying #{endpoint} of #{@exceptions.last.class} from api_key #{api_key}")
|
226
226
|
|
227
|
-
# Build the payload's exception event
|
228
|
-
payload_event = {
|
229
|
-
:app => {
|
230
|
-
:version => @configuration.app_version,
|
231
|
-
:releaseStage => @configuration.release_stage,
|
232
|
-
:type => @configuration.app_type
|
233
|
-
},
|
234
|
-
:context => self.context,
|
235
|
-
:user => @user,
|
236
|
-
:payloadVersion => payload_version,
|
237
|
-
:exceptions => exception_list,
|
238
|
-
:severity => self.severity,
|
239
|
-
:groupingHash => self.grouping_hash,
|
240
|
-
}
|
241
|
-
|
242
|
-
payload_event[:device] = {:hostname => @configuration.hostname} if @configuration.hostname
|
243
|
-
|
244
|
-
# cleanup character encodings
|
245
|
-
payload_event = Bugsnag::Helpers.cleanup_obj_encoding(payload_event)
|
246
|
-
|
247
|
-
# filter out sensitive values in (and cleanup encodings) metaData
|
248
|
-
payload_event[:metaData] = Bugsnag::Helpers.cleanup_obj(@meta_data, @configuration.params_filters)
|
249
|
-
payload_event.reject! {|k,v| v.nil? }
|
250
|
-
|
251
|
-
# Build the payload hash
|
252
|
-
payload = {
|
253
|
-
:apiKey => api_key,
|
254
|
-
:notifier => {
|
255
|
-
:name => NOTIFIER_NAME,
|
256
|
-
:version => NOTIFIER_VERSION,
|
257
|
-
:url => NOTIFIER_URL
|
258
|
-
},
|
259
|
-
:events => [payload_event]
|
260
|
-
}
|
261
|
-
|
262
227
|
# Deliver the payload
|
263
|
-
self.class.deliver_exception_payload(endpoint,
|
228
|
+
self.class.deliver_exception_payload(endpoint, build_exception_payload, @configuration, @delivery_method)
|
264
229
|
end
|
265
230
|
end
|
266
231
|
|
232
|
+
# Build an exception payload
|
233
|
+
def build_exception_payload
|
234
|
+
# Build the payload's exception event
|
235
|
+
payload_event = {
|
236
|
+
:app => {
|
237
|
+
:version => @configuration.app_version,
|
238
|
+
:releaseStage => @configuration.release_stage,
|
239
|
+
:type => @configuration.app_type
|
240
|
+
},
|
241
|
+
:context => self.context,
|
242
|
+
:user => @user,
|
243
|
+
:payloadVersion => payload_version,
|
244
|
+
:exceptions => exception_list,
|
245
|
+
:severity => self.severity,
|
246
|
+
:groupingHash => self.grouping_hash,
|
247
|
+
}
|
248
|
+
|
249
|
+
payload_event[:device] = {:hostname => @configuration.hostname} if @configuration.hostname
|
250
|
+
|
251
|
+
# cleanup character encodings
|
252
|
+
payload_event = Bugsnag::Helpers.cleanup_obj_encoding(payload_event)
|
253
|
+
|
254
|
+
# filter out sensitive values in (and cleanup encodings) metaData
|
255
|
+
payload_event[:metaData] = Bugsnag::Helpers.cleanup_obj(@meta_data, @configuration.params_filters)
|
256
|
+
payload_event.reject! {|k,v| v.nil? }
|
257
|
+
|
258
|
+
# return the payload hash
|
259
|
+
{
|
260
|
+
:apiKey => api_key,
|
261
|
+
:notifier => {
|
262
|
+
:name => NOTIFIER_NAME,
|
263
|
+
:version => NOTIFIER_VERSION,
|
264
|
+
:url => NOTIFIER_URL
|
265
|
+
},
|
266
|
+
:events => [payload_event]
|
267
|
+
}
|
268
|
+
end
|
269
|
+
|
267
270
|
def ignore?
|
268
271
|
@should_ignore || ignore_exception_class? || ignore_user_agent?
|
269
272
|
end
|
@@ -411,6 +414,9 @@ module Bugsnag
|
|
411
414
|
|
412
415
|
from_line = [line_number - num_lines, 1].max
|
413
416
|
|
417
|
+
# don't try and open '(irb)' or '-e'
|
418
|
+
return unless File.exist?(file)
|
419
|
+
|
414
420
|
# Populate code hash with line numbers and code lines
|
415
421
|
File.open(file) do |f|
|
416
422
|
current_line_number = 0
|
data/spec/helper_spec.rb
CHANGED
@@ -44,6 +44,17 @@ describe Bugsnag::Helpers do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
it "cleans up strings returned from #to_s properly" do
|
48
|
+
if RUBY_VERSION > "1.9"
|
49
|
+
str = "Andr\xc7\xff"
|
50
|
+
if str.respond_to? :force_encoding
|
51
|
+
str = str.force_encoding('BINARY')
|
52
|
+
end
|
53
|
+
obj = RuntimeError.new(str)
|
54
|
+
expect(Bugsnag::Helpers.cleanup_obj(obj)).to eq("Andr��")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
47
58
|
it "filters by string inclusion" do
|
48
59
|
expect(Bugsnag::Helpers.cleanup_obj({ :foo => 'bar' }, ['f'])).to eq({ :foo => '[FILTERED]' })
|
49
60
|
expect(Bugsnag::Helpers.cleanup_obj({ :foo => 'bar' }, ['b'])).to eq({ :foo => 'bar' })
|
data/spec/integration_spec.rb
CHANGED
@@ -55,6 +55,19 @@ describe 'Bugsnag' do
|
|
55
55
|
expect(request['appVersion']).to eq('1.1.1')
|
56
56
|
end
|
57
57
|
|
58
|
+
it 'should work with threadpool delivery' do
|
59
|
+
Bugsnag.configure do |config|
|
60
|
+
config.endpoint = "localhost:#{server.config[:Port]}"
|
61
|
+
config.use_ssl = false
|
62
|
+
config.delivery_method = :thread_queue
|
63
|
+
end
|
64
|
+
WebMock.allow_net_connect!
|
65
|
+
|
66
|
+
Bugsnag.notify 'yo'
|
67
|
+
|
68
|
+
expect(request['events'][0]['exceptions'][0]['message']).to eq('yo')
|
69
|
+
end
|
70
|
+
|
58
71
|
describe 'with a proxy' do
|
59
72
|
proxy = nil
|
60
73
|
pqueue = Queue.new
|
data/spec/rack_spec.rb
CHANGED
@@ -42,4 +42,15 @@ describe Bugsnag::Rack do
|
|
42
42
|
expect(Bugsnag::Notification).not_to have_sent_notification
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
it "don't mess with middlewares list on each req" do
|
47
|
+
stub_const('Rack', nil)
|
48
|
+
app = lambda { |env| ['200', {}, ['']] }
|
49
|
+
|
50
|
+
Bugsnag::Rack.new(app)
|
51
|
+
|
52
|
+
expect { 2.times { Bugsnag::Rack.new(app) } }.not_to change {
|
53
|
+
Bugsnag.configuration.middleware.instance_variable_get(:@middlewares)
|
54
|
+
}
|
55
|
+
end
|
45
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bugsnag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|