bugsnag 2.8.13 → 3.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d6aa2d47b176056a2296c83ed021e60535d8500
4
- data.tar.gz: 993b3197a9a58242cc35f27ee6e89144c0a5bc56
3
+ metadata.gz: c47737bc08fe70bfdc4b9391ab04d5b6aa6900aa
4
+ data.tar.gz: abe70b3cc901bf48a06fab50bd410e1927ca7a6d
5
5
  SHA512:
6
- metadata.gz: 42e61fc1a225f0428fe20357d0af38f022e9fecd835b0c414651f2873e26f00165beee2059920002185db91e082896fa225b68024bad6b74d5d6c20452c2eb46
7
- data.tar.gz: 4d55d3468985cc4a7b6b7b2275b26af66ae0b39d200b2063a9db687990e67f927d2fd663034484dfe4db6fb898f3ec66009c2eba1624846d68b590c6ae86fecf
6
+ metadata.gz: eedb7804e481f0ecfd3436b758e7880f7ebfe232cc7fc93ee5a670738e61df4751a7ff11523cd523c9ec873259f21880df84d214f2a63333c3f6bda704c34184
7
+ data.tar.gz: afc1a1885938f4926dea26e9eb4f22080ea506f15997afe4acd4302085a445e5ff7a0e7191c2d55f50f2919a8a56c664ea7e64b261d6c4c76d360ed823d5da23
@@ -1,3 +1,4 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
4
  - 2.1.0
@@ -9,7 +10,3 @@ rvm:
9
10
  before_install:
10
11
  - gem update --system 2.1.11
11
12
  - gem --version
