bugsnag 6.3.0.beta.0 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,17 +14,15 @@ require 'webmock/rspec'
14
14
  require 'rspec/expectations'
15
15
  require 'rspec/mocks'
16
16
 
17
- class BugsnagTestException < RuntimeError; end
17
+ class BugsnagTestException < RuntimeError
18
+ attr_accessor :skip_bugsnag
19
+ end
18
20
 
19
21
  def get_event_from_payload(payload)
20
22
  expect(payload["events"].size).to eq(1)
21
23
  payload["events"].first
22
24
  end
23
25
 
24
- def get_headers_from_payload(payload)
25
-
26
- end
27
-
28
26
  def get_exception_from_payload(payload)
29
27
  event = get_event_from_payload(payload)
30
28
  expect(event["exceptions"].size).to eq(1)
@@ -48,7 +46,6 @@ RSpec.configure do |config|
48
46
 
49
47
  config.before(:each) do
50
48
  WebMock.stub_request(:post, "https://notify.bugsnag.com/")
51
- WebMock.stub_request(:post, "https://sessions.bugsnag.com/")
52
49
 
53
50
  Bugsnag.instance_variable_set(:@configuration, Bugsnag::Configuration.new)
54
51
  Bugsnag.configure do |bugsnag|
@@ -65,21 +62,10 @@ RSpec.configure do |config|
65
62
  end
66
63
  end
67
64
 
68
- def have_sent_sessions(&matcher)
69
- have_requested(:post, "https://sessions.bugsnag.com/").with do |request|
70
- if matcher
71
- matcher.call([JSON.parse(request.body), request.headers])
72
- true
73
- else
74
- raise "no matcher provided to have_sent_sessions (did you use { })"
75
- end
76
- end
77
- end
78
-
79
65
  def have_sent_notification(&matcher)
80
66
  have_requested(:post, "https://notify.bugsnag.com/").with do |request|
81
67
  if matcher
82
- matcher.call([JSON.parse(request.body), request.headers])
68
+ matcher.call JSON.parse(request.body)
83
69
  true
84
70
  else
85
71
  raise "no matcher provided to have_sent_notification (did you use { })"
@@ -10,7 +10,7 @@ describe Bugsnag::Stacktrace do
10
10
  _e = 5
11
11
  _f = 6
12
12
 
