require 'net/protocol' require 'net/https' require 'socket' require 'thread' require 'uri' require 'forwardable' begin require 'securerandom' rescue LoadError end require 'rollbar/version' require 'rollbar/plugins' require 'rollbar/configuration' require 'rollbar/logger_proxy' require 'rollbar/exceptions' require 'rollbar/lazy_store' require 'rollbar/notifier' # The Rollbar module. It stores a Rollbar::Notifier per thread and # provides some module methods in order to use the current thread notifier. module Rollbar PUBLIC_NOTIFIER_METHODS = %w(debug info warn warning error critical log logger process_item process_from_async_handler scope send_failsafe log_info log_debug log_warning log_error silenced scope_object).freeze class << self extend Forwardable def_delegators :notifier, *PUBLIC_NOTIFIER_METHODS attr_writer :plugins attr_writer :root_notifier def notifier # Use the global instance @root_notifier so we don't fall # in a infinite loop Thread.current[:_rollbar_notifier] ||= Notifier.new(@root_notifier) end def notifier=(notifier) Thread.current[:_rollbar_notifier] = notifier end # It's the first notifier instantiated in the # process. We store it so all the next per-thread # notifiers can inherit its configuration # The methods Rollbar.configure, Rollbar.reconfigure, # Rollbar.preconfigure and Rollbar.unconfigure work # on this notifier. # Before v2.13.0 these methods worked on the global # configuration, so in the practice the behavior is the same, # since they work on the root notifier's configuration def root_notifier @root_notifier ||= notifier end def preconfigure(&block) root_notifier.preconfigure(&block) end # Configures the root notifier and loads the plugins def configure(&block) root_notifier.configure(&block) plugins.load! end # Reconfigures the root notifier def reconfigure(&block) root_notifier.reconfigure(&block) end # Unconfigures the root notifier def unconfigure root_notifier.unconfigure end # Returns the configuration for the current notifier. # The current notifier is Rollbar.notifier and exists # one per thread. def configuration notifier.configuration end def safely? configuration.safely? end def plugins @plugins ||= Rollbar::Plugins.new end def last_report Thread.current[:_rollbar_last_report] end def last_report=(report) Thread.current[:_rollbar_last_report] = report end # Resets the scope for the current thread notifier. The notifier # reference is kept so we reuse the notifier. # This is a change from version 2.13.0. Before this version # this method clears the notifier. # # It was used in order to reset the scope and reusing the global # configuration Rollbar.configuration. Since now Rollbar.configuration # points to the current notifier configuration, we can resue the # notifier instance and just reset the scope. def reset_notifier! notifier.reset! end # Clears the current thread notifier and the root notifier. # In the practice this should be used only on the specs def clear_notifier! self.notifier = nil self.root_notifier = nil end # Create a new Notifier instance using the received options and # set it as the current thread notifier. # The calls to Rollbar inside the received block will use then this # new Notifier object. # # @example # # new_scope = { job_type: 'scheduled' } # new_config = { use_async: false } # # Rollbar.scoped(new_scope, new_config) do # begin # # do stuff # rescue => e # Rollbar.error(e) # end # end def scoped(options = {}, config_overrides = {}) old_notifier = notifier self.notifier = old_notifier.scope(options, config_overrides) result = yield result ensure self.notifier = old_notifier end # Create a new Notifier instance with a new configuration # using the current one but merging the passed options. def with_config(overrides, &block) scoped(nil, overrides, &block) end def scope!(options = {}) notifier.scope!(options) end # Backwards compatibility methods def report_exception(exception, request_data = nil, person_data = nil, level = 'error') Kernel.warn('[DEPRECATION] Rollbar.report_exception has been deprecated, please use log() or one of the level functions') scope = {} scope[:request] = request_data if request_data scope[:person] = person_data if person_data Rollbar.scoped(scope) do Rollbar.notifier.log(level, exception, :use_exception_level_filters => true) end end def report_message(message, level = 'info', extra_data = nil) Kernel.warn('[DEPRECATION] Rollbar.report_message has been deprecated, please use log() or one of the level functions') Rollbar.notifier.log(level, message, extra_data) end def report_message_with_request(message, level = 'info', request_data = nil, person_data = nil, extra_data = nil) Kernel.warn('[DEPRECATION] Rollbar.report_message_with_request has been deprecated, please use log() or one of the level functions') scope = {} scope[:request] = request_data if request_data scope[:person] = person_data if person_data Rollbar.scoped(:request => request_data, :person => person_data) do Rollbar.notifier.log(level, message, extra_data) end end end self.root_notifier = nil end Rollbar.plugins.require_all