12
- notifications:
13
- hipchat:
14
- rooms:
15
- secure: cv5V8ivZExOywKL9n0CODnxy9m5u4rQ5ZMYK8XHPIoqQKkvH9DQOeb2ItW2aM2kxeupJEcQEy1Eu4sYMGhyzKUNdqbFtQBhDYxRwSAgTRIkGlHQCnznyExHWZbGfDB8y/m11HiZ1wuPuqs8ZZ+VccNb4bwJKbhPTbf1RZ+GPeU8=
@@ -1,6 +1,23 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 3.0.0 (23 Dec 2015)
5
+ -----
6
+
7
+ ### Enhancements
8
+
9
+ * Fix warning from usage of `before_filter` in Rails 5
10
+ | [Scott Ringwelski](https://github.com/sgringwe)
11
+ | [#267](https://github.com/bugsnag/bugsnag-ruby/pull/267)
12
+
13
+ * Use Rails 5-style deep parameter filtering
14
+ | [fimmtiu](https://github.com/fimmtiu)
15
+ | [#256](https://github.com/bugsnag/bugsnag-ruby/pull/256)
16
+
17
+ Note: This is a backwards incompatible change, as filters containing `.` are
18
+ now parsed as nested instead of as a single key.
19
+
20
+
4
21
  2.8.13
5
22
  ------
6
23
 
data/README.md CHANGED
@@ -24,16 +24,13 @@ Contents
24
24
  - [Sending Non-fatal Exceptions](#sending-non-fatal-exceptions)
25
25
  - [Deploy Tracking](#deploy-tracking)
26
26
  - [Callbacks](#callbacks)
27
+ - [Configuration](https://github.com/bugsnag/bugsnag-ruby/tree/master/docs/Configuration.md)
28
+ - [Notification Options](https://github.com/bugsnag/bugsnag-ruby/tree/master/docs/Notification Options.md)
27
29
  - [Demo Applications](#demo-applications)
28
30
  - [Support](#support)
29
31
  - [Contributing](#contributing)
30
32
  - [License](#license)
31
33
 
32
- - [Additional Documentation](https://github.com/bugsnag/bugsnag-ruby/tree/master/docs)
33
- - [Configuration](docs/Configuration.md)
34
- - [Notification Options](docs/Notification Options.md)
35
-
36
-
37
34
 
38
35
  Getting Started
39
36
  ---------------
@@ -69,17 +66,19 @@ Getting Started
69
66
  end
70
67
  ```
71
68
 
72
- The Bugsnag module will read the `BUGSNAG_API_KEY` environment variable if you
73
- do not configure one automatically.
69
+ The Bugsnag module will read the `BUGSNAG_API_KEY` environment variable if
70
+ you do not configure one automatically.
74
71
 
75
72
  ### Rake Integration
76
73
 
77
- Rake integration is automatically enabled in Rails 3/4 apps, so providing you load the environment
78
- in your Rake tasks you dont need to do anything to get Rake support. If you choose not to load
79
- your environment, you can manually configure Bugsnag with a `bugsnag.configure` block in the Rakefile.
74
+ Rake integration is automatically enabled in Rails 3/4/5 apps, so providing you
75
+ load the environment in your Rake tasks you dont need to do anything to get Rake
76
+ support. If you choose not to load your environment, you can manually configure
77
+ Bugsnag with a `bugsnag.configure` block in the Rakefile.
80
78
 
81
- Bugsnag can automatically notify of all exceptions that happen in your rake tasks. In order
82
- to enable this, you need to `require "bugsnag/rake"` in your Rakefile, like so:
79
+ Bugsnag can automatically notify of all exceptions that happen in your rake
80
+ tasks. In order to enable this, you need to `require "bugsnag/rake"` in your
81
+ Rakefile, like so:
83
82
 
84
83
  ```ruby
85
84
  require File.expand_path('../config/application', __FILE__)
@@ -93,27 +92,29 @@ end
93
92
  YourApp::Application.load_tasks
94
93
  ```
95
94
 
96
- > Note: We also configure Bugsnag in the Rakefile, so the tasks that do not load the full
97
- environment can still notify Bugsnag.
95
+ > Note: We also configure Bugsnag in the Rakefile, so the tasks that do not load
96
+ > the full environment can still notify Bugsnag.
98
97
 
99
98
  ### Sending a Test Notification
100
99
 
101
- To test that bugsnag is properly configured, you can use the `test_exception` rake task:
100
+ To test that bugsnag is properly configured, you can use the `test_exception`
101
+ rake task:
102
102
 
103
103
  ```bash
104
104
  rake bugsnag:test_exception
105
105
  ```
106
106
 
107
- A test exception will be sent to your bugsnag dashboard if everything is configured correctly.
107
+ A test exception will be sent to your bugsnag dashboard if everything is
108
+ configured correctly.
108
109
 
109
110
  Usage
110
111
  -----
111
112
 
112
113
  ### Catching and Reporting Exceptions
113
114
 
114
- Bugsnag Ruby works out of the box with Rails, Sidekiq, Resque, DelayedJob (3+), Mailman, Rake and Rack. It
115
- should be easy to add support for other frameworks, either by sending a pull request here or adding a hook
116
- to those projects.
115
+ Bugsnag Ruby works out of the box with Rails, Sidekiq, Resque, DelayedJob (3+),
116
+ Mailman, Rake and Rack. It should be easy to add support for other frameworks,
117
+ either by sending a pull request here or adding a hook to those projects.
117
118
 
118
119
  #### Rack/Sinatra Apps
119
120
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.8.13
1
+ 3.0.0
@@ -28,5 +28,6 @@ Gem::Specification.new do |s|
28
28
  s.add_development_dependency 'rspec'
29
29
  s.add_development_dependency 'rdoc'
30
30
  s.add_development_dependency 'pry'
31
+ s.add_development_dependency 'addressable', '~> 2.3.8'
31
32
  s.add_development_dependency 'webmock'
32
33
  end
@@ -5,6 +5,7 @@ require "bugsnag/version"
5
5
  require "bugsnag/configuration"
6
6
  require "bugsnag/meta_data"
7
7
  require "bugsnag/notification"
8
+ require "bugsnag/cleaner"
8
9
  require "bugsnag/helpers"
9
10
  require "bugsnag/deploy"
10
11
 
@@ -0,0 +1,122 @@
1
+ require 'uri'
2
+
3
+ module Bugsnag
4
+ class Cleaner
5
+ ENCODING_OPTIONS = {:invalid => :replace, :undef => :replace}.freeze
6
+ FILTERED = '[FILTERED]'.freeze
7
+ RECURSION = '[RECURSION]'.freeze
8
+ OBJECT = '[OBJECT]'.freeze
9
+
10
+ def initialize(filters)
11
+ @filters = Array(filters)
12
+ @deep_filters = @filters.any? {|f| f.kind_of?(Regexp) && f.to_s.include?("\\.".freeze) }
13
+ end
14
+
15
+ def clean_object(obj)
16
+ traverse_object(obj, {}, nil)
17
+ end
18
+
19
+ def traverse_object(obj, seen, scope)
20
+ return nil unless obj
21
+
22
+ # Protect against recursion of recursable items
23
+ protection = if obj.is_a?(Hash) || obj.is_a?(Array) || obj.is_a?(Set)
24
+ return seen[obj] if seen[obj]
25
+ seen[obj] = RECURSION
26
+ end
27
+
28
+ value = case obj
29
+ when Hash
30
+ clean_hash = {}
31
+ obj.each do |k,v|
32
+ if filters_match_deeply?(k, scope)
33
+ clean_hash[k] = FILTERED
34
+ else
35
+ clean_hash[k] = traverse_object(v, seen, [scope, k].compact.join('.'))
36
+ end
37
+ end
38
+ clean_hash
39
+ when Array, Set
40
+ obj.map { |el| traverse_object(el, seen, scope) }.compact
41
+ when Numeric, TrueClass, FalseClass
42
+ obj
43
+ when String
44
+ clean_string(obj)
45
+ else
46
+ str = obj.to_s
47
+ # avoid leaking potentially sensitive data from objects' #inspect output
48
+ if str =~ /#<.*>/
49
+ OBJECT
50
+ else
51
+ clean_string(str)
52
+ end
53
+ end
54
+
55
+ seen[obj] = value if protection
56
+ value
57
+ end
58
+
59
+ def clean_string(str)
60
+ if defined?(str.encoding) && defined?(Encoding::UTF_8)
61
+ if str.encoding == Encoding::UTF_8
62
+ str.valid_encoding? ? str : str.encode('utf-16', ENCODING_OPTIONS).encode('utf-8')
63
+ else
64
+ str.encode('utf-8', ENCODING_OPTIONS)
65
+ end
66
+ elsif defined?(Iconv)
67
+ Iconv.conv('UTF-8//IGNORE', 'UTF-8', str) || str
68
+ else
69
+ str
70
+ end
71
+ end
72
+
73
+ def self.clean_object_encoding(obj)
74
+ new(nil).clean_object(obj)
75
+ end
76
+
77
+ def clean_url(url)
78
+ return url if @filters.empty?
79
+
80
+ uri = URI(url)
81
+ return url unless uri.query
82
+
83
+ query_params = uri.query.split('&').map { |pair| pair.split('=') }
84
+ query_params.map! do |key, val|
85
+ if filters_match?(key)
86
+ "#{key}=#{FILTERED}"
87
+ else
88
+ "#{key}=#{val}"
89
+ end
90
+ end
91
+
92
+ uri.query = query_params.join('&')
93
+ uri.to_s
94
+ end
95
+
96
+ private
97
+
98
+ def filters_match?(key)
99
+ str = key.to_s
100
+
101
+ @filters.any? do |f|
102
+ case f
103
+ when Regexp
104
+ str.match(f)
105
+ else
106
+ str.include?(f.to_s)
107
+ end
108
+ end
109
+ end
110
+
111
+ # If someone has a Rails filter like /^stuff\.secret/, it won't match "request.params.stuff.secret",
112
+ # so we try it both with and without the "request.params." bit.
113
+ def filters_match_deeply?(key, scope)
114
+ return true if filters_match?(key)
115
+ return false unless @deep_filters
116
+
117
+ long = [scope, key].compact.join('.')
118
+ short = long.sub(/^request\.params\./, '')
119
+ filters_match?(long) || filters_match?(short)
120
+ end
121
+ end
122
+ end
@@ -24,8 +24,8 @@ module Bugsnag
24
24
 
25
25
  def start_once!
26
26
  MUTEX.synchronize do
27
- return if @started
28
- @started = true
27
+ return if @started == Process.pid
28
+ @started = Process.pid
29
29
 
30
30
  @queue = Queue.new
31
31
 
@@ -3,98 +3,6 @@ require 'uri'
3
3
  module Bugsnag
4
4
  module Helpers
5
5
  MAX_STRING_LENGTH = 4096
6
- ENCODING_OPTIONS = {:invalid => :replace, :undef => :replace}.freeze
7
-
8
- def self.cleanup_obj(obj, filters = nil, seen = {})
9
- return nil unless obj
10
-
11
- # Protect against recursion of recursable items
12
- protection = if obj.is_a?(Hash) || obj.is_a?(Array) || obj.is_a?(Set)
13
- return seen[obj] if seen[obj]
14
- seen[obj] = '[RECURSION]'.freeze
15
- end
16
-
17
- value = case obj
18
- when Hash
19
- clean_hash = {}
20
- obj.each do |k,v|
21
- if filters_match?(k, filters)
22
- clean_hash[k] = '[FILTERED]'.freeze
23
- else
24
- clean_obj = cleanup_obj(v, filters, seen)
25
- clean_hash[k] = clean_obj
26
- end
27
- end
28
- clean_hash
29
- when Array, Set
30
- obj.map { |el| cleanup_obj(el, filters, seen) }.compact
31
- when Numeric, TrueClass, FalseClass
32
- obj
33
- when String
34
- cleanup_string(obj)
35
- else
36
- str = obj.to_s
37
- # avoid leaking potentially sensitive data from objects' #inspect output
38
- if str =~ /#<.*>/
39
- '[OBJECT]'.freeze
40
- else
41
- cleanup_string(str)
42
- end
43
- end
44
-
45
- seen[obj] = value if protection
46
- value
47
- end
48
-
49
- def self.cleanup_string(str)
50
- if defined?(str.encoding) && defined?(Encoding::UTF_8)
51
- if str.encoding == Encoding::UTF_8
52
- str.valid_encoding? ? str : str.encode('utf-16', ENCODING_OPTIONS).encode('utf-8')
53
- else
54
- str.encode('utf-8', ENCODING_OPTIONS)
55
- end
56
- elsif defined?(Iconv)
57
- Iconv.conv('UTF-8//IGNORE', 'UTF-8', str) || str
58
- else
59
- str
60
- end
61
- end
62
-
63
- def self.cleanup_obj_encoding(obj)
64
- cleanup_obj(obj, nil)
65
- end
66
-
67
- def self.filters_match?(object, filters)
68
- str = object.to_s
69
-
70
- Array(filters).any? do |f|
71
- case f
72
- when Regexp
73
- str.match(f)
74
- else
75
- str.include?(f.to_s)
76
- end
77
- end
78
- end
79
-
80
- def self.cleanup_url(url, filters = [])
81
- return url if filters.empty?
82
-
83
- uri = URI(url)
84
- return url unless uri.query
85
-
86
- query_params = uri.query.split('&').map { |pair| pair.split('=') }
87
- query_params.map! do |key, val|
88
- if filters_match?(key, filters)
89
- "#{key}=[FILTERED]"
90
- else
91
- "#{key}=#{val}"
92
- end
93
- end
94
-
95
- uri.query = query_params.join('&')
96
- uri.to_s
97
- end
98
6
 
99
7
  def self.reduce_hash_size(hash)
100
8
  return {} unless hash.is_a?(Hash)
@@ -23,7 +23,7 @@ module Bugsnag::Middleware
23
23
  # Build the clean url (hide the port if it is obvious)
24
24
  url = "#{request.scheme}://#{request.host}"
25
25
  url << ":#{request.port}" unless [80, 443].include?(request.port)
26
- url << Bugsnag::Helpers.cleanup_url(request.fullpath, notification.configuration.params_filters)
26
+ url << Bugsnag::Cleaner.new(notification.configuration.params_filters).clean_url(request.fullpath)
27
27
 
28
28
  headers = {}
29
29
 
@@ -19,7 +19,7 @@ module Bugsnag::Middleware
19
19
  # Build the clean url
20
20
  url = "#{request.protocol}#{request.host}"
21
21
  url << ":#{request.port}" unless [80, 443].include?(request.port)
22
- url << Bugsnag::Helpers.cleanup_url(request.fullpath, notification.configuration.params_filters)
22
+ url << Bugsnag::Cleaner.new(notification.configuration.params_filters).clean_url(request.fullpath)
23
23
 
24
24
  # Add a request tab
25
25
  notification.add_tab(:request, {
@@ -250,10 +250,10 @@ module Bugsnag
250
250
  payload_event[:device] = {:hostname => @configuration.hostname} if @configuration.hostname
251
251
 
252
252
  # cleanup character encodings
253
- payload_event = Bugsnag::Helpers.cleanup_obj_encoding(payload_event)
253
+ payload_event = Bugsnag::Cleaner.clean_object_encoding(payload_event)
254
254
 
255
255
  # filter out sensitive values in (and cleanup encodings) metaData
256
- payload_event[:metaData] = Bugsnag::Helpers.cleanup_obj(@meta_data, @configuration.params_filters)
256
+ payload_event[:metaData] = Bugsnag::Cleaner.new(@configuration.params_filters).clean_object(@meta_data)
257
257
  payload_event.reject! {|k,v| v.nil? }
258
258
 
259
259
  # return the payload hash
@@ -17,7 +17,7 @@ module Bugsnag::Rails
17
17
  def _add_bugsnag_notify_callback(callback_key, *methods, &block)
18
18
  options = methods.last.is_a?(Hash) ? methods.pop : {}
19
19
 
20
- before_filter(options) do |controller|
20
+ action = lambda do |controller|
21
21
  request_data = Bugsnag.configuration.request_data
22
22
  request_data[callback_key] ||= []
23
23
 
@@ -33,6 +33,11 @@ module Bugsnag::Rails
33
33
  controller.instance_exec(notification, &block)
34
34
  } if block_given?
35
35
  end
36
+ if respond_to?(:before_action)
37
+ before_action(options, &action)
38
+ else
39
+ before_filter(options, &action)
40
+ end
36
41
  end
37
42
  end
38
43
 
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Bugsnag::Cleaner do
6
+ subject { described_class.new(nil) }
7
+
8
+ describe "#clean_object" do
9
+ it "cleans up recursive hashes" do
10
+ a = {:a => {}}
11
+ a[:a][:b] = a
12
+ expect(subject.clean_object(a)).to eq({:a => {:b => "[RECURSION]"}})
13
+ end
14
+
15
+ it "cleans up recursive arrays" do
16
+ a = []
17
+ a << a
18
+ a << "hello"
19
+ expect(subject.clean_object(a)).to eq(["[RECURSION]", "hello"])
20
+ end
21
+
22
+ it "allows multiple copies of the same string" do
23
+ a = {:name => "bugsnag"}
24
+ a[:second] = a[:name]
25
+ expect(subject.clean_object(a)).to eq({:name => "bugsnag", :second => "bugsnag"})
26
+ end
27
+
28
+ it "allows multiple copies of the same object" do
29
+ a = []
30
+ b = ["hello"]
31
+ a << b; a << b
32
+ expect(subject.clean_object(a)).to eq([["hello"], ["hello"]])
33
+ end
34
+
35
+ it "cleans up UTF8 strings properly" do
36
+ obj = "André"
37
+ expect(subject.clean_object(obj)).to eq("André")
38
+ end
39
+
40
+ it "cleans up binary strings properly" do
41
+ if RUBY_VERSION > "1.9"
42
+ obj = "Andr\xc7\xff"
43
+ if obj.respond_to? :force_encoding
44
+ obj = obj.force_encoding('BINARY')
45
+ end
46
+ expect(subject.clean_object(obj)).to eq("Andr��")
47
+ end
48
+ end
49
+
50
+ it "cleans up strings returned from #to_s properly" do
51
+ if RUBY_VERSION > "1.9"
52
+ str = "Andr\xc7\xff"
53
+ if str.respond_to? :force_encoding
54
+ str = str.force_encoding('BINARY')
55
+ end
56
+ obj = RuntimeError.new(str)
57
+ expect(subject.clean_object(obj)).to eq("Andr��")
58
+ end
59
+ end
60
+
61
+ it "filters by string inclusion" do
62
+ expect(described_class.new(['f']).clean_object({ :foo => 'bar' })).to eq({ :foo => '[FILTERED]' })
63
+ expect(described_class.new(['b']).clean_object({ :foo => 'bar' })).to eq({ :foo => 'bar' })
64
+ end
65
+
66
+ it "filters by regular expression" do
67
+ expect(described_class.new([/fb?/]).clean_object({ :foo => 'bar' })).to eq({ :foo => '[FILTERED]' })
68
+ expect(described_class.new([/fb+/]).clean_object({ :foo => 'bar' })).to eq({ :foo => 'bar' })
69
+ end
70
+
71
+ it "filters deeply nested keys" do
72
+ params = {:foo => {:bar => "baz"}}
73
+ expect(described_class.new([/^foo\.bar/]).clean_object(params)).to eq({:foo => {:bar => '[FILTERED]'}})
74
+ end
75
+
76
+ it "filters deeply nested request parameters" do
77
+ params = {:request => {:params => {:foo => {:bar => "baz"}}}}
78
+ expect(described_class.new([/^foo\.bar/]).clean_object(params)).to eq({:request => {:params => {:foo => {:bar => '[FILTERED]'}}}})
79
+ end
80
+ end
81
+
82
+ describe "#clean_url" do
83
+ let(:filters) { [] }
84
+ subject { described_class.new(filters).clean_url(url) }
85
+
86
+ context "with no filters configured" do
87
+ let(:url) { "/dir/page?param1=value1&param2=value2" }
88
+ it { should eq "/dir/page?param1=value1&param2=value2" }
89
+ end
90
+
91
+ context "with no get params" do
92
+ let(:url) { "/dir/page" }
93
+ it { should eq "/dir/page" }
94
+ end
95
+
96
+ context "with no matching parameters" do
97
+ let(:filters) { ["param3"] }
98
+ let(:url) { "/dir/page?param1=value1&param2=value2" }
99
+ it { should eq "/dir/page?param1=value1&param2=value2" }
100
+ end
101
+
102
+ context "with a single matching parameter" do
103
+ let(:filters) { ["param1"] }
104
+ let(:url) { "/dir/page?param1=value1&param2=value2" }
105
+ it { should eq "/dir/page?param1=[FILTERED]&param2=value2" }
106
+ end
107
+
108
+ context "with partially matching parameters" do
109
+ let(:filters) { ["param"] }
110
+ let(:url) { "/dir/page?param1=value1&param2=value2&bla=yes" }
111
+ it { should eq "/dir/page?param1=[FILTERED]&param2=[FILTERED]&bla=yes" }
112
+ end
113
+
114
+ context "with multiple matching filters" do
115
+ let(:filters) { ["param1", "param2"] }
116
+ let(:url) { "/dir/page?param1=value1&param2=value2&param3=value3" }
117
+ it { should eq "/dir/page?param1=[FILTERED]&param2=[FILTERED]&param3=value3" }
118
+ end
119
+
120
+ context "with both string and regexp filters" do
121
+ let(:filters) { ["param1", /param2/] }
122
+ let(:url) { "/dir/page?param1=value1&param2=value2&param3=value3" }
123
+ it { should eq "/dir/page?param1=[FILTERED]&param2=[FILTERED]&param3=value3" }
124
+ end
125
+
126
+ context "with matching regexp filters" do
127
+ let(:filters) { [/\Aaccess_token\z/] }
128
+ let(:url) { "https://host.example/sessions?access_token=abc123" }
129
+ it { should eq "https://host.example/sessions?access_token=[FILTERED]" }
130
+ end
131
+
132
+ context "with partially-matching regexp filters" do
133
+ let(:filters) { [/token/] }
134
+ let(:url) { "https://host.example/sessions?access_token=abc123" }
135
+ it { should eq "https://host.example/sessions?access_token=[FILTERED]" }
136
+ end
137
+ end
138
+ end
@@ -3,68 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Bugsnag::Helpers do
6
- it "cleans up recursive hashes" do
7
- a = {:a => {}}
8
- a[:a][:b] = a
9
- expect(Bugsnag::Helpers.cleanup_obj(a)).to eq({:a => {:b => "[RECURSION]"}})
10
- end
11
-
12
- it "cleans up recursive arrays" do
13
- a = []
14
- a << a
15
- a << "hello"
16
- expect(Bugsnag::Helpers.cleanup_obj(a)).to eq(["[RECURSION]", "hello"])
17
- end
18
-
19
- it "allows multiple copies of the same string" do
20
- a = {:name => "bugsnag"}
21
- a[:second] = a[:name]
22
- expect(Bugsnag::Helpers.cleanup_obj(a)).to eq({:name => "bugsnag", :second => "bugsnag"})
23
- end
24
-
25
- it "allows multiple copies of the same object" do
26
- a = []
27
- b = ["hello"]
28
- a << b; a << b
29
- expect(Bugsnag::Helpers.cleanup_obj(a)).to eq([["hello"], ["hello"]])
30
- end
31
-
32
- it "cleans up UTF8 strings properly" do
33
- obj = "André"
34
- expect(Bugsnag::Helpers.cleanup_obj(obj)).to eq("André")
35
- end
36
-
37
- it "cleans up binary strings properly" do
38
- if RUBY_VERSION > "1.9"
39
- obj = "Andr\xc7\xff"
40
- if obj.respond_to? :force_encoding
41
- obj = obj.force_encoding('BINARY')
42
- end
43
- expect(Bugsnag::Helpers.cleanup_obj(obj)).to eq("Andr��")
44
- end
45
- end
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
-
58
- it "filters by string inclusion" do
59
- expect(Bugsnag::Helpers.cleanup_obj({ :foo => 'bar' }, ['f'])).to eq({ :foo => '[FILTERED]' })
60
- expect(Bugsnag::Helpers.cleanup_obj({ :foo => 'bar' }, ['b'])).to eq({ :foo => 'bar' })
61
- end
62
-
63
- it "filters by regular expression" do
64
- expect(Bugsnag::Helpers.cleanup_obj({ :foo => 'bar' }, [/fb?/])).to eq({ :foo => '[FILTERED]' })
65
- expect(Bugsnag::Helpers.cleanup_obj({ :foo => 'bar' }, [/fb+/])).to eq({ :foo => 'bar' })
66
- end
67
-
68
6
  it "reduces hash size correctly" do
69
7
  meta_data = {
70
8
  :key_one => "this should not be truncated",
@@ -89,56 +27,4 @@ describe Bugsnag::Helpers do
89
27
  expect(meta_data[:key_one].length).to eq(28)
90
28
  expect(meta_data[:key_one]).to eq("this should not be truncated")
91
29
  end
92
-
93
- it "works with no filters configured" do
94
- url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1&param2=value2"
95
-
96
- expect(url).to eq("/dir/page?param1=value1&param2=value2")
97
- end
98
-
99
- it "does not filter with no get params" do
100
- url = Bugsnag::Helpers.cleanup_url "/dir/page"
101
-
102
- expect(url).to eq("/dir/page")
103
- end
104
-
105
- it "leaves a url alone if no filters match" do
106
- url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1&param2=value2", ["param3"]
107
-
108
- expect(url).to eq("/dir/page?param1=value1&param2=value2")
109
- end
110
-
111
- it "filters a single get param" do
112
- url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1&param2=value2", ["param1"]
113
-
114
- expect(url).to eq("/dir/page?param1=[FILTERED]&param2=value2")
115
- end
116
-
117
- it "filters a get param that contains a filtered term" do
118
- url = Bugsnag::Helpers.cleanup_url '/dir/page?param1=value1&param2=value2&bla=yes', ["param"]
119
-
120
- expect(url).to eq("/dir/page?param1=[FILTERED]&param2=[FILTERED]&bla=yes")
121
- end
122
-
123
- it "filters multiple matches" do
124
- url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1&param2=value2&param3=value3", ["param1", "param2"]
125
-
126
- expect(url).to eq("/dir/page?param1=[FILTERED]&param2=[FILTERED]&param3=value3")
127
- end
128
-
129
- it "filters using a combination of string and regex filters" do
130
- url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1&param2=value2&param3=value3", ["param1", /param2/]
131
-
132
- expect(url).to eq("/dir/page?param1=[FILTERED]&param2=[FILTERED]&param3=value3")
133
- end
134
-
135
- it "filters regex matches" do
136
- url = Bugsnag::Helpers.cleanup_url "https://host.example/sessions?access_token=abc123", [/\Aaccess_token\z/]
137
- expect(url).to eq("https://host.example/sessions?access_token=[FILTERED]")
138
- end
139
-
140
- it "filters partial regex matches" do
141
- url = Bugsnag::Helpers.cleanup_url "https://host.example/sessions?access_token=abc123", [/token/]
142
- expect(url).to eq("https://host.example/sessions?access_token=[FILTERED]")
143
- end
144
30
  end
@@ -17,6 +17,7 @@ describe 'Bugsnag' do
17
17
  end
18
18
  after do
19
19
  server.stop
20
+ queue.clear
20
21
  end
21
22
 
22
23
  let(:request) { JSON.parse(queue.pop) }
@@ -68,6 +69,27 @@ describe 'Bugsnag' do
68
69
  expect(request['events'][0]['exceptions'][0]['message']).to eq('yo')
69
70
  end
70
71
 
72
+ it 'should work with threadpool delivery after fork' do
73
+ is_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
74
+ unless is_jruby #jruby doesn't support fork, so this test doesn't apply
75
+ Bugsnag.configure do |config|
76
+ config.endpoint = "localhost:#{server.config[:Port]}"
77
+ config.use_ssl = false
78
+ config.delivery_method = :thread_queue
79
+ end
80
+ WebMock.allow_net_connect!
81
+
82
+ Bugsnag.notify 'yo'
83
+
84
+ Process.fork do
85
+ Bugsnag.notify 'yo too'
86
+ end
87
+ Process.wait
88
+
89
+ expect(queue.length).to eq(2)
90
+ end
91
+ end
92
+
71
93
  describe 'with a proxy' do
72
94
  proxy = nil
73
95
  pqueue = Queue.new
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.13
4
+ version: 3.0.0
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-12-04 00:00:00.000000000 Z
11
+ date: 2015-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -86,6 +86,20 @@ dependencies:
86
86
  - - '>='
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: addressable
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ version: 2.3.8
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: 2.3.8
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: webmock
91
105
  requirement: !ruby/object:Gem::Requirement
@@ -126,6 +140,7 @@ files:
126
140
  - lib/bugsnag.rb
127
141
  - lib/bugsnag/capistrano.rb
128
142
  - lib/bugsnag/capistrano2.rb
143
+ - lib/bugsnag/cleaner.rb
129
144
  - lib/bugsnag/configuration.rb
130
145
  - lib/bugsnag/delay/resque.rb
131
146
  - lib/bugsnag/delayed_job.rb
@@ -161,6 +176,7 @@ files:
161
176
  - lib/bugsnag/version.rb
162
177
  - lib/generators/bugsnag/bugsnag_generator.rb
163
178
  - rails/init.rb
179
+ - spec/cleaner_spec.rb
164
180
  - spec/code_spec.rb
165
181
  - spec/fixtures/crashes/end_of_file.rb
166
182
  - spec/fixtures/crashes/short_file.rb