rollbar 2.8.3 → 3.6.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 +5 -5
- data/.codeclimate.yml +18 -0
- data/.github/pull_request_template.md +34 -0
- data/.github/workflows/ci.yml +67 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +206 -7
- data/Appraisals +10 -10
- data/CHANGELOG.md +257 -3
- data/Gemfile +74 -13
- data/README.md +38 -833
- data/Rakefile +0 -0
- data/THANKS.md +1 -0
- data/data/rollbar.snippet.js +1 -1
- data/docs/configuration.md +64 -3
- data/docs/plugins.md +46 -0
- data/gemfiles/rails50.gemfile +56 -0
- data/gemfiles/rails51.gemfile +57 -0
- data/gemfiles/rails52.gemfile +56 -0
- data/gemfiles/rails60.gemfile +52 -0
- data/gemfiles/rails61.gemfile +52 -0
- data/gemfiles/rails70.gemfile +52 -0
- data/gemfiles/rails71.gemfile +52 -0
- data/lib/generators/rollbar/rollbar_generator.rb +24 -20
- data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +19 -5
- data/lib/rails/rollbar_runner.rb +26 -22
- data/lib/rollbar/capistrano.rb +78 -38
- data/lib/rollbar/capistrano3.rb +62 -1
- data/lib/rollbar/capistrano_tasks.rb +166 -0
- data/lib/rollbar/configuration.rb +291 -71
- data/lib/rollbar/delay/active_job.rb +17 -0
- data/lib/rollbar/delay/delayed_job.rb +23 -0
- data/lib/rollbar/delay/girl_friday.rb +4 -9
- data/lib/rollbar/delay/resque.rb +3 -6
- data/lib/rollbar/delay/shoryuken.rb +36 -0
- data/lib/rollbar/delay/sidekiq.rb +6 -8
- data/lib/rollbar/delay/sucker_punch.rb +17 -22
- data/lib/rollbar/delay/thread.rb +74 -3
- data/lib/rollbar/deploy.rb +91 -0
- data/lib/rollbar/encoding/encoder.rb +22 -11
- data/lib/rollbar/encoding.rb +2 -7
- data/lib/rollbar/exception_reporter.rb +36 -12
- data/lib/rollbar/item/backtrace.rb +118 -0
- data/lib/rollbar/item/frame.rb +121 -0
- data/lib/rollbar/item/locals.rb +103 -0
- data/lib/rollbar/item.rb +314 -0
- data/lib/rollbar/js.rb +0 -28
- data/lib/rollbar/json.rb +7 -55
- data/lib/rollbar/language_support.rb +7 -19
- data/lib/rollbar/lazy_store.rb +8 -12
- data/lib/rollbar/logger.rb +71 -0
- data/lib/rollbar/logger_proxy.rb +18 -1
- data/lib/rollbar/middleware/js/json_value.rb +36 -0
- data/lib/rollbar/middleware/js.rb +297 -0
- data/lib/rollbar/middleware/rack/builder.rb +4 -4
- data/lib/rollbar/middleware/rack/test_session.rb +4 -4
- data/lib/rollbar/middleware/rack.rb +52 -0
- data/lib/rollbar/middleware/rails/rollbar.rb +19 -7
- data/lib/rollbar/middleware/rails/show_exceptions.rb +21 -9
- data/lib/rollbar/middleware/sinatra.rb +2 -40
- data/lib/rollbar/notifier/trace_with_bindings.rb +75 -0
- data/lib/rollbar/notifier.rb +913 -0
- data/lib/rollbar/plugin.rb +126 -0
- data/lib/rollbar/plugins/active_job.rb +54 -0
- data/lib/rollbar/plugins/basic_socket.rb +31 -0
- data/lib/rollbar/plugins/delayed_job/job_data.rb +50 -0
- data/lib/rollbar/plugins/delayed_job/plugin.rb +88 -0
- data/lib/rollbar/plugins/delayed_job.rb +12 -0
- data/lib/rollbar/plugins/error_context.rb +11 -0
- data/lib/rollbar/plugins/goalie.rb +65 -0
- data/lib/rollbar/plugins/rack.rb +18 -0
- data/lib/rollbar/plugins/rails/controller_methods.rb +56 -0
- data/lib/rollbar/plugins/rails/error_subscriber.rb +12 -0
- data/lib/rollbar/plugins/rails/railtie30.rb +18 -0
- data/lib/rollbar/plugins/rails/railtie32.rb +18 -0
- data/lib/rollbar/plugins/rails/railtie_mixin.rb +37 -0
- data/lib/rollbar/plugins/rails.rb +89 -0
- data/lib/rollbar/plugins/rake.rb +73 -0
- data/lib/rollbar/plugins/resque/failure.rb +39 -0
- data/lib/rollbar/plugins/resque.rb +11 -0
- data/lib/rollbar/plugins/sidekiq/plugin.rb +77 -0
- data/lib/rollbar/plugins/sidekiq.rb +37 -0
- data/lib/rollbar/plugins/thread.rb +14 -0
- data/lib/rollbar/plugins/validations.rb +45 -0
- data/lib/rollbar/plugins.rb +47 -0
- data/lib/rollbar/rails.rb +0 -1
- data/lib/rollbar/rake_tasks.rb +4 -66
- data/lib/rollbar/request_data_extractor.rb +157 -117
- data/lib/rollbar/rollbar_test.rb +38 -0
- data/lib/rollbar/scrubbers/params.rb +133 -0
- data/lib/rollbar/scrubbers/url.rb +90 -35
- data/lib/rollbar/scrubbers.rb +13 -0
- data/lib/rollbar/truncation/frames_strategy.rb +2 -1
- data/lib/rollbar/truncation/min_body_strategy.rb +3 -4
- data/lib/rollbar/truncation/mixin.rb +1 -1
- data/lib/rollbar/truncation/remove_any_key_strategy.rb +126 -0
- data/lib/rollbar/truncation/remove_extra_strategy.rb +37 -0
- data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
- data/lib/rollbar/truncation/strings_strategy.rb +6 -5
- data/lib/rollbar/truncation.rb +10 -4
- data/lib/rollbar/util/hash.rb +37 -6
- data/lib/rollbar/util/ip_anonymizer.rb +33 -0
- data/lib/rollbar/util/ip_obfuscator.rb +1 -1
- data/lib/rollbar/util.rb +101 -55
- data/lib/rollbar/version.rb +1 -1
- data/lib/rollbar.rb +91 -879
- data/lib/tasks/benchmark.rake +104 -0
- data/lib/tasks/tasks.rake +3 -3
- data/rollbar.gemspec +21 -32
- data/spec/support/rollbar_api.rb +67 -0
- metadata +78 -439
- data/.travis.yml +0 -155
- data/gemfiles/rails30.gemfile +0 -20
- data/gemfiles/rails31.gemfile +0 -16
- data/gemfiles/rails32.gemfile +0 -17
- data/gemfiles/rails40.gemfile +0 -17
- data/gemfiles/rails41.gemfile +0 -15
- data/gemfiles/rails42.gemfile +0 -15
- data/lib/rollbar/active_job.rb +0 -11
- 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/delayed_job.rb +0 -78
- data/lib/rollbar/encoding/legacy_encoder.rb +0 -20
- data/lib/rollbar/goalie.rb +0 -33
- data/lib/rollbar/js/frameworks/rails.rb +0 -29
- data/lib/rollbar/js/frameworks.rb +0 -6
- data/lib/rollbar/js/middleware.rb +0 -129
- data/lib/rollbar/js/version.rb +0 -5
- data/lib/rollbar/json/default.rb +0 -11
- data/lib/rollbar/json/oj.rb +0 -15
- data/lib/rollbar/rack.rb +0 -9
- data/lib/rollbar/rails/controller_methods.rb +0 -40
- data/lib/rollbar/railtie.rb +0 -46
- data/lib/rollbar/rake.rb +0 -38
- data/lib/rollbar/sidekiq.rb +0 -40
- data/lib/rollbar/tasks/rollbar.cap +0 -45
- data/spec/cacert.pem +0 -3988
- data/spec/controllers/home_controller_spec.rb +0 -455
- data/spec/delay/sidekiq_spec.rb +0 -61
- data/spec/delay/sucker_punch_spec.rb +0 -25
- data/spec/delayed/backend/test.rb +0 -139
- data/spec/delayed/serialization/test.rb +0 -0
- data/spec/dummyapp/.gitignore +0 -73
- data/spec/dummyapp/Rakefile +0 -7
- data/spec/dummyapp/app/assets/javascripts/application.js +0 -3
- data/spec/dummyapp/app/assets/stylesheets/application.css.scss +0 -37
- data/spec/dummyapp/app/controllers/application_controller.rb +0 -3
- data/spec/dummyapp/app/controllers/home_controller.rb +0 -60
- data/spec/dummyapp/app/controllers/users_controller.rb +0 -17
- data/spec/dummyapp/app/helpers/.gitkeep +0 -0
- data/spec/dummyapp/app/mailers/.gitkeep +0 -0
- data/spec/dummyapp/app/models/.gitkeep +0 -0
- data/spec/dummyapp/app/models/user.rb +0 -7
- data/spec/dummyapp/app/views/devise/registrations/edit.html.erb +0 -27
- data/spec/dummyapp/app/views/devise/registrations/new.html.erb +0 -20
- data/spec/dummyapp/app/views/devise/shared/_links.html.erb +0 -25
- data/spec/dummyapp/app/views/home/cause_exception.html.erb +0 -1
- data/spec/dummyapp/app/views/home/index.html.erb +0 -4
- data/spec/dummyapp/app/views/home/report_exception.html.erb +0 -1
- data/spec/dummyapp/app/views/js/test.html.erb +0 -1
- data/spec/dummyapp/app/views/layouts/_messages.html.erb +0 -5
- data/spec/dummyapp/app/views/layouts/_navigation.html.erb +0 -21
- data/spec/dummyapp/app/views/layouts/application.html.erb +0 -25
- data/spec/dummyapp/app/views/layouts/simple.html.erb +0 -18
- data/spec/dummyapp/app/views/users/index.html.erb +0 -8
- data/spec/dummyapp/app/views/users/show.html.erb +0 -3
- data/spec/dummyapp/config/application.rb +0 -59
- data/spec/dummyapp/config/boot.rb +0 -10
- data/spec/dummyapp/config/database.yml +0 -25
- data/spec/dummyapp/config/environment.rb +0 -5
- data/spec/dummyapp/config/environments/development.rb +0 -37
- data/spec/dummyapp/config/environments/production.rb +0 -67
- data/spec/dummyapp/config/environments/test.rb +0 -37
- data/spec/dummyapp/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummyapp/config/initializers/inflections.rb +0 -15
- data/spec/dummyapp/config/initializers/mime_types.rb +0 -5
- data/spec/dummyapp/config/initializers/rollbar.rb +0 -23
- data/spec/dummyapp/config/initializers/secret_token.rb +0 -7
- data/spec/dummyapp/config/initializers/session_store.rb +0 -8
- data/spec/dummyapp/config/initializers/wrap_parameters.rb +0 -16
- data/spec/dummyapp/config/locales/devise.en.yml +0 -58
- data/spec/dummyapp/config/locales/en.yml +0 -5
- data/spec/dummyapp/config/routes.rb +0 -17
- data/spec/dummyapp/config.ru +0 -4
- data/spec/dummyapp/db/migrate/20121121184652_devise_create_users.rb +0 -46
- data/spec/dummyapp/db/migrate/20121121184654_add_name_to_users.rb +0 -5
- data/spec/dummyapp/db/schema.rb +0 -35
- data/spec/dummyapp/db/seeds.rb +0 -12
- data/spec/dummyapp/lib/assets/.gitkeep +0 -0
- data/spec/dummyapp/public/404.html +0 -26
- data/spec/dummyapp/public/422.html +0 -26
- data/spec/dummyapp/public/500.html +0 -25
- data/spec/dummyapp/public/favicon.ico +0 -0
- data/spec/dummyapp/script/rails +0 -6
- data/spec/fixtures/file1 +0 -1
- data/spec/fixtures/file2 +0 -1
- data/spec/fixtures/payloads/message.json +0 -25
- data/spec/fixtures/payloads/sample.trace.json +0 -275
- data/spec/fixtures/payloads/sample.trace_chain.json +0 -530
- data/spec/generators/rollbar/rollbar_generator_spec.rb +0 -24
- data/spec/requests/home_spec.rb +0 -49
- data/spec/rollbar/active_job_spec.rb +0 -33
- data/spec/rollbar/configuration_spec.rb +0 -24
- data/spec/rollbar/delay/girl_friday_spec.rb +0 -41
- data/spec/rollbar/delay/resque_spec.rb +0 -37
- data/spec/rollbar/delay/thread_spec.rb +0 -27
- data/spec/rollbar/delayed_job/job_data.rb +0 -35
- data/spec/rollbar/delayed_job_spec.rb +0 -90
- data/spec/rollbar/encoding/encoder_spec.rb +0 -63
- data/spec/rollbar/js/frameworks/rails_spec.rb +0 -19
- data/spec/rollbar/js/middleware_spec.rb +0 -162
- data/spec/rollbar/json/oj_spec.rb +0 -18
- data/spec/rollbar/json_spec.rb +0 -110
- data/spec/rollbar/lazy_store_spec.rb +0 -99
- data/spec/rollbar/logger_proxy_spec.rb +0 -34
- data/spec/rollbar/middleware/rack/builder_spec.rb +0 -151
- data/spec/rollbar/middleware/sinatra_spec.rb +0 -197
- data/spec/rollbar/rake_spec.rb +0 -34
- data/spec/rollbar/request_data_extractor_spec.rb +0 -82
- data/spec/rollbar/scrubbers/url_spec.rb +0 -111
- data/spec/rollbar/sidekiq_spec.rb +0 -90
- data/spec/rollbar/truncation/frames_strategy_spec.rb +0 -70
- data/spec/rollbar/truncation/min_body_strategy_spec.rb +0 -57
- data/spec/rollbar/truncation/strings_strategy_spec.rb +0 -89
- data/spec/rollbar/truncation_spec.rb +0 -27
- data/spec/rollbar/util/hash_spec.rb +0 -22
- data/spec/rollbar/util_spec.rb +0 -19
- data/spec/rollbar_bc_spec.rb +0 -380
- data/spec/rollbar_spec.rb +0 -2067
- data/spec/spec_helper.rb +0 -49
- data/spec/support/cause_exception.rb +0 -1
- data/spec/support/encoding_helpers.rb +0 -8
- data/spec/support/encodings/iso_8859_9 +0 -1
- data/spec/support/fixture_helpers.rb +0 -10
- data/spec/support/get_ip_raising.rb +0 -7
- data/spec/support/helpers.rb +0 -5
- data/spec/support/notifier_helpers.rb +0 -36
- data/spec/support/shared_contexts.rb +0 -12
@@ -0,0 +1,297 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'rack/response'
|
3
|
+
|
4
|
+
require 'rollbar/request_data_extractor'
|
5
|
+
require 'rollbar/util'
|
6
|
+
|
7
|
+
module Rollbar
|
8
|
+
module Middleware
|
9
|
+
# Middleware to inject the rollbar.js snippet into a 200 html response
|
10
|
+
class Js
|
11
|
+
include Rollbar::RequestDataExtractor
|
12
|
+
|
13
|
+
attr_reader :app, :config
|
14
|
+
|
15
|
+
JS_IS_INJECTED_KEY = 'rollbar.js_is_injected'.freeze
|
16
|
+
SNIPPET = File.read(File.expand_path('../../../../data/rollbar.snippet.js',
|
17
|
+
__FILE__))
|
18
|
+
|
19
|
+
def initialize(app, config)
|
20
|
+
@app = app
|
21
|
+
@config = config
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(env)
|
25
|
+
app_result = app.call(env)
|
26
|
+
|
27
|
+
begin
|
28
|
+
return app_result unless add_js?(env, app_result[1])
|
29
|
+
|
30
|
+
response_string = add_js(env, app_result[2])
|
31
|
+
build_response(env, app_result, response_string)
|
32
|
+
rescue StandardError => e
|
33
|
+
Rollbar.log_error(
|
34
|
+
"[Rollbar] Rollbar.js could not be added because #{e} exception"
|
35
|
+
)
|
36
|
+
|
37
|
+
app_result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def enabled?
|
44
|
+
!!config[:enabled]
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_js?(env, headers)
|
48
|
+
enabled? && !env[JS_IS_INJECTED_KEY] &&
|
49
|
+
html?(headers) && !attachment?(headers) && !streaming?(env)
|
50
|
+
end
|
51
|
+
|
52
|
+
def html?(headers)
|
53
|
+
headers['Content-Type'] && headers['Content-Type'].include?('text/html')
|
54
|
+
end
|
55
|
+
|
56
|
+
def attachment?(headers)
|
57
|
+
headers['Content-Disposition'].to_s.include?('attachment')
|
58
|
+
end
|
59
|
+
|
60
|
+
def streaming?(env)
|
61
|
+
return false unless defined?(ActionController::Live)
|
62
|
+
|
63
|
+
env['action_controller.instance']
|
64
|
+
.class.included_modules.include?(ActionController::Live)
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_js(env, response)
|
68
|
+
body = join_body(response)
|
69
|
+
close_old_response(response)
|
70
|
+
|
71
|
+
return nil unless body
|
72
|
+
|
73
|
+
insert_after_idx = find_insertion_point(body)
|
74
|
+
return nil unless insert_after_idx
|
75
|
+
|
76
|
+
build_body_with_js(env, body, insert_after_idx)
|
77
|
+
rescue StandardError => e
|
78
|
+
Rollbar.log_error(
|
79
|
+
"[Rollbar] Rollbar.js could not be added because #{e} exception"
|
80
|
+
)
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_response(env, app_result, response_string)
|
85
|
+
return app_result unless response_string
|
86
|
+
|
87
|
+
env[JS_IS_INJECTED_KEY] = true
|
88
|
+
|
89
|
+
status, headers, = app_result
|
90
|
+
if headers.key?('Content-Length')
|
91
|
+
headers['Content-Length'] =
|
92
|
+
response_string.bytesize.to_s
|
93
|
+
end
|
94
|
+
|
95
|
+
response = ::Rack::Response.new(response_string, status, headers)
|
96
|
+
|
97
|
+
finished = response.finish
|
98
|
+
|
99
|
+
# Rack < 2.x Response#finish returns self in array[2].
|
100
|
+
# Rack >= 2.x returns self.body.
|
101
|
+
# Always return with the response object here regardless of rack version.
|
102
|
+
finished[2] = response
|
103
|
+
finished
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_body_with_js(env, body, head_open_end)
|
107
|
+
return body unless head_open_end
|
108
|
+
|
109
|
+
body[0..head_open_end] << config_js_tag(env) << snippet_js_tag(env) <<
|
110
|
+
body[head_open_end + 1..-1]
|
111
|
+
end
|
112
|
+
|
113
|
+
def find_insertion_point(body)
|
114
|
+
find_end_after_regex(body, /<meta\s*charset=/i) ||
|
115
|
+
find_end_after_regex(body, /<meta\s*http-equiv="Content-Type"/i) ||
|
116
|
+
find_end_after_regex(body, /<head\W/i)
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_end_after_regex(body, regex)
|
120
|
+
open_idx = body.index(regex)
|
121
|
+
body.index('>', open_idx) if open_idx
|
122
|
+
end
|
123
|
+
|
124
|
+
def join_body(response)
|
125
|
+
response.to_enum.reduce('') do |acc, fragment|
|
126
|
+
acc << fragment.to_s
|
127
|
+
acc
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def close_old_response(response)
|
132
|
+
response.close if response.respond_to?(:close)
|
133
|
+
end
|
134
|
+
|
135
|
+
def config_js_tag(env)
|
136
|
+
require 'json'
|
137
|
+
require 'rollbar/middleware/js/json_value'
|
138
|
+
|
139
|
+
js_config = Rollbar::Util.deep_copy(config[:options])
|
140
|
+
|
141
|
+
add_person_data(js_config, env)
|
142
|
+
|
143
|
+
# MUST use the Ruby JSON encoder (JSON#generate).
|
144
|
+
# See lib/rollbar/middleware/js/json_value
|
145
|
+
json = ::JSON.generate(js_config, Rollbar::JSON::JsOptionsState.new)
|
146
|
+
|
147
|
+
script_tag("var _rollbarConfig = #{json};", env)
|
148
|
+
end
|
149
|
+
|
150
|
+
def add_person_data(js_config, env)
|
151
|
+
person_data = extract_person_data_from_controller(env)
|
152
|
+
|
153
|
+
return if person_data && person_data.empty?
|
154
|
+
|
155
|
+
js_config[:payload] ||= {}
|
156
|
+
js_config[:payload][:person] = person_data if person_data
|
157
|
+
end
|
158
|
+
|
159
|
+
def snippet_js_tag(env)
|
160
|
+
script_tag(js_snippet, env)
|
161
|
+
end
|
162
|
+
|
163
|
+
def js_snippet
|
164
|
+
SNIPPET
|
165
|
+
end
|
166
|
+
|
167
|
+
def script_tag(content, env)
|
168
|
+
nonce = rails5_nonce(env) || secure_headers_nonce(env)
|
169
|
+
script_tag_content = if nonce
|
170
|
+
"\n<script nonce=\"#{nonce}\">#{content}</script>"
|
171
|
+
else
|
172
|
+
"\n<script>#{content}</script>"
|
173
|
+
end
|
174
|
+
|
175
|
+
html_safe_if_needed(script_tag_content)
|
176
|
+
end
|
177
|
+
|
178
|
+
def html_safe_if_needed(string)
|
179
|
+
string = string.html_safe if string.respond_to?(:html_safe)
|
180
|
+
string
|
181
|
+
end
|
182
|
+
|
183
|
+
# Rails 5.2+ Secure Content Policy
|
184
|
+
def rails5_nonce(env)
|
185
|
+
req = ::ActionDispatch::Request.new(env)
|
186
|
+
|
187
|
+
# Rails will only return a nonce if the app has set a nonce generator.
|
188
|
+
# So if we get a valid nonce here, we know we should use it.
|
189
|
+
#
|
190
|
+
# Having both 'unsafe-inline' and a nonce is a valid and preferred
|
191
|
+
# browser compatibility configuration.
|
192
|
+
#
|
193
|
+
# If the script_src key is missing, Rails will not add the nonce to the headers,
|
194
|
+
# so we detect this and will not add it in this case.
|
195
|
+
req.respond_to?(:content_security_policy) &&
|
196
|
+
req.content_security_policy &&
|
197
|
+
req.content_security_policy.directives['script-src'] &&
|
198
|
+
req.content_security_policy_nonce
|
199
|
+
end
|
200
|
+
|
201
|
+
# Secure Headers gem
|
202
|
+
def secure_headers_nonce(env)
|
203
|
+
req = ::Rack::Request.new(env)
|
204
|
+
|
205
|
+
return unless secure_headers(req).append_nonce?
|
206
|
+
|
207
|
+
::SecureHeaders.content_security_policy_script_nonce(req)
|
208
|
+
end
|
209
|
+
|
210
|
+
def secure_headers(req)
|
211
|
+
return SecureHeadersFalse.new unless defined?(::SecureHeaders::Configuration)
|
212
|
+
|
213
|
+
# If the nonce key has been set, the app is using nonces for this request.
|
214
|
+
# If it hasn't, we shouldn't cause one to be added to script_src, so return now.
|
215
|
+
return SecureHeadersFalse.new unless secure_headers_nonce_key(req)
|
216
|
+
|
217
|
+
config = ::SecureHeaders::Configuration
|
218
|
+
|
219
|
+
has_nonce = ::SecureHeaders.respond_to?(
|
220
|
+
:content_security_policy_script_nonce
|
221
|
+
)
|
222
|
+
secure_headers_cls = if !has_nonce
|
223
|
+
SecureHeadersFalse
|
224
|
+
elsif config.respond_to?(:get)
|
225
|
+
SecureHeaders3To5
|
226
|
+
elsif config.dup.respond_to?(:csp)
|
227
|
+
SecureHeaders6
|
228
|
+
else
|
229
|
+
SecureHeadersFalse
|
230
|
+
end
|
231
|
+
|
232
|
+
secure_headers_cls.new
|
233
|
+
end
|
234
|
+
|
235
|
+
def secure_headers_nonce_key(req)
|
236
|
+
defined?(::SecureHeaders::NONCE_KEY) &&
|
237
|
+
req.env[::SecureHeaders::NONCE_KEY]
|
238
|
+
end
|
239
|
+
|
240
|
+
class SecureHeadersResolver
|
241
|
+
def append_nonce?
|
242
|
+
csp_needs_nonce?(find_csp)
|
243
|
+
end
|
244
|
+
|
245
|
+
private
|
246
|
+
|
247
|
+
def find_csp
|
248
|
+
raise NotImplementedError
|
249
|
+
end
|
250
|
+
|
251
|
+
def csp_needs_nonce?(csp)
|
252
|
+
!opt_out?(csp)
|
253
|
+
end
|
254
|
+
|
255
|
+
def opt_out?(_csp)
|
256
|
+
raise NotImplementedError
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class SecureHeadersFalse < SecureHeadersResolver
|
261
|
+
def append_nonce?
|
262
|
+
false
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class SecureHeaders3To5 < SecureHeadersResolver
|
267
|
+
private
|
268
|
+
|
269
|
+
def find_csp
|
270
|
+
::SecureHeaders::Configuration.get.csp
|
271
|
+
end
|
272
|
+
|
273
|
+
def opt_out?(csp)
|
274
|
+
if csp.respond_to?(:opt_out?) && csp.opt_out?
|
275
|
+
csp.opt_out?
|
276
|
+
# secure_headers csp 3.0.x-3.4.x doesn't respond to 'opt_out?'
|
277
|
+
elsif defined?(::SecureHeaders::OPT_OUT) &&
|
278
|
+
::SecureHeaders::OPT_OUT.is_a?(Symbol)
|
279
|
+
csp == ::SecureHeaders::OPT_OUT
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class SecureHeaders6 < SecureHeadersResolver
|
285
|
+
private
|
286
|
+
|
287
|
+
def find_csp
|
288
|
+
::SecureHeaders::Configuration.dup.csp
|
289
|
+
end
|
290
|
+
|
291
|
+
def opt_out?(csp)
|
292
|
+
csp.opt_out?
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
@@ -3,7 +3,7 @@ require 'rollbar/request_data_extractor'
|
|
3
3
|
|
4
4
|
module Rollbar
|
5
5
|
module Middleware
|
6
|
-
|
6
|
+
class Rack
|
7
7
|
module Builder
|
8
8
|
include ExceptionReporter
|
9
9
|
include RequestDataExtractor
|
@@ -14,8 +14,8 @@ module Rollbar
|
|
14
14
|
Rollbar.scoped(fetch_scope(env)) do
|
15
15
|
begin
|
16
16
|
call_without_rollbar(env)
|
17
|
-
rescue ::Exception =>
|
18
|
-
report_exception_to_rollbar(env,
|
17
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
18
|
+
report_exception_to_rollbar(env, e)
|
19
19
|
raise
|
20
20
|
end
|
21
21
|
end
|
@@ -26,7 +26,7 @@ module Rollbar
|
|
26
26
|
:request => proc { extract_request_data_from_rack(env) },
|
27
27
|
:person => person_data_proc(env)
|
28
28
|
}
|
29
|
-
rescue Exception => e
|
29
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
30
30
|
report_exception_to_rollbar(env, e)
|
31
31
|
raise
|
32
32
|
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Rollbar
|
2
2
|
module Middleware
|
3
|
-
|
3
|
+
class Rack
|
4
4
|
module TestSession
|
5
5
|
include ExceptionReporter
|
6
6
|
|
7
7
|
def env_for_with_rollbar(path, env)
|
8
8
|
env_for_without_rollbar(path, env)
|
9
|
-
rescue Exception =>
|
10
|
-
report_exception_to_rollbar(env,
|
11
|
-
raise
|
9
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
10
|
+
report_exception_to_rollbar(env, e)
|
11
|
+
raise e
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.included(base)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rollbar'
|
2
|
+
require 'rollbar/exception_reporter'
|
3
|
+
require 'rollbar/request_data_extractor'
|
4
|
+
|
5
|
+
module Rollbar
|
6
|
+
module Middleware
|
7
|
+
class Rack
|
8
|
+
include ::Rollbar::ExceptionReporter
|
9
|
+
include RequestDataExtractor
|
10
|
+
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
Rollbar.reset_notifier!
|
17
|
+
|
18
|
+
Rollbar.scoped(fetch_scope(env)) do
|
19
|
+
begin
|
20
|
+
Rollbar.notifier.enable_locals
|
21
|
+
response = @app.call(env)
|
22
|
+
report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
|
23
|
+
response
|
24
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
25
|
+
report_exception_to_rollbar(env, e)
|
26
|
+
raise
|
27
|
+
ensure
|
28
|
+
Rollbar.notifier.disable_locals
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch_scope(env)
|
34
|
+
{
|
35
|
+
:request => proc { extract_request_data_from_rack(env) },
|
36
|
+
:person => person_data_proc(env)
|
37
|
+
}
|
38
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
39
|
+
report_exception_to_rollbar(env, e)
|
40
|
+
raise
|
41
|
+
end
|
42
|
+
|
43
|
+
def person_data_proc(env)
|
44
|
+
proc { extract_person_data_from_controller(env) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def framework_error(env)
|
48
|
+
env['rack.exception']
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -21,6 +21,7 @@ module Rollbar
|
|
21
21
|
|
22
22
|
Rollbar.scoped(scope) do
|
23
23
|
begin
|
24
|
+
Rollbar.notifier.enable_locals
|
24
25
|
response = @app.call(env)
|
25
26
|
|
26
27
|
if (framework_exception = env['action_dispatch.exception'])
|
@@ -28,9 +29,11 @@ module Rollbar
|
|
28
29
|
end
|
29
30
|
|
30
31
|
response
|
31
|
-
rescue Exception =>
|
32
|
-
report_exception_to_rollbar(env,
|
32
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
33
|
+
report_exception_to_rollbar(env, e)
|
33
34
|
raise
|
35
|
+
ensure
|
36
|
+
Rollbar.notifier.disable_locals
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
@@ -60,17 +63,26 @@ module Rollbar
|
|
60
63
|
|
61
64
|
def person_data_proc(env)
|
62
65
|
block = proc { extract_person_data_from_controller(env) }
|
63
|
-
|
66
|
+
unless defined?(ActiveRecord::Base) && ActiveRecord::Base.connected?
|
67
|
+
return block
|
68
|
+
end
|
64
69
|
|
65
|
-
proc
|
70
|
+
proc do
|
71
|
+
begin
|
72
|
+
ActiveRecord::Base.connection_pool.with_connection(&block)
|
73
|
+
rescue ActiveRecord::ConnectionTimeoutError
|
74
|
+
{}
|
75
|
+
end
|
76
|
+
end
|
66
77
|
end
|
67
78
|
|
68
79
|
def context(request_data)
|
69
|
-
|
80
|
+
route_params = request_data[:params]
|
70
81
|
|
71
|
-
route = request_data[:route]
|
72
82
|
# make sure route is a hash built by RequestDataExtractor
|
73
|
-
return
|
83
|
+
return unless route_params.is_a?(Hash) && !route_params.empty?
|
84
|
+
|
85
|
+
"#{route_params[:controller]}##{route_params[:action]}"
|
74
86
|
end
|
75
87
|
end
|
76
88
|
end
|
@@ -4,10 +4,10 @@ module Rollbar
|
|
4
4
|
module ShowExceptions
|
5
5
|
include ExceptionReporter
|
6
6
|
|
7
|
-
def render_exception_with_rollbar(env, exception)
|
7
|
+
def render_exception_with_rollbar(env, exception, wrapper = nil)
|
8
8
|
key = 'action_dispatch.show_detailed_exceptions'
|
9
9
|
|
10
|
-
if exception.is_a?(ActionController::RoutingError) && env[key]
|
10
|
+
if exception.is_a?(ActionController::RoutingError) && env.params[key.to_s]
|
11
11
|
scope = extract_scope_from(env)
|
12
12
|
|
13
13
|
Rollbar.scoped(scope) do
|
@@ -15,32 +15,44 @@ module Rollbar
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
# Rails 7.1 changes the method signature for render_exception.
|
19
|
+
if self.class.instance_method(:render_exception_without_rollbar).arity == 2
|
20
|
+
render_exception_without_rollbar(env, exception)
|
21
|
+
else
|
22
|
+
render_exception_without_rollbar(env, exception, wrapper)
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
26
|
def call_with_rollbar(env)
|
22
27
|
call_without_rollbar(env)
|
23
|
-
rescue ActionController::RoutingError =>
|
28
|
+
rescue ActionController::RoutingError => e
|
24
29
|
# won't reach here if show_detailed_exceptions is true
|
25
30
|
scope = extract_scope_from(env)
|
26
31
|
|
27
32
|
Rollbar.scoped(scope) do
|
28
|
-
report_exception_to_rollbar(env,
|
33
|
+
report_exception_to_rollbar(env, e)
|
29
34
|
end
|
30
35
|
|
31
|
-
raise
|
36
|
+
raise e
|
32
37
|
end
|
33
38
|
|
34
39
|
def extract_scope_from(env)
|
35
40
|
scope = env['rollbar.scope']
|
36
|
-
|
41
|
+
unless scope
|
42
|
+
Rollbar.log_warn(
|
43
|
+
'[Rollbar] rollbar.scope key has been removed from Rack env.'
|
44
|
+
)
|
45
|
+
end
|
37
46
|
|
38
47
|
scope || {}
|
39
48
|
end
|
40
49
|
|
41
50
|
def self.included(base)
|
42
|
-
base.send(:
|
43
|
-
base.send(:
|
51
|
+
base.send(:alias_method, :call_without_rollbar, :call)
|
52
|
+
base.send(:alias_method, :call, :call_with_rollbar)
|
53
|
+
|
54
|
+
base.send(:alias_method, :render_exception_without_rollbar, :render_exception)
|
55
|
+
base.send(:alias_method, :render_exception, :render_exception_with_rollbar)
|
44
56
|
end
|
45
57
|
end
|
46
58
|
end
|
@@ -1,46 +1,8 @@
|
|
1
|
-
require 'rollbar'
|
2
|
-
require 'rollbar/exception_reporter'
|
3
|
-
require 'rollbar/request_data_extractor'
|
1
|
+
require 'rollbar/middleware/rack'
|
4
2
|
|
5
3
|
module Rollbar
|
6
4
|
module Middleware
|
7
|
-
class Sinatra
|
8
|
-
include ::Rollbar::ExceptionReporter
|
9
|
-
include RequestDataExtractor
|
10
|
-
|
11
|
-
def initialize(app)
|
12
|
-
@app = app
|
13
|
-
end
|
14
|
-
|
15
|
-
def call(env)
|
16
|
-
Rollbar.reset_notifier!
|
17
|
-
|
18
|
-
Rollbar.scoped(fetch_scope(env)) do
|
19
|
-
begin
|
20
|
-
response = @app.call(env)
|
21
|
-
report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
|
22
|
-
response
|
23
|
-
rescue Exception => e
|
24
|
-
report_exception_to_rollbar(env, e)
|
25
|
-
raise
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def fetch_scope(env)
|
31
|
-
{
|
32
|
-
:request => proc { extract_request_data_from_rack(env) },
|
33
|
-
:person => person_data_proc(env)
|
34
|
-
}
|
35
|
-
rescue Exception => e
|
36
|
-
report_exception_to_rollbar(env, e)
|
37
|
-
raise
|
38
|
-
end
|
39
|
-
|
40
|
-
def person_data_proc(env)
|
41
|
-
proc { extract_person_data_from_controller(env) }
|
42
|
-
end
|
43
|
-
|
5
|
+
class Sinatra < Rollbar::Middleware::Rack
|
44
6
|
def framework_error(env)
|
45
7
|
env['sinatra.error']
|
46
8
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Rollbar
|
2
|
+
class Notifier
|
3
|
+
class TraceWithBindings # :nodoc:
|
4
|
+
attr_reader :frames, :exception_frames
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
reset
|
8
|
+
end
|
9
|
+
|
10
|
+
def reset
|
11
|
+
@frames = []
|
12
|
+
@exception_frames = []
|
13
|
+
@exception_signature = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def enable
|
17
|
+
reset
|
18
|
+
trace_point.enable if defined?(TracePoint)
|
19
|
+
end
|
20
|
+
|
21
|
+
def disable
|
22
|
+
trace_point.disable if defined?(TracePoint)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def exception_signature(trace)
|
28
|
+
# use the exception backtrace to detect reraised exception.
|
29
|
+
trace.raised_exception.backtrace.first
|
30
|
+
end
|
31
|
+
|
32
|
+
def detect_reraise(trace)
|
33
|
+
@exception_signature == exception_signature(trace)
|
34
|
+
end
|
35
|
+
|
36
|
+
def trace_point
|
37
|
+
return unless defined?(TracePoint)
|
38
|
+
|
39
|
+
@trace_point ||= TracePoint.new(:call, :return, :b_call, :b_return, :c_call,
|
40
|
+
:c_return, :raise) do |tp|
|
41
|
+
case tp.event
|
42
|
+
when :call, :b_call, :c_call, :class
|
43
|
+
frames.push frame(tp)
|
44
|
+
when :return, :b_return, :c_return, :end
|
45
|
+
frames.pop
|
46
|
+
when :raise
|
47
|
+
unless detect_reraise(tp) # ignore reraised exceptions
|
48
|
+
# may be possible to optimize better than #dup
|
49
|
+
@exception_frames = @frames.dup
|
50
|
+
@exception_signature = exception_signature(tp)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def frame(trace)
|
57
|
+
{
|
58
|
+
:binding => binding(trace),
|
59
|
+
:defined_class => trace.defined_class,
|
60
|
+
:method_id => trace.method_id,
|
61
|
+
:path => trace.path,
|
62
|
+
:lineno => trace.lineno
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def binding(trace)
|
67
|
+
trace.binding
|
68
|
+
rescue StandardError
|
69
|
+
# Ruby internals will raise if we're on a Fiber,
|
70
|
+
# since bindings aren't valid on Fibers.
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|