bugsnag 6.3.0.beta.0 → 6.3.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.
@@ -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