sentry-rails 5.26.0 → 6.0.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 +14 -15
- data/bin/test +389 -0
- data/lib/sentry/rails/active_job.rb +7 -11
- data/lib/sentry/rails/background_worker.rb +11 -7
- data/lib/sentry/rails/configuration.rb +39 -2
- data/lib/sentry/rails/log_subscriber.rb +73 -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/overrides/streaming_reporter.rb +0 -11
- data/lib/sentry/rails/railtie.rb +10 -8
- data/lib/sentry/rails/structured_logging.rb +32 -0
- data/lib/sentry/rails/version.rb +1 -1
- data/lib/sentry/rails.rb +1 -0
- data/sentry-rails.gemspec +3 -3
- metadata +20 -15
- data/lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb +0 -46
- data/lib/sentry/rails/instrument_payload_cleanup_helper.rb +0 -15
- data/lib/sentry/rails/tracing/action_controller_subscriber.rb +0 -43
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2f1d7d083cce7bf8f0e04a82c63fd1284f836e2ae3aa30a9237eba989e72ae93
|
|
4
|
+
data.tar.gz: 681cc6a28160e9f8138cdfc2a9c9c8ab81e2a90e43559306d30061e92fe63c91
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: db6546de2db3507a022eff373b10bed7380568fd40055c50b3e80cfe907ecc2479799e7fbfc5f598baa7ebbf92e410823fe71951cd8ae664c15714bb8e49c607
|
|
7
|
+
data.tar.gz: c71fe0109e60f59e36c91d0e3cbc95c8f34cb5b7b767261e68f40c04716b7d296939ad507ff7166bb618f63fac78b0865313ba2f6b685ba46b659c7175a38575
|
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,16 @@ 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
|
+
else
|
|
25
|
+
"7.1"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
21
29
|
rails_version = Gem::Version.new(rails_version)
|
|
22
30
|
|
|
23
31
|
gem "rails", "~> #{rails_version}"
|
|
@@ -26,19 +34,16 @@ if rails_version >= Gem::Version.new("8.0.0")
|
|
|
26
34
|
gem "rspec-rails"
|
|
27
35
|
gem "sqlite3", "~> 2.1.1", platform: :ruby
|
|
28
36
|
elsif rails_version >= Gem::Version.new("7.1.0")
|
|
37
|
+
gem "psych", "~> 4.0.0"
|
|
29
38
|
gem "rspec-rails"
|
|
30
39
|
gem "sqlite3", "~> 1.7.3", platform: :ruby
|
|
31
40
|
elsif rails_version >= Gem::Version.new("6.1.0")
|
|
32
41
|
gem "rspec-rails", "~> 4.0"
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
gem "sqlite3", "~> 1.7.3", platform: :ruby
|
|
36
|
-
else
|
|
37
|
-
gem "sqlite3", "~> 1.6.9", platform: :ruby
|
|
38
|
-
end
|
|
43
|
+
gem "sqlite3", "~> 1.7.3", platform: :ruby
|
|
39
44
|
else
|
|
40
|
-
gem "rspec-rails", "~> 4.0"
|
|
41
45
|
gem "psych", "~> 3.0.0"
|
|
46
|
+
gem "rspec-rails", "~> 4.0"
|
|
42
47
|
|
|
43
48
|
if rails_version >= Gem::Version.new("6.0.0")
|
|
44
49
|
gem "sqlite3", "~> 1.4.0", platform: :ruby
|
|
@@ -47,12 +52,6 @@ else
|
|
|
47
52
|
end
|
|
48
53
|
end
|
|
49
54
|
|
|
50
|
-
if ruby_version < Gem::Version.new("2.5.0")
|
|
51
|
-
# https://github.com/flavorjones/loofah/pull/267
|
|
52
|
-
# loofah changed the required ruby version in a patch so we need to explicitly pin it
|
|
53
|
-
gem "loofah", "2.20.0"
|
|
54
|
-
end
|
|
55
|
-
|
|
56
55
|
gem "mini_magick"
|
|
57
56
|
|
|
58
57
|
gem "sprockets-rails"
|
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
|
|
@@ -32,17 +32,13 @@ module Sentry
|
|
|
32
32
|
Sentry.with_scope do |scope|
|
|
33
33
|
begin
|
|
34
34
|
scope.set_transaction_name(job.class.name, source: :task)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
op: OP_NAME,
|
|
43
|
-
origin: SPAN_ORIGIN
|
|
44
|
-
)
|
|
45
|
-
end
|
|
35
|
+
|
|
36
|
+
transaction = Sentry.start_transaction(
|
|
37
|
+
name: scope.transaction_name,
|
|
38
|
+
source: scope.transaction_source,
|
|
39
|
+
op: OP_NAME,
|
|
40
|
+
origin: SPAN_ORIGIN
|
|
41
|
+
)
|
|
46
42
|
|
|
47
43
|
scope.set_span(transaction) if transaction
|
|
48
44
|
|
|
@@ -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)
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "sentry/rails/tracing/action_controller_subscriber"
|
|
4
3
|
require "sentry/rails/tracing/action_view_subscriber"
|
|
5
4
|
require "sentry/rails/tracing/active_record_subscriber"
|
|
6
5
|
require "sentry/rails/tracing/active_storage_subscriber"
|
|
7
6
|
require "sentry/rails/tracing/active_support_subscriber"
|
|
8
7
|
|
|
8
|
+
require "sentry/rails/log_subscribers/active_record_subscriber"
|
|
9
|
+
require "sentry/rails/log_subscribers/action_controller_subscriber"
|
|
10
|
+
|
|
9
11
|
module Sentry
|
|
10
12
|
class Configuration
|
|
11
13
|
attr_reader :rails
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
after(:initialize) do
|
|
14
16
|
@rails = Sentry::Rails::Configuration.new
|
|
15
17
|
@excluded_exceptions = @excluded_exceptions.concat(Sentry::Rails::IGNORE_DEFAULT)
|
|
16
18
|
|
|
@@ -30,6 +32,10 @@ module Sentry
|
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
34
|
end
|
|
35
|
+
|
|
36
|
+
after(:configured) do
|
|
37
|
+
rails.structured_logging.enabled = enable_logs if rails.structured_logging.enabled.nil?
|
|
38
|
+
end
|
|
33
39
|
end
|
|
34
40
|
|
|
35
41
|
module Rails
|
|
@@ -159,6 +165,10 @@ module Sentry
|
|
|
159
165
|
# Set this option to true if you want Sentry to capture each retry failure
|
|
160
166
|
attr_accessor :active_job_report_on_retry_error
|
|
161
167
|
|
|
168
|
+
# Configuration for structured logging feature
|
|
169
|
+
# @return [StructuredLoggingConfiguration]
|
|
170
|
+
attr_reader :structured_logging
|
|
171
|
+
|
|
162
172
|
def initialize
|
|
163
173
|
@register_error_subscriber = false
|
|
164
174
|
@report_rescued_exceptions = true
|
|
@@ -176,6 +186,33 @@ module Sentry
|
|
|
176
186
|
@db_query_source_threshold_ms = 100
|
|
177
187
|
@active_support_logger_subscription_items = Sentry::Rails::ACTIVE_SUPPORT_LOGGER_SUBSCRIPTION_ITEMS_DEFAULT.dup
|
|
178
188
|
@active_job_report_on_retry_error = false
|
|
189
|
+
@structured_logging = StructuredLoggingConfiguration.new
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
class StructuredLoggingConfiguration
|
|
194
|
+
# Enable or disable structured logging
|
|
195
|
+
# @return [Boolean]
|
|
196
|
+
attr_accessor :enabled
|
|
197
|
+
|
|
198
|
+
# Hash of components to subscriber classes for structured logging
|
|
199
|
+
# @return [Hash<Symbol, Class>]
|
|
200
|
+
attr_accessor :subscribers
|
|
201
|
+
|
|
202
|
+
DEFAULT_SUBSCRIBERS = {
|
|
203
|
+
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber,
|
|
204
|
+
action_controller: Sentry::Rails::LogSubscribers::ActionControllerSubscriber
|
|
205
|
+
}.freeze
|
|
206
|
+
|
|
207
|
+
def initialize
|
|
208
|
+
@enabled = nil
|
|
209
|
+
@subscribers = DEFAULT_SUBSCRIBERS.dup
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Returns true if structured logging should be enabled.
|
|
213
|
+
# @return [Boolean]
|
|
214
|
+
def enabled?
|
|
215
|
+
enabled
|
|
179
216
|
end
|
|
180
217
|
end
|
|
181
218
|
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/log_subscriber"
|
|
4
|
+
|
|
5
|
+
module Sentry
|
|
6
|
+
module Rails
|
|
7
|
+
# Base class for Sentry log subscribers that extends ActiveSupport::LogSubscriber
|
|
8
|
+
# to provide structured logging capabilities for Rails components.
|
|
9
|
+
#
|
|
10
|
+
# This class follows Rails' LogSubscriber pattern and provides common functionality
|
|
11
|
+
# for capturing Rails instrumentation events and logging them through Sentry's
|
|
12
|
+
# structured logging system.
|
|
13
|
+
#
|
|
14
|
+
# @example Creating a custom log subscriber
|
|
15
|
+
# class MySubscriber < Sentry::Rails::LogSubscriber
|
|
16
|
+
# attach_to :my_component
|
|
17
|
+
#
|
|
18
|
+
# def my_event(event)
|
|
19
|
+
# log_structured_event(
|
|
20
|
+
# message: "My event occurred",
|
|
21
|
+
# level: :info,
|
|
22
|
+
# attributes: {
|
|
23
|
+
# duration_ms: event.duration,
|
|
24
|
+
# custom_data: event.payload[:custom_data]
|
|
25
|
+
# }
|
|
26
|
+
# )
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
|
30
|
+
ORIGIN = "auto.log.rails.log_subscriber"
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
if ::Rails.version.to_f < 6.0
|
|
34
|
+
# Rails 5.x does not provide detach_from
|
|
35
|
+
def detach_from(namespace, notifications = ActiveSupport::Notifications)
|
|
36
|
+
listeners = public_instance_methods(false)
|
|
37
|
+
.flat_map { |key|
|
|
38
|
+
notifications.notifier.listeners_for("#{key}.#{namespace}")
|
|
39
|
+
}
|
|
40
|
+
.select { |listener| listener.instance_variable_get(:@delegate).is_a?(self) }
|
|
41
|
+
|
|
42
|
+
listeners.map do |listener|
|
|
43
|
+
notifications.notifier.unsubscribe(listener)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
# Log a structured event using Sentry's structured logger
|
|
52
|
+
#
|
|
53
|
+
# @param message [String] The log message
|
|
54
|
+
# @param level [Symbol] The log level (:trace, :debug, :info, :warn, :error, :fatal)
|
|
55
|
+
# @param attributes [Hash] Additional structured attributes to include
|
|
56
|
+
# @param origin [String] The origin of the log event
|
|
57
|
+
def log_structured_event(message:, level: :info, attributes: {}, origin: ORIGIN)
|
|
58
|
+
Sentry.logger.public_send(level, message, **attributes, origin: origin)
|
|
59
|
+
rescue => e
|
|
60
|
+
# Silently handle any errors in logging to avoid breaking the application
|
|
61
|
+
Sentry.configuration.sdk_logger.debug("Failed to log structured event: #{e.message}")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Calculate duration in milliseconds from an event
|
|
65
|
+
#
|
|
66
|
+
# @param event [ActiveSupport::Notifications::Event] The event
|
|
67
|
+
# @return [Float] Duration in milliseconds
|
|
68
|
+
def duration_ms(event)
|
|
69
|
+
event.duration.round(2)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|