rollbar 2.10.0 → 2.11.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/.travis.yml +7 -2
- data/CHANGELOG.md +20 -0
- data/README.md +73 -16
- data/docs/configuration.md +10 -0
- data/gemfiles/rails30.gemfile +2 -0
- data/gemfiles/rails31.gemfile +2 -0
- data/gemfiles/rails32.gemfile +2 -0
- data/gemfiles/rails40.gemfile +2 -0
- data/gemfiles/rails41.gemfile +2 -0
- data/gemfiles/rails42.gemfile +2 -0
- data/gemfiles/rails50.gemfile +2 -0
- data/gemfiles/ruby_1_8_and_1_9_2.gemfile +43 -0
- data/lib/rollbar.rb +139 -353
- data/lib/rollbar/configuration.rb +4 -0
- data/lib/rollbar/item.rb +225 -0
- data/lib/rollbar/item/backtrace.rb +97 -0
- data/lib/rollbar/js.rb +0 -28
- data/lib/rollbar/language_support.rb +10 -0
- data/lib/rollbar/{js/middleware.rb → middleware/js.rb} +3 -4
- data/lib/rollbar/plugin.rb +63 -0
- data/lib/rollbar/plugins.rb +41 -0
- data/lib/rollbar/{active_job.rb → plugins/active_job.rb} +0 -0
- data/lib/rollbar/plugins/basic_socket.rb +16 -0
- data/lib/rollbar/plugins/delayed_job.rb +12 -0
- data/lib/rollbar/plugins/delayed_job/job_data.rb +16 -0
- data/lib/rollbar/{delayed_job.rb → plugins/delayed_job/plugin.rb} +1 -17
- data/lib/rollbar/plugins/goalie.rb +46 -0
- data/lib/rollbar/plugins/rack.rb +16 -0
- data/lib/rollbar/plugins/rails.rb +77 -0
- data/lib/rollbar/{rails → plugins/rails}/controller_methods.rb +0 -0
- data/lib/rollbar/plugins/rails/railtie30.rb +17 -0
- data/lib/rollbar/plugins/rails/railtie32.rb +18 -0
- data/lib/rollbar/plugins/rails/railtie_mixin.rb +33 -0
- data/lib/rollbar/plugins/rake.rb +45 -0
- data/lib/rollbar/plugins/sidekiq.rb +35 -0
- data/lib/rollbar/{sidekiq.rb → plugins/sidekiq/plugin.rb} +0 -18
- data/lib/rollbar/plugins/thread.rb +13 -0
- data/lib/rollbar/plugins/validations.rb +33 -0
- data/lib/rollbar/request_data_extractor.rb +30 -18
- data/lib/rollbar/scrubbers/params.rb +4 -2
- data/lib/rollbar/scrubbers/url.rb +30 -28
- data/lib/rollbar/util.rb +10 -0
- data/lib/rollbar/version.rb +1 -1
- data/spec/controllers/home_controller_spec.rb +4 -3
- data/spec/dummyapp/app/models/post.rb +9 -0
- data/spec/dummyapp/app/models/user.rb +2 -0
- data/spec/dummyapp/config/initializers/rollbar.rb +1 -0
- data/spec/fixtures/plugins/dummy1.rb +5 -0
- data/spec/fixtures/plugins/dummy2.rb +5 -0
- data/spec/rollbar/item_spec.rb +635 -0
- data/spec/rollbar/logger_proxy_spec.rb +4 -0
- data/spec/rollbar/{js/middleware_spec.rb → middleware/js_spec.rb} +32 -3
- data/spec/rollbar/plugin_spec.rb +147 -0
- data/spec/rollbar/{active_job_spec.rb → plugins/active_job_spec.rb} +0 -1
- data/spec/rollbar/{delayed_job → plugins/delayed_job}/job_data.rb +0 -0
- data/spec/rollbar/{delayed_job_spec.rb → plugins/delayed_job_spec.rb} +3 -6
- data/spec/rollbar/{middleware/rack/builder_spec.rb → plugins/rack_spec.rb} +2 -1
- data/spec/rollbar/{js/frameworks/rails_spec.rb → plugins/rails_js_spec.rb} +1 -1
- data/spec/rollbar/{rake_spec.rb → plugins/rake_spec.rb} +2 -1
- data/spec/rollbar/{sidekiq_spec.rb → plugins/sidekiq_spec.rb} +2 -1
- data/spec/rollbar/plugins/validations_spec.rb +43 -0
- data/spec/rollbar/plugins_spec.rb +68 -0
- data/spec/rollbar/request_data_extractor_spec.rb +56 -10
- data/spec/rollbar/scrubbers/params_spec.rb +13 -10
- data/spec/rollbar/scrubbers/url_spec.rb +17 -12
- data/spec/rollbar/sidekig/clear_scope_spec.rb +2 -1
- data/spec/rollbar/util_spec.rb +61 -0
- data/spec/rollbar_bc_spec.rb +10 -10
- data/spec/rollbar_spec.rb +57 -706
- data/spec/spec_helper.rb +8 -0
- data/spec/support/notifier_helpers.rb +1 -0
- data/spec/support/rollbar_api.rb +57 -0
- metadata +57 -33
- data/lib/rollbar/active_record_extension.rb +0 -14
- data/lib/rollbar/core_ext/basic_socket.rb +0 -7
- data/lib/rollbar/core_ext/thread.rb +0 -9
- data/lib/rollbar/goalie.rb +0 -33
- data/lib/rollbar/js/frameworks.rb +0 -6
- data/lib/rollbar/js/frameworks/rails.rb +0 -49
- data/lib/rollbar/js/version.rb +0 -5
- data/lib/rollbar/rack.rb +0 -9
- data/lib/rollbar/railtie.rb +0 -46
- data/lib/rollbar/rake.rb +0 -40
@@ -31,7 +31,9 @@ module Rollbar
|
|
31
31
|
attr_accessor :person_email_method
|
32
32
|
attr_accessor :populate_empty_backtraces
|
33
33
|
attr_accessor :report_dj_data
|
34
|
+
attr_accessor :open_timeout
|
34
35
|
attr_accessor :request_timeout
|
36
|
+
attr_accessor :net_retries
|
35
37
|
attr_accessor :root
|
36
38
|
attr_accessor :js_options
|
37
39
|
attr_accessor :js_enabled
|
@@ -88,7 +90,9 @@ module Rollbar
|
|
88
90
|
@project_gems = []
|
89
91
|
@populate_empty_backtraces = false
|
90
92
|
@report_dj_data = true
|
93
|
+
@open_timeout = 3
|
91
94
|
@request_timeout = 3
|
95
|
+
@net_retries = 3
|
92
96
|
@js_enabled = false
|
93
97
|
@js_options = {}
|
94
98
|
@scrub_fields = [:passwd, :password, :password_confirmation, :secret,
|
data/lib/rollbar/item.rb
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'securerandom'
|
6
|
+
rescue LoadError
|
7
|
+
nil
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rollbar/item/backtrace'
|
11
|
+
require 'rollbar/util'
|
12
|
+
require 'rollbar/encoding'
|
13
|
+
|
14
|
+
module Rollbar
|
15
|
+
# This class represents the payload to be sent to the API.
|
16
|
+
# It contains the logic to build the payload, trucante it
|
17
|
+
# and dump the JSON.
|
18
|
+
class Item
|
19
|
+
extend Forwardable
|
20
|
+
|
21
|
+
attr_writer :payload
|
22
|
+
|
23
|
+
attr_reader :level
|
24
|
+
attr_reader :message
|
25
|
+
attr_reader :exception
|
26
|
+
attr_reader :extra
|
27
|
+
|
28
|
+
attr_reader :configuration
|
29
|
+
attr_reader :scope
|
30
|
+
attr_reader :logger
|
31
|
+
attr_reader :notifier
|
32
|
+
|
33
|
+
def_delegators :payload, :[]
|
34
|
+
|
35
|
+
class << self
|
36
|
+
def build_with(payload, options = {})
|
37
|
+
new(options).tap do |item|
|
38
|
+
item.payload = payload
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(options)
|
44
|
+
@level = options[:level]
|
45
|
+
@message = options[:message]
|
46
|
+
@exception = options[:exception]
|
47
|
+
@extra = options[:extra]
|
48
|
+
@configuration = options[:configuration]
|
49
|
+
@logger = options[:logger]
|
50
|
+
@scope = options[:scope]
|
51
|
+
@payload = nil
|
52
|
+
@notifier = options[:notifier]
|
53
|
+
end
|
54
|
+
|
55
|
+
def payload
|
56
|
+
@payload ||= build
|
57
|
+
end
|
58
|
+
|
59
|
+
def build
|
60
|
+
data = build_data
|
61
|
+
self.payload = {
|
62
|
+
'access_token' => configuration.access_token,
|
63
|
+
'data' => data
|
64
|
+
}
|
65
|
+
|
66
|
+
enforce_valid_utf8
|
67
|
+
transform
|
68
|
+
payload
|
69
|
+
end
|
70
|
+
|
71
|
+
def build_data
|
72
|
+
data = {
|
73
|
+
:timestamp => Time.now.to_i,
|
74
|
+
:environment => build_environment,
|
75
|
+
:level => level,
|
76
|
+
:language => 'ruby',
|
77
|
+
:framework => configuration.framework,
|
78
|
+
:server => server_data,
|
79
|
+
:notifier => {
|
80
|
+
:name => 'rollbar-gem',
|
81
|
+
:version => VERSION
|
82
|
+
},
|
83
|
+
:body => build_body
|
84
|
+
}
|
85
|
+
data[:project_package_paths] = configuration.project_gem_paths if configuration.project_gem_paths
|
86
|
+
data[:code_version] = configuration.code_version if configuration.code_version
|
87
|
+
data[:uuid] = SecureRandom.uuid if defined?(SecureRandom) && SecureRandom.respond_to?(:uuid)
|
88
|
+
|
89
|
+
Util.deep_merge(data, configuration.payload_options)
|
90
|
+
Util.deep_merge(data, scope)
|
91
|
+
|
92
|
+
# Our API doesn't allow null context values, so just delete
|
93
|
+
# the key if value is nil.
|
94
|
+
data.delete(:context) unless data[:context]
|
95
|
+
|
96
|
+
data
|
97
|
+
end
|
98
|
+
|
99
|
+
def dump
|
100
|
+
# Ensure all keys are strings since we can receive the payload inline or
|
101
|
+
# from an async handler job, which can be serialized.
|
102
|
+
stringified_payload = Util::Hash.deep_stringify_keys(payload)
|
103
|
+
result = Truncation.truncate(stringified_payload)
|
104
|
+
return result unless Truncation.truncate?(result)
|
105
|
+
|
106
|
+
original_size = Rollbar::JSON.dump(payload).bytesize
|
107
|
+
final_size = result.bytesize
|
108
|
+
notifier.send_failsafe("Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Final size: #{final_size}", nil)
|
109
|
+
logger.error("[Rollbar] Payload too large to be sent: #{Rollbar::JSON.dump(payload)}")
|
110
|
+
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
|
114
|
+
def ignored?
|
115
|
+
data = payload['data']
|
116
|
+
|
117
|
+
return unless data[:person]
|
118
|
+
|
119
|
+
person_id = data[:person][configuration.person_id_method.to_sym]
|
120
|
+
configuration.ignored_person_ids.include?(person_id)
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def build_environment
|
126
|
+
env = configuration.environment
|
127
|
+
env = 'unspecified' if env.nil? || env.empty?
|
128
|
+
|
129
|
+
env
|
130
|
+
end
|
131
|
+
|
132
|
+
def build_body
|
133
|
+
exception ? build_backtrace_body : build_message_body
|
134
|
+
end
|
135
|
+
|
136
|
+
def build_backtrace_body
|
137
|
+
backtrace = Backtrace.new(exception,
|
138
|
+
:message => message,
|
139
|
+
:extra => build_extra,
|
140
|
+
:configuration => configuration
|
141
|
+
)
|
142
|
+
|
143
|
+
backtrace.build
|
144
|
+
end
|
145
|
+
|
146
|
+
def build_extra
|
147
|
+
if custom_data_method?
|
148
|
+
Util.deep_merge(custom_data, extra || {})
|
149
|
+
else
|
150
|
+
extra
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def custom_data_method?
|
155
|
+
!!configuration.custom_data_method
|
156
|
+
end
|
157
|
+
|
158
|
+
def custom_data
|
159
|
+
data = configuration.custom_data_method.call
|
160
|
+
Rollbar::Util.deep_copy(data)
|
161
|
+
rescue => e
|
162
|
+
return {} if configuration.safely?
|
163
|
+
|
164
|
+
report_custom_data_error(e)
|
165
|
+
end
|
166
|
+
|
167
|
+
def report_custom_data_error(e)
|
168
|
+
data = notifier.safely.error(e)
|
169
|
+
|
170
|
+
return {} unless data.is_a?(Hash) && data[:uuid]
|
171
|
+
|
172
|
+
uuid_url = Util.uuid_rollbar_url(data, configuration)
|
173
|
+
|
174
|
+
{ :_error_in_custom_data_method => uuid_url }
|
175
|
+
end
|
176
|
+
|
177
|
+
def build_message_body
|
178
|
+
extra = build_extra
|
179
|
+
result = { :body => message || 'Empty message' }
|
180
|
+
result[:extra] = extra if extra
|
181
|
+
|
182
|
+
{ :message => result }
|
183
|
+
end
|
184
|
+
|
185
|
+
def server_data
|
186
|
+
data = {
|
187
|
+
:host => Socket.gethostname
|
188
|
+
}
|
189
|
+
data[:root] = configuration.root.to_s if configuration.root
|
190
|
+
data[:branch] = configuration.branch if configuration.branch
|
191
|
+
data[:pid] = Process.pid
|
192
|
+
|
193
|
+
data
|
194
|
+
end
|
195
|
+
|
196
|
+
def enforce_valid_utf8
|
197
|
+
Util.enforce_valid_utf8(payload)
|
198
|
+
end
|
199
|
+
|
200
|
+
def transform
|
201
|
+
handlers = configuration.transform
|
202
|
+
|
203
|
+
handlers.each do |handler|
|
204
|
+
begin
|
205
|
+
handler.call(transform_options)
|
206
|
+
rescue => e
|
207
|
+
logger.error("[Rollbar] Error calling the `transform` hook: #{e}")
|
208
|
+
|
209
|
+
break
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def transform_options
|
215
|
+
{
|
216
|
+
:level => level,
|
217
|
+
:scope => scope,
|
218
|
+
:exception => exception,
|
219
|
+
:message => message,
|
220
|
+
:extra => extra,
|
221
|
+
:payload => payload
|
222
|
+
}
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Rollbar
|
2
|
+
class Item
|
3
|
+
class Backtrace
|
4
|
+
attr_reader :exception
|
5
|
+
attr_reader :message
|
6
|
+
attr_reader :extra
|
7
|
+
attr_reader :configuration
|
8
|
+
|
9
|
+
def initialize(exception, options = {})
|
10
|
+
@exception = exception
|
11
|
+
@message = options[:message]
|
12
|
+
@extra = options[:extra]
|
13
|
+
@configuration = options[:configuration]
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
traces = trace_chain
|
18
|
+
|
19
|
+
traces[0][:exception][:description] = message if message
|
20
|
+
traces[0][:extra] = extra if extra
|
21
|
+
|
22
|
+
if traces.size > 1
|
23
|
+
{ :trace_chain => traces }
|
24
|
+
elsif traces.size == 1
|
25
|
+
{ :trace => traces[0] }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def trace_chain
|
32
|
+
exception
|
33
|
+
traces = [trace_data(exception)]
|
34
|
+
visited = [exception]
|
35
|
+
|
36
|
+
current_exception = exception
|
37
|
+
|
38
|
+
while current_exception.respond_to?(:cause) && (cause = current_exception.cause) && cause.is_a?(Exception) && !visited.include?(cause)
|
39
|
+
traces << trace_data(cause)
|
40
|
+
visited << cause
|
41
|
+
current_exception = cause
|
42
|
+
end
|
43
|
+
|
44
|
+
traces
|
45
|
+
end
|
46
|
+
|
47
|
+
def trace_data(current_exception)
|
48
|
+
frames = reduce_frames(current_exception)
|
49
|
+
# reverse so that the order is as rollbar expects
|
50
|
+
frames.reverse!
|
51
|
+
|
52
|
+
{
|
53
|
+
:frames => frames,
|
54
|
+
:exception => {
|
55
|
+
:class => current_exception.class.name,
|
56
|
+
:message => current_exception.message
|
57
|
+
}
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def reduce_frames(current_exception)
|
62
|
+
exception_backtrace(current_exception).map do |frame|
|
63
|
+
# parse the line
|
64
|
+
match = frame.match(/(.*):(\d+)(?::in `([^']+)')?/)
|
65
|
+
|
66
|
+
if match
|
67
|
+
{ :filename => match[1], :lineno => match[2].to_i, :method => match[3] }
|
68
|
+
else
|
69
|
+
{ :filename => '<unknown>', :lineno => 0, :method => frame }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the backtrace to be sent to our API. There are 3 options:
|
75
|
+
#
|
76
|
+
# 1. The exception received has a backtrace, then that backtrace is returned.
|
77
|
+
# 2. configuration.populate_empty_backtraces is disabled, we return [] here
|
78
|
+
# 3. The user has configuration.populate_empty_backtraces is enabled, then:
|
79
|
+
#
|
80
|
+
# We want to send the caller as backtrace, but the first lines of that array
|
81
|
+
# are those from the user's Rollbar.error line until this method. We want
|
82
|
+
# to remove those lines.
|
83
|
+
def exception_backtrace(current_exception)
|
84
|
+
return current_exception.backtrace if current_exception.backtrace.respond_to?(:map)
|
85
|
+
return [] unless configuration.populate_empty_backtraces
|
86
|
+
|
87
|
+
caller_backtrace = caller
|
88
|
+
caller_backtrace.shift while caller_backtrace[0].include?(rollbar_lib_gem_dir)
|
89
|
+
caller_backtrace
|
90
|
+
end
|
91
|
+
|
92
|
+
def rollbar_lib_gem_dir
|
93
|
+
Gem::Specification.find_by_name('rollbar').gem_dir + '/lib'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/rollbar/js.rb
CHANGED
@@ -1,32 +1,4 @@
|
|
1
|
-
require "rollbar/js/version"
|
2
|
-
|
3
1
|
module Rollbar
|
4
2
|
module Js
|
5
|
-
extend self
|
6
|
-
|
7
|
-
attr_reader :framework
|
8
|
-
attr_reader :framework_loader
|
9
|
-
|
10
|
-
def prepare
|
11
|
-
@framework ||= detect_framework
|
12
|
-
@framework_loader ||= load_framework_class.new
|
13
|
-
|
14
|
-
@framework_loader.prepare
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def detect_framework
|
20
|
-
case
|
21
|
-
when defined?(::Rails::VERSION)
|
22
|
-
:rails
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def load_framework_class
|
27
|
-
require "rollbar/js/frameworks/#{framework}"
|
28
|
-
|
29
|
-
Rollbar::Js::Frameworks.const_get(framework.to_s.capitalize)
|
30
|
-
end
|
31
3
|
end
|
32
4
|
end
|
@@ -26,10 +26,20 @@ module Rollbar
|
|
26
26
|
version?('1.8')
|
27
27
|
end
|
28
28
|
|
29
|
+
def ruby_19?
|
30
|
+
version?('1.9')
|
31
|
+
end
|
32
|
+
|
29
33
|
def version?(version)
|
30
34
|
numbers = version.split('.')
|
31
35
|
|
32
36
|
numbers == ::RUBY_VERSION.split('.')[0, numbers.size]
|
33
37
|
end
|
38
|
+
|
39
|
+
def timeout_exceptions
|
40
|
+
return [] if ruby_18? || ruby_19?
|
41
|
+
|
42
|
+
[Net::ReadTimeout, Net::OpenTimeout]
|
43
|
+
end
|
34
44
|
end
|
35
45
|
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'rack/response'
|
3
3
|
|
4
|
-
|
5
4
|
module Rollbar
|
6
|
-
module
|
7
|
-
class
|
5
|
+
module Middleware
|
6
|
+
class Js
|
8
7
|
attr_reader :app
|
9
8
|
attr_reader :config
|
10
9
|
|
@@ -117,7 +116,7 @@ module Rollbar
|
|
117
116
|
end
|
118
117
|
|
119
118
|
def script_tag(content, env)
|
120
|
-
if defined?(::SecureHeaders)
|
119
|
+
if defined?(::SecureHeaders) && ::SecureHeaders.respond_to?(:content_security_policy_script_nonce)
|
121
120
|
nonce = ::SecureHeaders.content_security_policy_script_nonce(::Rack::Request.new(env))
|
122
121
|
script_tag_content = "\n<script type=\"text/javascript\" nonce=\"#{nonce}\">#{content}</script>"
|
123
122
|
else
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Rollbar
|
2
|
+
# Represents a plugin in the gem. Every plugin can have multiple dependencies
|
3
|
+
# and multiple execution blocks.
|
4
|
+
# On Rollbar initialization, all plugins will be saved in memory and those that
|
5
|
+
# satisfy the dependencies will be loaded
|
6
|
+
class Plugin
|
7
|
+
attr_reader :name
|
8
|
+
attr_reader :dependencies
|
9
|
+
attr_reader :callables
|
10
|
+
attr_accessor :loaded
|
11
|
+
|
12
|
+
private :loaded=
|
13
|
+
|
14
|
+
def initialize(name)
|
15
|
+
@name = name
|
16
|
+
@dependencies = []
|
17
|
+
@callables = []
|
18
|
+
@loaded = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def configuration
|
22
|
+
Rollbar.configuration
|
23
|
+
end
|
24
|
+
|
25
|
+
def load!
|
26
|
+
return unless load?
|
27
|
+
|
28
|
+
begin
|
29
|
+
callables.each(&:call)
|
30
|
+
rescue => e
|
31
|
+
log_loading_error(e)
|
32
|
+
ensure
|
33
|
+
self.loaded = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute(&block)
|
38
|
+
callables << block
|
39
|
+
end
|
40
|
+
|
41
|
+
def execute!(&block)
|
42
|
+
block.call if load?
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def dependency(&block)
|
48
|
+
dependencies << block
|
49
|
+
end
|
50
|
+
|
51
|
+
def load?
|
52
|
+
!loaded && dependencies.all?(&:call)
|
53
|
+
rescue => e
|
54
|
+
log_loading_error(e)
|
55
|
+
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def log_loading_error(e)
|
60
|
+
Rollbar.log_error("Error trying to load plugin '#{name}': #{e.class}, #{e.message}")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|