Skip to content

Commit

Permalink
Removed several unneccessary threads, streamlined delivery
Browse files Browse the repository at this point in the history
  • Loading branch information
Cawllec committed Jan 5, 2018
1 parent af264a0 commit 77456f6
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 70 deletions.
6 changes: 4 additions & 2 deletions lib/bugsnag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ def configure
@key_warning = true
end

session_tracker.config = configuration
if configuration.track_sessions
session_tracker.start_delivery_thread
end
end

# Explicitly notify of an exception
Expand Down Expand Up @@ -130,7 +132,7 @@ def configuration

def session_tracker
@session_tracker = nil unless defined?(@session_tracker)
@session_tracker || LOCK.synchronize { @session_tracker ||= Bugsnag::SessionTracker.new(configuration)}
@session_tracker || LOCK.synchronize { @session_tracker ||= Bugsnag::SessionTracker.new}
end

# Allow access to "before notify" callbacks
Expand Down
120 changes: 52 additions & 68 deletions lib/bugsnag/session_tracker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ module Bugsnag
class SessionTracker

THREAD_SESSION = "bugsnag_session"
TIME_THRESHOLD = 60
FALLBACK_TIME = 300
MAXIMUM_SESSION_COUNT = 50
MAXIMUM_SESSION_COUNT = 100
SESSION_PAYLOAD_VERSION = "1.0"

attr_reader :session_counts
attr_writer :config
attr_accessor :track_sessions

def self.set_current_session(session)
Thread.current[THREAD_SESSION] = session
Expand All @@ -22,15 +20,14 @@ def self.get_current_session
Thread.current[THREAD_SESSION]
end

def initialize(configuration)
def initialize
@session_counts = {}
@config = configuration
@mutex = Mutex.new
@last_sent = Time.now
@track_sessions = false
end

def create_session
return unless @config.track_sessions
return unless @track_sessions
start_time = Time.now().utc().strftime('%Y-%m-%dT%H:%M:00')
new_session = {
:id => SecureRandom.uuid,
Expand All @@ -41,88 +38,76 @@ def create_session
}
}
SessionTracker.set_current_session(new_session)
add_thread = Thread.new { add_session(start_time) }
add_session(start_time)
end

def send_sessions
return unless @track_sessions
@mutex.lock
begin
deliver_sessions
sessions = []
@session_counts.each do |min, count|
sessions << {
:startedAt => min,
:sessionsStarted => count
}
end
@session_counts = {}
ensure
@mutex.unlock
end
deliver(sessions)
end

def start_delivery_thread
@track_sessions = true
@initialised_sessions = false unless defined?(@initialised_sessions)
if !@initialised_sessions
@initialised_sessions = true
at_exit do
if !@delivery_thread.nil? && @delivery_thread.status == 'sleep'
@delivery_thread.terminate
send_sessions
else
@delivery_thread.join
end
end
@delivery_thread = Thread.new do
while true
sleep(30)
if @session_counts.size > 0
send_sessions
end
end
end
end
end

private
def add_session(min)
@mutex.lock
begin
@registered_at_exit = false unless defined?(@registered_at_exit)
if !@registered_at_exit
@registered_at_exit = true
at_exit do
if !@deliver_fallback.nil? && @deliver_fallback.status == 'sleep'
@deliver_fallback.terminate
end
deliver_sessions
end
end
@session_counts[min] ||= 0
@session_counts[min] += 1
if Time.now() - @last_sent > TIME_THRESHOLD
deliver_sessions
end
ensure
@mutex.unlock
end
end

def deliver_sessions
return unless @config.track_sessions
sessions = []
@session_counts.each do |min, count|
sessions << {
:startedAt => min,
:sessionsStarted => count
}
if sessions.size >= MAXIMUM_SESSION_COUNT
deliver(sessions)
sessions = []
end
end
@session_counts = {}
reset_delivery_thread
deliver(sessions)
end

def reset_delivery_thread
if !@deliver_fallback.nil? && @deliver_fallback.status == 'sleep'
@deliver_fallback.terminate
end
@deliver_fallback = Thread.new do
sleep(FALLBACK_TIME)
deliver_sessions
end
end

def deliver(sessionCounts)
config = Bugsnag.configuration
if sessionCounts.length == 0
@config.debug("No sessions to deliver")
return
end

if !@config.valid_api_key?
@config.debug("Not delivering sessions due to an invalid api_key")
config.debug("No sessions to deliver")
return
end

if !@config.should_notify_release_stage?
@config.debug("Not delivering sessions due to notify_release_stages :#{@config.notify_release_stages.inspect}")
if !Bugsnag.configuration.valid_api_key?
config.debug("Not delivering sessions due to an invalid api_key")
return
end

if @config.delivery_method != :thread_queue
@config.debug("Not delivering sessions due to asynchronous delivery being disabled")
if !config.should_notify_release_stage?
config.debug("Not delivering sessions due to notify_release_stages :#{@config.notify_release_stages.inspect}")
return
end

Expand All @@ -133,25 +118,24 @@ def deliver(sessionCounts)
:version => Bugsnag::Report::NOTIFIER_VERSION
},
:device => {
:hostname => @config.hostname
:hostname => config.hostname
},
:app => {
:version => @config.app_version,
:releaseStage => @config.release_stage,
:type => @config.app_type
:version => config.app_version,
:releaseStage => config.release_stage,
:type => config.app_type
},
:sessionCounts => sessionCounts
}
payload = ::JSON.dump(body)

headers = {
"Bugsnag-Api-Key" => @config.api_key,
"Bugsnag-Api-Key" => config.api_key,
"Bugsnag-Payload-Version" => SESSION_PAYLOAD_VERSION
}

options = {:headers => headers, :success => '202'}
@last_sent = Time.now
Bugsnag::Delivery[@config.delivery_method].deliver(@config.session_endpoint, payload, @config, options)
Bugsnag::Delivery[config.delivery_method].deliver(config.session_endpoint, payload, config, options)
end
end
end

0 comments on commit 77456f6

Please sign in to comment.