13
- expect(Bugsnag).to have_sent_notification{ |payload, headers|
13
+ expect(Bugsnag).to have_sent_notification{ |payload|
14
14
  exception = get_exception_from_payload(payload)
15
15
  starting_line = __LINE__ - 10
16
16
  expect(exception["stacktrace"][1]["code"]).to eq({
@@ -30,7 +30,7 @@ describe Bugsnag::Stacktrace do
30
30
 
31
31
  notify_test_exception
32
32
 
33
- expect(Bugsnag).to have_sent_notification{ |payload, headers|
33
+ expect(Bugsnag).to have_sent_notification{ |payload|
34
34
  exception = get_exception_from_payload(payload)
35
35
  expect(exception["stacktrace"][1]["code"]).to eq(nil)
36
36
  }
@@ -39,7 +39,7 @@ describe Bugsnag::Stacktrace do
39
39
  it 'should send the first 7 lines of the file for exceptions near the top' do
40
40
  load 'spec/fixtures/crashes/start_of_file.rb' rescue Bugsnag.notify $!
41
41
 
42
- expect(Bugsnag).to have_sent_notification{ |payload, headers|
42
+ expect(Bugsnag).to have_sent_notification{ |payload|
43
43
  exception = get_exception_from_payload(payload)
44
44
 
45
45
  expect(exception["stacktrace"][0]["code"]).to eq({
@@ -57,7 +57,7 @@ describe Bugsnag::Stacktrace do
57
57
  it 'should send the last 7 lines of the file for exceptions near the bottom' do
58
58
  load 'spec/fixtures/crashes/end_of_file.rb' rescue Bugsnag.notify $!
59
59
 
60
- expect(Bugsnag).to have_sent_notification{ |payload, headers|
60
+ expect(Bugsnag).to have_sent_notification{ |payload|
61
61
  exception = get_exception_from_payload(payload)
62
62
 
63
63
  expect(exception["stacktrace"][0]["code"]).to eq({
@@ -75,7 +75,7 @@ describe Bugsnag::Stacktrace do
75
75
  it 'should send the last 7 lines of the file for exceptions near the bottom' do
76
76
  load 'spec/fixtures/crashes/short_file.rb' rescue Bugsnag.notify $!
77
77
 
78
- expect(Bugsnag).to have_sent_notification{ |payload, headers|
78
+ expect(Bugsnag).to have_sent_notification{ |payload|
79
79
  exception = get_exception_from_payload(payload)
80
80
 
81
81
  expect(exception["stacktrace"][0]["code"]).to eq({
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: 6.3.0.beta.0
4
+ version: 6.3.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: 2017-12-12 00:00:00.000000000 Z
11
+ date: 2017-12-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby notifier for bugsnag.com
14
14
  email: james@bugsnag.com
@@ -60,13 +60,11 @@ files:
60
60
  - lib/bugsnag/middleware/rack_request.rb
61
61
  - lib/bugsnag/middleware/rails3_request.rb
62
62
  - lib/bugsnag/middleware/rake.rb
63
- - lib/bugsnag/middleware/session_data.rb
64
63
  - lib/bugsnag/middleware/sidekiq.rb
65
64
  - lib/bugsnag/middleware/suggestion_data.rb
66
65
  - lib/bugsnag/middleware/warden_user.rb
67
66
  - lib/bugsnag/middleware_stack.rb
68
67
  - lib/bugsnag/report.rb
69
- - lib/bugsnag/session_tracker.rb
70
68
  - lib/bugsnag/stacktrace.rb
71
69
  - lib/bugsnag/tasks.rb
72
70
  - lib/bugsnag/tasks/bugsnag.rake
@@ -89,7 +87,6 @@ files:
89
87
  - spec/rack_spec.rb
90
88
  - spec/rails3_request_spec.rb
91
89
  - spec/report_spec.rb
92
- - spec/session_tracker_spec.rb
93
90
  - spec/spec_helper.rb
94
91
  - spec/stacktrace_spec.rb
95
92
  homepage: http://github.com/bugsnag/bugsnag-ruby
@@ -107,9 +104,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
104
  version: 1.9.2
108
105
  required_rubygems_version: !ruby/object:Gem::Requirement
109
106
  requirements:
110
- - - ">"
107
+ - - ">="
111
108
  - !ruby/object:Gem::Version
112
- version: 1.3.1
109
+ version: '0'
113
110
  requirements: []
114
111
  rubyforge_project:
115
112
  rubygems_version: 2.6.13
@@ -1,21 +0,0 @@
1
- module Bugsnag::Middleware
2
- class SessionData
3
- def initialize(bugsnag)
4
- @bugsnag = bugsnag
5
- end
6
-
7
- def call(report)
8
- session = Bugsnag::SessionTracker.get_current_session
9
- unless session.nil?
10
- if report.unhandled
11
- session[:events][:unhandled] += 1
12
- else
13
- session[:events][:handled] += 1
14
- end
15
- report.session = session
16
- end
17
-
18
- @bugsnag.call(report)
19
- end
20
- end
21
- end
@@ -1,157 +0,0 @@
1
- require 'thread'
2
- require 'time'
3
- require 'securerandom'
4
-
5
- module Bugsnag
6
- class SessionTracker
7
-
8
- THREAD_SESSION = "bugsnag_session"
9
- TIME_THRESHOLD = 60
10
- FALLBACK_TIME = 300
11
- MAXIMUM_SESSION_COUNT = 50
12
- SESSION_PAYLOAD_VERSION = "1.0"
13
-
14
- attr_reader :session_counts
15
- attr_writer :config
16
-
17
- def self.set_current_session(session)
18
- Thread.current[THREAD_SESSION] = session
19
- end
20
-
21
- def self.get_current_session
22
- Thread.current[THREAD_SESSION]
23
- end
24
-
25
- def initialize(configuration)
26
- @session_counts = {}
27
- @config = configuration
28
- @mutex = Mutex.new
29
- @last_sent = Time.now
30
- end
31
-
32
- def create_session
33
- return unless @config.track_sessions
34
- start_time = Time.now().utc().strftime('%Y-%m-%dT%H:%M:00')
35
- new_session = {
36
- :id => SecureRandom.uuid,
37
- :startedAt => start_time,
38
- :events => {
39
- :handled => 0,
40
- :unhandled => 0
41
- }
42
- }
43
- SessionTracker.set_current_session(new_session)
44
- add_thread = Thread.new { add_session(start_time) }
45
- add_thread.join()
46
- end
47
-
48
- def send_sessions
49
- @mutex.lock
50
- begin
51
- deliver_sessions
52
- ensure
53
- @mutex.unlock
54
- end
55
- end
56
-
57
- private
58
- def add_session(min)
59
- @mutex.lock
60
- begin
61
- @registered_at_exit = false unless defined?(@registered_at_exit)
62
- if !@registered_at_exit
63
- @registered_at_exit = true
64
- at_exit do
65
- if !@deliver_fallback.nil? && @deliver_fallback.status == 'sleep'
66
- @deliver_fallback.terminate
67
- end
68
- deliver_sessions
69
- end
70
- end
71
- @session_counts[min] ||= 0
72
- @session_counts[min] += 1
73
- if Time.now() - @last_sent > TIME_THRESHOLD
74
- deliver_sessions
75
- end
76
- ensure
77
- @mutex.unlock
78
- end
79
- end
80
-
81
- def deliver_sessions
82
- return unless @config.track_sessions
83
- sessions = []
84
- @session_counts.each do |min, count|
85
- sessions << {
86
- :startedAt => min,
87
- :sessionsStarted => count
88
- }
89
- if sessions.size >= MAXIMUM_SESSION_COUNT
90
- deliver(sessions)
91
- sessions = []
92
- end
93
- end
94
- @session_counts = {}
95
- reset_delivery_thread
96
- deliver(sessions)
97
- end
98
-
99
- def reset_delivery_thread
100
- if !@deliver_fallback.nil? && @deliver_fallback.status == 'sleep'
101
- @deliver_fallback.terminate
102
- end
103
- @deliver_fallback = Thread.new do
104
- sleep(FALLBACK_TIME)
105
- deliver_sessions
106
- end
107
- end
108
-
109
- def deliver(sessionCounts)
110
- if sessionCounts.length == 0
111
- @config.debug("No sessions to deliver")
112
- return
113
- end
114
-
115
- if !@config.valid_api_key?
116
- @config.debug("Not delivering sessions due to an invalid api_key")
117
- return
118
- end
119
-
120
- if !@config.should_notify_release_stage?
121
- @config.debug("Not delivering sessions due to notify_release_stages :#{@config.notify_release_stages.inspect}")
122
- return
123
- end
124
-
125
- if @config.delivery_method != :thread_queue
126
- @config.debug("Not delivering sessions due to asynchronous delivery being disabled")
127
- return
128
- end
129
-
130
- payload = {
131
- :notifier => {
132
- :name => Bugsnag::Report::NOTIFIER_NAME,
133
- :url => Bugsnag::Report::NOTIFIER_URL,
134
- :version => Bugsnag::Report::NOTIFIER_VERSION
135
- },
136
- :device => {
137
- :hostname => @config.hostname
138
- },
139
- :app => {
140
- :version => @config.app_version,
141
- :releaseStage => @config.release_stage,
142
- :type => @config.app_type
143
- },
144
- :sessionCounts => sessionCounts
145
- }
146
-
147
- headers = {
148
- "Bugsnag-Api-Key" => @config.api_key,
149
- "Bugsnag-Payload-Version" => SESSION_PAYLOAD_VERSION
150
- }
151
-
152
- options = {:headers => headers, :backoff => true, :success => '202'}
153
- @last_sent = Time.now
154
- Bugsnag::Delivery[@config.delivery_method].deliver(@config.session_endpoint, payload, @config, options)
155
- end
156
- end
157
- end
@@ -1,153 +0,0 @@
1
- # encoding: utf-8
2
- require 'webrick'
3
- require 'spec_helper'
4
- require 'json'
5
-
6
- describe Bugsnag::SessionTracker do
7
- server = nil
8
- queue = Queue.new
9
-
10
- before do
11
- @config = Bugsnag::Configuration.new
12
- @config.track_sessions = true
13
- server = WEBrick::HTTPServer.new :Port => 0, :Logger => WEBrick::Log.new("/dev/null"), :AccessLog => []
14
- server.mount_proc '/' do |req, res|
15
- headers = []
16
- req.each { |header| headers << header }
17
- queue << [JSON.parse(req.body), headers]
18
- res.status = 202
19
- res.body = "OK\n"
20
- end
21
- Thread.new{ server.start }
22
- end
23
-
24
- after do
25
- Bugsnag.configure do |conf|
26
- conf.track_sessions = false
27
- conf.delivery_method = :synchronous
28
- end
29
- server.stop
30
- queue.clear
31
- end
32
-
33
- it 'does not create session object if disabled' do
34
- config = Bugsnag::Configuration.new
35
- config.track_sessions = false
36
- tracker = Bugsnag::SessionTracker.new(config)
37
- tracker.create_session
38
- expect(tracker.session_counts.size).to eq(0)
39
- end
40
-
41
- it 'adds session object to queue' do
42
- tracker = Bugsnag::SessionTracker.new(@config)
43
- tracker.create_session
44
- expect(tracker.session_counts.size).to eq(1)
45
- time = tracker.session_counts.keys.last
46
- count = tracker.session_counts[time]
47
-
48
- expect(count).to eq(1)
49
- end
50
-
51
- it 'stores session in thread' do
52
- tracker = Bugsnag::SessionTracker.new(@config)
53
- tracker.create_session
54
- session = Thread.current[Bugsnag::SessionTracker::THREAD_SESSION]
55
- expect(session.include? :id).to be true
56
- expect(session.include? :startedAt).to be true
57
- expect(session.include? :events).to be true
58
- expect(session[:events].include? :handled).to be true
59
- expect(session[:events].include? :unhandled).to be true
60
- expect(session[:events][:handled]).to eq(0)
61
- expect(session[:events][:unhandled]).to eq(0)
62
- end
63
-
64
- it 'gives unique ids to each session' do
65
- tracker = Bugsnag::SessionTracker.new(@config)
66
- tracker.create_session
67
- session_one = Thread.current[Bugsnag::SessionTracker::THREAD_SESSION]
68
- tracker.create_session
69
- session_two = Thread.current[Bugsnag::SessionTracker::THREAD_SESSION]
70
- expect(session_one[:id]).to_not eq(session_two[:id])
71
- end
72
-
73
- it 'sends sessions when send_sessions is called' do
74
- Bugsnag.configure do |conf|
75
- conf.track_sessions = true
76
- conf.delivery_method = :thread_queue
77
- conf.session_endpoint = "http://localhost:#{server.config[:Port]}"
78
- end
79
- WebMock.allow_net_connect!
80
- Bugsnag.session_tracker.create_session
81
- expect(Bugsnag.session_tracker.session_counts.size).to eq(1)
82
- Bugsnag.session_tracker.send_sessions
83
- expect(Bugsnag.session_tracker.session_counts.size).to eq(0)
84
- while queue.empty?
85
- sleep(0.05)
86
- end
87
- payload, headers = queue.pop
88
- expect(payload.include?("app")).to be true
89
- expect(payload.include?("notifier")).to be true
90
- expect(payload.include?("device")).to be true
91
- expect(payload.include?("sessionCounts")).to be true
92
- expect(payload["sessionCounts"].size).to eq(1)
93
- end
94
-
95
- it 'sets details from config' do
96
- Bugsnag.configure do |conf|
97
- conf.track_sessions = true
98
- conf.release_stage = "test_stage"
99
- conf.delivery_method = :thread_queue
100
- conf.session_endpoint = "http://localhost:#{server.config[:Port]}"
101
- end
102
- WebMock.allow_net_connect!
103
- Bugsnag.session_tracker.create_session
104
- expect(Bugsnag.session_tracker.session_counts.size).to eq(1)
105
- Bugsnag.session_tracker.send_sessions
106
- expect(Bugsnag.session_tracker.session_counts.size).to eq(0)
107
- while queue.empty?
108
- sleep(0.05)
109
- end
110
- payload, headers = queue.pop
111
- notifier = payload["notifier"]
112
- expect(notifier.include?("name")).to be true
113
- expect(notifier["name"]).to eq(Bugsnag::Report::NOTIFIER_NAME)
114
- expect(notifier.include?("url")).to be true
115
- expect(notifier["url"]).to eq(Bugsnag::Report::NOTIFIER_URL)
116
- expect(notifier.include?("version")).to be true
117
- expect(notifier["version"]).to eq(Bugsnag::Report::NOTIFIER_VERSION)
118
-
119
- app = payload["app"]
120
- expect(app.include?("releaseStage")).to be true
121
- expect(app["releaseStage"]).to eq(Bugsnag.configuration.release_stage)
122
- expect(app.include?("version")).to be true
123
- expect(app["version"]).to eq(Bugsnag.configuration.app_version)
124
- expect(app.include?("type")).to be true
125
- expect(app["type"]).to eq(Bugsnag.configuration.app_type)
126
-
127
- device = payload["device"]
128
- expect(device.include?("hostname")).to be true
129
- expect(device["hostname"]).to eq(Bugsnag.configuration.hostname)
130
- end
131
-
132
- it 'uses middleware to attach session to notification' do
133
- Bugsnag.configure do |conf|
134
- conf.track_sessions = true
135
- conf.release_stage = "test_stage"
136
- end
137
- Bugsnag.session_tracker.create_session
138
- Bugsnag.notify(BugsnagTestException.new("It crashed"))
139
- expect(Bugsnag).to have_sent_notification{ |payload, headers|
140
- event = payload["events"][0]
141
- expect(event.include?("session")).to be true
142
- session = event["session"]
143
- expect(session.include?("id")).to be true
144
- expect(session.include?("startedAt")).to be true
145
- expect(session.include?("events")).to be true
146
- sesevents = session['events']
147
- expect(sesevents.include?("unhandled")).to be true
148
- expect(sesevents["unhandled"]).to eq(0)
149
- expect(sesevents.include?("handled")).to be true
150
- expect(sesevents["handled"]).to eq(1)
151
- }
152
- end
153
- end