bugsnag 6.2.0 → 6.3.0.beta.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 +4 -4
- data/VERSION +1 -1
- data/lib/bugsnag.rb +10 -2
- data/lib/bugsnag/configuration.rb +8 -1
- data/lib/bugsnag/delivery/synchronous.rb +107 -6
- data/lib/bugsnag/delivery/thread_queue.rb +2 -2
- data/lib/bugsnag/helpers.rb +24 -0
- data/lib/bugsnag/integrations/rack.rb +1 -0
- data/lib/bugsnag/integrations/rails/controller_methods.rb +1 -0
- data/lib/bugsnag/middleware/session_data.rb +21 -0
- data/lib/bugsnag/report.rb +12 -3
- data/lib/bugsnag/session_tracker.rb +157 -0
- data/spec/configuration_spec.rb +5 -0
- data/spec/integrations/sidekiq_spec.rb +1 -1
- data/spec/middleware_spec.rb +10 -10
- data/spec/rack_spec.rb +2 -2
- data/spec/rails3_request_spec.rb +2 -2
- data/spec/report_spec.rb +61 -61
- data/spec/session_tracker_spec.rb +153 -0
- data/spec/spec_helper.rb +17 -1
- data/spec/stacktrace_spec.rb +5 -5
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0643f03a70da437fa3983ee21f1f9ec4466085e
|
4
|
+
data.tar.gz: bdcdb50f10d93babed837ad0f6ec3ad174c765b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d4341b5a7e9566d16c4f9fee869d570824ee89a8092260f54c19791984241f163237beb564622850cb163479f5dff81d34860917f91f16eb639461bcca755f7
|
7
|
+
data.tar.gz: 541e02bf501da119d9ddb4acde6ca3df1c2805c4513c7ab201a837d5d18e54a9eefbf95205fa5dd433b0f811d56c801fec3b53d871a696e9c7b8738db1b12c35
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
6.
|
1
|
+
6.3.0.beta.0
|
data/lib/bugsnag.rb
CHANGED
@@ -7,6 +7,7 @@ require "bugsnag/meta_data"
|
|
7
7
|
require "bugsnag/report"
|
8
8
|
require "bugsnag/cleaner"
|
9
9
|
require "bugsnag/helpers"
|
10
|
+
require "bugsnag/session_tracker"
|
10
11
|
|
11
12
|
require "bugsnag/delivery"
|
12
13
|
require "bugsnag/delivery/synchronous"
|
@@ -38,6 +39,8 @@ module Bugsnag
|
|
38
39
|
configuration.warn("No valid API key has been set, notifications will not be sent")
|
39
40
|
@key_warning = true
|
40
41
|
end
|
42
|
+
|
43
|
+
session_tracker.config = configuration
|
41
44
|
end
|
42
45
|
|
43
46
|
# Explicitly notify of an exception
|
@@ -108,8 +111,8 @@ module Bugsnag
|
|
108
111
|
|
109
112
|
# Deliver
|
110
113
|
configuration.info("Notifying #{configuration.endpoint} of #{report.exceptions.last[:errorClass]}")
|
111
|
-
|
112
|
-
Bugsnag::Delivery[configuration.delivery_method].deliver(configuration.endpoint,
|
114
|
+
options = {:headers => report.headers, :trim_payload => true}
|
115
|
+
Bugsnag::Delivery[configuration.delivery_method].deliver(configuration.endpoint, report.as_json, configuration, options)
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
@@ -119,6 +122,11 @@ module Bugsnag
|
|
119
122
|
@configuration || LOCK.synchronize { @configuration ||= Bugsnag::Configuration.new }
|
120
123
|
end
|
121
124
|
|
125
|
+
def session_tracker
|
126
|
+
@session_tracker = nil unless defined?(@session_tracker)
|
127
|
+
@session_tracker || LOCK.synchronize { @session_tracker ||= Bugsnag::SessionTracker.new(configuration)}
|
128
|
+
end
|
129
|
+
|
122
130
|
# Allow access to "before notify" callbacks
|
123
131
|
def before_notify_callbacks
|
124
132
|
Bugsnag.configuration.request_data[:before_callbacks] ||= []
|
@@ -7,6 +7,7 @@ require "bugsnag/middleware/exception_meta_data"
|
|
7
7
|
require "bugsnag/middleware/ignore_error_class"
|
8
8
|
require "bugsnag/middleware/suggestion_data"
|
9
9
|
require "bugsnag/middleware/classify_error"
|
10
|
+
require "bugsnag/middleware/session_data"
|
10
11
|
|
11
12
|
module Bugsnag
|
12
13
|
class Configuration
|
@@ -22,7 +23,7 @@ module Bugsnag
|
|
22
23
|
attr_accessor :app_type
|
23
24
|
attr_accessor :meta_data_filters
|
24
25
|
attr_accessor :endpoint
|
25
|
-
attr_accessor :logger
|
26
|
+
attr_accessor :logger
|
26
27
|
attr_accessor :middleware
|
27
28
|
attr_accessor :internal_middleware
|
28
29
|
attr_accessor :proxy_host
|
@@ -32,10 +33,13 @@ module Bugsnag
|
|
32
33
|
attr_accessor :timeout
|
33
34
|
attr_accessor :hostname
|
34
35
|
attr_accessor :ignore_classes
|
36
|
+
attr_accessor :track_sessions
|
37
|
+
attr_accessor :session_endpoint
|
35
38
|
|
36
39
|
API_KEY_REGEX = /[0-9a-f]{32}/i
|
37
40
|
THREAD_LOCAL_NAME = "bugsnag_req_data"
|
38
41
|
DEFAULT_ENDPOINT = "https://notify.bugsnag.com"
|
42
|
+
DEFAULT_SESSION_ENDPOINT = "https://sessions.bugsnag.com"
|
39
43
|
|
40
44
|
DEFAULT_META_DATA_FILTERS = [
|
41
45
|
/authorization/i,
|
@@ -57,6 +61,8 @@ module Bugsnag
|
|
57
61
|
self.hostname = default_hostname
|
58
62
|
self.timeout = 15
|
59
63
|
self.notify_release_stages = nil
|
64
|
+
self.track_sessions = false
|
65
|
+
self.session_endpoint = DEFAULT_SESSION_ENDPOINT
|
60
66
|
|
61
67
|
# SystemExit and Interrupt are common Exception types seen with successful
|
62
68
|
# exits and are not automatically reported to Bugsnag
|
@@ -81,6 +87,7 @@ module Bugsnag
|
|
81
87
|
self.internal_middleware.use Bugsnag::Middleware::IgnoreErrorClass
|
82
88
|
self.internal_middleware.use Bugsnag::Middleware::SuggestionData
|
83
89
|
self.internal_middleware.use Bugsnag::Middleware::ClassifyError
|
90
|
+
self.internal_middleware.use Bugsnag::Middleware::SessionData
|
84
91
|
|
85
92
|
self.middleware = Bugsnag::MiddlewareStack.new
|
86
93
|
self.middleware.use Bugsnag::Middleware::Callbacks
|
@@ -4,13 +4,19 @@ require "uri"
|
|
4
4
|
module Bugsnag
|
5
5
|
module Delivery
|
6
6
|
class Synchronous
|
7
|
-
|
7
|
+
BACKOFF_THREADS = {}
|
8
|
+
BACKOFF_REQUESTS = {}
|
9
|
+
BACKOFF_LOCK = Mutex.new
|
8
10
|
|
9
11
|
class << self
|
10
|
-
def deliver(url, body, configuration)
|
12
|
+
def deliver(url, body, configuration, options={})
|
11
13
|
begin
|
12
|
-
response = request(url, body, configuration)
|
14
|
+
response = request(url, body, configuration, options)
|
13
15
|
configuration.debug("Request to #{url} completed, status: #{response.code}")
|
16
|
+
success = options[:success] || '200'
|
17
|
+
if options[:backoff] && !(response.code == success)
|
18
|
+
backoff(url, body, configuration, options)
|
19
|
+
end
|
14
20
|
rescue StandardError => e
|
15
21
|
# KLUDGE: Since we don't re-raise http exceptions, this breaks rspec
|
16
22
|
raise if e.class.to_s == "RSpec::Expectations::ExpectationNotMetError"
|
@@ -22,9 +28,14 @@ module Bugsnag
|
|
22
28
|
|
23
29
|
private
|
24
30
|
|
25
|
-
def request(url, body, configuration)
|
31
|
+
def request(url, body, configuration, options)
|
26
32
|
uri = URI.parse(url)
|
27
33
|
|
34
|
+
if options[:trim_payload]
|
35
|
+
body = Bugsnag::Helpers.trim_if_needed(body)
|
36
|
+
end
|
37
|
+
payload = ::JSON.dump(body)
|
38
|
+
|
28
39
|
if configuration.proxy_host
|
29
40
|
http = Net::HTTP.new(uri.host, uri.port, configuration.proxy_host, configuration.proxy_port, configuration.proxy_user, configuration.proxy_password)
|
30
41
|
else
|
@@ -39,14 +50,104 @@ module Bugsnag
|
|
39
50
|
http.ca_file = configuration.ca_file if configuration.ca_file
|
40
51
|
end
|
41
52
|
|
42
|
-
|
43
|
-
|
53
|
+
headers = options.key?(:headers) ? options[:headers] : {}
|
54
|
+
headers.merge!(default_headers)
|
55
|
+
|
56
|
+
request = Net::HTTP::Post.new(path(uri), headers)
|
57
|
+
request.body = payload
|
58
|
+
|
44
59
|
http.request(request)
|
45
60
|
end
|
46
61
|
|
62
|
+
def backoff(url, body, configuration, options)
|
63
|
+
# Ensure we have the latest configuration for making these requests
|
64
|
+
@latest_configuration = configuration
|
65
|
+
|
66
|
+
BACKOFF_LOCK.lock
|
67
|
+
begin
|
68
|
+
# Define an exit function once to handle outstanding requests
|
69
|
+
@registered_at_exit = false unless defined?(@registered_at_exit)
|
70
|
+
if !@registered_at_exit
|
71
|
+
@registered_at_exit = true
|
72
|
+
at_exit do
|
73
|
+
backoff_exit
|
74
|
+
end
|
75
|
+
end
|
76
|
+
if BACKOFF_REQUESTS[url] && !BACKOFF_REQUESTS[url].empty?
|
77
|
+
last_request = BACKOFF_REQUESTS[url].last
|
78
|
+
new_body_length = ::JSON.dump(body).length
|
79
|
+
old_body_length = ::JSON.dump(last_request[:body]).length
|
80
|
+
if new_body_length + old_body_length >= Bugsnag::Helpers::MAX_PAYLOAD_LENGTH
|
81
|
+
BACKOFF_REQUESTS[url].push({:body => body, :options => options})
|
82
|
+
else
|
83
|
+
Bugsnag::Helpers::deep_merge!(last_request, {:body => body, :options => options})
|
84
|
+
end
|
85
|
+
else
|
86
|
+
BACKOFF_REQUESTS[url] = [{:body => body, :options => options}]
|
87
|
+
end
|
88
|
+
if !(BACKOFF_THREADS[url] && BACKOFF_THREADS[url].status)
|
89
|
+
spawn_backoff_thread(url)
|
90
|
+
end
|
91
|
+
ensure
|
92
|
+
BACKOFF_LOCK.unlock
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def backoff_exit
|
97
|
+
# Kill existing threads
|
98
|
+
BACKOFF_THREADS.each do |url, thread|
|
99
|
+
thread.exit
|
100
|
+
end
|
101
|
+
# Retry outstanding requests once, then exit
|
102
|
+
BACKOFF_REQUESTS.each do |url, requests|
|
103
|
+
requests.map! do |req|
|
104
|
+
response = request(url, req[:body], @latest_configuration, req[:options])
|
105
|
+
success = req[:options][:success] || '200'
|
106
|
+
response.code == success
|
107
|
+
end
|
108
|
+
requests.reject! { |i| i }
|
109
|
+
@latest_configuration.warn("Requests to #{url} finished, #{requests.size} failed")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def spawn_backoff_thread(url)
|
114
|
+
new_thread = Thread.new(url) do |url|
|
115
|
+
interval = 2
|
116
|
+
while BACKOFF_REQUESTS[url].size > 0
|
117
|
+
sleep(interval)
|
118
|
+
interval = interval * 2
|
119
|
+
interval = 600 if interval > 600
|
120
|
+
BACKOFF_LOCK.lock
|
121
|
+
begin
|
122
|
+
BACKOFF_REQUESTS[url].map! do |req|
|
123
|
+
response = request(url, req[:body], @latest_configuration, req[:options])
|
124
|
+
success = req[:options][:success] || '200'
|
125
|
+
if response.code == success
|
126
|
+
@latest_configuration.debug("Request to #{url} completed, status: #{response.code}")
|
127
|
+
false
|
128
|
+
else
|
129
|
+
req
|
130
|
+
end
|
131
|
+
end
|
132
|
+
BACKOFF_REQUESTS[url].reject! { |i| !i }
|
133
|
+
ensure
|
134
|
+
BACKOFF_LOCK.unlock
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
BACKOFF_THREADS[url] = new_thread
|
139
|
+
end
|
140
|
+
|
47
141
|
def path(uri)
|
48
142
|
uri.path == "" ? "/" : uri.path
|
49
143
|
end
|
144
|
+
|
145
|
+
def default_headers
|
146
|
+
{
|
147
|
+
"Content-Type" => "application/json",
|
148
|
+
"Bugsnag-Sent-At" => Time.now().utc().strftime('%Y-%m-%dT%H:%M:%S')
|
149
|
+
}
|
150
|
+
end
|
50
151
|
end
|
51
152
|
end
|
52
153
|
end
|
@@ -8,7 +8,7 @@ module Bugsnag
|
|
8
8
|
MUTEX = Mutex.new
|
9
9
|
|
10
10
|
class << self
|
11
|
-
def deliver(url, body, configuration)
|
11
|
+
def deliver(url, body, configuration, options={})
|
12
12
|
@configuration = configuration
|
13
13
|
|
14
14
|
start_once!
|
@@ -19,7 +19,7 @@ module Bugsnag
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Add delivery to the worker thread
|
22
|
-
@queue.push proc { super(url, body, configuration) }
|
22
|
+
@queue.push proc { super(url, body, configuration, options) }
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
data/lib/bugsnag/helpers.rb
CHANGED
@@ -23,6 +23,30 @@ module Bugsnag
|
|
23
23
|
remove_metadata_from_events(reduced_value)
|
24
24
|
end
|
25
25
|
|
26
|
+
def self.deep_merge(l_hash, r_hash)
|
27
|
+
l_hash.merge(r_hash) do |key, l_val, r_val|
|
28
|
+
if l_val.is_a?(Hash) && r_val.is_a?(Hash)
|
29
|
+
deep_merge(l_val, r_val)
|
30
|
+
elsif l_val.is_a?(Array) && r_val.is_a?(Array)
|
31
|
+
l_val.concat(r_val)
|
32
|
+
else
|
33
|
+
r_val
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.deep_merge!(l_hash, r_hash)
|
39
|
+
l_hash.merge!(r_hash) do |key, l_val, r_val|
|
40
|
+
if l_val.is_a?(Hash) && r_val.is_a?(Hash)
|
41
|
+
deep_merge(l_val, r_val)
|
42
|
+
elsif l_val.is_a?(Array) && r_val.is_a?(Array)
|
43
|
+
l_val.concat(r_val)
|
44
|
+
else
|
45
|
+
r_val
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
26
50
|
private
|
27
51
|
|
28
52
|
TRUNCATION_INFO = '[TRUNCATED]'
|
@@ -0,0 +1,21 @@
|
|
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
|
data/lib/bugsnag/report.rb
CHANGED
@@ -17,8 +17,9 @@ module Bugsnag
|
|
17
17
|
|
18
18
|
MAX_EXCEPTIONS_TO_UNWRAP = 5
|
19
19
|
|
20
|
-
CURRENT_PAYLOAD_VERSION = "
|
20
|
+
CURRENT_PAYLOAD_VERSION = "4.0"
|
21
21
|
|
22
|
+
attr_reader :unhandled
|
22
23
|
attr_accessor :api_key
|
23
24
|
attr_accessor :app_type
|
24
25
|
attr_accessor :app_version
|
@@ -31,6 +32,7 @@ module Bugsnag
|
|
31
32
|
attr_accessor :meta_data
|
32
33
|
attr_accessor :raw_exceptions
|
33
34
|
attr_accessor :release_stage
|
35
|
+
attr_accessor :session
|
34
36
|
attr_accessor :severity
|
35
37
|
attr_accessor :severity_reason
|
36
38
|
attr_accessor :user
|
@@ -92,7 +94,7 @@ module Bugsnag
|
|
92
94
|
},
|
93
95
|
exceptions: exceptions,
|
94
96
|
groupingHash: grouping_hash,
|
95
|
-
|
97
|
+
session: session,
|
96
98
|
severity: severity,
|
97
99
|
severityReason: severity_reason,
|
98
100
|
unhandled: @unhandled,
|
@@ -108,7 +110,6 @@ module Bugsnag
|
|
108
110
|
|
109
111
|
# return the payload hash
|
110
112
|
{
|
111
|
-
:apiKey => api_key,
|
112
113
|
:notifier => {
|
113
114
|
:name => NOTIFIER_NAME,
|
114
115
|
:version => NOTIFIER_VERSION,
|
@@ -118,6 +119,14 @@ module Bugsnag
|
|
118
119
|
}
|
119
120
|
end
|
120
121
|
|
122
|
+
def headers
|
123
|
+
{
|
124
|
+
"Bugsnag-Api-Key" => api_key,
|
125
|
+
"Bugsnag-Payload-Version" => CURRENT_PAYLOAD_VERSION,
|
126
|
+
"Bugsnag-Sent-At" => Time.now().utc().strftime('%Y-%m-%dT%H:%M:%S')
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
121
130
|
def ignore?
|
122
131
|
@should_ignore
|
123
132
|
end
|
@@ -0,0 +1,157 @@
|
|
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
|