sentry-rails 5.23.0 → 5.27.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/Gemfile +15 -4
- data/Rakefile +11 -28
- data/bin/test +389 -0
- data/lib/sentry/rails/active_job.rb +55 -8
- data/lib/sentry/rails/background_worker.rb +11 -7
- data/lib/sentry/rails/configuration.rb +35 -3
- data/lib/sentry/rails/log_subscriber.rb +70 -0
- data/lib/sentry/rails/log_subscribers/action_controller_subscriber.rb +116 -0
- data/lib/sentry/rails/log_subscribers/action_mailer_subscriber.rb +88 -0
- data/lib/sentry/rails/log_subscribers/active_job_subscriber.rb +155 -0
- data/lib/sentry/rails/log_subscribers/active_record_subscriber.rb +134 -0
- data/lib/sentry/rails/log_subscribers/parameter_filter.rb +52 -0
- data/lib/sentry/rails/railtie.rb +12 -0
- data/lib/sentry/rails/structured_logging.rb +32 -0
- data/lib/sentry/rails/tracing/action_controller_subscriber.rb +1 -1
- data/lib/sentry/rails/tracing/active_storage_subscriber.rb +4 -1
- data/lib/sentry/rails/version.rb +1 -1
- data/lib/sentry/rails.rb +1 -0
- data/sentry-rails.gemspec +1 -1
- metadata +19 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15c5cac1232851c12adb474d437c228335f2c23b3f9f65e9000d769b6265d52d
|
4
|
+
data.tar.gz: fe44e7fe542de216cf8eb97bef21a72f058c62e862dec51edbbd244a98cd21aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed7cc92a5d90ce2d251f1afaeaa1a08cc5e4af878f4b254b3a7bcf369e1353af3acba97228cec5c86d20f63e354b44860bc4a8120f1577dd66c01fb2d75600d7
|
7
|
+
data.tar.gz: 30b11a5ed39d0351a91348938d4aa6a2a7625c28e55293c591087747e71e2488b086967f6e811a5281292a332b1f66b3e94e18ed7e7783eab50f9d1408740a3b
|
data/Gemfile
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
git_source(:github) { |name| "https://github.com/#{name}.git" }
|
5
5
|
|
6
|
-
eval_gemfile "../Gemfile"
|
6
|
+
eval_gemfile "../Gemfile.dev"
|
7
7
|
|
8
8
|
# Specify your gem's dependencies in sentry-ruby.gemspec
|
9
9
|
gemspec
|
@@ -16,8 +16,18 @@ end
|
|
16
16
|
|
17
17
|
ruby_version = Gem::Version.new(RUBY_VERSION)
|
18
18
|
|
19
|
-
rails_version = ENV
|
20
|
-
|
19
|
+
rails_version = ENV.fetch("RAILS_VERSION") do
|
20
|
+
if ruby_version >= Gem::Version.new("3.2")
|
21
|
+
"8.0"
|
22
|
+
elsif ruby_version >= Gem::Version.new("3.1")
|
23
|
+
"7.2"
|
24
|
+
elsif ruby_version >= Gem::Version.new("2.7")
|
25
|
+
"7.1"
|
26
|
+
elsif ruby_version >= Gem::Version.new("2.4")
|
27
|
+
"5.2"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
21
31
|
rails_version = Gem::Version.new(rails_version)
|
22
32
|
|
23
33
|
gem "rails", "~> #{rails_version}"
|
@@ -26,6 +36,7 @@ if rails_version >= Gem::Version.new("8.0.0")
|
|
26
36
|
gem "rspec-rails"
|
27
37
|
gem "sqlite3", "~> 2.1.1", platform: :ruby
|
28
38
|
elsif rails_version >= Gem::Version.new("7.1.0")
|
39
|
+
gem "psych", "~> 4.0.0"
|
29
40
|
gem "rspec-rails"
|
30
41
|
gem "sqlite3", "~> 1.7.3", platform: :ruby
|
31
42
|
elsif rails_version >= Gem::Version.new("6.1.0")
|
@@ -37,8 +48,8 @@ elsif rails_version >= Gem::Version.new("6.1.0")
|
|
37
48
|
gem "sqlite3", "~> 1.6.9", platform: :ruby
|
38
49
|
end
|
39
50
|
else
|
40
|
-
gem "rspec-rails", "~> 4.0"
|
41
51
|
gem "psych", "~> 3.0.0"
|
52
|
+
gem "rspec-rails", "~> 4.0"
|
42
53
|
|
43
54
|
if rails_version >= Gem::Version.new("6.0.0")
|
44
55
|
gem "sqlite3", "~> 1.4.0", platform: :ruby
|
data/Rakefile
CHANGED
@@ -1,34 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
|
-
|
4
|
+
require_relative "../lib/sentry/test/rake_tasks"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
Sentry::Test::RakeTasks.define_spec_tasks(
|
7
|
+
spec_pattern: "spec/sentry/**/*_spec.rb",
|
8
|
+
spec_rspec_opts: "--order rand --format progress",
|
9
|
+
isolated_specs_pattern: "spec/isolated/**/*_spec.rb",
|
10
|
+
isolated_rspec_opts: "--format progress"
|
11
|
+
)
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
matching_dir = Dir["spec/versioned/*"].detect { |dir| File.basename(dir) <= ruby_ver_dir }
|
13
|
+
Sentry::Test::RakeTasks.define_versioned_specs_task(
|
14
|
+
rspec_opts: "--order rand --format progress"
|
15
|
+
)
|
15
16
|
|
16
|
-
|
17
|
-
puts "No versioned specs found for ruby #{RUBY_VERSION}"
|
18
|
-
exit 0
|
19
|
-
end
|
20
|
-
|
21
|
-
puts "Running versioned specs from #{matching_dir} for ruby #{RUBY_VERSION}"
|
22
|
-
|
23
|
-
task.rspec_opts = "--order rand"
|
24
|
-
task.pattern = "#{matching_dir}/**/*_spec.rb"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
task :isolated_specs do
|
29
|
-
Dir["spec/isolated/*"].each do |file|
|
30
|
-
sh "bundle exec ruby #{file}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
task default: [:spec, :"spec:versioned", :isolated_specs]
|
17
|
+
task default: [:spec, :"spec:versioned", :"spec:isolated"]
|
data/bin/test
ADDED
@@ -0,0 +1,389 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
# Standalone CLI script to test sentry-rails against multiple Rails versions
|
6
|
+
#
|
7
|
+
# FEATURES:
|
8
|
+
# - Dedicated lock files for each Ruby/Rails version combination
|
9
|
+
# - Prevents dependency conflicts between different Rails versions
|
10
|
+
# - Automatic lock file management and restoration
|
11
|
+
# - Clean up functionality for old lock files
|
12
|
+
#
|
13
|
+
# LOCK FILE STRATEGY:
|
14
|
+
# Each Ruby/Rails combination gets its own lock file:
|
15
|
+
# - Ruby 3.4.5 + Rails 6.1 → Gemfile-ruby-3.4.5-rails-6.1.lock
|
16
|
+
# - Ruby 3.4.5 + Rails 7.0 → Gemfile-ruby-3.4.5-rails-7.0.lock
|
17
|
+
#
|
18
|
+
# Usage:
|
19
|
+
# ./bin/test --version 5.0
|
20
|
+
# ./bin/test --all
|
21
|
+
# ./bin/test --help
|
22
|
+
|
23
|
+
require 'optparse'
|
24
|
+
require 'fileutils'
|
25
|
+
|
26
|
+
class RailsVersionTester
|
27
|
+
SUPPORTED_VERSIONS = %w[5.0 5.1 5.2 6.0 6.1 7.0 7.1 7.2 8.0].freeze
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@options = {}
|
31
|
+
@failed_versions = []
|
32
|
+
@ruby_version = RUBY_VERSION
|
33
|
+
@spec_paths = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def run(args)
|
37
|
+
parse_options(args)
|
38
|
+
|
39
|
+
case
|
40
|
+
when @options[:help]
|
41
|
+
show_help
|
42
|
+
when @options[:list]
|
43
|
+
list_versions
|
44
|
+
when @options[:clean]
|
45
|
+
clean_lock_files
|
46
|
+
when @options[:all]
|
47
|
+
test_all_versions
|
48
|
+
when @options[:version]
|
49
|
+
test_single_version(@options[:version])
|
50
|
+
else
|
51
|
+
puts "Error: No action specified. Use --help for usage information."
|
52
|
+
exit(1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def parse_options(args)
|
59
|
+
OptionParser.new do |opts|
|
60
|
+
opts.banner = "Usage: #{$0} [options] [spec_paths...]"
|
61
|
+
|
62
|
+
opts.on("-v", "--version VERSION", "Test specific Rails version") do |version|
|
63
|
+
unless SUPPORTED_VERSIONS.include?(version)
|
64
|
+
puts "Error: Unsupported Rails version '#{version}'"
|
65
|
+
puts "Supported versions: #{SUPPORTED_VERSIONS.join(', ')}"
|
66
|
+
exit(1)
|
67
|
+
end
|
68
|
+
@options[:version] = version
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on("-a", "--all", "Test all supported Rails versions") do
|
72
|
+
@options[:all] = true
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("-l", "--list", "List supported Rails versions and lock file status") do
|
76
|
+
@options[:list] = true
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on("-c", "--clean", "Clean up old lock files for current Ruby version") do
|
80
|
+
@options[:clean] = true
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("-h", "--help", "Show this help message") do
|
84
|
+
@options[:help] = true
|
85
|
+
end
|
86
|
+
end.parse!(args)
|
87
|
+
|
88
|
+
# Remaining arguments are spec paths
|
89
|
+
@spec_paths = args
|
90
|
+
end
|
91
|
+
|
92
|
+
def show_help
|
93
|
+
puts <<~HELP
|
94
|
+
Rails Version Tester for sentry-rails
|
95
|
+
|
96
|
+
This script tests sentry-rails against different Rails versions by:
|
97
|
+
1. Setting the RAILS_VERSION environment variable
|
98
|
+
2. Managing bundle dependencies with dedicated lock files per Ruby/Rails combination
|
99
|
+
3. Running the test suite in isolated processes
|
100
|
+
4. Providing proper exit codes for CI/CD integration
|
101
|
+
|
102
|
+
Each Ruby/Rails version combination gets its own Gemfile.lock to prevent conflicts:
|
103
|
+
- Ruby #{@ruby_version} + Rails 6.1 → Gemfile-ruby-#{@ruby_version}-rails-6.1.lock
|
104
|
+
- Ruby #{@ruby_version} + Rails 7.0 → Gemfile-ruby-#{@ruby_version}-rails-7.0.lock
|
105
|
+
|
106
|
+
Usage:
|
107
|
+
#{$0} --version 6.1 # Test specific Rails version (all specs)
|
108
|
+
#{$0} --version 7.0 spec/sentry/rails/log_subscribers # Test specific Rails version with specific specs
|
109
|
+
#{$0} --all # Test all supported versions
|
110
|
+
#{$0} --list # List supported versions and lock file status
|
111
|
+
#{$0} --clean # Clean up old lock files for current Ruby version
|
112
|
+
#{$0} --help # Show this help
|
113
|
+
|
114
|
+
Supported Rails versions: #{SUPPORTED_VERSIONS.join(', ')}
|
115
|
+
|
116
|
+
Examples:
|
117
|
+
#{$0} -v 7.1 # Test Rails 7.1 (all specs)
|
118
|
+
#{$0} -v 7.0 spec/sentry/rails/log_subscribers # Test Rails 7.0 log subscriber specs only
|
119
|
+
#{$0} -v 7.0 spec/sentry/rails/tracing # Test Rails 7.0 tracing specs only
|
120
|
+
#{$0} -a # Test all versions
|
121
|
+
#{$0} -c # Clean up old lock files
|
122
|
+
HELP
|
123
|
+
end
|
124
|
+
|
125
|
+
def list_versions
|
126
|
+
puts "Supported Rails versions:"
|
127
|
+
SUPPORTED_VERSIONS.each do |version|
|
128
|
+
lock_file = generate_lock_file_name(version)
|
129
|
+
status = File.exist?(lock_file) ? "(has lock file)" : "(no lock file)"
|
130
|
+
puts " - #{version} #{status}"
|
131
|
+
end
|
132
|
+
puts
|
133
|
+
puts "Current Ruby version: #{@ruby_version}"
|
134
|
+
puts "Lock files are stored as: Gemfile-ruby-X.X.X-rails-Y.Y.lock"
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_all_versions
|
138
|
+
puts "Testing sentry-rails against all supported Rails versions: #{SUPPORTED_VERSIONS.join(', ')}"
|
139
|
+
puts
|
140
|
+
|
141
|
+
SUPPORTED_VERSIONS.each do |version|
|
142
|
+
puts "=" * 60
|
143
|
+
puts "Testing Rails #{version}"
|
144
|
+
puts "=" * 60
|
145
|
+
|
146
|
+
exit_code = test_rails_version(version)
|
147
|
+
|
148
|
+
if exit_code == 0
|
149
|
+
puts "✓ Rails #{version} - PASSED"
|
150
|
+
else
|
151
|
+
puts "✗ Rails #{version} - FAILED (exit code: #{exit_code})"
|
152
|
+
@failed_versions << version
|
153
|
+
end
|
154
|
+
puts
|
155
|
+
end
|
156
|
+
|
157
|
+
print_summary
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_single_version(version)
|
161
|
+
puts "Testing sentry-rails against Rails #{version}..."
|
162
|
+
exit_code = test_rails_version(version)
|
163
|
+
exit(exit_code) unless exit_code == 0
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_rails_version(version)
|
167
|
+
puts "Setting up environment for Rails #{version}..."
|
168
|
+
|
169
|
+
# Generate dedicated lock file name for this Ruby/Rails combination
|
170
|
+
dedicated_lock_file = generate_lock_file_name(version)
|
171
|
+
current_lock_file = "Gemfile.lock"
|
172
|
+
|
173
|
+
# Set up environment variables
|
174
|
+
env = {
|
175
|
+
"RAILS_VERSION" => version,
|
176
|
+
"BUNDLE_GEMFILE" => File.expand_path("Gemfile", Dir.pwd)
|
177
|
+
}
|
178
|
+
|
179
|
+
puts "Using dedicated lock file: #{dedicated_lock_file}"
|
180
|
+
|
181
|
+
# Manage lock file switching
|
182
|
+
setup_lock_file(dedicated_lock_file, current_lock_file)
|
183
|
+
|
184
|
+
begin
|
185
|
+
# Check if bundle update is needed
|
186
|
+
if bundle_update_needed?(env, dedicated_lock_file)
|
187
|
+
puts "Dependencies need to be updated for Rails #{version}..."
|
188
|
+
unless update_bundle(env, dedicated_lock_file)
|
189
|
+
puts "✗ Failed to update bundle for Rails #{version}"
|
190
|
+
return 1
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Run the tests in a separate process
|
195
|
+
puts "Running test suite..."
|
196
|
+
run_tests(env, @spec_paths)
|
197
|
+
ensure
|
198
|
+
# Save the current lock file back to the dedicated location
|
199
|
+
save_lock_file(dedicated_lock_file, current_lock_file)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def generate_lock_file_name(rails_version)
|
204
|
+
# Create a unique lock file name for this Ruby/Rails combination
|
205
|
+
ruby_version_clean = @ruby_version.gsub(/[^\d\.]/, '')
|
206
|
+
rails_version_clean = rails_version.gsub(/[^\d\.]/, '')
|
207
|
+
"Gemfile-ruby-#{ruby_version_clean}-rails-#{rails_version_clean}.lock"
|
208
|
+
end
|
209
|
+
|
210
|
+
def setup_lock_file(dedicated_lock_file, current_lock_file)
|
211
|
+
# If we have a dedicated lock file, copy it to the current location
|
212
|
+
if File.exist?(dedicated_lock_file)
|
213
|
+
puts "Restoring lock file from #{dedicated_lock_file}"
|
214
|
+
FileUtils.cp(dedicated_lock_file, current_lock_file)
|
215
|
+
elsif File.exist?(current_lock_file)
|
216
|
+
# If no dedicated lock file exists but current one does, remove it
|
217
|
+
# so we get a fresh resolution
|
218
|
+
puts "Removing existing lock file for fresh dependency resolution"
|
219
|
+
File.delete(current_lock_file)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def save_lock_file(dedicated_lock_file, current_lock_file)
|
224
|
+
# Save the current lock file to the dedicated location
|
225
|
+
if File.exist?(current_lock_file)
|
226
|
+
puts "Saving lock file to #{dedicated_lock_file}"
|
227
|
+
FileUtils.cp(current_lock_file, dedicated_lock_file)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def bundle_update_needed?(env, dedicated_lock_file)
|
232
|
+
# Check if current Gemfile.lock exists
|
233
|
+
current_lock_file = "Gemfile.lock"
|
234
|
+
gemfile_path = env["BUNDLE_GEMFILE"] || "Gemfile"
|
235
|
+
|
236
|
+
return true unless File.exist?(current_lock_file)
|
237
|
+
|
238
|
+
# Check if Gemfile is newer than the current lock file
|
239
|
+
return true if File.mtime(gemfile_path) > File.mtime(current_lock_file)
|
240
|
+
|
241
|
+
# For Rails version changes, check if lockfile has incompatible Rails version
|
242
|
+
if env["RAILS_VERSION"] && lockfile_has_incompatible_rails_version?(current_lock_file, env["RAILS_VERSION"])
|
243
|
+
return true
|
244
|
+
end
|
245
|
+
|
246
|
+
# Check if bundle check passes
|
247
|
+
system(env, "bundle check > /dev/null 2>&1") == false
|
248
|
+
end
|
249
|
+
|
250
|
+
def lockfile_has_incompatible_rails_version?(lockfile_path, target_rails_version)
|
251
|
+
return false unless File.exist?(lockfile_path)
|
252
|
+
|
253
|
+
lockfile_content = File.read(lockfile_path)
|
254
|
+
|
255
|
+
# Extract Rails version from lockfile
|
256
|
+
if lockfile_content =~ /^\s*rails \(([^)]+)\)/
|
257
|
+
locked_rails_version = $1
|
258
|
+
target_major_minor = target_rails_version.split('.')[0..1].join('.')
|
259
|
+
locked_major_minor = locked_rails_version.split('.')[0..1].join('.')
|
260
|
+
|
261
|
+
# If major.minor versions don't match, we need to update
|
262
|
+
return target_major_minor != locked_major_minor
|
263
|
+
end
|
264
|
+
|
265
|
+
# If we can't determine the Rails version, assume update is needed
|
266
|
+
true
|
267
|
+
end
|
268
|
+
|
269
|
+
def update_bundle(env, dedicated_lock_file)
|
270
|
+
puts "Updating bundle for Rails #{env['RAILS_VERSION']}..."
|
271
|
+
|
272
|
+
current_lock_file = "Gemfile.lock"
|
273
|
+
|
274
|
+
# Try bundle update first
|
275
|
+
if system(env, "bundle update --quiet")
|
276
|
+
puts "Bundle updated successfully"
|
277
|
+
return true
|
278
|
+
end
|
279
|
+
|
280
|
+
puts "Bundle update failed, trying clean install..."
|
281
|
+
|
282
|
+
# Remove the current lockfile and try fresh install
|
283
|
+
File.delete(current_lock_file) if File.exist?(current_lock_file)
|
284
|
+
|
285
|
+
if system(env, "bundle install --quiet")
|
286
|
+
puts "Bundle installed successfully"
|
287
|
+
return true
|
288
|
+
end
|
289
|
+
|
290
|
+
puts "Bundle install failed"
|
291
|
+
false
|
292
|
+
end
|
293
|
+
|
294
|
+
def run_tests(env, spec_paths = [])
|
295
|
+
# Determine the command to run
|
296
|
+
if spec_paths.empty?
|
297
|
+
# Run all tests via rake
|
298
|
+
command = "bundle exec rake"
|
299
|
+
else
|
300
|
+
# Run specific specs via rspec
|
301
|
+
command = "bundle exec rspec #{spec_paths.join(' ')}"
|
302
|
+
end
|
303
|
+
|
304
|
+
puts "Executing: #{command}"
|
305
|
+
|
306
|
+
# Run the tests in a separate process with proper signal handling
|
307
|
+
pid = spawn(env, command,
|
308
|
+
out: $stdout,
|
309
|
+
err: $stderr,
|
310
|
+
pgroup: true)
|
311
|
+
|
312
|
+
begin
|
313
|
+
_, status = Process.wait2(pid)
|
314
|
+
status.exitstatus
|
315
|
+
rescue Interrupt
|
316
|
+
puts "\nInterrupted! Terminating test process..."
|
317
|
+
terminate_process_group(pid)
|
318
|
+
130 # Standard exit code for SIGINT
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def terminate_process_group(pid)
|
323
|
+
begin
|
324
|
+
Process.kill("TERM", -pid) # Kill the process group
|
325
|
+
sleep(2)
|
326
|
+
Process.kill("KILL", -pid) if process_running?(pid)
|
327
|
+
rescue Errno::ESRCH
|
328
|
+
# Process already terminated
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def process_running?(pid)
|
333
|
+
Process.getpgid(pid)
|
334
|
+
true
|
335
|
+
rescue Errno::ESRCH
|
336
|
+
false
|
337
|
+
end
|
338
|
+
|
339
|
+
def clean_lock_files
|
340
|
+
puts "Cleaning up lock files for Ruby #{@ruby_version}..."
|
341
|
+
|
342
|
+
# Find all lock files matching our pattern
|
343
|
+
pattern = "Gemfile-ruby-#{@ruby_version.gsub(/[^\d\.]/, '')}-rails-*.lock"
|
344
|
+
lock_files = Dir.glob(pattern)
|
345
|
+
|
346
|
+
if lock_files.empty?
|
347
|
+
puts "No lock files found matching pattern: #{pattern}"
|
348
|
+
return
|
349
|
+
end
|
350
|
+
|
351
|
+
puts "Found #{lock_files.length} lock file(s):"
|
352
|
+
lock_files.each { |file| puts " - #{file}" }
|
353
|
+
|
354
|
+
print "Delete these files? [y/N]: "
|
355
|
+
response = $stdin.gets.chomp.downcase
|
356
|
+
|
357
|
+
if response == 'y' || response == 'yes'
|
358
|
+
lock_files.each do |file|
|
359
|
+
File.delete(file)
|
360
|
+
puts "Deleted: #{file}"
|
361
|
+
end
|
362
|
+
puts "Cleanup complete!"
|
363
|
+
else
|
364
|
+
puts "Cleanup cancelled."
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def print_summary
|
369
|
+
puts "=" * 60
|
370
|
+
puts "SUMMARY"
|
371
|
+
puts "=" * 60
|
372
|
+
|
373
|
+
if @failed_versions.empty?
|
374
|
+
puts "✓ All Rails versions passed!"
|
375
|
+
exit(0)
|
376
|
+
else
|
377
|
+
puts "✗ Failed versions: #{@failed_versions.join(', ')}"
|
378
|
+
puts
|
379
|
+
puts "Some Rails versions failed. See output above for details."
|
380
|
+
exit(1)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# Run the script if called directly
|
386
|
+
if __FILE__ == $0
|
387
|
+
tester = RailsVersionTester.new
|
388
|
+
tester.run(ARGV)
|
389
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "set"
|
4
|
+
|
3
5
|
module Sentry
|
4
6
|
module Rails
|
5
7
|
module ActiveJobExtensions
|
@@ -21,6 +23,10 @@ module Sentry
|
|
21
23
|
OP_NAME = "queue.active_job"
|
22
24
|
SPAN_ORIGIN = "auto.queue.active_job"
|
23
25
|
|
26
|
+
EVENT_HANDLERS = {
|
27
|
+
"enqueue_retry.active_job" => :retry_handler
|
28
|
+
}
|
29
|
+
|
24
30
|
class << self
|
25
31
|
def record(job, &block)
|
26
32
|
Sentry.with_scope do |scope|
|
@@ -46,19 +52,54 @@ module Sentry
|
|
46
52
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
47
53
|
finish_sentry_transaction(transaction, 500)
|
48
54
|
|
49
|
-
|
50
|
-
|
51
|
-
extra: sentry_context(job),
|
52
|
-
tags: {
|
53
|
-
job_id: job.job_id,
|
54
|
-
provider_job_id: job.provider_job_id
|
55
|
-
}
|
56
|
-
)
|
55
|
+
capture_exception(job, e)
|
56
|
+
|
57
57
|
raise
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
def capture_exception(job, e)
|
63
|
+
Sentry::Rails.capture_exception(
|
64
|
+
e,
|
65
|
+
extra: sentry_context(job),
|
66
|
+
tags: {
|
67
|
+
job_id: job.job_id,
|
68
|
+
provider_job_id: job.provider_job_id
|
69
|
+
}
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
def register_event_handlers
|
74
|
+
EVENT_HANDLERS.each do |name, handler|
|
75
|
+
subscribers << ActiveSupport::Notifications.subscribe(name) do |*args|
|
76
|
+
public_send(handler, *args)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def detach_event_handlers
|
82
|
+
subscribers.each do |subscriber|
|
83
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
84
|
+
end
|
85
|
+
subscribers.clear
|
86
|
+
end
|
87
|
+
|
88
|
+
# This handler does not capture error unless `active_job_report_on_retry_error` is true
|
89
|
+
def retry_handler(*args)
|
90
|
+
handle_error_event(*args) do |job, error|
|
91
|
+
return if !Sentry.initialized? || job.already_supported_by_sentry_integration?
|
92
|
+
return unless Sentry.configuration.rails.active_job_report_on_retry_error
|
93
|
+
|
94
|
+
capture_exception(job, error)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def handle_error_event(*args)
|
99
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
100
|
+
yield(event.payload[:job], event.payload[:error])
|
101
|
+
end
|
102
|
+
|
62
103
|
def finish_sentry_transaction(transaction, status)
|
63
104
|
return unless transaction
|
64
105
|
|
@@ -95,6 +136,12 @@ module Sentry
|
|
95
136
|
argument
|
96
137
|
end
|
97
138
|
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def subscribers
|
143
|
+
@__subscribers__ ||= Set.new
|
144
|
+
end
|
98
145
|
end
|
99
146
|
end
|
100
147
|
end
|
@@ -2,14 +2,18 @@
|
|
2
2
|
|
3
3
|
module Sentry
|
4
4
|
class BackgroundWorker
|
5
|
-
|
6
|
-
block
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
module ActiveRecordConnectionPatch
|
6
|
+
def _perform(&block)
|
7
|
+
super(&block)
|
8
|
+
ensure
|
9
|
+
# some applications have partial or even no AR connection
|
10
|
+
if ActiveRecord::Base.connected?
|
11
|
+
# make sure the background worker returns AR connection if it accidentally acquire one during serialization
|
12
|
+
ActiveRecord::Base.connection_pool.release_connection
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
18
|
+
|
19
|
+
Sentry::BackgroundWorker.prepend(Sentry::BackgroundWorker::ActiveRecordConnectionPatch)
|
@@ -6,6 +6,9 @@ require "sentry/rails/tracing/active_record_subscriber"
|
|
6
6
|
require "sentry/rails/tracing/active_storage_subscriber"
|
7
7
|
require "sentry/rails/tracing/active_support_subscriber"
|
8
8
|
|
9
|
+
require "sentry/rails/log_subscribers/active_record_subscriber"
|
10
|
+
require "sentry/rails/log_subscribers/action_controller_subscriber"
|
11
|
+
|
9
12
|
module Sentry
|
10
13
|
class Configuration
|
11
14
|
attr_reader :rails
|
@@ -17,12 +20,12 @@ module Sentry
|
|
17
20
|
if ::Rails.logger
|
18
21
|
if defined?(::ActiveSupport::BroadcastLogger) && ::Rails.logger.is_a?(::ActiveSupport::BroadcastLogger)
|
19
22
|
dupped_broadcasts = ::Rails.logger.broadcasts.map(&:dup)
|
20
|
-
|
23
|
+
self.sdk_logger = ::ActiveSupport::BroadcastLogger.new(*dupped_broadcasts)
|
21
24
|
else
|
22
|
-
|
25
|
+
self.sdk_logger = ::Rails.logger.dup
|
23
26
|
end
|
24
27
|
else
|
25
|
-
|
28
|
+
sdk_logger.warn(Sentry::LOGGER_PROGNAME) do
|
26
29
|
<<~MSG
|
27
30
|
sentry-rails can't detect Rails.logger. it may be caused by misplacement of the SDK initialization code
|
28
31
|
please make sure you place the Sentry.init block under the `config/initializers` folder, e.g. `config/initializers/sentry.rb`
|
@@ -156,6 +159,13 @@ module Sentry
|
|
156
159
|
# @return [Hash<String, Array<Symbol>>]
|
157
160
|
attr_accessor :active_support_logger_subscription_items
|
158
161
|
|
162
|
+
# Set this option to true if you want Sentry to capture each retry failure
|
163
|
+
attr_accessor :active_job_report_on_retry_error
|
164
|
+
|
165
|
+
# Configuration for structured logging feature
|
166
|
+
# @return [StructuredLoggingConfiguration]
|
167
|
+
attr_reader :structured_logging
|
168
|
+
|
159
169
|
def initialize
|
160
170
|
@register_error_subscriber = false
|
161
171
|
@report_rescued_exceptions = true
|
@@ -172,6 +182,28 @@ module Sentry
|
|
172
182
|
@enable_db_query_source = true
|
173
183
|
@db_query_source_threshold_ms = 100
|
174
184
|
@active_support_logger_subscription_items = Sentry::Rails::ACTIVE_SUPPORT_LOGGER_SUBSCRIPTION_ITEMS_DEFAULT.dup
|
185
|
+
@active_job_report_on_retry_error = false
|
186
|
+
@structured_logging = StructuredLoggingConfiguration.new
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class StructuredLoggingConfiguration
|
191
|
+
# Enable or disable structured logging
|
192
|
+
# @return [Boolean]
|
193
|
+
attr_accessor :enabled
|
194
|
+
|
195
|
+
# Hash of components to subscriber classes for structured logging
|
196
|
+
# @return [Hash<Symbol, Class>]
|
197
|
+
attr_accessor :subscribers
|
198
|
+
|
199
|
+
DEFAULT_SUBSCRIBERS = {
|
200
|
+
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber,
|
201
|
+
action_controller: Sentry::Rails::LogSubscribers::ActionControllerSubscriber
|
202
|
+
}.freeze
|
203
|
+
|
204
|
+
def initialize
|
205
|
+
@enabled = false
|
206
|
+
@subscribers = DEFAULT_SUBSCRIBERS.dup
|
175
207
|
end
|
176
208
|
end
|
177
209
|
end
|