bugsnag 1.8.6 → 1.8.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/CHANGELOG.md +7 -0
- data/README.md +11 -5
- data/VERSION +1 -1
- data/bugsnag.gemspec +2 -1
- data/lib/bugsnag/notification.rb +15 -1
- data/lib/bugsnag/tasks/bugsnag.cap +4 -1
- data/lib/bugsnag/tasks/bugsnag.rake +15 -11
- data/spec/helper_spec.rb +30 -30
- data/spec/middleware_spec.rb +37 -39
- data/spec/notification_spec.rb +227 -212
- data/spec/rack_spec.rb +9 -9
- data/spec/spec_helper.rb +4 -2
- metadata +24 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1ded05b67617d43a3ec3d4201f289268e557532
|
4
|
+
data.tar.gz: f555a022921c989415992c649dde17f669c4ee2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc89fe2fe2a176e82b130159968bafa9ccba23408ec648dd76a4a1fa81bae287866fce45aad2cbf53e7a16aa0c2db7fadc0819bde435b11bbde2db892af28841
|
7
|
+
data.tar.gz: 7c8e42b005712c3817a48c79641396cbb01975d5ff4ee0ddb39a35354ed1db75bad4df9a7643c8c31df2e0f3ff85d43487fc2e120a9ecdfdfa66f74ee577e3e4
|
data/.gitignore
CHANGED
@@ -16,7 +16,8 @@ Gemfile.lock
|
|
16
16
|
pkg
|
17
17
|
*.gem
|
18
18
|
|
19
|
-
|
19
|
+
vendor
|
20
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
20
21
|
#
|
21
22
|
# * Create a file at ~/.gitignore
|
22
23
|
# * Include files you want ignored
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -470,6 +470,17 @@ rescue => e
|
|
470
470
|
end
|
471
471
|
```
|
472
472
|
|
473
|
+
### Grouping hash
|
474
|
+
|
475
|
+
If you want to override Bugsnag's grouping algorithm, you can specify a grouping hash key as a parameter to `Bugsnag.notify`:
|
476
|
+
|
477
|
+
```ruby
|
478
|
+
rescue => e
|
479
|
+
Bugsnag.notify e, grouping_hash: "this-is-my-grouping-hash"
|
480
|
+
end
|
481
|
+
```
|
482
|
+
|
483
|
+
All errors with the same groupingHash will be grouped together within the bugsnag dashboard.
|
473
484
|
|
474
485
|
Deploy Tracking
|
475
486
|
---------------
|
@@ -515,23 +526,18 @@ additional deploy information:
|
|
515
526
|
The release stage (eg, production, staging) currently being deployed.
|
516
527
|
This is set automatically from your Bugsnag settings or rails/rack
|
517
528
|
environment.
|
518
|
-
|
519
529
|
- **BUGSNAG_API_KEY** -
|
520
530
|
Your Bugsnag API key. This is set automatically from your Bugsnag
|
521
531
|
settings in your app.
|
522
|
-
|
523
532
|
- **BUGSNAG_REPOSITORY** -
|
524
533
|
The repository from which you are deploying the code. This is set
|
525
534
|
automatically if you are using capistrano.
|
526
|
-
|
527
535
|
- **BUGSNAG_BRANCH** -
|
528
536
|
The source control branch from which you are deploying the code.
|
529
537
|
This is set automatically if you are using capistrano.
|
530
|
-
|
531
538
|
- **BUGSNAG_REVISION** -
|
532
539
|
The source control revision for the code you are currently deploying.
|
533
540
|
This is set automatically if you are using capistrano.
|
534
|
-
|
535
541
|
- **BUGSNAG_APP_VERSION** -
|
536
542
|
The app version of the code you are currently deploying. Only set this
|
537
543
|
if you tag your releases with [semantic version numbers](http://semver.org/)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.8.
|
1
|
+
1.8.7
|
data/bugsnag.gemspec
CHANGED
@@ -22,12 +22,13 @@ Gem::Specification.new do |s|
|
|
22
22
|
if RUBY_VERSION < "1.9"
|
23
23
|
# Use ruby 1.8 compatible httparty
|
24
24
|
s.add_runtime_dependency 'httparty', ["< 0.12.0", ">= 0.6"]
|
25
|
+
s.add_development_dependency "rake", "~> 10.1.1"
|
25
26
|
else
|
26
27
|
s.add_runtime_dependency 'httparty', ["< 1.0", ">= 0.6"]
|
28
|
+
s.add_development_dependency 'rake'
|
27
29
|
end
|
28
30
|
|
29
31
|
s.add_development_dependency 'rspec'
|
30
32
|
s.add_development_dependency 'rdoc'
|
31
|
-
s.add_development_dependency 'rake'
|
32
33
|
end
|
33
34
|
|
data/lib/bugsnag/notification.rb
CHANGED
@@ -59,6 +59,11 @@ module Bugsnag
|
|
59
59
|
self.severity = @overrides[:severity]
|
60
60
|
@overrides.delete :severity
|
61
61
|
|
62
|
+
if @overrides.key? :grouping_hash
|
63
|
+
self.grouping_hash = @overrides[:grouping_hash]
|
64
|
+
@overrides.delete :grouping_hash
|
65
|
+
end
|
66
|
+
|
62
67
|
if @overrides.key? :api_key
|
63
68
|
self.api_key = @overrides[:api_key]
|
64
69
|
@overrides.delete :api_key
|
@@ -143,6 +148,14 @@ module Bugsnag
|
|
143
148
|
@severity || "error"
|
144
149
|
end
|
145
150
|
|
151
|
+
def grouping_hash=(grouping_hash)
|
152
|
+
@grouping_hash = grouping_hash
|
153
|
+
end
|
154
|
+
|
155
|
+
def grouping_hash
|
156
|
+
@grouping_hash || nil
|
157
|
+
end
|
158
|
+
|
146
159
|
def api_key=(api_key)
|
147
160
|
@api_key = api_key
|
148
161
|
end
|
@@ -183,7 +196,7 @@ module Bugsnag
|
|
183
196
|
end
|
184
197
|
end
|
185
198
|
|
186
|
-
[:user_id, :context, :user].each do |symbol|
|
199
|
+
[:user_id, :context, :user, :grouping_hash].each do |symbol|
|
187
200
|
if @overrides[symbol]
|
188
201
|
self.send("#{symbol}=", @overrides[symbol])
|
189
202
|
@overrides.delete symbol
|
@@ -205,6 +218,7 @@ module Bugsnag
|
|
205
218
|
:user => @user,
|
206
219
|
:exceptions => exception_list,
|
207
220
|
:severity => self.severity,
|
221
|
+
:groupingHash => self.grouping_hash,
|
208
222
|
:metaData => Bugsnag::Helpers.cleanup_obj(generate_meta_data(@exceptions, @overrides), @configuration.params_filters)
|
209
223
|
}.reject {|k,v| v.nil? }
|
210
224
|
|
@@ -44,7 +44,9 @@ namespace :bugsnag do
|
|
44
44
|
|
45
45
|
within release_path do
|
46
46
|
with rails_env: rails_env do
|
47
|
-
|
47
|
+
params = "bugsnag:deploy #{new_env.map{|k,v| "#{k}=#{v}"}.join(" ")}"
|
48
|
+
rake = fetch(:rake, "rake")
|
49
|
+
execute rake, params
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -53,3 +55,4 @@ namespace :bugsnag do
|
|
53
55
|
end
|
54
56
|
|
55
57
|
end
|
58
|
+
# vi:ft=ruby
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "bugsnag"
|
2
|
+
require "pathname"
|
2
3
|
require "httparty"
|
3
4
|
require "multi_json"
|
4
5
|
require "net/http"
|
@@ -11,17 +12,20 @@ namespace :bugsnag do
|
|
11
12
|
begin
|
12
13
|
require 'bugsnag'
|
13
14
|
|
14
|
-
api_key
|
15
|
+
api_key = ENV["BUGSNAG_API_KEY"]
|
15
16
|
releaseStage = ENV["BUGSNAG_RELEASE_STAGE"] || "production"
|
16
|
-
appVersion
|
17
|
-
revision
|
18
|
-
repository
|
19
|
-
branch
|
17
|
+
appVersion = ENV["BUGSNAG_APP_VERSION"]
|
18
|
+
revision = ENV["BUGSNAG_REVISION"]
|
19
|
+
repository = ENV["BUGSNAG_REPOSITORY"]
|
20
|
+
branch = ENV["BUGSNAG_BRANCH"]
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
# TODO: more reliable ways to infer this are needed
|
23
|
+
path = defined?(Rails.root) ? Rails.root : Pathname.pwd
|
24
|
+
initializer = path + 'config/initializers/bugsnag'
|
25
|
+
if File.exist?(initializer)
|
26
|
+
require initializer
|
27
|
+
else
|
28
|
+
yml_filename = path + 'config/bugsnag.yml'
|
25
29
|
config = YAML.load_file(yml_filename) if File.exists?(yml_filename)
|
26
30
|
Bugsnag.configure(config[releaseStage] ? config[releaseStage] : config) if config
|
27
31
|
end
|
@@ -65,7 +69,7 @@ namespace :bugsnag do
|
|
65
69
|
end
|
66
70
|
|
67
71
|
desc "Send a test exception to Bugsnag."
|
68
|
-
task :test_exception => :load do
|
72
|
+
task :test_exception => :load do
|
69
73
|
begin
|
70
74
|
raise RuntimeError.new("Bugsnag test exception")
|
71
75
|
rescue => e
|
@@ -80,7 +84,7 @@ namespace :bugsnag do
|
|
80
84
|
end
|
81
85
|
|
82
86
|
task :load do
|
83
|
-
begin
|
87
|
+
begin
|
84
88
|
Rake::Task["environment"].invoke
|
85
89
|
rescue
|
86
90
|
end
|
data/spec/helper_spec.rb
CHANGED
@@ -1,33 +1,33 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Bugsnag::Helpers do
|
4
|
-
it "
|
4
|
+
it "cleans up recursive hashes" do
|
5
5
|
a = {:a => {}}
|
6
6
|
a[:a][:b] = a
|
7
|
-
Bugsnag::Helpers.cleanup_obj(a).
|
7
|
+
expect(Bugsnag::Helpers.cleanup_obj(a)).to eq({:a => {:b => "[RECURSION]"}})
|
8
8
|
end
|
9
9
|
|
10
|
-
it "
|
10
|
+
it "cleans up recursive arrays" do
|
11
11
|
a = []
|
12
12
|
a << a
|
13
13
|
a << "hello"
|
14
|
-
Bugsnag::Helpers.cleanup_obj(a).
|
14
|
+
expect(Bugsnag::Helpers.cleanup_obj(a)).to eq(["[RECURSION]", "hello"])
|
15
15
|
end
|
16
16
|
|
17
|
-
it "
|
17
|
+
it "allows multiple copies of the same string" do
|
18
18
|
a = {:name => "bugsnag"}
|
19
19
|
a[:second] = a[:name]
|
20
|
-
Bugsnag::Helpers.cleanup_obj(a).
|
20
|
+
expect(Bugsnag::Helpers.cleanup_obj(a)).to eq({:name => "bugsnag", :second => "bugsnag"})
|
21
21
|
end
|
22
22
|
|
23
|
-
it "
|
23
|
+
it "allows multiple copies of the same object" do
|
24
24
|
a = []
|
25
25
|
b = ["hello"]
|
26
26
|
a << b; a << b
|
27
|
-
Bugsnag::Helpers.cleanup_obj(a).
|
27
|
+
expect(Bugsnag::Helpers.cleanup_obj(a)).to eq([["hello"], ["hello"]])
|
28
28
|
end
|
29
29
|
|
30
|
-
it "
|
30
|
+
it "reduces hash size correctly" do
|
31
31
|
meta_data = {
|
32
32
|
:key_one => "this should not be truncated",
|
33
33
|
:key_two => ""
|
@@ -35,56 +35,56 @@ describe Bugsnag::Helpers do
|
|
35
35
|
|
36
36
|
1000.times {|i| meta_data[:key_two] += "this should be truncated " }
|
37
37
|
|
38
|
-
meta_data[:key_two].length.
|
38
|
+
expect(meta_data[:key_two].length).to be > 4096
|
39
39
|
|
40
40
|
meta_data_return = Bugsnag::Helpers.reduce_hash_size meta_data
|
41
41
|
|
42
|
-
meta_data_return[:key_one].length.
|
43
|
-
meta_data_return[:key_one].
|
42
|
+
expect(meta_data_return[:key_one].length).to eq(28)
|
43
|
+
expect(meta_data_return[:key_one]).to eq("this should not be truncated")
|
44
44
|
|
45
|
-
meta_data_return[:key_two].length.
|
46
|
-
meta_data_return[:key_two].match(/\[TRUNCATED\]$/).nil
|
45
|
+
expect(meta_data_return[:key_two].length).to eq(4107)
|
46
|
+
expect(meta_data_return[:key_two].match(/\[TRUNCATED\]$/).nil?).to eq(false)
|
47
47
|
|
48
|
-
meta_data[:key_two].length.
|
49
|
-
meta_data[:key_two].match(/\[TRUNCATED\]$/).nil
|
48
|
+
expect(meta_data[:key_two].length).to be > 4096
|
49
|
+
expect(meta_data[:key_two].match(/\[TRUNCATED\]$/).nil?).to eq(true)
|
50
50
|
|
51
|
-
meta_data[:key_one].length.
|
52
|
-
meta_data[:key_one].
|
51
|
+
expect(meta_data[:key_one].length).to eq(28)
|
52
|
+
expect(meta_data[:key_one]).to eq("this should not be truncated")
|
53
53
|
end
|
54
54
|
|
55
|
-
it "
|
55
|
+
it "works with no filters configured" do
|
56
56
|
url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1¶m2=value2"
|
57
57
|
|
58
|
-
url.
|
58
|
+
expect(url).to eq("/dir/page?param1=value1¶m2=value2")
|
59
59
|
end
|
60
60
|
|
61
|
-
it "
|
61
|
+
it "does not filter with no get params" do
|
62
62
|
url = Bugsnag::Helpers.cleanup_url "/dir/page"
|
63
63
|
|
64
|
-
url.
|
64
|
+
expect(url).to eq("/dir/page")
|
65
65
|
end
|
66
66
|
|
67
|
-
it "
|
67
|
+
it "leaves a url alone if no filters match" do
|
68
68
|
url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1¶m2=value2", ["param3"]
|
69
69
|
|
70
|
-
url.
|
70
|
+
expect(url).to eq("/dir/page?param1=value1¶m2=value2")
|
71
71
|
end
|
72
72
|
|
73
|
-
it "
|
73
|
+
it "filters a single get param" do
|
74
74
|
url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1¶m2=value2", ["param1"]
|
75
75
|
|
76
|
-
url.
|
76
|
+
expect(url).to eq("/dir/page?param1=[FILTERED]¶m2=value2")
|
77
77
|
end
|
78
78
|
|
79
|
-
it "
|
79
|
+
it "filters a get param that contains a filtered term" do
|
80
80
|
url = Bugsnag::Helpers.cleanup_url '/dir/page?param1=value1¶m2=value2&bla=yes', ["param"]
|
81
81
|
|
82
|
-
url.
|
82
|
+
expect(url).to eq("/dir/page?param1=[FILTERED]¶m2=[FILTERED]&bla=yes")
|
83
83
|
end
|
84
84
|
|
85
|
-
it "
|
85
|
+
it "filters multiple matches" do
|
86
86
|
url = Bugsnag::Helpers.cleanup_url "/dir/page?param1=value1¶m2=value2¶m3=value3", ["param1", "param2"]
|
87
87
|
|
88
|
-
url.
|
88
|
+
expect(url).to eq("/dir/page?param1=[FILTERED]¶m2=[FILTERED]¶m3=value3")
|
89
89
|
end
|
90
90
|
end
|
data/spec/middleware_spec.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Bugsnag::MiddlewareStack do
|
4
|
-
it "
|
5
|
-
Bugsnag::Notification.
|
4
|
+
it "runs before_bugsnag_notify callbacks, adding a tab" do
|
5
|
+
expect(Bugsnag::Notification).to receive(:deliver_exception_payload) do |endpoint, payload|
|
6
6
|
event = get_event_from_payload(payload)
|
7
|
-
event[:metaData][:some_tab].
|
8
|
-
event[:metaData][:some_tab][:info].
|
9
|
-
event[:metaData][:some_tab][:data].
|
7
|
+
expect(event[:metaData][:some_tab]).not_to be_nil
|
8
|
+
expect(event[:metaData][:some_tab][:info]).to eq("here")
|
9
|
+
expect(event[:metaData][:some_tab][:data]).to eq("also here")
|
10
10
|
end
|
11
11
|
|
12
12
|
callback_run_count = 0
|
@@ -19,15 +19,15 @@ describe Bugsnag::MiddlewareStack do
|
|
19
19
|
}
|
20
20
|
|
21
21
|
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
22
|
-
callback_run_count.
|
22
|
+
expect(callback_run_count).to eq(1)
|
23
23
|
end
|
24
24
|
|
25
|
-
it "
|
26
|
-
Bugsnag::Notification.
|
25
|
+
it "runs before_bugsnag_notify callbacks, adding custom data" do
|
26
|
+
expect(Bugsnag::Notification).to receive(:deliver_exception_payload) do |endpoint, payload|
|
27
27
|
event = get_event_from_payload(payload)
|
28
|
-
event[:metaData][:custom].
|
29
|
-
event[:metaData][:custom][:info].
|
30
|
-
event[:metaData][:custom][:data].
|
28
|
+
expect(event[:metaData][:custom]).not_to be_nil
|
29
|
+
expect(event[:metaData][:custom][:info]).to eq("here")
|
30
|
+
expect(event[:metaData][:custom][:data]).to eq("also here")
|
31
31
|
end
|
32
32
|
|
33
33
|
callback_run_count = 0
|
@@ -39,17 +39,17 @@ describe Bugsnag::MiddlewareStack do
|
|
39
39
|
}
|
40
40
|
|
41
41
|
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
42
|
-
callback_run_count.
|
42
|
+
expect(callback_run_count).to eq(1)
|
43
43
|
end
|
44
44
|
|
45
|
-
it "
|
46
|
-
Bugsnag::Notification.
|
45
|
+
it "runs before_bugsnag_notify callbacks, setting the user" do
|
46
|
+
expect(Bugsnag::Notification).to receive(:deliver_exception_payload) do |endpoint, payload|
|
47
47
|
event = get_event_from_payload(payload)
|
48
|
-
event[:user].
|
49
|
-
event[:user][:id].
|
50
|
-
event[:user][:email].
|
51
|
-
event[:user][:name].
|
52
|
-
event[:user][:random_key].
|
48
|
+
expect(event[:user]).not_to be_nil
|
49
|
+
expect(event[:user][:id]).to eq("here")
|
50
|
+
expect(event[:user][:email]).to eq("also here")
|
51
|
+
expect(event[:user][:name]).to eq("also here too")
|
52
|
+
expect(event[:user][:random_key]).to eq("also here too too")
|
53
53
|
end
|
54
54
|
|
55
55
|
callback_run_count = 0
|
@@ -59,15 +59,15 @@ describe Bugsnag::MiddlewareStack do
|
|
59
59
|
}
|
60
60
|
|
61
61
|
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
62
|
-
callback_run_count.
|
62
|
+
expect(callback_run_count).to eq(1)
|
63
63
|
end
|
64
64
|
|
65
|
-
it "overrides
|
66
|
-
Bugsnag::Notification.
|
65
|
+
it "overrides data set in before_notify" do
|
66
|
+
expect(Bugsnag::Notification).to receive(:deliver_exception_payload) do |endpoint, payload|
|
67
67
|
event = get_event_from_payload(payload)
|
68
|
-
event[:metaData][:custom].
|
69
|
-
event[:metaData][:custom][:info].
|
70
|
-
event[:metaData][:custom][:data].
|
68
|
+
expect(event[:metaData][:custom]).not_to be_nil
|
69
|
+
expect(event[:metaData][:custom][:info]).to eq("here2")
|
70
|
+
expect(event[:metaData][:custom][:data]).to eq("also here")
|
71
71
|
end
|
72
72
|
|
73
73
|
callback_run_count = 0
|
@@ -79,24 +79,22 @@ describe Bugsnag::MiddlewareStack do
|
|
79
79
|
}
|
80
80
|
|
81
81
|
Bugsnag.notify(BugsnagTestException.new("It crashed"), {:info => "here2"})
|
82
|
-
callback_run_count.
|
82
|
+
expect(callback_run_count).to eq(1)
|
83
83
|
end
|
84
84
|
|
85
|
-
it "
|
86
|
-
Bugsnag::Notification.
|
85
|
+
it "does not have have before or after callbacks by default" do
|
86
|
+
expect(Bugsnag::Notification).to receive(:deliver_exception_payload) do |endpoint, payload|
|
87
87
|
event = get_event_from_payload(payload)
|
88
|
-
event[:metaData].
|
88
|
+
expect(event[:metaData].size).to eq(0)
|
89
89
|
end
|
90
90
|
|
91
|
-
Bugsnag.before_notify_callbacks.
|
92
|
-
Bugsnag.after_notify_callbacks.
|
91
|
+
expect(Bugsnag.before_notify_callbacks.size).to eq(0)
|
92
|
+
expect(Bugsnag.after_notify_callbacks.size).to eq(0)
|
93
93
|
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
94
94
|
end
|
95
95
|
|
96
|
-
it "
|
97
|
-
Bugsnag::Notification.
|
98
|
-
event = get_event_from_payload(payload)
|
99
|
-
end
|
96
|
+
it "runs after_bugsnag_notify callbacks" do
|
97
|
+
expect(Bugsnag::Notification).to receive(:deliver_exception_payload)
|
100
98
|
|
101
99
|
callback_run_count = 0
|
102
100
|
Bugsnag.after_notify_callbacks << lambda {|notif|
|
@@ -105,10 +103,10 @@ describe Bugsnag::MiddlewareStack do
|
|
105
103
|
|
106
104
|
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
107
105
|
|
108
|
-
callback_run_count.
|
106
|
+
expect(callback_run_count).to eq(1)
|
109
107
|
end
|
110
108
|
|
111
|
-
it "
|
109
|
+
it "does not execute disabled bugsnag middleware" do
|
112
110
|
callback_run_count = 0
|
113
111
|
Bugsnag.configure do |config|
|
114
112
|
config.middleware.disable(Bugsnag::Middleware::Callbacks)
|
@@ -119,6 +117,6 @@ describe Bugsnag::MiddlewareStack do
|
|
119
117
|
}
|
120
118
|
|
121
119
|
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
122
|
-
callback_run_count.
|
120
|
+
expect(callback_run_count).to eq(0)
|
123
121
|
end
|
124
|
-
end
|
122
|
+
end
|