From 653b06f344403cd093ab35036228cbad22862484 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Tue, 2 Jul 2024 12:52:20 +0100 Subject: [PATCH 01/96] Drop `Gem::Specification`'s usage so it doesn't break bundler standalone (#2335) * Bump sqlite3 to 1.7.* series for Ruby 3.3 * Avoid using Gem::Specification to determine Sentry gems' paths This will break users with bundler standalone setup. * Update changelog --- .github/workflows/build_batch_release.yml | 2 +- CHANGELOG.md | 6 ++++++ sentry-rails/Gemfile | 7 +++++-- .../sentry/rails/tracing/active_record_subscriber.rb | 12 +++++------- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build_batch_release.yml b/.github/workflows/build_batch_release.yml index cb0639992..ffc30fcbd 100644 --- a/.github/workflows/build_batch_release.yml +++ b/.github/workflows/build_batch_release.yml @@ -13,7 +13,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: 3.3 - name: Build gem source run: ruby .scripts/batch_build.rb - name: Archive Artifacts diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aea96c8a..bdb6260c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Bug Fixes + +- Drop `Gem::Specification`'s usage so it doesn't break bundler standalone ([#2335](https://github.com/getsentry/sentry-ruby/pull/2335)) + ## 5.18.0 ### Features diff --git a/sentry-rails/Gemfile b/sentry-rails/Gemfile index fd2ce76cb..8449f342a 100644 --- a/sentry-rails/Gemfile +++ b/sentry-rails/Gemfile @@ -17,8 +17,11 @@ rails_version = Gem::Version.new(rails_version) if rails_version < Gem::Version.new("6.0.0") gem "sqlite3", "~> 1.3.0", platform: :ruby else - # 1.7.0 dropped support for ruby < 3.0, remove later after upgrading craft setup - gem "sqlite3", "1.6.9", platform: :ruby + if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0") + gem "sqlite3", "~> 1.7.3", platform: :ruby + else + gem "sqlite3", "~> 1.6.9", platform: :ruby + end end if rails_version >= Gem::Version.new("7.2.0.alpha") diff --git a/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb b/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb index 813aa9589..480e7011a 100644 --- a/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/rails/tracing/abstract_subscriber" module Sentry @@ -5,19 +7,15 @@ module Rails module Tracing class ActiveRecordSubscriber < AbstractSubscriber EVENT_NAMES = ["sql.active_record"].freeze - SPAN_PREFIX = "db.".freeze - SPAN_ORIGIN = "auto.db.rails".freeze + SPAN_PREFIX = "db." + SPAN_ORIGIN = "auto.db.rails" EXCLUDED_EVENTS = ["SCHEMA", "TRANSACTION"].freeze SUPPORT_SOURCE_LOCATION = ActiveSupport::BacktraceCleaner.method_defined?(:clean_frame) if SUPPORT_SOURCE_LOCATION - # Need to be specific down to the lib path so queries generated in specs don't get ignored - SENTRY_RUBY_PATH = File.join(Gem::Specification.find_by_name("sentry-ruby").full_gem_path, "lib") - SENTRY_RAILS_PATH = File.join(Gem::Specification.find_by_name("sentry-rails").full_gem_path, "lib") - class_attribute :backtrace_cleaner, default: (ActiveSupport::BacktraceCleaner.new.tap do |cleaner| - cleaner.add_silencer { |line| line.include?(SENTRY_RUBY_PATH) || line.include?(SENTRY_RAILS_PATH) } + cleaner.add_silencer { |line| line.include?("sentry-ruby/lib") || line.include?("sentry-rails/lib") } end) end From 97a8554b4e322b8c31689a414b3e96b1c633923f Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 2 Jul 2024 17:39:18 +0200 Subject: [PATCH 02/96] Prepare changelog for 5.18.1 (#2336) Also fix sqlite3 delayed_job CI --- CHANGELOG.md | 2 +- sentry-delayed_job/Gemfile | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb6260c8..8d32d04ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## 5.18.1 ### Bug Fixes diff --git a/sentry-delayed_job/Gemfile b/sentry-delayed_job/Gemfile index c1b2a698b..936bec48a 100644 --- a/sentry-delayed_job/Gemfile +++ b/sentry-delayed_job/Gemfile @@ -20,7 +20,10 @@ platform :jruby do gem "jdbc-sqlite3" end -# 1.7.0 dropped support for ruby < 3.0, remove later after upgrading craft setup -gem "sqlite3", "1.6.9", platform: :ruby +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0") + gem "sqlite3", "~> 1.3.0", platform: :ruby +else + gem "sqlite3", "~> 1.6.9", platform: :ruby +end eval_gemfile File.expand_path("../Gemfile", __dir__) From 9a2b5ba196f640d23d079518a8d2590ecdfc818b Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Tue, 2 Jul 2024 15:48:18 +0000 Subject: [PATCH 03/96] release: 5.18.1 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index a0e159863..47d717991 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -1,5 +1,5 @@ module Sentry module DelayedJob - VERSION = "5.18.0" + VERSION = "5.18.1" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index 1034fa8bf..04f3f0259 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -22,6 +22,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.0" + spec.add_dependency "sentry-ruby", "~> 5.18.1" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index e8dd18200..72ef9303b 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.18.0" + VERSION = "5.18.1" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 1ab98a6b0..b1cefe550 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -24,6 +24,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.0" + spec.add_dependency "sentry-ruby", "~> 5.18.1" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index 2e8928c9f..4a03e8451 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -1,5 +1,5 @@ module Sentry module Rails - VERSION = "5.18.0" + VERSION = "5.18.1" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 996a722e4..3e5f88842 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -23,5 +23,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.18.0" + spec.add_dependency "sentry-ruby", "~> 5.18.1" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index 0d02e6b0c..87b3174a2 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -1,5 +1,5 @@ module Sentry module Resque - VERSION = "5.18.0" + VERSION = "5.18.1" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index e8e9e2eb4..a2c118012 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -22,6 +22,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.0" + spec.add_dependency "sentry-ruby", "~> 5.18.1" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index ebf58e46d..3f5398559 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.18.0" + VERSION = "5.18.1" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index a717827f3..ef6100b35 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -1,5 +1,5 @@ module Sentry module Sidekiq - VERSION = "5.18.0" + VERSION = "5.18.1" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index 837008d5a..191ec4f9b 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -22,6 +22,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.0" + spec.add_dependency "sentry-ruby", "~> 5.18.1" spec.add_dependency "sidekiq", ">= 3.0" end From 142ec2f352f01c9adeda15fa53e7e202c24d5e6a Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Tue, 9 Jul 2024 12:58:39 +0100 Subject: [PATCH 04/96] Use Concurrent.usable_processor_count when it is available (#2339) * Use Concurrent.usable_processor_count when it is available It's a new API introduced in concurrent-ruby 1.3.1, which works better in the container environment. https://github.com/ruby-concurrency/concurrent-ruby/pull/1038 Since there are gems like sorbet-runtime that still use older versions of concurrent-ruby, we can't directly bump concurrent-ruby's requirement, but need to check if the method is available before calling it. * Update changelog --- CHANGELOG.md | 6 ++++++ sentry-ruby/lib/sentry/configuration.rb | 10 +++++++++- sentry-ruby/spec/sentry/configuration_spec.rb | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d32d04ad..763734e42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Internal + +- Use Concurrent.usable_processor_count when it is available ([#2339](https://github.com/getsentry/sentry-ruby/pull/2339)) + ## 5.18.1 ### Bug Fixes diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index 069094bda..8d4564694 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -351,7 +351,7 @@ def add_post_initialization_callback(&block) def initialize self.app_dirs_pattern = nil self.debug = false - self.background_worker_threads = (Concurrent.processor_count / 2.0).ceil + self.background_worker_threads = (processor_count / 2.0).ceil self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE self.backtrace_cleanup_callback = nil self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE @@ -654,5 +654,13 @@ def run_post_initialization_callbacks instance_eval(&hook) end end + + def processor_count + if Concurrent.respond_to?(:usable_processor_count) + Concurrent.usable_processor_count + else + Concurrent.processor_count + end + end end end diff --git a/sentry-ruby/spec/sentry/configuration_spec.rb b/sentry-ruby/spec/sentry/configuration_spec.rb index a88559c4e..92926836a 100644 --- a/sentry-ruby/spec/sentry/configuration_spec.rb +++ b/sentry-ruby/spec/sentry/configuration_spec.rb @@ -26,12 +26,12 @@ describe "#background_worker_threads" do it "sets to have of the processors count" do - allow(Concurrent).to receive(:processor_count).and_return(8) + allow_any_instance_of(Sentry::Configuration).to receive(:processor_count).and_return(8) expect(subject.background_worker_threads).to eq(4) end it "sets to 1 with only 1 processor" do - allow(Concurrent).to receive(:processor_count).and_return(1) + allow_any_instance_of(Sentry::Configuration).to receive(:processor_count).and_return(1) expect(subject.background_worker_threads).to eq(1) end end From a1b61bbe23be6e32fb6e5203964433db7e5462ae Mon Sep 17 00:00:00 2001 From: Stephanie Anderson Date: Wed, 10 Jul 2024 12:17:47 +0200 Subject: [PATCH 05/96] Show contributors on README.md (#2326) --- sentry-ruby/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sentry-ruby/README.md b/sentry-ruby/README.md index 878056150..c98757a32 100644 --- a/sentry-ruby/README.md +++ b/sentry-ruby/README.md @@ -106,3 +106,13 @@ To learn more about sampling transactions, please visit the [official documentat * [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) + +## Contributing to the SDK + +Please make sure to read the [CONTRIBUTING.md](https://github.com/getsentry/sentry-ruby/blob/master/CONTRIBUTING.md) before making a pull request. + +Thanks to everyone who has contributed to this project so far. + + + + From 90edcb82c32b7eabc71af05676202d9a985f0a93 Mon Sep 17 00:00:00 2001 From: Masato Ohba Date: Wed, 10 Jul 2024 19:26:56 +0900 Subject: [PATCH 06/96] Fix typos (#2332) --- sentry-rails/lib/sentry/rails/railtie.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-rails/lib/sentry/rails/railtie.rb b/sentry-rails/lib/sentry/rails/railtie.rb index ef09851c5..44dd450dc 100644 --- a/sentry-rails/lib/sentry/rails/railtie.rb +++ b/sentry-rails/lib/sentry/rails/railtie.rb @@ -12,7 +12,7 @@ class Railtie < ::Rails::Railtie app.config.middleware.insert_after ActionDispatch::DebugExceptions, Sentry::Rails::RescuedExceptionInterceptor end - # because the extension works by registering the around_perform callcack, it should always be ran + # because the extension works by registering the around_perform callback, it should always be run # before the application is eager-loaded (before user's jobs register their own callbacks) # See https://github.com/getsentry/sentry-ruby/issues/1249#issuecomment-853871871 for the detail explanation initializer "sentry.extend_active_job", before: :eager_load! do |app| From 36866c54ea67933c36a5d8ce2b52dae972e3edd1 Mon Sep 17 00:00:00 2001 From: Alexander Popov Date: Wed, 10 Jul 2024 13:27:56 +0300 Subject: [PATCH 07/96] Make links more specific in gemspecs (#2311) * Make links in `sentry-rails` gemspec more accurate 1. Add subdir with the gem. 2. Add specific version. * Tranform gemspec metadata to a single Hash for `sentry-rails` * Add bug tracker and documentation links into `sentry-rails` gemspec * Make the same URI changes for `sentry-ruby` gemspec * Make the same URI changes for `sentry-sidekiq` gemspec * Make the same URI changes for `sentry-rescue` gemspec * Make the same URI changes for `sentry-opentelemetry` gemspec * Make the same URI changes for `sentry-delayed_job` gemspec * fix changelogs --------- Co-authored-by: Neel Shah --- sentry-delayed_job/sentry-delayed_job.gemspec | 14 ++++++++++---- sentry-opentelemetry/sentry-opentelemetry.gemspec | 14 ++++++++++---- sentry-rails/sentry-rails.gemspec | 14 ++++++++++---- sentry-resque/sentry-resque.gemspec | 14 ++++++++++---- sentry-ruby/sentry-ruby.gemspec | 14 ++++++++++---- sentry-sidekiq/sentry-sidekiq.gemspec | 14 ++++++++++---- 6 files changed, 60 insertions(+), 24 deletions(-) diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index 04f3f0259..26d9071a7 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -7,16 +7,22 @@ Gem::Specification.new do |spec| spec.description = spec.summary = "A gem that provides DelayedJob integration for the Sentry error logger" spec.email = "accounts@sentry.io" spec.license = 'MIT' - spec.homepage = "https://github.com/getsentry/sentry-ruby" spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md" + github_root_uri = 'https://github.com/getsentry/sentry-ruby' + spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" + + spec.metadata = { + "homepage_uri" => spec.homepage, + "source_code_uri" => spec.homepage, + "changelog_uri" => "#{github_root_uri}/blob/#{spec.version}/CHANGELOG.md", + "bug_tracker_uri" => "#{github_root_uri}/issues", + "documentation_uri" => "http://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + } spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index b1cefe550..7897c62f4 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -9,16 +9,22 @@ Gem::Specification.new do |spec| spec.description = spec.summary = "A gem that provides OpenTelemetry integration for the Sentry error logger" spec.email = "accounts@sentry.io" spec.license = 'MIT' - spec.homepage = "https://github.com/getsentry/sentry-ruby" spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md" + github_root_uri = 'https://github.com/getsentry/sentry-ruby' + spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" + + spec.metadata = { + "homepage_uri" => spec.homepage, + "source_code_uri" => spec.homepage, + "changelog_uri" => "#{github_root_uri}/blob/#{spec.version}/CHANGELOG.md", + "bug_tracker_uri" => "#{github_root_uri}/issues", + "documentation_uri" => "http://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + } spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 3e5f88842..1f9b74261 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -7,16 +7,22 @@ Gem::Specification.new do |spec| spec.description = spec.summary = "A gem that provides Rails integration for the Sentry error logger" spec.email = "accounts@sentry.io" spec.license = 'MIT' - spec.homepage = "https://github.com/getsentry/sentry-ruby" spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md" + github_root_uri = 'https://github.com/getsentry/sentry-ruby' + spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" + + spec.metadata = { + "homepage_uri" => spec.homepage, + "source_code_uri" => spec.homepage, + "changelog_uri" => "#{github_root_uri}/blob/#{spec.version}/CHANGELOG.md", + "bug_tracker_uri" => "#{github_root_uri}/issues", + "documentation_uri" => "http://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + } spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index a2c118012..36ef2b10e 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -7,16 +7,22 @@ Gem::Specification.new do |spec| spec.description = spec.summary = "A gem that provides Resque integration for the Sentry error logger" spec.email = "accounts@sentry.io" spec.license = 'MIT' - spec.homepage = "https://github.com/getsentry/sentry-ruby" spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md" + github_root_uri = 'https://github.com/getsentry/sentry-ruby' + spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" + + spec.metadata = { + "homepage_uri" => spec.homepage, + "source_code_uri" => spec.homepage, + "changelog_uri" => "#{github_root_uri}/blob/#{spec.version}/CHANGELOG.md", + "bug_tracker_uri" => "#{github_root_uri}/issues", + "documentation_uri" => "http://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + } spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } diff --git a/sentry-ruby/sentry-ruby.gemspec b/sentry-ruby/sentry-ruby.gemspec index 77e9711ec..31fa0b581 100644 --- a/sentry-ruby/sentry-ruby.gemspec +++ b/sentry-ruby/sentry-ruby.gemspec @@ -7,16 +7,22 @@ Gem::Specification.new do |spec| spec.description = spec.summary = "A gem that provides a client interface for the Sentry error logger" spec.email = "accounts@sentry.io" spec.license = 'MIT' - spec.homepage = "https://github.com/getsentry/sentry-ruby" spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md" + github_root_uri = 'https://github.com/getsentry/sentry-ruby' + spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" + + spec.metadata = { + "homepage_uri" => spec.homepage, + "source_code_uri" => spec.homepage, + "changelog_uri" => "#{github_root_uri}/blob/#{spec.version}/CHANGELOG.md", + "bug_tracker_uri" => "#{github_root_uri}/issues", + "documentation_uri" => "http://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + } spec.require_paths = ["lib"] diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index 191ec4f9b..be8448fa7 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -7,16 +7,22 @@ Gem::Specification.new do |spec| spec.description = spec.summary = "A gem that provides Sidekiq integration for the Sentry error logger" spec.email = "accounts@sentry.io" spec.license = 'MIT' - spec.homepage = "https://github.com/getsentry/sentry-ruby" spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md" + github_root_uri = 'https://github.com/getsentry/sentry-ruby' + spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" + + spec.metadata = { + "homepage_uri" => spec.homepage, + "source_code_uri" => spec.homepage, + "changelog_uri" => "#{github_root_uri}/blob/#{spec.version}/CHANGELOG.md", + "bug_tracker_uri" => "#{github_root_uri}/issues", + "documentation_uri" => "http://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + } spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } From 89f371f2f593aeba70c1d135e5562ebfc243553f Mon Sep 17 00:00:00 2001 From: moznion Date: Tue, 23 Jul 2024 18:27:31 +0900 Subject: [PATCH 08/96] =?UTF-8?q?Suppress=20the=20unnecessary=20=E2=80=9Cu?= =?UTF-8?q?nsupported=20options=20notice=E2=80=9D=20(#2349)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Suppress the unnecessary “unsupported options notice” In `Scope#update_from_options()`, the method strips key-value pairs from the `options` according to its parameters. When all keys in `options` are supported, it still logs an “unsupported options notice” for an empty `unsupported_option_keys` value with empty array literal in `Sentry::Hub#capture_event`, like: "Options [] are not supported and will not be applied to the event." Example: When calling `subject.capture_event(event, level: 'DEBUG')`, the `capture_event` method should handle the options like this: # In this case, options == {:level=>'DEBUG'} unsupported_option_keys = scope.update_from_options(**options) # unsupported_option_keys should be [], but the following debug log will be shown # like "Options [] are not supported and will not be applied to the event." configuration.log_debug <<~MSG Options #{unsupported_option_keys} are not supported and will not be applied to the event. You may want to set them under the `extra` option. MSG This patch changes the logic to check whether `unsupported_option_keys` is empty before logging the notice, thus suppressing unnecessary logs. Signed-off-by: moznion * Update sentry-ruby/spec/sentry/hub_spec.rb --------- Signed-off-by: moznion Co-authored-by: Stan Lo --- CHANGELOG.md | 4 ++++ sentry-ruby/lib/sentry/hub.rb | 10 ++++++---- sentry-ruby/spec/sentry/hub_spec.rb | 8 ++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 763734e42..856d68d0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ - Use Concurrent.usable_processor_count when it is available ([#2339](https://github.com/getsentry/sentry-ruby/pull/2339)) +### Bug Fixes + +- Suppress the unnecessary “unsupported options notice” ([#2349](https://github.com/getsentry/sentry-ruby/pull/2349)) + ## 5.18.1 ### Bug Fixes diff --git a/sentry-ruby/lib/sentry/hub.rb b/sentry-ruby/lib/sentry/hub.rb index d0615ee28..66d0b379a 100644 --- a/sentry-ruby/lib/sentry/hub.rb +++ b/sentry-ruby/lib/sentry/hub.rb @@ -195,10 +195,12 @@ def capture_event(event, **options, &block) elsif !options.empty? unsupported_option_keys = scope.update_from_options(**options) - configuration.log_debug <<~MSG - Options #{unsupported_option_keys} are not supported and will not be applied to the event. - You may want to set them under the `extra` option. - MSG + unless unsupported_option_keys.empty? + configuration.log_debug <<~MSG + Options #{unsupported_option_keys} are not supported and will not be applied to the event. + You may want to set them under the `extra` option. + MSG + end end event = current_client.capture_event(event, scope, hint) diff --git a/sentry-ruby/spec/sentry/hub_spec.rb b/sentry-ruby/spec/sentry/hub_spec.rb index 2448be413..6d06595aa 100644 --- a/sentry-ruby/spec/sentry/hub_spec.rb +++ b/sentry-ruby/spec/sentry/hub_spec.rb @@ -350,6 +350,14 @@ expect(string_io.string).to include("Options [:unsupported] are not supported and will not be applied to the event.") end + it "does not warn about unsupported options if all passed options are supported" do + expect do + subject.capture_event(event, level: 'DEBUG') + end.not_to raise_error + + expect(string_io.string).not_to include("Options [] are not supported and will not be applied to the event.") + end + context "when event is a transaction" do it "transaction.set_context merges and takes precedence over scope.set_context" do scope.set_context(:foo, { val: 42 }) From 18029e32b7d1a82b3fb52b9775c0c96a9555fd72 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Tue, 23 Jul 2024 13:13:47 +0100 Subject: [PATCH 09/96] `teardown_sentry_test` helper should clear global even processors too (#2342) * teardown_sentry_test helper should clear global even processors too * Update changelog * Don't fail fast on sentry-ruby jobs --- .github/workflows/sentry_ruby_test.yml | 1 + CHANGELOG.md | 1 + sentry-ruby/lib/sentry/test_helper.rb | 1 + sentry-ruby/spec/sentry/test_helper_spec.rb | 6 ++++++ 4 files changed, 9 insertions(+) diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index 2e6f64126..a154df326 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -26,6 +26,7 @@ jobs: name: Ruby ${{ matrix.ruby_version }} & Rack ${{ matrix.rack_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: ruby_version: ${{ fromJson(needs.ruby-versions.outputs.versions) }} rack_version: [2.0, 3.0] diff --git a/CHANGELOG.md b/CHANGELOG.md index 856d68d0c..c4d06b62a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Bug Fixes +- `teardown_sentry_test` helper should clear global even processors too ([#2342](https://github.com/getsentry/sentry-ruby/pull/2342)) - Suppress the unnecessary “unsupported options notice” ([#2349](https://github.com/getsentry/sentry-ruby/pull/2349)) ## 5.18.1 diff --git a/sentry-ruby/lib/sentry/test_helper.rb b/sentry-ruby/lib/sentry/test_helper.rb index 4d4987e92..7db34cbd2 100644 --- a/sentry-ruby/lib/sentry/test_helper.rb +++ b/sentry-ruby/lib/sentry/test_helper.rb @@ -50,6 +50,7 @@ def teardown_sentry_test if Sentry.get_current_hub.instance_variable_get(:@stack).size > 1 Sentry.get_current_hub.pop_scope end + Sentry::Scope.global_event_processors.clear end # @return [Transport] diff --git a/sentry-ruby/spec/sentry/test_helper_spec.rb b/sentry-ruby/spec/sentry/test_helper_spec.rb index 200356661..2753b9b64 100644 --- a/sentry-ruby/spec/sentry/test_helper_spec.rb +++ b/sentry-ruby/spec/sentry/test_helper_spec.rb @@ -127,6 +127,12 @@ expect(Sentry.get_current_scope.tags).to eq({}) end + it "clears global processors" do + Sentry.add_global_event_processor { |event| event } + teardown_sentry_test + expect(Sentry::Scope.global_event_processors).to eq([]) + end + context "when the configuration is mutated" do it "rolls back client changes" do Sentry.configuration.environment = "quack" From c16a0f2a028d1400b164020e619ce0988d25e5d1 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 23 Jul 2024 14:31:03 +0200 Subject: [PATCH 10/96] Don't overwrite ip_address if already set on user (#2350) --- CHANGELOG.md | 5 +++++ sentry-ruby/lib/sentry/event.rb | 4 +--- sentry-ruby/spec/sentry/event_spec.rb | 6 ++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4d06b62a..1b5cf6465 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Unreleased +### Bug Fixes + +- Don't overwrite `ip_address` if already set on `user` [#2350](https://github.com/getsentry/sentry-ruby/pull/2350) + - Fixes [#2347](https://github.com/getsentry/sentry-ruby/issues/2347) + ### Internal - Use Concurrent.usable_processor_count when it is available ([#2339](https://github.com/getsentry/sentry-ruby/pull/2339)) diff --git a/sentry-ruby/lib/sentry/event.rb b/sentry-ruby/lib/sentry/event.rb index 97777a1c9..b3fb5b275 100644 --- a/sentry-ruby/lib/sentry/event.rb +++ b/sentry-ruby/lib/sentry/event.rb @@ -104,9 +104,7 @@ def rack_env=(env) unless request || env.empty? add_request_interface(env) - if @send_default_pii - user[:ip_address] = calculate_real_ip_from_rack(env) - end + user[:ip_address] ||= calculate_real_ip_from_rack(env) if @send_default_pii if request_id = Utils::RequestId.read_from(env) tags[:request_id] = request_id diff --git a/sentry-ruby/spec/sentry/event_spec.rb b/sentry-ruby/spec/sentry/event_spec.rb index a5ca457e7..5eeb232f9 100644 --- a/sentry-ruby/spec/sentry/event_spec.rb +++ b/sentry-ruby/spec/sentry/event_spec.rb @@ -141,6 +141,12 @@ expect(event.to_hash[:user][:ip_address]).to eq("2.2.2.2") end + it "doesn't overwrite already set ip address" do + Sentry.set_user({ ip_address: "3.3.3.3" }) + Sentry.get_current_scope.apply_to_event(event) + expect(event.to_hash[:user][:ip_address]).to eq("3.3.3.3") + end + context "with config.trusted_proxies = [\"2.2.2.2\"]" do before do Sentry.configuration.trusted_proxies = ["2.2.2.2"] From c785d0444ed77c9e8ffe675184e2a2442a526ca4 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 23 Jul 2024 15:19:04 +0200 Subject: [PATCH 11/96] Add client reports for span drop counts (#2346) --- CHANGELOG.md | 3 +- sentry-ruby/lib/sentry/client.rb | 23 +- sentry-ruby/lib/sentry/envelope.rb | 2 +- sentry-ruby/lib/sentry/transaction.rb | 1 + sentry-ruby/lib/sentry/transport.rb | 4 +- .../spec/sentry/client/event_sending_spec.rb | 223 ++++++++++++------ sentry-ruby/spec/sentry/envelope_spec.rb | 1 + sentry-ruby/spec/sentry/transaction_spec.rb | 2 + sentry-ruby/spec/sentry/transport_spec.rb | 4 +- sentry-ruby/spec/spec_helper.rb | 4 +- 10 files changed, 182 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b5cf6465..3bd7bc977 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ ### Internal -- Use Concurrent.usable_processor_count when it is available ([#2339](https://github.com/getsentry/sentry-ruby/pull/2339)) +- Use `Concurrent.usable_processor_count` when it is available ([#2339](https://github.com/getsentry/sentry-ruby/pull/2339)) +- Report dropped spans in Client Reports ([#2346](https://github.com/getsentry/sentry-ruby/pull/2346)) ### Bug Fixes diff --git a/sentry-ruby/lib/sentry/client.rb b/sentry-ruby/lib/sentry/client.rb index 608c4e1d5..6176508b7 100644 --- a/sentry-ruby/lib/sentry/client.rb +++ b/sentry-ruby/lib/sentry/client.rb @@ -55,19 +55,29 @@ def capture_event(event, scope, hint = {}) event_type = event.is_a?(Event) ? event.type : event["type"] data_category = Envelope::Item.data_category(event_type) + + is_transaction = event.is_a?(TransactionEvent) + spans_before = is_transaction ? event.spans.size : 0 + event = scope.apply_to_event(event, hint) if event.nil? log_debug("Discarded event because one of the event processors returned nil") transport.record_lost_event(:event_processor, data_category) + transport.record_lost_event(:event_processor, 'span', num: spans_before + 1) if is_transaction return + elsif is_transaction + spans_delta = spans_before - event.spans.size + transport.record_lost_event(:event_processor, 'span', num: spans_delta) if spans_delta > 0 end if async_block = configuration.async dispatch_async_event(async_block, event, hint) elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true) - queued = dispatch_background_event(event, hint) - transport.record_lost_event(:queue_overflow, data_category) unless queued + unless dispatch_background_event(event, hint) + transport.record_lost_event(:queue_overflow, data_category) + transport.record_lost_event(:queue_overflow, 'span', num: spans_before + 1) if is_transaction + end else send_event(event, hint) end @@ -168,6 +178,7 @@ def event_from_transaction(transaction) def send_event(event, hint = nil) event_type = event.is_a?(Event) ? event.type : event["type"] data_category = Envelope::Item.data_category(event_type) + spans_before = event.is_a?(TransactionEvent) ? event.spans.size : 0 if event_type != TransactionEvent::TYPE && configuration.before_send event = configuration.before_send.call(event, hint) @@ -184,8 +195,13 @@ def send_event(event, hint = nil) if event.nil? log_debug("Discarded event because before_send_transaction returned nil") - transport.record_lost_event(:before_send, data_category) + transport.record_lost_event(:before_send, 'transaction') + transport.record_lost_event(:before_send, 'span', num: spans_before + 1) return + else + spans_after = event.is_a?(TransactionEvent) ? event.spans.size : 0 + spans_delta = spans_before - spans_after + transport.record_lost_event(:before_send, 'span', num: spans_delta) if spans_delta > 0 end end @@ -196,6 +212,7 @@ def send_event(event, hint = nil) rescue => e log_error("Event sending failed", e, debug: configuration.debug) transport.record_lost_event(:network_error, data_category) + transport.record_lost_event(:network_error, 'span', num: spans_before + 1) if event.is_a?(TransactionEvent) raise end diff --git a/sentry-ruby/lib/sentry/envelope.rb b/sentry-ruby/lib/sentry/envelope.rb index 96bb83beb..51220a062 100644 --- a/sentry-ruby/lib/sentry/envelope.rb +++ b/sentry-ruby/lib/sentry/envelope.rb @@ -21,7 +21,7 @@ def type # rate limits and client reports use the data_category rather than envelope item type def self.data_category(type) case type - when 'session', 'attachment', 'transaction', 'profile' then type + when 'session', 'attachment', 'transaction', 'profile', 'span' then type when 'sessions' then 'session' when 'check_in' then 'monitor' when 'statsd', 'metric_meta' then 'metric_bucket' diff --git a/sentry-ruby/lib/sentry/transaction.rb b/sentry-ruby/lib/sentry/transaction.rb index 456b49e74..89d169512 100644 --- a/sentry-ruby/lib/sentry/transaction.rb +++ b/sentry-ruby/lib/sentry/transaction.rb @@ -266,6 +266,7 @@ def finish(hub: nil, end_timestamp: nil) is_backpressure = Sentry.backpressure_monitor&.downsample_factor&.positive? reason = is_backpressure ? :backpressure : :sample_rate hub.current_client.transport.record_lost_event(reason, 'transaction') + hub.current_client.transport.record_lost_event(reason, 'span') end end diff --git a/sentry-ruby/lib/sentry/transport.rb b/sentry-ruby/lib/sentry/transport.rb index 564734791..acef83de0 100644 --- a/sentry-ruby/lib/sentry/transport.rb +++ b/sentry-ruby/lib/sentry/transport.rb @@ -151,11 +151,11 @@ def envelope_from_event(event) envelope end - def record_lost_event(reason, data_category) + def record_lost_event(reason, data_category, num: 1) return unless @send_client_reports return unless CLIENT_REPORT_REASONS.include?(reason) - @discarded_events[[reason, data_category]] += 1 + @discarded_events[[reason, data_category]] += num end def flush diff --git a/sentry-ruby/spec/sentry/client/event_sending_spec.rb b/sentry-ruby/spec/sentry/client/event_sending_spec.rb index 86098a469..b1b1a041c 100644 --- a/sentry-ruby/spec/sentry/client/event_sending_spec.rb +++ b/sentry-ruby/spec/sentry/client/event_sending_spec.rb @@ -8,16 +8,23 @@ config.transport.transport_class = Sentry::DummyTransport end end - subject { Sentry::Client.new(configuration) } + subject(:client) { Sentry::Client.new(configuration) } let(:hub) do - Sentry::Hub.new(subject, Sentry::Scope.new) + Sentry::Hub.new(client, Sentry::Scope.new) end + let(:transaction) do + transaction = Sentry::Transaction.new(name: "test transaction", op: "rack.request", hub: hub) + 5.times { |i| transaction.with_child_span(description: "span_#{i}") { } } + transaction + end + let(:transaction_event) { client.event_from_transaction(transaction) } + describe "#capture_event" do let(:message) { "Test message" } let(:scope) { Sentry::Scope.new } - let(:event) { subject.event_from_message(message) } + let(:event) { client.event_from_message(message) } context "with sample_rate set" do before do @@ -28,26 +35,23 @@ context "with Event" do it "sends the event when it's sampled" do allow(Random).to receive(:rand).and_return(0.49) - subject.capture_event(event, scope) - expect(subject.transport.events.count).to eq(1) + client.capture_event(event, scope) + expect(client.transport.events.count).to eq(1) end it "doesn't send the event when it's not sampled" do allow(Random).to receive(:rand).and_return(0.51) - subject.capture_event(event, scope) - expect(subject.transport).to have_recorded_lost_event(:sample_rate, 'error') - expect(subject.transport.events.count).to eq(0) + client.capture_event(event, scope) + expect(client.transport).to have_recorded_lost_event(:sample_rate, 'error') + expect(client.transport.events.count).to eq(0) end end context "with TransactionEvent" do it "ignores the sampling" do - transaction_event = subject.event_from_transaction(Sentry::Transaction.new(hub: hub)) allow(Random).to receive(:rand).and_return(0.51) - - subject.capture_event(transaction_event, scope) - - expect(subject.transport.events.count).to eq(1) + client.capture_event(transaction_event, scope) + expect(client.transport.events.count).to eq(1) end end end @@ -55,7 +59,7 @@ context 'with config.async set' do let(:async_block) do lambda do |event| - subject.send_event(event) + client.send_event(event) end end @@ -69,10 +73,10 @@ it "executes the given block" do expect(async_block).to receive(:call).and_call_original - returned = subject.capture_event(event, scope) + returned = client.capture_event(event, scope) expect(returned).to be_a(Sentry::ErrorEvent) - expect(subject.transport.events.first).to eq(event.to_json_compatible) + expect(client.transport.events.first).to eq(event.to_json_compatible) end it "doesn't call the async block if not allow sending events" do @@ -80,7 +84,7 @@ expect(async_block).not_to receive(:call) - returned = subject.capture_event(event, scope) + returned = client.capture_event(event, scope) expect(returned).to eq(nil) end @@ -88,12 +92,12 @@ context "with to json conversion failed" do let(:logger) { ::Logger.new(string_io) } let(:string_io) { StringIO.new } - let(:event) { subject.event_from_message("Bad data '\x80\xF8'") } + let(:event) { client.event_from_message("Bad data '\x80\xF8'") } it "does not mask the exception" do configuration.logger = logger - subject.capture_event(event, scope) + client.capture_event(event, scope) expect(string_io.string).to include("Converting event (#{event.event_id}) to JSON compatible hash failed: source sequence is illegal/malformed utf-8") end @@ -103,10 +107,10 @@ let(:async_block) { nil } it "doesn't cause any issue" do - returned = subject.capture_event(event, scope, { background: false }) + returned = client.capture_event(event, scope, { background: false }) expect(returned).to be_a(Sentry::ErrorEvent) - expect(subject.transport.events.first).to eq(event) + expect(client.transport.events.first).to eq(event) end end @@ -114,17 +118,17 @@ let(:async_block) do lambda do |event, hint| event["tags"]["hint"] = hint - subject.send_event(event) + client.send_event(event) end end it "serializes hint and supplies it as the second argument" do expect(configuration.async).to receive(:call).and_call_original - returned = subject.capture_event(event, scope, { foo: "bar" }) + returned = client.capture_event(event, scope, { foo: "bar" }) expect(returned).to be_a(Sentry::ErrorEvent) - event = subject.transport.events.first + event = client.transport.events.first expect(event.dig("tags", "hint")).to eq({ "foo" => "bar" }) end end @@ -140,20 +144,20 @@ end it "sends events asynchronously" do - subject.capture_event(event, scope) + client.capture_event(event, scope) - expect(subject.transport.events.count).to eq(0) + expect(client.transport.events.count).to eq(0) sleep(0.2) - expect(subject.transport.events.count).to eq(1) + expect(client.transport.events.count).to eq(1) end context "with hint: { background: false }" do it "sends the event immediately" do - subject.capture_event(event, scope, { background: false }) + client.capture_event(event, scope, { background: false }) - expect(subject.transport.events.count).to eq(1) + expect(client.transport.events.count).to eq(1) end end @@ -161,48 +165,57 @@ it "sends the event immediately" do configuration.background_worker_threads = 0 - subject.capture_event(event, scope) + client.capture_event(event, scope) - expect(subject.transport.events.count).to eq(1) + expect(client.transport.events.count).to eq(1) end end - it "records queue overflow" do + it "records queue overflow for error event" do + allow(Sentry.background_worker).to receive(:perform).and_return(false) + + client.capture_event(event, scope) + expect(client.transport).to have_recorded_lost_event(:queue_overflow, 'error') + + expect(client.transport.events.count).to eq(0) + sleep(0.2) + expect(client.transport.events.count).to eq(0) + end + + it "records queue overflow for transaction event with span counts" do allow(Sentry.background_worker).to receive(:perform).and_return(false) - subject.capture_event(event, scope) - expect(subject.transport).to have_recorded_lost_event(:queue_overflow, 'error') + client.capture_event(transaction_event, scope) + expect(client.transport).to have_recorded_lost_event(:queue_overflow, 'transaction') + expect(client.transport).to have_recorded_lost_event(:queue_overflow, 'span', num: 6) - expect(subject.transport.events.count).to eq(0) + expect(client.transport.events.count).to eq(0) sleep(0.2) - expect(subject.transport.events.count).to eq(0) + expect(client.transport.events.count).to eq(0) end end end describe "#send_event" do let(:event_object) do - subject.event_from_exception(ZeroDivisionError.new("divided by 0")) - end - let(:transaction_event_object) do - subject.event_from_transaction(Sentry::Transaction.new(hub: hub)) + client.event_from_exception(ZeroDivisionError.new("divided by 0")) end shared_examples "Event in send_event" do context "when there's an exception" do before do - expect(subject.transport).to receive(:send_event).and_raise(Sentry::ExternalError.new("networking error")) + expect(client.transport).to receive(:send_event).and_raise(Sentry::ExternalError.new("networking error")) end it "raises the error" do expect do - subject.send_event(event) + client.send_event(event) end.to raise_error(Sentry::ExternalError, "networking error") end end it "sends data through the transport" do - expect(subject.transport).to receive(:send_event).with(event) - subject.send_event(event) + expect(client.transport).to receive(:send_event).with(event) + client.send_event(event) end it "applies before_send callback before sending the event" do @@ -216,7 +229,7 @@ event end - subject.send_event(event) + client.send_event(event) if event.is_a?(Sentry::Event) expect(event.tags[:called]).to eq(true) @@ -231,7 +244,7 @@ configuration.before_send_transaction = dbl expect(dbl).not_to receive(:call) - subject.send_event(event) + client.send_event(event) end end @@ -245,7 +258,7 @@ shared_examples "TransactionEvent in send_event" do it "sends data through the transport" do - subject.send_event(event) + client.send_event(event) end it "doesn't apply before_send to TransactionEvent" do @@ -253,7 +266,7 @@ raise "shouldn't trigger me" end - subject.send_event(event) + client.send_event(event) end it "applies before_send_transaction callback before sending the event" do @@ -267,7 +280,7 @@ event end - subject.send_event(event) + client.send_event(event) if event.is_a?(Sentry::Event) expect(event.tags[:called]).to eq(true) @@ -278,11 +291,11 @@ end it_behaves_like "TransactionEvent in send_event" do - let(:event) { transaction_event_object } + let(:event) { transaction_event } end it_behaves_like "TransactionEvent in send_event" do - let(:event) { transaction_event_object.to_json_compatible } + let(:event) { transaction_event.to_json_compatible } end end @@ -300,7 +313,7 @@ let(:message) { "Test message" } let(:scope) { Sentry::Scope.new } - let(:event) { subject.event_from_message(message) } + let(:event) { client.event_from_message(message) } describe "#capture_event" do around do |example| @@ -317,11 +330,35 @@ end it "discards the event and logs a info" do - expect(subject.capture_event(event, scope)).to be_nil + expect(client.capture_event(event, scope)).to be_nil - expect(subject.transport).to have_recorded_lost_event(:event_processor, 'error') expect(string_io.string).to match(/Discarded event because one of the event processors returned nil/) end + + it "records correct client report for error event" do + client.capture_event(event, scope) + expect(client.transport).to have_recorded_lost_event(:event_processor, 'error') + end + + it "records correct transaction and span client reports for transaction event" do + client.capture_event(transaction_event, scope) + expect(client.transport).to have_recorded_lost_event(:event_processor, 'transaction') + expect(client.transport).to have_recorded_lost_event(:event_processor, 'span', num: 6) + end + end + + context "when scope.apply_to_event modifies spans" do + before do + scope.add_event_processor do |event, hint| + 2.times { event.spans.pop } + event + end + end + + it "records correct span delta client report for transaction event" do + client.capture_event(transaction_event, scope) + expect(client.transport).to have_recorded_lost_event(:event_processor, 'span', num: 2) + end end context "when scope.apply_to_event fails" do @@ -332,7 +369,7 @@ end it "swallows the event and logs the failure" do - expect(subject.capture_event(event, scope)).to be_nil + expect(client.capture_event(event, scope)).to be_nil expect(string_io.string).to match(/Event capturing failed: TypeError/) expect(string_io.string).not_to match(__FILE__) @@ -343,7 +380,7 @@ configuration.debug = true end it "logs the error with backtrace" do - expect(subject.capture_event(event, scope)).to be_nil + expect(client.capture_event(event, scope)).to be_nil expect(string_io.string).to match(/Event capturing failed: TypeError/) expect(string_io.string).to match(__FILE__) @@ -358,9 +395,8 @@ end it "swallows and logs Sentry::ExternalError (caused by transport's networking error)" do - expect(subject.capture_event(event, scope)).to be_nil + expect(client.capture_event(event, scope)).to be_nil - expect(subject.transport).to have_recorded_lost_event(:network_error, 'error') expect(string_io.string).to match(/Event sending failed: Failed to open TCP connection/) expect(string_io.string).to match(/Event capturing failed: Failed to open TCP connection/) end @@ -368,10 +404,21 @@ it "swallows and logs errors caused by the user (like in before_send)" do configuration.before_send = ->(_, _) { raise TypeError } - expect(subject.capture_event(event, scope)).to be_nil + expect(client.capture_event(event, scope)).to be_nil expect(string_io.string).to match(/Event sending failed: TypeError/) end + + it "captures client report for error event" do + client.capture_event(event, scope) + expect(client.transport).to have_recorded_lost_event(:network_error, 'error') + end + + it "captures client report for transaction event with span counts" do + client.capture_event(transaction_event, scope) + expect(client.transport).to have_recorded_lost_event(:network_error, 'transaction') + expect(client.transport).to have_recorded_lost_event(:network_error, 'span', num: 6) + end end context "when sending events in background causes error", retry: 3 do @@ -380,32 +427,44 @@ end it "swallows and logs Sentry::ExternalError (caused by transport's networking error)" do - expect(subject.capture_event(event, scope)).to be_a(Sentry::ErrorEvent) + expect(client.capture_event(event, scope)).to be_a(Sentry::ErrorEvent) sleep(0.2) - expect(subject.transport).to have_recorded_lost_event(:network_error, 'error') expect(string_io.string).to match(/Event sending failed: Failed to open TCP connection/) end it "swallows and logs errors caused by the user (like in before_send)" do configuration.before_send = ->(_, _) { raise TypeError } - expect(subject.capture_event(event, scope)).to be_a(Sentry::ErrorEvent) + expect(client.capture_event(event, scope)).to be_a(Sentry::ErrorEvent) sleep(0.2) expect(string_io.string).to match(/Event sending failed: TypeError/) end + + it "captures client report for error event" do + client.capture_event(event, scope) + sleep(0.2) + expect(client.transport).to have_recorded_lost_event(:network_error, 'error') + end + + it "captures client report for transaction event with span counts" do + client.capture_event(transaction_event, scope) + sleep(0.2) + expect(client.transport).to have_recorded_lost_event(:network_error, 'transaction') + expect(client.transport).to have_recorded_lost_event(:network_error, 'span', num: 6) + end end context "when config.async causes error" do before do - expect(subject).to receive(:send_event) + expect(client).to receive(:send_event) end it "swallows Redis related error and send the event synchronizely" do configuration.async = ->(_, _) { raise Redis::ConnectionError } - subject.capture_event(event, scope) + client.capture_event(event, scope) expect(string_io.string).to match(/Async event sending failed: Redis::ConnectionError/) end @@ -413,7 +472,7 @@ it "swallows and logs the exception" do configuration.async = ->(_, _) { raise TypeError } - subject.capture_event(event, scope) + client.capture_event(event, scope) expect(string_io.string).to match(/Async event sending failed: TypeError/) end @@ -424,7 +483,7 @@ context "error happens when sending the event" do it "raises the error" do expect do - subject.send_event(event) + client.send_event(event) end.to raise_error(Sentry::ExternalError) expect(string_io.string).to match(/Event sending failed: Failed to open TCP connection/) @@ -440,7 +499,7 @@ it "raises the error" do expect do - subject.send_event(event) + client.send_event(event) end.to raise_error(TypeError) expect(string_io.string).to match(/Event sending failed: TypeError/) @@ -453,7 +512,7 @@ it "logs the error with backtrace" do expect do - subject.send_event(event) + client.send_event(event) end.to raise_error(TypeError) expect(string_io.string).to match(/Event sending failed: TypeError/) @@ -469,9 +528,9 @@ end end - it "records lost event" do - subject.send_event(event) - expect(subject.transport).to have_recorded_lost_event(:before_send, 'error') + it "records lost error event" do + client.send_event(event) + expect(client.transport).to have_recorded_lost_event(:before_send, 'error') end end @@ -482,10 +541,24 @@ end end - it "records lost event" do - transaction_event = subject.event_from_transaction(Sentry::Transaction.new(hub: hub)) - subject.send_event(transaction_event) - expect(subject.transport).to have_recorded_lost_event(:before_send, 'transaction') + it "records lost transaction with span counts client reports" do + client.send_event(transaction_event) + expect(client.transport).to have_recorded_lost_event(:before_send, 'transaction') + expect(client.transport).to have_recorded_lost_event(:before_send, 'span', num: 6) + end + end + + context "before_send_transaction modifies spans" do + before do + configuration.before_send_transaction = lambda do |event, _hint| + 2.times { event.spans.pop } + event + end + end + + it "records lost span delta client reports" do + expect { client.send_event(transaction_event) }.to raise_error(Sentry::ExternalError) + expect(client.transport).to have_recorded_lost_event(:before_send, 'span', num: 2) end end end diff --git a/sentry-ruby/spec/sentry/envelope_spec.rb b/sentry-ruby/spec/sentry/envelope_spec.rb index c12ee3052..8936c7707 100644 --- a/sentry-ruby/spec/sentry/envelope_spec.rb +++ b/sentry-ruby/spec/sentry/envelope_spec.rb @@ -7,6 +7,7 @@ ['sessions', 'session'], ['attachment', 'attachment'], ['transaction', 'transaction'], + ['span', 'span'], ['profile', 'profile'], ['check_in', 'monitor'], ['statsd', 'metric_bucket'], diff --git a/sentry-ruby/spec/sentry/transaction_spec.rb b/sentry-ruby/spec/sentry/transaction_spec.rb index 6dafc1371..effb249f1 100644 --- a/sentry-ruby/spec/sentry/transaction_spec.rb +++ b/sentry-ruby/spec/sentry/transaction_spec.rb @@ -494,6 +494,7 @@ it "records lost event with reason sample_rate" do subject.finish expect(Sentry.get_current_client.transport).to have_recorded_lost_event(:sample_rate, 'transaction') + expect(Sentry.get_current_client.transport).to have_recorded_lost_event(:sample_rate, 'span') end end @@ -514,6 +515,7 @@ subject.finish expect(Sentry.get_current_client.transport).to have_recorded_lost_event(:backpressure, 'transaction') + expect(Sentry.get_current_client.transport).to have_recorded_lost_event(:backpressure, 'span') end end diff --git a/sentry-ruby/spec/sentry/transport_spec.rb b/sentry-ruby/spec/sentry/transport_spec.rb index 35ebed86a..73b22d91d 100644 --- a/sentry-ruby/spec/sentry/transport_spec.rb +++ b/sentry-ruby/spec/sentry/transport_spec.rb @@ -153,6 +153,7 @@ before do 5.times { subject.record_lost_event(:ratelimit_backoff, 'error') } 3.times { subject.record_lost_event(:queue_overflow, 'transaction') } + 2.times { subject.record_lost_event(:network_error, 'span', num: 5) } end it "incudes client report in envelope" do @@ -170,7 +171,8 @@ timestamp: Time.now.utc.iso8601, discarded_events: [ { reason: :ratelimit_backoff, category: 'error', quantity: 5 }, - { reason: :queue_overflow, category: 'transaction', quantity: 3 } + { reason: :queue_overflow, category: 'transaction', quantity: 3 }, + { reason: :network_error, category: 'span', quantity: 10 } ] }.to_json ) diff --git a/sentry-ruby/spec/spec_helper.rb b/sentry-ruby/spec/spec_helper.rb index 1d4a6ff15..6ba0ccee0 100644 --- a/sentry-ruby/spec/spec_helper.rb +++ b/sentry-ruby/spec/spec_helper.rb @@ -50,9 +50,9 @@ skip("skip rack related tests") unless defined?(Rack) end - RSpec::Matchers.define :have_recorded_lost_event do |reason, data_category| + RSpec::Matchers.define :have_recorded_lost_event do |reason, data_category, num: 1| match do |transport| - expect(transport.discarded_events[[reason, data_category]]).to be > 0 + expect(transport.discarded_events[[reason, data_category]]).to eq(num) end end end From 7bcf2d97c21e4debecd1e7bd1e424bb41dcc0a56 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 23 Jul 2024 15:30:04 +0200 Subject: [PATCH 12/96] meta: Changelog for 5.18.2 (#2353) --- CHANGELOG.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bd7bc977..f581a8b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,17 @@ -## Unreleased +## 5.18.2 ### Bug Fixes - Don't overwrite `ip_address` if already set on `user` [#2350](https://github.com/getsentry/sentry-ruby/pull/2350) - Fixes [#2347](https://github.com/getsentry/sentry-ruby/issues/2347) +- `teardown_sentry_test` helper should clear global even processors too ([#2342](https://github.com/getsentry/sentry-ruby/pull/2342)) +- Suppress the unnecessary “unsupported options notice” ([#2349](https://github.com/getsentry/sentry-ruby/pull/2349)) ### Internal - Use `Concurrent.usable_processor_count` when it is available ([#2339](https://github.com/getsentry/sentry-ruby/pull/2339)) - Report dropped spans in Client Reports ([#2346](https://github.com/getsentry/sentry-ruby/pull/2346)) -### Bug Fixes - -- `teardown_sentry_test` helper should clear global even processors too ([#2342](https://github.com/getsentry/sentry-ruby/pull/2342)) -- Suppress the unnecessary “unsupported options notice” ([#2349](https://github.com/getsentry/sentry-ruby/pull/2349)) - ## 5.18.1 ### Bug Fixes From cdf8a4aa20b00b5e83abce9140bc975ee7c93628 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Tue, 23 Jul 2024 13:31:51 +0000 Subject: [PATCH 13/96] release: 5.18.2 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index 47d717991..983cfafda 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -1,5 +1,5 @@ module Sentry module DelayedJob - VERSION = "5.18.1" + VERSION = "5.18.2" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index 26d9071a7..d8a44d4cb 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.1" + spec.add_dependency "sentry-ruby", "~> 5.18.2" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index 72ef9303b..daf8d6bd7 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.18.1" + VERSION = "5.18.2" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 7897c62f4..28f6692a1 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.1" + spec.add_dependency "sentry-ruby", "~> 5.18.2" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index 4a03e8451..ab8ce6bd6 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -1,5 +1,5 @@ module Sentry module Rails - VERSION = "5.18.1" + VERSION = "5.18.2" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 1f9b74261..30c09390c 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -29,5 +29,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.18.1" + spec.add_dependency "sentry-ruby", "~> 5.18.2" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index 87b3174a2..a21a6180c 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -1,5 +1,5 @@ module Sentry module Resque - VERSION = "5.18.1" + VERSION = "5.18.2" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 36ef2b10e..34796ee10 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.1" + spec.add_dependency "sentry-ruby", "~> 5.18.2" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index 3f5398559..d37911dac 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.18.1" + VERSION = "5.18.2" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index ef6100b35..dfeec9914 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -1,5 +1,5 @@ module Sentry module Sidekiq - VERSION = "5.18.1" + VERSION = "5.18.2" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index be8448fa7..cace76b46 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.1" + spec.add_dependency "sentry-ruby", "~> 5.18.2" spec.add_dependency "sidekiq", ">= 3.0" end From 09f348e2b21fb17ea79ee6403e16f3487dcde274 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 26 Jul 2024 13:07:16 +0200 Subject: [PATCH 14/96] Support for tracing Faraday requests (#2345) * Support for Faraday instrumentation * Require sentry/faraday by default * Update CHANGELOG.md * Use prepend in Faraday patch * Simplify inserting faraday instrumentation * Ensure none of the spans come from faraday when net/http is used --- CHANGELOG.md | 8 + sentry-ruby/Gemfile | 1 + sentry-ruby/lib/sentry-ruby.rb | 1 + sentry-ruby/lib/sentry/faraday.rb | 111 ++++++++++ sentry-ruby/spec/sentry/faraday_spec.rb | 257 ++++++++++++++++++++++++ 5 files changed, 378 insertions(+) create mode 100644 sentry-ruby/lib/sentry/faraday.rb create mode 100644 sentry-ruby/spec/sentry/faraday_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index f581a8b45..7a04bb011 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## Unreleased + +### Features + +- Support for tracing Faraday requests ([#2345](https://github.com/getsentry/sentry-ruby/pull/2345)) + - Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795) + - Please note that the Faraday instrumentation has some limitations in case of async requests: https://github.com/lostisland/faraday/issues/1381 + ## 5.18.2 ### Bug Fixes diff --git a/sentry-ruby/Gemfile b/sentry-ruby/Gemfile index 9c7524dd1..c6e1db011 100644 --- a/sentry-ruby/Gemfile +++ b/sentry-ruby/Gemfile @@ -24,5 +24,6 @@ gem "benchmark-memory" gem "yard", github: "lsegal/yard" gem "webrick" +gem "faraday" eval_gemfile File.expand_path("../Gemfile", __dir__) diff --git a/sentry-ruby/lib/sentry-ruby.rb b/sentry-ruby/lib/sentry-ruby.rb index a48906925..dd59d6e67 100644 --- a/sentry-ruby/lib/sentry-ruby.rb +++ b/sentry-ruby/lib/sentry-ruby.rb @@ -601,3 +601,4 @@ def utc_now require "sentry/redis" require "sentry/puma" require "sentry/graphql" +require "sentry/faraday" diff --git a/sentry-ruby/lib/sentry/faraday.rb b/sentry-ruby/lib/sentry/faraday.rb new file mode 100644 index 000000000..e2608cd97 --- /dev/null +++ b/sentry-ruby/lib/sentry/faraday.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +module Sentry + module Faraday + OP_NAME = "http.client" + SPAN_ORIGIN = "auto.http.faraday" + BREADCRUMB_CATEGORY = "http" + + module Connection + # Since there's no way to preconfigure Faraday connections and add our instrumentation + # by default, we need to extend the connection constructor and do it there + # + # @see https://lostisland.github.io/faraday/#/customization/index?id=configuration + def initialize(url = nil, options = nil) + super + + # Ensure that we attach instrumentation only if the adapter is not net/http + # because if is is, then the net/http instrumentation will take care of it + if builder.adapter.name != "Faraday::Adapter::NetHttp" + # Make sure that it's going to be the first middleware so that it can capture + # the entire request processing involving other middlewares + builder.insert(0, ::Faraday::Request::Instrumentation, name: OP_NAME, instrumenter: Instrumenter.new) + end + end + end + + class Instrumenter + attr_reader :configuration + + def initialize + @configuration = Sentry.configuration + end + + def instrument(op_name, env, &block) + return unless Sentry.initialized? + + Sentry.with_child_span(op: op_name, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |sentry_span| + request_info = extract_request_info(env) + + if propagate_trace?(request_info[:url]) + set_propagation_headers(env[:request_headers]) + end + + res = block.call + + if record_sentry_breadcrumb? + record_sentry_breadcrumb(request_info, res) + end + + if sentry_span + sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}") + sentry_span.set_data(Span::DataConventions::URL, request_info[:url]) + sentry_span.set_data(Span::DataConventions::HTTP_METHOD, request_info[:method]) + sentry_span.set_data(Span::DataConventions::HTTP_QUERY, request_info[:query]) if request_info[:query] + sentry_span.set_data(Span::DataConventions::HTTP_STATUS_CODE, res.status) + end + + res + end + end + + private + + def extract_request_info(env) + url = env[:url].scheme + "://" + env[:url].host + env[:url].path + result = { method: env[:method].to_s.upcase, url: url } + + if configuration.send_default_pii + result[:query] = env[:url].query + result[:body] = env[:body] + end + + result + end + + def record_sentry_breadcrumb(request_info, res) + crumb = Sentry::Breadcrumb.new( + level: :info, + category: BREADCRUMB_CATEGORY, + type: :info, + data: { + status: res.status, + **request_info + } + ) + + Sentry.add_breadcrumb(crumb) + end + + def record_sentry_breadcrumb? + configuration.breadcrumbs_logger.include?(:http_logger) + end + + def propagate_trace?(url) + url && + configuration.propagate_traces && + configuration.trace_propagation_targets.any? { |target| url.match?(target) } + end + + def set_propagation_headers(headers) + Sentry.get_trace_propagation_headers&.each { |k, v| headers[k] = v } + end + end + end +end + +Sentry.register_patch(:faraday) do + if defined?(::Faraday) + ::Faraday::Connection.prepend(Sentry::Faraday::Connection) + end +end diff --git a/sentry-ruby/spec/sentry/faraday_spec.rb b/sentry-ruby/spec/sentry/faraday_spec.rb new file mode 100644 index 000000000..abb63ddb5 --- /dev/null +++ b/sentry-ruby/spec/sentry/faraday_spec.rb @@ -0,0 +1,257 @@ +require "faraday" +require_relative "../spec_helper" + +RSpec.describe Sentry::Faraday do + before(:all) do + perform_basic_setup do |config| + config.enabled_patches << :faraday + config.traces_sample_rate = 1.0 + config.logger = ::Logger.new(StringIO.new) + end + end + + after(:all) do + Sentry.configuration.enabled_patches = Sentry::Configuration::DEFAULT_PATCHES + end + + context "with tracing enabled" do + let(:http) do + Faraday.new(url) do |f| + f.request :json + + f.adapter Faraday::Adapter::Test do |stub| + stub.get("/test") do + [200, { "Content-Type" => "text/html" }, "

hello world

"] + end + end + end + end + + let(:url) { "http://example.com" } + + it "records the request's span" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + _response = http.get("/test") + + request_span = transaction.span_recorder.spans.last + + expect(request_span.op).to eq("http.client") + expect(request_span.origin).to eq("auto.http.faraday") + expect(request_span.start_timestamp).not_to be_nil + expect(request_span.timestamp).not_to be_nil + expect(request_span.start_timestamp).not_to eq(request_span.timestamp) + expect(request_span.description).to eq("GET http://example.com/test") + + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "http://example.com/test", + "http.request.method" => "GET" + }) + end + end + + context "with config.send_default_pii = true" do + let(:http) do + Faraday.new(url) do |f| + f.adapter Faraday::Adapter::Test do |stub| + stub.get("/test") do + [200, { "Content-Type" => "text/html" }, "

hello world

"] + end + + stub.post("/test") do + [200, { "Content-Type" => "application/json" }, { hello: "world" }.to_json] + end + end + end + end + + let(:url) { "http://example.com" } + + before do + Sentry.configuration.send_default_pii = true + Sentry.configuration.breadcrumbs_logger = [:http_logger] + end + + it "records the request's span with query string in data" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + _response = http.get("/test?foo=bar") + + request_span = transaction.span_recorder.spans.last + + expect(request_span.description).to eq("GET http://example.com/test") + + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "http://example.com/test", + "http.request.method" => "GET", + "http.query" => "foo=bar" + }) + end + + it "records breadcrumbs" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + _response = http.get("/test?foo=bar") + + transaction.span_recorder.spans.last + + crumb = Sentry.get_current_scope.breadcrumbs.peek + + expect(crumb.category).to eq("http") + expect(crumb.data[:status]).to eq(200) + expect(crumb.data[:method]).to eq("GET") + expect(crumb.data[:url]).to eq("http://example.com/test") + expect(crumb.data[:query]).to eq("foo=bar") + expect(crumb.data[:body]).to be(nil) + end + + it "records POST request body" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + body = { foo: "bar" }.to_json + _response = http.post("/test?foo=bar", body, "Content-Type" => "application/json") + + request_span = transaction.span_recorder.spans.last + + expect(request_span.description).to eq("POST http://example.com/test") + + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "http://example.com/test", + "http.request.method" => "POST", + "http.query" => "foo=bar" + }) + + crumb = Sentry.get_current_scope.breadcrumbs.peek + + expect(crumb.data[:body]).to eq(body) + end + + context "with custom trace_propagation_targets" do + let(:http) do + Faraday.new(url) do |f| + f.adapter Faraday::Adapter::Test do |stub| + stub.get("/test") do + [200, { "Content-Type" => "text/html" }, "

hello world

"] + end + end + end + end + + before do + Sentry.configuration.trace_propagation_targets = ["example.com", /foobar.org\/api\/v2/] + end + + context "when the request is not to the same target" do + let(:url) { "http://another.site" } + + it "doesn't add sentry headers to outgoing requests to different target" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + response = http.get("/test") + + request_span = transaction.span_recorder.spans.last + + expect(request_span.description).to eq("GET #{url}/test") + + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "#{url}/test", + "http.request.method" => "GET" + }) + + expect(response.headers.key?("sentry-trace")).to eq(false) + expect(response.headers.key?("baggage")).to eq(false) + end + end + + context "when the request is to the same target" do + let(:url) { "http://example.com" } + + before do + Sentry.configuration.trace_propagation_targets = ["example.com"] + end + + it "adds sentry headers to outgoing requests" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + response = http.get("/test") + + request_span = transaction.span_recorder.spans.last + + expect(request_span.description).to eq("GET #{url}/test") + + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "#{url}/test", + "http.request.method" => "GET" + }) + + expect(response.env.request_headers.key?("sentry-trace")).to eq(true) + expect(response.env.request_headers.key?("baggage")).to eq(true) + end + end + + context "when the request's url configured target regexp" do + let(:url) { "http://example.com" } + + before do + Sentry.configuration.trace_propagation_targets = [/example/] + end + + it "adds sentry headers to outgoing requests" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + response = http.get("/test") + + request_span = transaction.span_recorder.spans.last + + expect(request_span.description).to eq("GET #{url}/test") + + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "#{url}/test", + "http.request.method" => "GET" + }) + + expect(response.env.request_headers.key?("sentry-trace")).to eq(true) + expect(response.env.request_headers.key?("baggage")).to eq(true) + end + end + end + end + + context "when adapter is net/http" do + let(:http) do + Faraday.new(url) do |f| + f.request :json + f.adapter :net_http + end + end + + let(:url) { "http://example.com" } + + it "skips instrumentation" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + _response = http.get("/test") + + request_span = transaction.span_recorder.spans.last + + expect(request_span.op).to eq("http.client") + expect(request_span.origin).to eq("auto.http.net_http") + + expect(transaction.span_recorder.spans.map(&:origin)).not_to include("auto.http.faraday") + end + end +end From ef1eeb3a25fa8d557c2f2a60de843d4697dd6352 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Mon, 5 Aug 2024 12:00:07 +0200 Subject: [PATCH 15/96] Unify Net::HTTP and Faraday implementations (#2360) * Unify Net::HTTP and Faraday implementations * Fix early return in Faraday when Sentry is not initialized --- sentry-ruby/Gemfile | 2 +- sentry-ruby/lib/sentry/faraday.rb | 50 +++---------------- sentry-ruby/lib/sentry/net/http.rb | 52 ++++++-------------- sentry-ruby/lib/sentry/utils/http_tracing.rb | 41 +++++++++++++++ sentry-ruby/spec/sentry/faraday_spec.rb | 22 +++++++++ 5 files changed, 87 insertions(+), 80 deletions(-) create mode 100644 sentry-ruby/lib/sentry/utils/http_tracing.rb diff --git a/sentry-ruby/Gemfile b/sentry-ruby/Gemfile index c6e1db011..a5e4967b9 100644 --- a/sentry-ruby/Gemfile +++ b/sentry-ruby/Gemfile @@ -15,7 +15,7 @@ gem "puma" gem "timecop" gem "stackprof" unless RUBY_PLATFORM == "java" -gem "graphql", ">= 2.2.6" if RUBY_VERSION.to_f >= 2.7 +gem "graphql", ">= 2.2.6", "< 2.3.11" if RUBY_VERSION.to_f >= 2.7 gem "benchmark-ips" gem "benchmark_driver" diff --git a/sentry-ruby/lib/sentry/faraday.rb b/sentry-ruby/lib/sentry/faraday.rb index e2608cd97..05d5f45bd 100644 --- a/sentry-ruby/lib/sentry/faraday.rb +++ b/sentry-ruby/lib/sentry/faraday.rb @@ -3,8 +3,6 @@ module Sentry module Faraday OP_NAME = "http.client" - SPAN_ORIGIN = "auto.http.faraday" - BREADCRUMB_CATEGORY = "http" module Connection # Since there's no way to preconfigure Faraday connections and add our instrumentation @@ -25,14 +23,13 @@ def initialize(url = nil, options = nil) end class Instrumenter - attr_reader :configuration + SPAN_ORIGIN = "auto.http.faraday" + BREADCRUMB_CATEGORY = "http" - def initialize - @configuration = Sentry.configuration - end + include Utils::HttpTracing def instrument(op_name, env, &block) - return unless Sentry.initialized? + return block.call unless Sentry.initialized? Sentry.with_child_span(op: op_name, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |sentry_span| request_info = extract_request_info(env) @@ -42,17 +39,14 @@ def instrument(op_name, env, &block) end res = block.call + response_status = res.status if record_sentry_breadcrumb? - record_sentry_breadcrumb(request_info, res) + record_sentry_breadcrumb(request_info, response_status) end if sentry_span - sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}") - sentry_span.set_data(Span::DataConventions::URL, request_info[:url]) - sentry_span.set_data(Span::DataConventions::HTTP_METHOD, request_info[:method]) - sentry_span.set_data(Span::DataConventions::HTTP_QUERY, request_info[:query]) if request_info[:query] - sentry_span.set_data(Span::DataConventions::HTTP_STATUS_CODE, res.status) + set_span_info(sentry_span, request_info, response_status) end res @@ -65,41 +59,13 @@ def extract_request_info(env) url = env[:url].scheme + "://" + env[:url].host + env[:url].path result = { method: env[:method].to_s.upcase, url: url } - if configuration.send_default_pii + if Sentry.configuration.send_default_pii result[:query] = env[:url].query result[:body] = env[:body] end result end - - def record_sentry_breadcrumb(request_info, res) - crumb = Sentry::Breadcrumb.new( - level: :info, - category: BREADCRUMB_CATEGORY, - type: :info, - data: { - status: res.status, - **request_info - } - ) - - Sentry.add_breadcrumb(crumb) - end - - def record_sentry_breadcrumb? - configuration.breadcrumbs_logger.include?(:http_logger) - end - - def propagate_trace?(url) - url && - configuration.propagate_traces && - configuration.trace_propagation_targets.any? { |target| url.match?(target) } - end - - def set_propagation_headers(headers) - Sentry.get_trace_propagation_headers&.each { |k, v| headers[k] = v } - end end end end diff --git a/sentry-ruby/lib/sentry/net/http.rb b/sentry-ruby/lib/sentry/net/http.rb index 205c79c55..c769b4c3d 100644 --- a/sentry-ruby/lib/sentry/net/http.rb +++ b/sentry-ruby/lib/sentry/net/http.rb @@ -2,11 +2,14 @@ require "net/http" require "resolv" +require "sentry/utils/http_tracing" module Sentry # @api private module Net module HTTP + include Utils::HttpTracing + OP_NAME = "http.client" SPAN_ORIGIN = "auto.http.net_http" BREADCRUMB_CATEGORY = "net.http" @@ -21,8 +24,7 @@ module HTTP # req['connection'] ||= 'close' # return request(req, body, &block) # <- request will be called for the second time from the first call # } - # end - # # ..... + # end # ..... # end # ``` # @@ -34,44 +36,26 @@ def request(req, body = nil, &block) Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |sentry_span| request_info = extract_request_info(req) - if propagate_trace?(request_info[:url], Sentry.configuration) + if propagate_trace?(request_info[:url]) set_propagation_headers(req) end - super.tap do |res| - record_sentry_breadcrumb(request_info, res) + res = super + response_status = res.code.to_i - if sentry_span - sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}") - sentry_span.set_data(Span::DataConventions::URL, request_info[:url]) - sentry_span.set_data(Span::DataConventions::HTTP_METHOD, request_info[:method]) - sentry_span.set_data(Span::DataConventions::HTTP_QUERY, request_info[:query]) if request_info[:query] - sentry_span.set_data(Span::DataConventions::HTTP_STATUS_CODE, res.code.to_i) - end + if record_sentry_breadcrumb? + record_sentry_breadcrumb(request_info, response_status) end - end - end - private + if sentry_span + set_span_info(sentry_span, request_info, response_status) + end - def set_propagation_headers(req) - Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v } + res + end end - def record_sentry_breadcrumb(request_info, res) - return unless Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger) - - crumb = Sentry::Breadcrumb.new( - level: :info, - category: BREADCRUMB_CATEGORY, - type: :info, - data: { - status: res.code.to_i, - **request_info - } - ) - Sentry.add_breadcrumb(crumb) - end + private def from_sentry_sdk? dsn = Sentry.configuration.dsn @@ -94,12 +78,6 @@ def extract_request_info(req) result end - - def propagate_trace?(url, configuration) - url && - configuration.propagate_traces && - configuration.trace_propagation_targets.any? { |target| url.match?(target) } - end end end end diff --git a/sentry-ruby/lib/sentry/utils/http_tracing.rb b/sentry-ruby/lib/sentry/utils/http_tracing.rb new file mode 100644 index 000000000..abf6a9141 --- /dev/null +++ b/sentry-ruby/lib/sentry/utils/http_tracing.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Sentry + module Utils + module HttpTracing + def set_span_info(sentry_span, request_info, response_status) + sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}") + sentry_span.set_data(Span::DataConventions::URL, request_info[:url]) + sentry_span.set_data(Span::DataConventions::HTTP_METHOD, request_info[:method]) + sentry_span.set_data(Span::DataConventions::HTTP_QUERY, request_info[:query]) if request_info[:query] + sentry_span.set_data(Span::DataConventions::HTTP_STATUS_CODE, response_status) + end + + def set_propagation_headers(req) + Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v } + end + + def record_sentry_breadcrumb(request_info, response_status) + crumb = Sentry::Breadcrumb.new( + level: :info, + category: self.class::BREADCRUMB_CATEGORY, + type: :info, + data: { status: response_status, **request_info } + ) + + Sentry.add_breadcrumb(crumb) + end + + def record_sentry_breadcrumb? + Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger) + end + + def propagate_trace?(url) + url && + Sentry.initialized? && + Sentry.configuration.propagate_traces && + Sentry.configuration.trace_propagation_targets.any? { |target| url.match?(target) } + end + end + end +end diff --git a/sentry-ruby/spec/sentry/faraday_spec.rb b/sentry-ruby/spec/sentry/faraday_spec.rb index abb63ddb5..f4632032f 100644 --- a/sentry-ruby/spec/sentry/faraday_spec.rb +++ b/sentry-ruby/spec/sentry/faraday_spec.rb @@ -254,4 +254,26 @@ expect(transaction.span_recorder.spans.map(&:origin)).not_to include("auto.http.faraday") end end + + context "when Sentry is not initialized" do + let(:http) do + Faraday.new(url) do |f| + f.adapter Faraday::Adapter::Test do |stub| + stub.get("/test") do + [200, { "Content-Type" => "text/html" }, "

hello world

"] + end + end + end + end + + let(:url) { "http://example.com" } + + it "skips instrumentation" do + allow(Sentry).to receive(:initialized?).and_return(false) + + response = http.get("/test") + + expect(response.status).to eq(200) + end + end end From e4571d9f2d90cc353501e32471d46e40521a37db Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Tue, 6 Aug 2024 10:11:41 +0100 Subject: [PATCH 16/96] Remove upper limit on graphql gem version (#2362) The original issue should be addressed in https://github.com/rmosolgo/graphql-ruby/pull/5052 --- sentry-ruby/Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-ruby/Gemfile b/sentry-ruby/Gemfile index a5e4967b9..c6e1db011 100644 --- a/sentry-ruby/Gemfile +++ b/sentry-ruby/Gemfile @@ -15,7 +15,7 @@ gem "puma" gem "timecop" gem "stackprof" unless RUBY_PLATFORM == "java" -gem "graphql", ">= 2.2.6", "< 2.3.11" if RUBY_VERSION.to_f >= 2.7 +gem "graphql", ">= 2.2.6" if RUBY_VERSION.to_f >= 2.7 gem "benchmark-ips" gem "benchmark_driver" From 47c44582aab111be5ff31e579310faebfddf561d Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 8 Aug 2024 14:47:51 +0200 Subject: [PATCH 17/96] Include transaction data in the trace context (#2365) --- CHANGELOG.md | 2 ++ sentry-ruby/lib/sentry/span.rb | 3 ++- sentry-ruby/spec/sentry/span_spec.rb | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a04bb011..cdb83c687 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ - Support for tracing Faraday requests ([#2345](https://github.com/getsentry/sentry-ruby/pull/2345)) - Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795) - Please note that the Faraday instrumentation has some limitations in case of async requests: https://github.com/lostisland/faraday/issues/1381 +- Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365)) + - Closes [#2364](https://github.com/getsentry/sentry-ruby/issues/2363) ## 5.18.2 diff --git a/sentry-ruby/lib/sentry/span.rb b/sentry-ruby/lib/sentry/span.rb index 061b7b1e0..da7232d9a 100644 --- a/sentry-ruby/lib/sentry/span.rb +++ b/sentry-ruby/lib/sentry/span.rb @@ -192,7 +192,8 @@ def get_trace_context description: @description, op: @op, status: @status, - origin: @origin + origin: @origin, + data: @data } end diff --git a/sentry-ruby/spec/sentry/span_spec.rb b/sentry-ruby/spec/sentry/span_spec.rb index 0bc187eec..d890dfa25 100644 --- a/sentry-ruby/spec/sentry/span_spec.rb +++ b/sentry-ruby/spec/sentry/span_spec.rb @@ -28,12 +28,15 @@ it "returns correct context data" do context = subject.get_trace_context + subject.set_data(:foo, "bar") + expect(context[:op]).to eq("sql.query") expect(context[:description]).to eq("SELECT * FROM users;") expect(context[:status]).to eq("ok") expect(context[:trace_id].length).to eq(32) expect(context[:span_id].length).to eq(16) expect(context[:origin]).to eq('manual') + expect(context[:data]).to eq(foo: "bar") end end From 278316c10765957c5edce6b6f4ee94bc5fae436d Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 8 Aug 2024 14:50:01 +0200 Subject: [PATCH 18/96] Fix skipping 'connect' spans (#2364) --- CHANGELOG.md | 4 ++++ .../lib/sentry/opentelemetry/span_processor.rb | 2 +- .../sentry/opentelemetry/span_processor_spec.rb | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdb83c687..087f72996 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ - Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365)) - Closes [#2364](https://github.com/getsentry/sentry-ruby/issues/2363) +### Bug Fixes + +- Fix skipping `connect` spans in open-telemetry [#2364](https://github.com/getsentry/sentry-ruby/pull/2364) + ## 5.18.2 ### Bug Fixes diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb index db6d500f0..71152ad29 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb @@ -83,7 +83,7 @@ def from_sentry_sdk?(otel_span) dsn = Sentry.configuration.dsn return false unless dsn - if otel_span.name.start_with?("HTTP") + if otel_span.name.start_with?("HTTP") || otel_span.name == "connect" # only check client requests, connects are sometimes internal return false unless INTERNAL_SPAN_KINDS.include?(otel_span.kind) diff --git a/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb b/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb index 48d27596e..0d5626730 100644 --- a/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb +++ b/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb @@ -64,6 +64,18 @@ tracer.start_span('HTTP POST', with_parent: root_parent_context, attributes: attributes, kind: :client) end + let(:child_internal_span_connect) do + attributes = { + 'http.method' => 'POST', + 'http.scheme' => 'https', + 'http.target' => '/api/5434472/envelope/', + 'net.peer.name' => 'sentry.localdomain', + 'net.peer.port' => 443 + } + + tracer.start_span('connect', with_parent: root_parent_context, attributes: attributes, kind: :internal) + end + before do perform_basic_setup perform_otel_setup @@ -153,6 +165,11 @@ subject.on_start(child_internal_span, root_parent_context) end + it 'noops on `connect` requests' do + expect(transaction).not_to receive(:start_child) + subject.on_start(child_internal_span_connect, root_parent_context) + end + it 'starts a sentry child span on otel child span' do expect(transaction).to receive(:start_child).and_call_original subject.on_start(child_db_span, root_parent_context) From 837577a4c750c69d17d8a8fd48fa5ffb6d5669f2 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 8 Aug 2024 14:51:24 +0200 Subject: [PATCH 19/96] File/attachment uploads (#2357) --- CHANGELOG.md | 7 ++++ sentry-ruby/lib/sentry-ruby.rb | 7 ++++ sentry-ruby/lib/sentry/attachment.rb | 42 +++++++++++++++++++ sentry-ruby/lib/sentry/event.rb | 4 ++ sentry-ruby/lib/sentry/scope.rb | 14 +++++++ sentry-ruby/lib/sentry/transport.rb | 6 +++ sentry-ruby/sentry-ruby.gemspec | 2 +- sentry-ruby/spec/fixtures/attachment.txt | 1 + sentry-ruby/spec/sentry/scope_spec.rb | 24 +++++++++++ sentry-ruby/spec/sentry/transport_spec.rb | 18 ++++++++ sentry-ruby/spec/sentry_spec.rb | 51 +++++++++++++++++++++++ sentry-ruby/spec/spec_helper.rb | 8 ++++ 12 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 sentry-ruby/lib/sentry/attachment.rb create mode 100644 sentry-ruby/spec/fixtures/attachment.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 087f72996..cf7041e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ - Support for tracing Faraday requests ([#2345](https://github.com/getsentry/sentry-ruby/pull/2345)) - Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795) - Please note that the Faraday instrumentation has some limitations in case of async requests: https://github.com/lostisland/faraday/issues/1381 +- Support for attachments ([#2357](https://github.com/getsentry/sentry-ruby/pull/2357)) + Usage: + + ```ruby + Sentry.add_attachment(path: '/foo/bar.txt') + Sentry.add_attachment(filename: 'payload.json', bytes: '{"value": 42}')) + ``` - Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365)) - Closes [#2364](https://github.com/getsentry/sentry-ruby/issues/2363) diff --git a/sentry-ruby/lib/sentry-ruby.rb b/sentry-ruby/lib/sentry-ruby.rb index dd59d6e67..358a7c329 100644 --- a/sentry-ruby/lib/sentry-ruby.rb +++ b/sentry-ruby/lib/sentry-ruby.rb @@ -211,6 +211,13 @@ def set_context(*args) get_current_scope.set_context(*args) end + # @!method add_attachment + # @!macro add_attachment + def add_attachment(**opts) + return unless initialized? + get_current_scope.add_attachment(**opts) + end + ##### Main APIs ##### # Initializes the SDK with given configuration. diff --git a/sentry-ruby/lib/sentry/attachment.rb b/sentry-ruby/lib/sentry/attachment.rb new file mode 100644 index 000000000..f40971599 --- /dev/null +++ b/sentry-ruby/lib/sentry/attachment.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module Sentry + class Attachment + PathNotFoundError = Class.new(StandardError) + + attr_reader :bytes, :filename, :path, :content_type + + def initialize(bytes: nil, filename: nil, content_type: nil, path: nil) + @bytes = bytes + @filename = infer_filename(filename, path) + @path = path + @content_type = content_type + end + + def to_envelope_headers + { type: 'attachment', filename: filename, content_type: content_type, length: payload.bytesize } + end + + def payload + @payload ||= if bytes + bytes + else + File.binread(path) + end + rescue Errno::ENOENT + raise PathNotFoundError, "Failed to read attachment file, file not found: #{path}" + end + + private + + def infer_filename(filename, path) + return filename if filename + + if path + File.basename(path) + else + raise ArgumentError, "filename or path is required" + end + end + end +end diff --git a/sentry-ruby/lib/sentry/event.rb b/sentry-ruby/lib/sentry/event.rb index b3fb5b275..7fbd6172c 100644 --- a/sentry-ruby/lib/sentry/event.rb +++ b/sentry-ruby/lib/sentry/event.rb @@ -42,6 +42,9 @@ class Event # @return [Hash, nil] attr_accessor :dynamic_sampling_context + # @return [Array] + attr_accessor :attachments + # @param configuration [Configuration] # @param integration_meta [Hash, nil] # @param message [String, nil] @@ -57,6 +60,7 @@ def initialize(configuration:, integration_meta: nil, message: nil) @extra = {} @contexts = {} @tags = {} + @attachments = [] @fingerprint = [] @dynamic_sampling_context = nil diff --git a/sentry-ruby/lib/sentry/scope.rb b/sentry-ruby/lib/sentry/scope.rb index 591a00682..73e873f43 100644 --- a/sentry-ruby/lib/sentry/scope.rb +++ b/sentry-ruby/lib/sentry/scope.rb @@ -2,6 +2,7 @@ require "sentry/breadcrumb_buffer" require "sentry/propagation_context" +require "sentry/attachment" require "etc" module Sentry @@ -22,6 +23,7 @@ class Scope :rack_env, :span, :session, + :attachments, :propagation_context ] @@ -55,6 +57,7 @@ def apply_to_event(event, hint = nil) event.level = level event.breadcrumbs = breadcrumbs event.rack_env = rack_env if rack_env + event.attachments = attachments end if span @@ -102,6 +105,7 @@ def dup copy.span = span.deep_dup copy.session = session.deep_dup copy.propagation_context = propagation_context.deep_dup + copy.attachments = attachments.dup copy end @@ -119,6 +123,7 @@ def update_from_scope(scope) self.fingerprint = scope.fingerprint self.span = scope.span self.propagation_context = scope.propagation_context + self.attachments = scope.attachments end # Updates the scope's data from the given options. @@ -128,6 +133,7 @@ def update_from_scope(scope) # @param user [Hash] # @param level [String, Symbol] # @param fingerprint [Array] + # @param attachments [Array] # @return [Array] def update_from_options( contexts: nil, @@ -136,6 +142,7 @@ def update_from_options( user: nil, level: nil, fingerprint: nil, + attachments: nil, **options ) self.contexts.merge!(contexts) if contexts @@ -283,6 +290,12 @@ def generate_propagation_context(env = nil) @propagation_context = PropagationContext.new(self, env) end + # Add a new attachment to the scope. + def add_attachment(**opts) + attachments << (attachment = Attachment.new(**opts)) + attachment + end + protected # for duplicating scopes internally @@ -303,6 +316,7 @@ def set_default_value @rack_env = {} @span = nil @session = nil + @attachments = [] generate_propagation_context set_new_breadcrumb_buffer end diff --git a/sentry-ruby/lib/sentry/transport.rb b/sentry-ruby/lib/sentry/transport.rb index acef83de0..39a993fe5 100644 --- a/sentry-ruby/lib/sentry/transport.rb +++ b/sentry-ruby/lib/sentry/transport.rb @@ -145,6 +145,12 @@ def envelope_from_event(event) ) end + if event.is_a?(Event) && event.attachments.any? + event.attachments.each do |attachment| + envelope.add_item(attachment.to_envelope_headers, attachment.payload) + end + end + client_report_headers, client_report_payload = fetch_pending_client_report envelope.add_item(client_report_headers, client_report_payload) if client_report_headers diff --git a/sentry-ruby/sentry-ruby.gemspec b/sentry-ruby/sentry-ruby.gemspec index 31fa0b581..52cbcc180 100644 --- a/sentry-ruby/sentry-ruby.gemspec +++ b/sentry-ruby/sentry-ruby.gemspec @@ -26,6 +26,6 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] - spec.add_dependency "concurrent-ruby", '~> 1.0', '>= 1.0.2' + spec.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2" spec.add_dependency "bigdecimal" end diff --git a/sentry-ruby/spec/fixtures/attachment.txt b/sentry-ruby/spec/fixtures/attachment.txt new file mode 100644 index 000000000..3b18e512d --- /dev/null +++ b/sentry-ruby/spec/fixtures/attachment.txt @@ -0,0 +1 @@ +hello world diff --git a/sentry-ruby/spec/sentry/scope_spec.rb b/sentry-ruby/spec/sentry/scope_spec.rb index 651c995d1..5de4d8d6d 100644 --- a/sentry-ruby/spec/sentry/scope_spec.rb +++ b/sentry-ruby/spec/sentry/scope_spec.rb @@ -201,6 +201,7 @@ scope.set_user({ id: 1 }) scope.set_transaction_name("WelcomeController#index", source: :view) scope.set_fingerprint(["foo"]) + scope.add_attachment(bytes: "file-data", filename: "test.txt") scope end @@ -219,6 +220,10 @@ expect(event.contexts).to include(:trace) expect(event.contexts[:os].keys).to match_array([:name, :version, :build, :kernel_version, :machine]) expect(event.contexts.dig(:runtime, :version)).to match(/ruby/) + + attachment = event.attachments.first + expect(attachment.filename).to eql("test.txt") + expect(attachment.bytes).to eql("file-data") end it "does not apply the contextual data to a check-in event" do @@ -361,4 +366,23 @@ expect(result).to eq([:foo, :bar]) end end + + describe "#add_attachment" do + before { perform_basic_setup } + + let(:opts) do + { bytes: "file-data", filename: "test.txt" } + end + + subject do + described_class.new + end + + it "adds a new attachment" do + attachment = subject.add_attachment(**opts) + + expect(attachment.bytes).to eq("file-data") + expect(attachment.filename).to eq("test.txt") + end + end end diff --git a/sentry-ruby/spec/sentry/transport_spec.rb b/sentry-ruby/spec/sentry/transport_spec.rb index 73b22d91d..b78dc7878 100644 --- a/sentry-ruby/spec/sentry/transport_spec.rb +++ b/sentry-ruby/spec/sentry/transport_spec.rb @@ -435,6 +435,24 @@ end end end + + context "event with attachments" do + let(:event) { client.event_from_exception(ZeroDivisionError.new("divided by 0")) } + let(:envelope) { subject.envelope_from_event(event) } + + before do + event.attachments << Sentry::Attachment.new(filename: "test-1.txt", bytes: "test") + event.attachments << Sentry::Attachment.new(path: fixture_path("attachment.txt")) + end + + it "sends the event and logs the action" do + expect(subject).to receive(:send_data) + + subject.send_envelope(envelope) + + expect(io.string).to match(/Sending envelope with items \[event, attachment, attachment\]/) + end + end end describe "#send_event" do diff --git a/sentry-ruby/spec/sentry_spec.rb b/sentry-ruby/spec/sentry_spec.rb index 0e30d150e..dd3f85c93 100644 --- a/sentry-ruby/spec/sentry_spec.rb +++ b/sentry-ruby/spec/sentry_spec.rb @@ -713,6 +713,57 @@ end end + describe ".add_attachment" do + it "adds a new attachment to the current scope with provided filename and bytes" do + described_class.add_attachment(filename: "test.txt", bytes: "test") + + expect(described_class.get_current_scope.attachments.size).to be(1) + + attachment = described_class.get_current_scope.attachments.first + expect(attachment.filename).to eq("test.txt") + expect(attachment.bytes).to eq("test") + end + + it "adds a new attachment to the current scope with provided path to a file" do + described_class.add_attachment(path: fixture_path("attachment.txt")) + + expect(described_class.get_current_scope.attachments.size).to be(1) + + attachment = described_class.get_current_scope.attachments.first + expect(attachment.filename).to eq("attachment.txt") + expect(attachment.payload).to eq("hello world\n") + end + + it "adds a new attachment to the current scope favoring bytes over path" do + described_class.add_attachment(path: fixture_path("attachment.txt"), bytes: "test", content_type: "text/plain") + + expect(described_class.get_current_scope.attachments.size).to be(1) + + attachment = described_class.get_current_scope.attachments.first + expect(attachment.filename).to eq("attachment.txt") + expect(attachment.content_type).to eq("text/plain") + expect(attachment.payload).to eq("test") + end + + it "raises meaningful error when path is invalid" do + described_class.add_attachment(path: "/not-here/oops") + + expect(described_class.get_current_scope.attachments.size).to be(1) + + attachment = described_class.get_current_scope.attachments.first + + expect { attachment.payload } + .to raise_error( + Sentry::Attachment::PathNotFoundError, + "Failed to read attachment file, file not found: /not-here/oops" + ) + end + + it "requires either filename or path" do + expect { described_class.add_attachment(bytes: "test") }.to raise_error(ArgumentError, "filename or path is required") + end + end + describe ".csp_report_uri" do it "returns the csp_report_uri generated from the main Configuration" do expect(Sentry.configuration).to receive(:csp_report_uri).and_call_original diff --git a/sentry-ruby/spec/spec_helper.rb b/sentry-ruby/spec/spec_helper.rb index 6ba0ccee0..611205163 100644 --- a/sentry-ruby/spec/spec_helper.rb +++ b/sentry-ruby/spec/spec_helper.rb @@ -57,6 +57,14 @@ end end +def fixtures_root + @fixtures_root ||= Pathname(__dir__).join("fixtures") +end + +def fixture_path(name) + fixtures_root.join(name).realpath +end + def build_exception_with_cause(cause = "exception a") begin raise cause From 3fb9b67534f44ea05eae1c477593ea56758bc089 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Thu, 8 Aug 2024 14:58:02 +0200 Subject: [PATCH 20/96] Update CHANGELOG.md (#2366) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf7041e5c..8870a20c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795) - Please note that the Faraday instrumentation has some limitations in case of async requests: https://github.com/lostisland/faraday/issues/1381 - Support for attachments ([#2357](https://github.com/getsentry/sentry-ruby/pull/2357)) + Usage: ```ruby From 8c1c259f7d288052e90dea15e3aa8b48c5c21c20 Mon Sep 17 00:00:00 2001 From: Koo Date: Mon, 12 Aug 2024 06:33:58 +0900 Subject: [PATCH 21/96] Use `Concurrent.available_processor_count` instead of `Concurrent.usable_processor_count` (#2358) --- CHANGELOG.md | 2 ++ sentry-ruby/lib/sentry/configuration.rb | 7 ++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8870a20c5..352ef2472 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +- Use `Concurrent.available_processor_count` instead of `Concurrent.usable_processor_count` ([#2358](https://github.com/getsentry/sentry-ruby/pull/2358)) + - Support for tracing Faraday requests ([#2345](https://github.com/getsentry/sentry-ruby/pull/2345)) - Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795) - Please note that the Faraday instrumentation has some limitations in case of async requests: https://github.com/lostisland/faraday/issues/1381 diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index 8d4564694..480172a88 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -656,11 +656,8 @@ def run_post_initialization_callbacks end def processor_count - if Concurrent.respond_to?(:usable_processor_count) - Concurrent.usable_processor_count - else - Concurrent.processor_count - end + available_processor_count = Concurrent.available_processor_count if Concurrent.respond_to?(:available_processor_count) + available_processor_count || Concurrent.processor_count end end end From a09da50d47d47cd4c3c3bea360977fefbf5af195 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 13 Aug 2024 16:19:45 +0200 Subject: [PATCH 22/96] Include Sentry meta tag in the layout automatically (#2369) * Include Sentry meta tag in the layout automatically * Add --inject-meta option --- CHANGELOG.md | 2 + .../lib/generators/sentry_generator.rb | 10 +++++ sentry-rails/spec/sentry/generator_spec.rb | 41 +++++++++++++++++++ sentry-sidekiq/spec/sentry/rails_spec.rb | 2 + 4 files changed, 55 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 352ef2472..aed6c3666 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ - Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365)) - Closes [#2364](https://github.com/getsentry/sentry-ruby/issues/2363) +- Include Sentry meta tag in the layout automatically ([#2369](https://github.com/getsentry/sentry-ruby/pull/2369)) + ### Bug Fixes - Fix skipping `connect` spans in open-telemetry [#2364](https://github.com/getsentry/sentry-ruby/pull/2364) diff --git a/sentry-rails/lib/generators/sentry_generator.rb b/sentry-rails/lib/generators/sentry_generator.rb index 76ad3ecf9..de694e40d 100644 --- a/sentry-rails/lib/generators/sentry_generator.rb +++ b/sentry-rails/lib/generators/sentry_generator.rb @@ -3,6 +3,8 @@ class SentryGenerator < ::Rails::Generators::Base class_option :dsn, type: :string, desc: "Sentry DSN" + class_option :inject_meta, type: :boolean, default: true, desc: "Inject meta tag into layout" + def copy_initializer_file dsn = options[:dsn] ? "'#{options[:dsn]}'" : "ENV['SENTRY_DSN']" @@ -16,4 +18,12 @@ def copy_initializer_file end RUBY end + + def inject_code_into_layout + return unless options[:inject_meta] + + inject_into_file "app/views/layouts/application.html.erb", before: "\n" do + " <%= Sentry.get_trace_propagation_meta.html_safe %>\n " + end + end end diff --git a/sentry-rails/spec/sentry/generator_spec.rb b/sentry-rails/spec/sentry/generator_spec.rb index ac4aff730..7da9e12a7 100644 --- a/sentry-rails/spec/sentry/generator_spec.rb +++ b/sentry-rails/spec/sentry/generator_spec.rb @@ -10,8 +10,33 @@ self.destination File.expand_path('../../tmp', __dir__) self.generator_class = described_class + let(:layout_file) do + File.join(destination_root, "app/views/layouts/application.html.erb") + end + before do prepare_destination + + FileUtils.mkdir_p(File.dirname(layout_file)) + + File.write(layout_file, <<~STR) + + + + SentryTesting + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> + <%= javascript_importmap_tags %> + + + + <%= yield %> + + + STR end it "creates a initializer file" do @@ -29,6 +54,22 @@ RUBY end + it "injects meta tag into the layout" do + run_generator + + content = File.read(layout_file) + + expect(content).to include("Sentry.get_trace_propagation_meta.html_safe") + end + + it "doesn't inject meta tag when it's disabled" do + run_generator %w[--inject-meta false] + + content = File.read(layout_file) + + expect(content).not_to include("Sentry.get_trace_propagation_meta.html_safe") + end + context "with a DSN option" do it "creates a initializer file with the DSN" do run_generator %w[--dsn foobarbaz] diff --git a/sentry-sidekiq/spec/sentry/rails_spec.rb b/sentry-sidekiq/spec/sentry/rails_spec.rb index 903f8ab38..87518ea06 100644 --- a/sentry-sidekiq/spec/sentry/rails_spec.rb +++ b/sentry-sidekiq/spec/sentry/rails_spec.rb @@ -4,6 +4,8 @@ require "sentry-rails" require "spec_helper" +require "action_controller/railtie" + class TestApp < Rails::Application end From 3ac5b8031e42858e53387c9fa2c829af513bf8d1 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 13 Aug 2024 16:26:35 +0200 Subject: [PATCH 23/96] Changelog for 5.19.0 (#2370) --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aed6c3666..d3d9f5627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## 5.19.0 ### Features @@ -18,7 +18,12 @@ - Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365)) - Closes [#2364](https://github.com/getsentry/sentry-ruby/issues/2363) -- Include Sentry meta tag in the layout automatically ([#2369](https://github.com/getsentry/sentry-ruby/pull/2369)) +- Inject Sentry meta tags in the Rails application layout automatically in the generator ([#2369](https://github.com/getsentry/sentry-ruby/pull/2369)) + + To turn this behavior off, use + ```bash + bin/rails generate sentry --inject-meta false + ``` ### Bug Fixes From 43c5cc231726963345580f6a2559be1725d7ef24 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Tue, 13 Aug 2024 14:30:17 +0000 Subject: [PATCH 24/96] release: 5.19.0 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index 983cfafda..95d3630b0 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -1,5 +1,5 @@ module Sentry module DelayedJob - VERSION = "5.18.2" + VERSION = "5.19.0" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index d8a44d4cb..e97096bcb 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.2" + spec.add_dependency "sentry-ruby", "~> 5.19.0" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index daf8d6bd7..ddc0cbe67 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.18.2" + VERSION = "5.19.0" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 28f6692a1..aaee606be 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.2" + spec.add_dependency "sentry-ruby", "~> 5.19.0" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index ab8ce6bd6..ac6bcb23b 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -1,5 +1,5 @@ module Sentry module Rails - VERSION = "5.18.2" + VERSION = "5.19.0" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 30c09390c..7cfdd0e70 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -29,5 +29,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.18.2" + spec.add_dependency "sentry-ruby", "~> 5.19.0" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index a21a6180c..9e6a6ec4f 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -1,5 +1,5 @@ module Sentry module Resque - VERSION = "5.18.2" + VERSION = "5.19.0" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 34796ee10..36d777b00 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.2" + spec.add_dependency "sentry-ruby", "~> 5.19.0" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index d37911dac..a06f8cebc 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.18.2" + VERSION = "5.19.0" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index dfeec9914..b127d83ba 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -1,5 +1,5 @@ module Sentry module Sidekiq - VERSION = "5.18.2" + VERSION = "5.19.0" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index cace76b46..56f737887 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.18.2" + spec.add_dependency "sentry-ruby", "~> 5.19.0" spec.add_dependency "sidekiq", ">= 3.0" end From fa0973ac04d4ad27849cc49d905f2ab52b9a74f5 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Wed, 14 Aug 2024 14:43:50 +0200 Subject: [PATCH 25/96] Add Faraday instruction to changelog (#2371) --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d9f5627..5cfdbbc5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ - Support for tracing Faraday requests ([#2345](https://github.com/getsentry/sentry-ruby/pull/2345)) - Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795) - Please note that the Faraday instrumentation has some limitations in case of async requests: https://github.com/lostisland/faraday/issues/1381 + + Usage: + + ```rb + Sentry.init do |config| + # ... + config.enabled_patches << :faraday + end + ``` + - Support for attachments ([#2357](https://github.com/getsentry/sentry-ruby/pull/2357)) Usage: @@ -15,6 +25,7 @@ Sentry.add_attachment(path: '/foo/bar.txt') Sentry.add_attachment(filename: 'payload.json', bytes: '{"value": 42}')) ``` + - Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365)) - Closes [#2364](https://github.com/getsentry/sentry-ruby/issues/2363) From ec7067790062786f4877400f6d18b54ed50669f2 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 16 Aug 2024 13:01:12 +0200 Subject: [PATCH 26/96] rubocop -a --only Style/StringLiterals (#2373) --- sentry-ruby/lib/sentry-ruby.rb | 2 +- sentry-ruby/lib/sentry/attachment.rb | 2 +- sentry-ruby/lib/sentry/baggage.rb | 12 ++++---- .../lib/sentry/breadcrumb/sentry_logger.rb | 12 ++++---- sentry-ruby/lib/sentry/check_in_event.rb | 8 ++--- sentry-ruby/lib/sentry/client.rb | 18 +++++------ sentry-ruby/lib/sentry/configuration.rb | 22 +++++++------- .../lib/sentry/core_ext/object/deep_dup.rb | 2 +- .../lib/sentry/cron/monitor_check_ins.rb | 2 +- sentry-ruby/lib/sentry/cron/monitor_config.rb | 2 +- sentry-ruby/lib/sentry/dsn.rb | 6 ++-- sentry-ruby/lib/sentry/envelope.rb | 16 +++++----- sentry-ruby/lib/sentry/event.rb | 14 ++++----- sentry-ruby/lib/sentry/graphql.rb | 2 +- .../lib/sentry/interfaces/mechanism.rb | 2 +- sentry-ruby/lib/sentry/interfaces/request.rb | 10 +++---- .../lib/sentry/interfaces/single_exception.rb | 2 +- sentry-ruby/lib/sentry/logger.rb | 2 +- sentry-ruby/lib/sentry/metrics.rb | 30 +++++++++---------- sentry-ruby/lib/sentry/metrics/aggregator.rb | 24 +++++++-------- sentry-ruby/lib/sentry/metrics/set_metric.rb | 4 +-- sentry-ruby/lib/sentry/profiler.rb | 30 +++++++++---------- sentry-ruby/lib/sentry/rack.rb | 4 +-- .../lib/sentry/rack/capture_exceptions.rb | 2 +- sentry-ruby/lib/sentry/rake.rb | 4 +-- sentry-ruby/lib/sentry/release_detector.rb | 8 ++--- sentry-ruby/lib/sentry/session_flusher.rb | 2 +- sentry-ruby/lib/sentry/test_helper.rb | 2 +- sentry-ruby/lib/sentry/transaction.rb | 4 +-- sentry-ruby/lib/sentry/transaction_event.rb | 2 +- sentry-ruby/lib/sentry/transport.rb | 8 ++--- .../lib/sentry/transport/http_transport.rb | 24 +++++++-------- sentry-ruby/lib/sentry/utils/real_ip.rb | 2 +- 33 files changed, 143 insertions(+), 143 deletions(-) diff --git a/sentry-ruby/lib/sentry-ruby.rb b/sentry-ruby/lib/sentry-ruby.rb index 358a7c329..734bc2cc9 100644 --- a/sentry-ruby/lib/sentry-ruby.rb +++ b/sentry-ruby/lib/sentry-ruby.rb @@ -563,7 +563,7 @@ def get_trace_propagation_headers # # @return [String] def get_trace_propagation_meta - return '' unless initialized? + return "" unless initialized? get_current_hub.get_trace_propagation_meta end diff --git a/sentry-ruby/lib/sentry/attachment.rb b/sentry-ruby/lib/sentry/attachment.rb index f40971599..71a2b2b76 100644 --- a/sentry-ruby/lib/sentry/attachment.rb +++ b/sentry-ruby/lib/sentry/attachment.rb @@ -14,7 +14,7 @@ def initialize(bytes: nil, filename: nil, content_type: nil, path: nil) end def to_envelope_headers - { type: 'attachment', filename: filename, content_type: content_type, length: payload.bytesize } + { type: "attachment", filename: filename, content_type: content_type, length: payload.bytesize } end def payload diff --git a/sentry-ruby/lib/sentry/baggage.rb b/sentry-ruby/lib/sentry/baggage.rb index d766e999d..2b375a846 100644 --- a/sentry-ruby/lib/sentry/baggage.rb +++ b/sentry-ruby/lib/sentry/baggage.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'cgi' +require "cgi" module Sentry # A {https://www.w3.org/TR/baggage W3C Baggage Header} implementation. class Baggage - SENTRY_PREFIX = 'sentry-' + SENTRY_PREFIX = "sentry-" SENTRY_PREFIX_REGEX = /^sentry-/.freeze # @return [Hash] @@ -30,14 +30,14 @@ def self.from_incoming_header(header) items = {} mutable = true - header.split(',').each do |item| + header.split(",").each do |item| item = item.strip - key, val = item.split('=') + key, val = item.split("=") next unless key && val next unless key =~ SENTRY_PREFIX_REGEX - baggage_key = key.split('-')[1] + baggage_key = key.split("-")[1] next unless baggage_key items[CGI.unescape(baggage_key)] = CGI.unescape(val) @@ -64,7 +64,7 @@ def dynamic_sampling_context # @return [String] def serialize items = @items.map { |k, v| "#{SENTRY_PREFIX}#{CGI.escape(k)}=#{CGI.escape(v)}" } - items.join(',') + items.join(",") end end end diff --git a/sentry-ruby/lib/sentry/breadcrumb/sentry_logger.rb b/sentry-ruby/lib/sentry/breadcrumb/sentry_logger.rb index 455535f01..4d94e513a 100644 --- a/sentry-ruby/lib/sentry/breadcrumb/sentry_logger.rb +++ b/sentry-ruby/lib/sentry/breadcrumb/sentry_logger.rb @@ -1,16 +1,16 @@ # frozen_string_literal: true -require 'logger' +require "logger" module Sentry class Breadcrumb module SentryLogger LEVELS = { - ::Logger::DEBUG => 'debug', - ::Logger::INFO => 'info', - ::Logger::WARN => 'warn', - ::Logger::ERROR => 'error', - ::Logger::FATAL => 'fatal' + ::Logger::DEBUG => "debug", + ::Logger::INFO => "info", + ::Logger::WARN => "warn", + ::Logger::ERROR => "error", + ::Logger::FATAL => "fatal" }.freeze def add(*args, &block) diff --git a/sentry-ruby/lib/sentry/check_in_event.rb b/sentry-ruby/lib/sentry/check_in_event.rb index 7a10872b5..91ae17dc3 100644 --- a/sentry-ruby/lib/sentry/check_in_event.rb +++ b/sentry-ruby/lib/sentry/check_in_event.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'securerandom' -require 'sentry/cron/monitor_config' +require "securerandom" +require "sentry/cron/monitor_config" module Sentry class CheckInEvent < Event - TYPE = 'check_in' + TYPE = "check_in" # uuid to identify this check-in. # @return [String] @@ -43,7 +43,7 @@ def initialize( self.status = status self.duration = duration self.monitor_config = monitor_config - self.check_in_id = check_in_id || SecureRandom.uuid.delete('-') + self.check_in_id = check_in_id || SecureRandom.uuid.delete("-") end # @return [Hash] diff --git a/sentry-ruby/lib/sentry/client.rb b/sentry-ruby/lib/sentry/client.rb index 6176508b7..9d48ee301 100644 --- a/sentry-ruby/lib/sentry/client.rb +++ b/sentry-ruby/lib/sentry/client.rb @@ -30,7 +30,7 @@ def initialize(configuration) else @transport = case configuration.dsn&.scheme - when 'http', 'https' + when "http", "https" HTTPTransport.new(configuration) else DummyTransport.new(configuration) @@ -49,7 +49,7 @@ def capture_event(event, scope, hint = {}) return unless configuration.sending_allowed? if event.is_a?(ErrorEvent) && !configuration.sample_allowed? - transport.record_lost_event(:sample_rate, 'error') + transport.record_lost_event(:sample_rate, "error") return end @@ -64,11 +64,11 @@ def capture_event(event, scope, hint = {}) if event.nil? log_debug("Discarded event because one of the event processors returned nil") transport.record_lost_event(:event_processor, data_category) - transport.record_lost_event(:event_processor, 'span', num: spans_before + 1) if is_transaction + transport.record_lost_event(:event_processor, "span", num: spans_before + 1) if is_transaction return elsif is_transaction spans_delta = spans_before - event.spans.size - transport.record_lost_event(:event_processor, 'span', num: spans_delta) if spans_delta > 0 + transport.record_lost_event(:event_processor, "span", num: spans_delta) if spans_delta > 0 end if async_block = configuration.async @@ -76,7 +76,7 @@ def capture_event(event, scope, hint = {}) elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true) unless dispatch_background_event(event, hint) transport.record_lost_event(:queue_overflow, data_category) - transport.record_lost_event(:queue_overflow, 'span', num: spans_before + 1) if is_transaction + transport.record_lost_event(:queue_overflow, "span", num: spans_before + 1) if is_transaction end else send_event(event, hint) @@ -195,13 +195,13 @@ def send_event(event, hint = nil) if event.nil? log_debug("Discarded event because before_send_transaction returned nil") - transport.record_lost_event(:before_send, 'transaction') - transport.record_lost_event(:before_send, 'span', num: spans_before + 1) + transport.record_lost_event(:before_send, "transaction") + transport.record_lost_event(:before_send, "span", num: spans_before + 1) return else spans_after = event.is_a?(TransactionEvent) ? event.spans.size : 0 spans_delta = spans_before - spans_after - transport.record_lost_event(:before_send, 'span', num: spans_delta) if spans_delta > 0 + transport.record_lost_event(:before_send, "span", num: spans_delta) if spans_delta > 0 end end @@ -212,7 +212,7 @@ def send_event(event, hint = nil) rescue => e log_error("Event sending failed", e, debug: configuration.debug) transport.record_lost_event(:network_error, data_category) - transport.record_lost_event(:network_error, 'span', num: spans_before + 1) if event.is_a?(TransactionEvent) + transport.record_lost_event(:network_error, "span", num: spans_before + 1) if event.is_a?(TransactionEvent) raise end diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index 480172a88..44ea574b4 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -3,7 +3,7 @@ require "concurrent/utility/processor_counter" require "sentry/utils/exception_cause_chain" -require 'sentry/utils/custom_inspection' +require "sentry/utils/custom_inspection" require "sentry/dsn" require "sentry/release_detector" require "sentry/transport/configuration" @@ -302,18 +302,18 @@ def capture_exception_frame_locals=(value) # But they are mostly considered as noise and should be ignored by default # Please see https://github.com/getsentry/sentry-ruby/pull/2026 for more information PUMA_IGNORE_DEFAULT = [ - 'Puma::MiniSSL::SSLError', - 'Puma::HttpParserError', - 'Puma::HttpParserError501' + "Puma::MiniSSL::SSLError", + "Puma::HttpParserError", + "Puma::HttpParserError501" ].freeze # Most of these errors generate 4XX responses. In general, Sentry clients # only automatically report 5xx responses. IGNORE_DEFAULT = [ - 'Mongoid::Errors::DocumentNotFound', - 'Rack::QueryParser::InvalidParameterError', - 'Rack::QueryParser::ParameterTypeError', - 'Sinatra::NotFound' + "Mongoid::Errors::DocumentNotFound", + "Rack::QueryParser::InvalidParameterError", + "Rack::QueryParser::ParameterTypeError", + "Sinatra::NotFound" ].freeze RACK_ENV_WHITELIST_DEFAULT = %w[ @@ -376,7 +376,7 @@ def initialize self.auto_session_tracking = true self.enable_backpressure_handling = false self.trusted_proxies = [] - self.dsn = ENV['SENTRY_DSN'] + self.dsn = ENV["SENTRY_DSN"] self.spotlight = false self.server_name = server_name_from_env self.instrumenter = :sentry @@ -632,12 +632,12 @@ def valid? end def environment_from_env - ENV['SENTRY_CURRENT_ENV'] || ENV['SENTRY_ENVIRONMENT'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development' + ENV["SENTRY_CURRENT_ENV"] || ENV["SENTRY_ENVIRONMENT"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development" end def server_name_from_env if running_on_heroku? - ENV['DYNO'] + ENV["DYNO"] else # Try to resolve the hostname to an FQDN, but fall back to whatever # the load name is. diff --git a/sentry-ruby/lib/sentry/core_ext/object/deep_dup.rb b/sentry-ruby/lib/sentry/core_ext/object/deep_dup.rb index d1141f128..2cc0d47f6 100644 --- a/sentry-ruby/lib/sentry/core_ext/object/deep_dup.rb +++ b/sentry-ruby/lib/sentry/core_ext/object/deep_dup.rb @@ -2,7 +2,7 @@ return if Object.method_defined?(:deep_dup) -require 'sentry/core_ext/object/duplicable' +require "sentry/core_ext/object/duplicable" ######################################### # This file was copied from Rails 5.2 # diff --git a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb index b7eee3f5f..ac7e35d81 100644 --- a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb +++ b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb @@ -57,7 +57,7 @@ def sentry_monitor_check_ins(slug: nil, monitor_config: nil) def sentry_monitor_slug(name: self.name) @sentry_monitor_slug ||= begin - slug = name.gsub('::', '-').downcase + slug = name.gsub("::", "-").downcase slug[-MAX_SLUG_LENGTH..-1] || slug end end diff --git a/sentry-ruby/lib/sentry/cron/monitor_config.rb b/sentry-ruby/lib/sentry/cron/monitor_config.rb index 68b8c709c..dfd28a4bd 100644 --- a/sentry-ruby/lib/sentry/cron/monitor_config.rb +++ b/sentry-ruby/lib/sentry/cron/monitor_config.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'sentry/cron/monitor_schedule' +require "sentry/cron/monitor_schedule" module Sentry module Cron diff --git a/sentry-ruby/lib/sentry/dsn.rb b/sentry-ruby/lib/sentry/dsn.rb index b05ace531..3877b57fb 100644 --- a/sentry-ruby/lib/sentry/dsn.rb +++ b/sentry-ruby/lib/sentry/dsn.rb @@ -4,7 +4,7 @@ module Sentry class DSN - PORT_MAP = { 'http' => 80, 'https' => 443 }.freeze + PORT_MAP = { "http" => 80, "https" => 443 }.freeze REQUIRED_ATTRIBUTES = %w[host path public_key project_id].freeze attr_reader :scheme, :secret_key, :port, *REQUIRED_ATTRIBUTES @@ -13,7 +13,7 @@ def initialize(dsn_string) @raw_value = dsn_string uri = URI.parse(dsn_string) - uri_path = uri.path.split('/') + uri_path = uri.path.split("/") if uri.user # DSN-style string @@ -25,7 +25,7 @@ def initialize(dsn_string) @scheme = uri.scheme @host = uri.host @port = uri.port if uri.port - @path = uri_path.join('/') + @path = uri_path.join("/") end def valid? diff --git a/sentry-ruby/lib/sentry/envelope.rb b/sentry-ruby/lib/sentry/envelope.rb index 51220a062..4e1d8acb2 100644 --- a/sentry-ruby/lib/sentry/envelope.rb +++ b/sentry-ruby/lib/sentry/envelope.rb @@ -15,19 +15,19 @@ def initialize(headers, payload) end def type - @headers[:type] || 'event' + @headers[:type] || "event" end # rate limits and client reports use the data_category rather than envelope item type def self.data_category(type) case type - when 'session', 'attachment', 'transaction', 'profile', 'span' then type - when 'sessions' then 'session' - when 'check_in' then 'monitor' - when 'statsd', 'metric_meta' then 'metric_bucket' - when 'event' then 'error' - when 'client_report' then 'internal' - else 'default' + when "session", "attachment", "transaction", "profile", "span" then type + when "sessions" then "session" + when "check_in" then "monitor" + when "statsd", "metric_meta" then "metric_bucket" + when "event" then "error" + when "client_report" then "internal" + else "default" end end diff --git a/sentry-ruby/lib/sentry/event.rb b/sentry-ruby/lib/sentry/event.rb index 7fbd6172c..154452599 100644 --- a/sentry-ruby/lib/sentry/event.rb +++ b/sentry-ruby/lib/sentry/event.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -require 'socket' -require 'securerandom' -require 'sentry/interface' -require 'sentry/backtrace' -require 'sentry/utils/real_ip' -require 'sentry/utils/request_id' -require 'sentry/utils/custom_inspection' +require "socket" +require "securerandom" +require "sentry/interface" +require "sentry/backtrace" +require "sentry/utils/real_ip" +require "sentry/utils/request_id" +require "sentry/utils/custom_inspection" module Sentry # This is an abstract class that defines the shared attributes of an event. diff --git a/sentry-ruby/lib/sentry/graphql.rb b/sentry-ruby/lib/sentry/graphql.rb index 17bb792c6..645481a4d 100644 --- a/sentry-ruby/lib/sentry/graphql.rb +++ b/sentry-ruby/lib/sentry/graphql.rb @@ -4,6 +4,6 @@ if defined?(::GraphQL::Schema) && defined?(::GraphQL::Tracing::SentryTrace) && ::GraphQL::Schema.respond_to?(:trace_with) ::GraphQL::Schema.trace_with(::GraphQL::Tracing::SentryTrace, set_transaction_name: true) else - config.logger.warn(Sentry::LOGGER_PROGNAME) { 'You tried to enable the GraphQL integration but no GraphQL gem was detected. Make sure you have the `graphql` gem (>= 2.2.6) in your Gemfile.' } + config.logger.warn(Sentry::LOGGER_PROGNAME) { "You tried to enable the GraphQL integration but no GraphQL gem was detected. Make sure you have the `graphql` gem (>= 2.2.6) in your Gemfile." } end end diff --git a/sentry-ruby/lib/sentry/interfaces/mechanism.rb b/sentry-ruby/lib/sentry/interfaces/mechanism.rb index 95179a77a..df672e7d9 100644 --- a/sentry-ruby/lib/sentry/interfaces/mechanism.rb +++ b/sentry-ruby/lib/sentry/interfaces/mechanism.rb @@ -12,7 +12,7 @@ class Mechanism < Interface # @return [Boolean] attr_accessor :handled - def initialize(type: 'generic', handled: true) + def initialize(type: "generic", handled: true) @type = type @handled = handled end diff --git a/sentry-ruby/lib/sentry/interfaces/request.rb b/sentry-ruby/lib/sentry/interfaces/request.rb index 519f7859a..4647e6562 100644 --- a/sentry-ruby/lib/sentry/interfaces/request.rb +++ b/sentry-ruby/lib/sentry/interfaces/request.rb @@ -59,7 +59,7 @@ def initialize(env:, send_default_pii:, rack_env_whitelist:) self.query_string = request.query_string end - self.url = request.scheme && request.url.split('?').first + self.url = request.scheme && request.url.split("?").first self.method = request.request_method self.headers = filter_and_format_headers(env, send_default_pii) @@ -85,14 +85,14 @@ def filter_and_format_headers(env, send_default_pii) env.each_with_object({}) do |(key, value), memo| begin key = key.to_s # rack env can contain symbols - next memo['X-Request-Id'] ||= Utils::RequestId.read_from(env) if Utils::RequestId::REQUEST_ID_HEADERS.include?(key) + next memo["X-Request-Id"] ||= Utils::RequestId.read_from(env) if Utils::RequestId::REQUEST_ID_HEADERS.include?(key) next if is_server_protocol?(key, value, env["SERVER_PROTOCOL"]) next if is_skippable_header?(key) next if key == "HTTP_AUTHORIZATION" && !send_default_pii # Rack stores headers as HTTP_WHAT_EVER, we need What-Ever key = key.sub(/^HTTP_/, "") - key = key.split('_').map(&:capitalize).join('-') + key = key.split("_").map(&:capitalize).join("-") memo[key] = Utils::EncodingHelper.encode_to_utf_8(value.to_s) rescue StandardError => e @@ -108,7 +108,7 @@ def filter_and_format_headers(env, send_default_pii) def is_skippable_header?(key) key.upcase != key || # lower-case envs aren't real http headers key == "HTTP_COOKIE" || # Cookies don't go here, they go somewhere else - !(key.start_with?('HTTP_') || CONTENT_HEADERS.include?(key)) + !(key.start_with?("HTTP_") || CONTENT_HEADERS.include?(key)) end # In versions < 3, Rack adds in an incorrect HTTP_VERSION key, which causes downstream @@ -120,7 +120,7 @@ def is_server_protocol?(key, value, protocol_version) rack_version = Gem::Version.new(::Rack.release) return false if rack_version >= Gem::Version.new("3.0") - key == 'HTTP_VERSION' && value == protocol_version + key == "HTTP_VERSION" && value == protocol_version end def filter_and_format_env(env, rack_env_whitelist) diff --git a/sentry-ruby/lib/sentry/interfaces/single_exception.rb b/sentry-ruby/lib/sentry/interfaces/single_exception.rb index d35491206..f7126e702 100644 --- a/sentry-ruby/lib/sentry/interfaces/single_exception.rb +++ b/sentry-ruby/lib/sentry/interfaces/single_exception.rb @@ -26,7 +26,7 @@ def initialize(exception:, mechanism:, stacktrace: nil) @value = Utils::EncodingHelper.encode_to_utf_8(exception_message.byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES)) - @module = exception.class.to_s.split('::')[0...-1].join('::') + @module = exception.class.to_s.split("::")[0...-1].join("::") @thread_id = Thread.current.object_id @stacktrace = stacktrace @mechanism = mechanism diff --git a/sentry-ruby/lib/sentry/logger.rb b/sentry-ruby/lib/sentry/logger.rb index 7f910d86e..b0e65f442 100644 --- a/sentry-ruby/lib/sentry/logger.rb +++ b/sentry-ruby/lib/sentry/logger.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'logger' +require "logger" module Sentry class Logger < ::Logger diff --git a/sentry-ruby/lib/sentry/metrics.rb b/sentry-ruby/lib/sentry/metrics.rb index 99bd9f7f1..bcab324f4 100644 --- a/sentry-ruby/lib/sentry/metrics.rb +++ b/sentry-ruby/lib/sentry/metrics.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -require 'sentry/metrics/metric' -require 'sentry/metrics/counter_metric' -require 'sentry/metrics/distribution_metric' -require 'sentry/metrics/gauge_metric' -require 'sentry/metrics/set_metric' -require 'sentry/metrics/timing' -require 'sentry/metrics/aggregator' +require "sentry/metrics/metric" +require "sentry/metrics/counter_metric" +require "sentry/metrics/distribution_metric" +require "sentry/metrics/gauge_metric" +require "sentry/metrics/set_metric" +require "sentry/metrics/timing" +require "sentry/metrics/aggregator" module Sentry module Metrics @@ -14,32 +14,32 @@ module Metrics INFORMATION_UNITS = %w[bit byte kilobyte kibibyte megabyte mebibyte gigabyte gibibyte terabyte tebibyte petabyte pebibyte exabyte exbibyte] FRACTIONAL_UNITS = %w[ratio percent] - OP_NAME = 'metric.timing' - SPAN_ORIGIN = 'auto.metric.timing' + OP_NAME = "metric.timing" + SPAN_ORIGIN = "auto.metric.timing" class << self - def increment(key, value = 1.0, unit: 'none', tags: {}, timestamp: nil) + def increment(key, value = 1.0, unit: "none", tags: {}, timestamp: nil) Sentry.metrics_aggregator&.add(:c, key, value, unit: unit, tags: tags, timestamp: timestamp) end - def distribution(key, value, unit: 'none', tags: {}, timestamp: nil) + def distribution(key, value, unit: "none", tags: {}, timestamp: nil) Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp) end - def set(key, value, unit: 'none', tags: {}, timestamp: nil) + def set(key, value, unit: "none", tags: {}, timestamp: nil) Sentry.metrics_aggregator&.add(:s, key, value, unit: unit, tags: tags, timestamp: timestamp) end - def gauge(key, value, unit: 'none', tags: {}, timestamp: nil) + def gauge(key, value, unit: "none", tags: {}, timestamp: nil) Sentry.metrics_aggregator&.add(:g, key, value, unit: unit, tags: tags, timestamp: timestamp) end - def timing(key, unit: 'second', tags: {}, timestamp: nil, &block) + def timing(key, unit: "second", tags: {}, timestamp: nil, &block) return unless block_given? return yield unless DURATION_UNITS.include?(unit) result, value = Sentry.with_child_span(op: OP_NAME, description: key, origin: SPAN_ORIGIN) do |span| - tags.each { |k, v| span.set_tag(k, v.is_a?(Array) ? v.join(', ') : v.to_s) } if span + tags.each { |k, v| span.set_tag(k, v.is_a?(Array) ? v.join(", ") : v.to_s) } if span start = Timing.send(unit.to_sym) result = yield diff --git a/sentry-ruby/lib/sentry/metrics/aggregator.rb b/sentry-ruby/lib/sentry/metrics/aggregator.rb index 45ffbd687..12ad54f69 100644 --- a/sentry-ruby/lib/sentry/metrics/aggregator.rb +++ b/sentry-ruby/lib/sentry/metrics/aggregator.rb @@ -41,8 +41,8 @@ def initialize(configuration, client) @stacktrace_builder = configuration.stacktrace_builder @default_tags = {} - @default_tags['release'] = configuration.release if configuration.release - @default_tags['environment'] = configuration.environment if configuration.environment + @default_tags["release"] = configuration.release if configuration.release + @default_tags["environment"] = configuration.environment if configuration.environment @mutex = Mutex.new @@ -59,7 +59,7 @@ def initialize(configuration, client) def add(type, key, value, - unit: 'none', + unit: "none", tags: {}, timestamp: nil, stacklevel: nil) @@ -98,7 +98,7 @@ def flush(force: false) unless flushable_buckets.empty? payload = serialize_buckets(flushable_buckets) envelope.add_item( - { type: 'statsd', length: payload.bytesize }, + { type: "statsd", length: payload.bytesize }, payload ) end @@ -107,7 +107,7 @@ def flush(force: false) code_locations.each do |timestamp, locations| payload = serialize_locations(timestamp, locations) envelope.add_item( - { type: 'metric_meta', content_type: 'application/json' }, + { type: "metric_meta", content_type: "application/json" }, payload ) end @@ -161,8 +161,8 @@ def serialize_buckets(buckets) buckets.map do |timestamp, timestamp_buckets| timestamp_buckets.map do |metric_key, metric| type, key, unit, tags = metric_key - values = metric.serialize.join(':') - sanitized_tags = tags.map { |k, v| "#{sanitize_tag_key(k)}:#{sanitize_tag_value(v)}" }.join(',') + values = metric.serialize.join(":") + sanitized_tags = tags.map { |k, v| "#{sanitize_tag_key(k)}:#{sanitize_tag_value(v)}" }.join(",") "#{sanitize_key(key)}@#{sanitize_unit(unit)}:#{values}|#{type}|\##{sanitized_tags}|T#{timestamp}" end @@ -175,22 +175,22 @@ def serialize_locations(timestamp, locations) mri = "#{type}:#{sanitize_key(key)}@#{sanitize_unit(unit)}" # note this needs to be an array but it really doesn't serve a purpose right now - [mri, [location.merge(type: 'location')]] + [mri, [location.merge(type: "location")]] end.to_h { timestamp: timestamp, mapping: mapping } end def sanitize_key(key) - key.gsub(KEY_SANITIZATION_REGEX, '_') + key.gsub(KEY_SANITIZATION_REGEX, "_") end def sanitize_unit(unit) - unit.gsub(UNIT_SANITIZATION_REGEX, '') + unit.gsub(UNIT_SANITIZATION_REGEX, "") end def sanitize_tag_key(key) - key.gsub(TAG_KEY_SANITIZATION_REGEX, '') + key.gsub(TAG_KEY_SANITIZATION_REGEX, "") end def sanitize_tag_value(value) @@ -209,7 +209,7 @@ def get_updated_tags(tags) updated_tags = @default_tags.merge(tags) transaction_name = get_transaction_name - updated_tags['transaction'] = transaction_name if transaction_name + updated_tags["transaction"] = transaction_name if transaction_name updated_tags end diff --git a/sentry-ruby/lib/sentry/metrics/set_metric.rb b/sentry-ruby/lib/sentry/metrics/set_metric.rb index 02c5c26a6..b38af2743 100644 --- a/sentry-ruby/lib/sentry/metrics/set_metric.rb +++ b/sentry-ruby/lib/sentry/metrics/set_metric.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'set' -require 'zlib' +require "set" +require "zlib" module Sentry module Metrics diff --git a/sentry-ruby/lib/sentry/profiler.rb b/sentry-ruby/lib/sentry/profiler.rb index 949a9aecb..cec7c70ce 100644 --- a/sentry-ruby/lib/sentry/profiler.rb +++ b/sentry-ruby/lib/sentry/profiler.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'securerandom' +require "securerandom" module Sentry class Profiler - VERSION = '1' - PLATFORM = 'ruby' + VERSION = "1" + PLATFORM = "ruby" # 101 Hz in microseconds DEFAULT_INTERVAL = 1e6 / 101 MICRO_TO_NANO_SECONDS = 1e3 @@ -14,7 +14,7 @@ class Profiler attr_reader :sampled, :started, :event_id def initialize(configuration) - @event_id = SecureRandom.uuid.delete('-') + @event_id = SecureRandom.uuid.delete("-") @started = false @sampled = nil @@ -33,7 +33,7 @@ def start raw: true, aggregate: false) - @started ? log('Started') : log('Not started since running elsewhere') + @started ? log("Started") : log("Not started since running elsewhere") end def stop @@ -41,7 +41,7 @@ def stop return unless @started StackProf.stop - log('Stopped') + log("Stopped") end # Sets initial sampling decision of the profile. @@ -54,14 +54,14 @@ def set_initial_sample_decision(transaction_sampled) unless transaction_sampled @sampled = false - log('Discarding profile because transaction not sampled') + log("Discarding profile because transaction not sampled") return end case @profiles_sample_rate when 0.0 @sampled = false - log('Discarding profile because sample_rate is 0') + log("Discarding profile because sample_rate is 0") return when 1.0 @sampled = true @@ -70,7 +70,7 @@ def set_initial_sample_decision(transaction_sampled) @sampled = Random.rand < @profiles_sample_rate end - log('Discarding profile due to sampling decision') unless @sampled + log("Discarding profile due to sampling decision") unless @sampled end def to_hash @@ -130,7 +130,7 @@ def to_hash num_seen << results[:raw][idx + len] idx += len + 1 - log('Unknown frame in stack') if stack.size != len + log("Unknown frame in stack") if stack.size != len end idx = 0 @@ -155,16 +155,16 @@ def to_hash # Till then, on multi-threaded servers like puma, we will get frames from other active threads when the one # we're profiling is idle/sleeping/waiting for IO etc. # https://bugs.ruby-lang.org/issues/10602 - thread_id: '0', + thread_id: "0", elapsed_since_start_ns: elapsed_since_start_ns.to_s } end end - log('Some samples thrown away') if samples.size != results[:samples] + log("Some samples thrown away") if samples.size != results[:samples] if samples.size <= MIN_SAMPLES_REQUIRED - log('Not enough samples, discarding profiler') + log("Not enough samples, discarding profiler") record_lost_event(:insufficient_data) return {} end @@ -219,7 +219,7 @@ def compute_filename(abs_path, in_app) def split_module(name) # last module plus class/instance method - i = name.rindex('::') + i = name.rindex("::") function = i ? name[(i + 2)..-1] : name mod = i ? name[0...i] : nil @@ -227,7 +227,7 @@ def split_module(name) end def record_lost_event(reason) - Sentry.get_current_client&.transport&.record_lost_event(reason, 'profile') + Sentry.get_current_client&.transport&.record_lost_event(reason, "profile") end end end diff --git a/sentry-ruby/lib/sentry/rack.rb b/sentry-ruby/lib/sentry/rack.rb index 03bff096c..ab565c6d1 100644 --- a/sentry-ruby/lib/sentry/rack.rb +++ b/sentry-ruby/lib/sentry/rack.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rack' +require "rack" -require 'sentry/rack/capture_exceptions' +require "sentry/rack/capture_exceptions" diff --git a/sentry-ruby/lib/sentry/rack/capture_exceptions.rb b/sentry-ruby/lib/sentry/rack/capture_exceptions.rb index 653188e10..5bb8eda67 100644 --- a/sentry-ruby/lib/sentry/rack/capture_exceptions.rb +++ b/sentry-ruby/lib/sentry/rack/capture_exceptions.rb @@ -50,7 +50,7 @@ def call(env) private def collect_exception(env) - env['rack.exception'] || env['sinatra.error'] + env["rack.exception"] || env["sinatra.error"] end def transaction_op diff --git a/sentry-ruby/lib/sentry/rake.rb b/sentry-ruby/lib/sentry/rake.rb index 0e3e6e8c7..243113023 100644 --- a/sentry-ruby/lib/sentry/rake.rb +++ b/sentry-ruby/lib/sentry/rake.rb @@ -8,10 +8,10 @@ module Rake module Application # @api private def display_error_message(ex) - mechanism = Sentry::Mechanism.new(type: 'rake', handled: false) + mechanism = Sentry::Mechanism.new(type: "rake", handled: false) Sentry.capture_exception(ex, hint: { mechanism: mechanism }) do |scope| - task_name = top_level_tasks.join(' ') + task_name = top_level_tasks.join(" ") scope.set_transaction_name(task_name, source: :task) scope.set_tag("rake_task", task_name) end if Sentry.initialized? && !Sentry.configuration.skip_rake_integration diff --git a/sentry-ruby/lib/sentry/release_detector.rb b/sentry-ruby/lib/sentry/release_detector.rb index a975520eb..c71b216a5 100644 --- a/sentry-ruby/lib/sentry/release_detector.rb +++ b/sentry-ruby/lib/sentry/release_detector.rb @@ -13,12 +13,12 @@ def detect_release(project_root:, running_on_heroku:) def detect_release_from_heroku(running_on_heroku) return unless running_on_heroku - ENV['HEROKU_SLUG_COMMIT'] + ENV["HEROKU_SLUG_COMMIT"] end def detect_release_from_capistrano(project_root) - revision_file = File.join(project_root, 'REVISION') - revision_log = File.join(project_root, '..', 'revisions.log') + revision_file = File.join(project_root, "REVISION") + revision_log = File.join(project_root, "..", "revisions.log") if File.exist?(revision_file) File.read(revision_file).strip @@ -32,7 +32,7 @@ def detect_release_from_git end def detect_release_from_env - ENV['SENTRY_RELEASE'] + ENV["SENTRY_RELEASE"] end end end diff --git a/sentry-ruby/lib/sentry/session_flusher.rb b/sentry-ruby/lib/sentry/session_flusher.rb index 5971cfc59..f992a3b20 100644 --- a/sentry-ruby/lib/sentry/session_flusher.rb +++ b/sentry-ruby/lib/sentry/session_flusher.rb @@ -44,7 +44,7 @@ def init_aggregates(aggregation_key) def pending_envelope envelope = Envelope.new - header = { type: 'sessions' } + header = { type: "sessions" } payload = { attrs: attrs, aggregates: @pending_aggregates.values } envelope.add_item(header, payload) diff --git a/sentry-ruby/lib/sentry/test_helper.rb b/sentry-ruby/lib/sentry/test_helper.rb index 7db34cbd2..212c35db5 100644 --- a/sentry-ruby/lib/sentry/test_helper.rb +++ b/sentry-ruby/lib/sentry/test_helper.rb @@ -1,6 +1,6 @@ module Sentry module TestHelper - DUMMY_DSN = 'http://12345:67890@sentry.localdomain/sentry/42' + DUMMY_DSN = "http://12345:67890@sentry.localdomain/sentry/42" # Alters the existing SDK configuration with test-suitable options. Mainly: # - Sets a dummy DSN instead of `nil` or an actual DSN. diff --git a/sentry-ruby/lib/sentry/transaction.rb b/sentry-ruby/lib/sentry/transaction.rb index 89d169512..ac6256555 100644 --- a/sentry-ruby/lib/sentry/transaction.rb +++ b/sentry-ruby/lib/sentry/transaction.rb @@ -265,8 +265,8 @@ def finish(hub: nil, end_timestamp: nil) else is_backpressure = Sentry.backpressure_monitor&.downsample_factor&.positive? reason = is_backpressure ? :backpressure : :sample_rate - hub.current_client.transport.record_lost_event(reason, 'transaction') - hub.current_client.transport.record_lost_event(reason, 'span') + hub.current_client.transport.record_lost_event(reason, "transaction") + hub.current_client.transport.record_lost_event(reason, "span") end end diff --git a/sentry-ruby/lib/sentry/transaction_event.rb b/sentry-ruby/lib/sentry/transaction_event.rb index d2e39dc1f..4136ac6aa 100644 --- a/sentry-ruby/lib/sentry/transaction_event.rb +++ b/sentry-ruby/lib/sentry/transaction_event.rb @@ -75,7 +75,7 @@ def populate_profile(transaction) name: transaction.name, trace_id: transaction.trace_id, # TODO-neel-profiler stubbed for now, see thread_id note in profiler.rb - active_thead_id: '0' + active_thead_id: "0" } ) diff --git a/sentry-ruby/lib/sentry/transport.rb b/sentry-ruby/lib/sentry/transport.rb index 39a993fe5..d446387f2 100644 --- a/sentry-ruby/lib/sentry/transport.rb +++ b/sentry-ruby/lib/sentry/transport.rb @@ -5,7 +5,7 @@ module Sentry class Transport - PROTOCOL_VERSION = '7' + PROTOCOL_VERSION = "7" USER_AGENT = "sentry-ruby/#{Sentry::VERSION}" CLIENT_REPORT_INTERVAL = 30 @@ -134,13 +134,13 @@ def envelope_from_event(event) envelope = Envelope.new(envelope_headers) envelope.add_item( - { type: item_type, content_type: 'application/json' }, + { type: item_type, content_type: "application/json" }, event_payload ) if event.is_a?(TransactionEvent) && event.profile envelope.add_item( - { type: 'profile', content_type: 'application/json' }, + { type: "profile", content_type: "application/json" }, event.profile ) end @@ -185,7 +185,7 @@ def fetch_pending_client_report(force: false) { reason: reason, category: category, quantity: val } end - item_header = { type: 'client_report' } + item_header = { type: "client_report" } item_payload = { timestamp: Sentry.utc_now.iso8601, discarded_events: discarded_events_hash diff --git a/sentry-ruby/lib/sentry/transport/http_transport.rb b/sentry-ruby/lib/sentry/transport/http_transport.rb index 4a9ee620f..e79bd0634 100644 --- a/sentry-ruby/lib/sentry/transport/http_transport.rb +++ b/sentry-ruby/lib/sentry/transport/http_transport.rb @@ -7,7 +7,7 @@ module Sentry class HTTPTransport < Transport GZIP_ENCODING = "gzip" GZIP_THRESHOLD = 1024 * 30 - CONTENT_TYPE = 'application/x-sentry-envelope' + CONTENT_TYPE = "application/x-sentry-envelope" DEFAULT_DELAY = 60 RETRY_AFTER_HEADER = "retry-after" @@ -38,13 +38,13 @@ def send_data(data) end headers = { - 'Content-Type' => CONTENT_TYPE, - 'Content-Encoding' => encoding, - 'User-Agent' => USER_AGENT + "Content-Type" => CONTENT_TYPE, + "Content-Encoding" => encoding, + "User-Agent" => USER_AGENT } auth_header = generate_auth_header - headers['X-Sentry-Auth'] = auth_header if auth_header + headers["X-Sentry-Auth"] = auth_header if auth_header response = conn.start do |http| request = ::Net::HTTP::Post.new(endpoint, headers) @@ -60,7 +60,7 @@ def send_data(data) else error_info = "the server responded with status #{response.code}" error_info += "\nbody: #{response.body}" - error_info += " Error in headers is: #{response['x-sentry-error']}" if response['x-sentry-error'] + error_info += " Error in headers is: #{response['x-sentry-error']}" if response["x-sentry-error"] raise Sentry::ExternalError, error_info end @@ -78,13 +78,13 @@ def generate_auth_header now = Sentry.utc_now.to_i fields = { - 'sentry_version' => PROTOCOL_VERSION, - 'sentry_client' => USER_AGENT, - 'sentry_timestamp' => now, - 'sentry_key' => @dsn.public_key + "sentry_version" => PROTOCOL_VERSION, + "sentry_client" => USER_AGENT, + "sentry_timestamp" => now, + "sentry_key" => @dsn.public_key } - fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key - 'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ') + fields["sentry_secret"] = @dsn.secret_key if @dsn.secret_key + "Sentry " + fields.map { |key, value| "#{key}=#{value}" }.join(", ") end def conn diff --git a/sentry-ruby/lib/sentry/utils/real_ip.rb b/sentry-ruby/lib/sentry/utils/real_ip.rb index d470051d7..08085bf19 100644 --- a/sentry-ruby/lib/sentry/utils/real_ip.rb +++ b/sentry-ruby/lib/sentry/utils/real_ip.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'ipaddr' +require "ipaddr" # Based on ActionDispatch::RemoteIp. All security-related precautions from that # middleware have been removed, because the Event IP just needs to be accurate, From 5c26b9e3a481a76a4b5e6245a8d4f78e83c13078 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 16 Aug 2024 18:27:22 +0200 Subject: [PATCH 27/96] Fix rubocop setup (for some envs) (#2377) * Fix rubocop setup (for some envs) This makes it possible to use rubocop when working from inside a subdir. It also fixes running rubocop from the root where it would actually use the config that we have. Previously it would ignore it for some reason, symlinking did the trick. The rubocop-packaging was needed because something somewhere tries to require it. * [sentry-opentelemetry] rubocop -a --only Style/StringLiterals * [sentry-rails] rubocop -a --only Style/StringLiterals * [sentry-resque] rubocop -a --only Style/StringLiterals * [sentry-sidekiq] rubocop -a --only Style/StringLiterals --- .rubocop.yml | 3 +- Gemfile | 1 + sentry-delayed_job/.rubocop.yml | 1 + sentry-opentelemetry/.rubocop.yml | 1 + .../lib/sentry/opentelemetry/propagator.rb | 8 +++--- .../sentry/opentelemetry/span_processor.rb | 6 ++-- sentry-rails/.rubocop.yml | 1 + sentry-rails/Gemfile | 2 +- .../lib/sentry/rails/capture_exceptions.rb | 2 +- .../lib/sentry/rails/configuration.rb | 28 +++++++++---------- .../sentry/rails/controller_transaction.rb | 2 +- sentry-rails/lib/sentry/rails/railtie.rb | 4 +-- sentry-resque/.rubocop.yml | 1 + sentry-resque/lib/sentry/resque.rb | 8 +++--- sentry-sidekiq/.rubocop.yml | 1 + .../lib/sentry/sidekiq/error_handler.rb | 2 +- .../sidekiq/sentry_context_middleware.rb | 2 +- 17 files changed, 40 insertions(+), 33 deletions(-) create mode 120000 sentry-delayed_job/.rubocop.yml create mode 120000 sentry-opentelemetry/.rubocop.yml create mode 120000 sentry-rails/.rubocop.yml create mode 120000 sentry-resque/.rubocop.yml create mode 120000 sentry-sidekiq/.rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml index cb409d1a8..451fd8589 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,4 +6,5 @@ Layout/SpaceInsideArrayLiteralBrackets: AllCops: Exclude: - - 'sentry-raven/**/*' + - "sentry-raven/**/*" + - "sentry-*/tmp/**/*" diff --git a/Gemfile b/Gemfile index c4344ea66..c42bc20c6 100644 --- a/Gemfile +++ b/Gemfile @@ -20,3 +20,4 @@ gem "simplecov-cobertura", "~> 1.4" gem "rexml" gem "rubocop-rails-omakase" +gem "rubocop-packaging" diff --git a/sentry-delayed_job/.rubocop.yml b/sentry-delayed_job/.rubocop.yml new file mode 120000 index 000000000..7cc18e076 --- /dev/null +++ b/sentry-delayed_job/.rubocop.yml @@ -0,0 +1 @@ +../.rubocop.yml \ No newline at end of file diff --git a/sentry-opentelemetry/.rubocop.yml b/sentry-opentelemetry/.rubocop.yml new file mode 120000 index 000000000..7cc18e076 --- /dev/null +++ b/sentry-opentelemetry/.rubocop.yml @@ -0,0 +1 @@ +../.rubocop.yml \ No newline at end of file diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/propagator.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/propagator.rb index 7bfb5424a..51045e209 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/propagator.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/propagator.rb @@ -5,8 +5,8 @@ module OpenTelemetry class Propagator FIELDS = [SENTRY_TRACE_HEADER_NAME, BAGGAGE_HEADER_NAME].freeze - SENTRY_TRACE_KEY = ::OpenTelemetry::Context.create_key('sentry-trace') - SENTRY_BAGGAGE_KEY = ::OpenTelemetry::Context.create_key('sentry-baggage') + SENTRY_TRACE_KEY = ::OpenTelemetry::Context.create_key("sentry-trace") + SENTRY_BAGGAGE_KEY = ::OpenTelemetry::Context.create_key("sentry-baggage") def inject( carrier, @@ -41,8 +41,8 @@ def extract( trace_id, span_id, _parent_sampled = sentry_trace_data span_context = ::OpenTelemetry::Trace::SpanContext.new( - trace_id: [trace_id].pack('H*'), - span_id: [span_id].pack('H*'), + trace_id: [trace_id].pack("H*"), + span_id: [span_id].pack("H*"), # we simulate a sampled trace on the otel side and leave the sampling to sentry trace_flags: ::OpenTelemetry::Trace::TraceFlags::SAMPLED, remote: true diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb index 71152ad29..fceef7e64 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'singleton' +require "singleton" module Sentry module OpenTelemetry @@ -151,14 +151,14 @@ def update_span_status(sentry_span, otel_span) if (http_status_code = otel_span.attributes[SEMANTIC_CONVENTIONS::HTTP_STATUS_CODE]) sentry_span.set_http_status(http_status_code) elsif (status_code = otel_span.status.code) - status = [0, 1].include?(status_code) ? 'ok' : 'unknown_error' + status = [0, 1].include?(status_code) ? "ok" : "unknown_error" sentry_span.set_status(status) end end def update_span_with_otel_data(sentry_span, otel_span) update_span_status(sentry_span, otel_span) - sentry_span.set_data('otel.kind', otel_span.kind) + sentry_span.set_data("otel.kind", otel_span.kind) otel_span.attributes&.each { |k, v| sentry_span.set_data(k, v) } op, description = parse_span_description(otel_span) diff --git a/sentry-rails/.rubocop.yml b/sentry-rails/.rubocop.yml new file mode 120000 index 000000000..7cc18e076 --- /dev/null +++ b/sentry-rails/.rubocop.yml @@ -0,0 +1 @@ +../.rubocop.yml \ No newline at end of file diff --git a/sentry-rails/Gemfile b/sentry-rails/Gemfile index 8449f342a..c67dbefce 100644 --- a/sentry-rails/Gemfile +++ b/sentry-rails/Gemfile @@ -6,7 +6,7 @@ gemspec gem "sentry-ruby", path: "../sentry-ruby" platform :jruby do - gem 'activerecord-jdbcmysql-adapter' + gem "activerecord-jdbcmysql-adapter" gem "jdbc-sqlite3" end diff --git a/sentry-rails/lib/sentry/rails/capture_exceptions.rb b/sentry-rails/lib/sentry/rails/capture_exceptions.rb index d52456081..3216d2a3a 100644 --- a/sentry-rails/lib/sentry/rails/capture_exceptions.rb +++ b/sentry-rails/lib/sentry/rails/capture_exceptions.rb @@ -2,7 +2,7 @@ module Sentry module Rails class CaptureExceptions < Sentry::Rack::CaptureExceptions RAILS_7_1 = Gem::Version.new(::Rails.version) >= Gem::Version.new("7.1.0.alpha") - SPAN_ORIGIN = 'auto.http.rails'.freeze + SPAN_ORIGIN = "auto.http.rails".freeze def initialize(_) super diff --git a/sentry-rails/lib/sentry/rails/configuration.rb b/sentry-rails/lib/sentry/rails/configuration.rb index 883700142..609e03ca4 100644 --- a/sentry-rails/lib/sentry/rails/configuration.rb +++ b/sentry-rails/lib/sentry/rails/configuration.rb @@ -31,20 +31,20 @@ class Configuration module Rails IGNORE_DEFAULT = [ - 'AbstractController::ActionNotFound', - 'ActionController::BadRequest', - 'ActionController::InvalidAuthenticityToken', - 'ActionController::InvalidCrossOriginRequest', - 'ActionController::MethodNotAllowed', - 'ActionController::NotImplemented', - 'ActionController::ParameterMissing', - 'ActionController::RoutingError', - 'ActionController::UnknownAction', - 'ActionController::UnknownFormat', - 'ActionDispatch::Http::MimeNegotiation::InvalidType', - 'ActionController::UnknownHttpMethod', - 'ActionDispatch::Http::Parameters::ParseError', - 'ActiveRecord::RecordNotFound' + "AbstractController::ActionNotFound", + "ActionController::BadRequest", + "ActionController::InvalidAuthenticityToken", + "ActionController::InvalidCrossOriginRequest", + "ActionController::MethodNotAllowed", + "ActionController::NotImplemented", + "ActionController::ParameterMissing", + "ActionController::RoutingError", + "ActionController::UnknownAction", + "ActionController::UnknownFormat", + "ActionDispatch::Http::MimeNegotiation::InvalidType", + "ActionController::UnknownHttpMethod", + "ActionDispatch::Http::Parameters::ParseError", + "ActiveRecord::RecordNotFound" ].freeze ACTIVE_SUPPORT_LOGGER_SUBSCRIPTION_ITEMS_DEFAULT = { diff --git a/sentry-rails/lib/sentry/rails/controller_transaction.rb b/sentry-rails/lib/sentry/rails/controller_transaction.rb index b85506a3d..cd3ffa38b 100644 --- a/sentry-rails/lib/sentry/rails/controller_transaction.rb +++ b/sentry-rails/lib/sentry/rails/controller_transaction.rb @@ -1,7 +1,7 @@ module Sentry module Rails module ControllerTransaction - SPAN_ORIGIN = 'auto.view.rails'.freeze + SPAN_ORIGIN = "auto.view.rails".freeze def self.included(base) base.prepend_around_action(:sentry_around_action) diff --git a/sentry-rails/lib/sentry/rails/railtie.rb b/sentry-rails/lib/sentry/rails/railtie.rb index 44dd450dc..e4926cc0f 100644 --- a/sentry-rails/lib/sentry/rails/railtie.rb +++ b/sentry-rails/lib/sentry/rails/railtie.rb @@ -94,14 +94,14 @@ def patch_background_worker def inject_breadcrumbs_logger if Sentry.configuration.breadcrumbs_logger.include?(:active_support_logger) - require 'sentry/rails/breadcrumb/active_support_logger' + require "sentry/rails/breadcrumb/active_support_logger" Sentry::Rails::Breadcrumb::ActiveSupportLogger.inject(Sentry.configuration.rails.active_support_logger_subscription_items) end if Sentry.configuration.breadcrumbs_logger.include?(:monotonic_active_support_logger) return warn "Usage of `monotonic_active_support_logger` require a version of Rails >= 6.1, please upgrade your Rails version or use another logger" if ::Rails.version.to_f < 6.1 - require 'sentry/rails/breadcrumb/monotonic_active_support_logger' + require "sentry/rails/breadcrumb/monotonic_active_support_logger" Sentry::Rails::Breadcrumb::MonotonicActiveSupportLogger.inject end end diff --git a/sentry-resque/.rubocop.yml b/sentry-resque/.rubocop.yml new file mode 120000 index 000000000..7cc18e076 --- /dev/null +++ b/sentry-resque/.rubocop.yml @@ -0,0 +1 @@ +../.rubocop.yml \ No newline at end of file diff --git a/sentry-resque/lib/sentry/resque.rb b/sentry-resque/lib/sentry/resque.rb index 84907d84f..4ef85e0dc 100644 --- a/sentry-resque/lib/sentry/resque.rb +++ b/sentry-resque/lib/sentry/resque.rb @@ -40,14 +40,14 @@ def record(queue, worker, payload, &block) finish_transaction(transaction, 200) rescue Exception => exception - klass = if payload['class'].respond_to?(:constantize) - payload['class'].constantize + klass = if payload["class"].respond_to?(:constantize) + payload["class"].constantize else - Object.const_get(payload['class']) + Object.const_get(payload["class"]) end raise if Sentry.configuration.resque.report_after_job_retries && - defined?(::Resque::Plugins::Retry) == 'constant' && + defined?(::Resque::Plugins::Retry) == "constant" && klass.is_a?(::Resque::Plugins::Retry) && !klass.retry_limit_reached? diff --git a/sentry-sidekiq/.rubocop.yml b/sentry-sidekiq/.rubocop.yml new file mode 120000 index 000000000..7cc18e076 --- /dev/null +++ b/sentry-sidekiq/.rubocop.yml @@ -0,0 +1 @@ +../.rubocop.yml \ No newline at end of file diff --git a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb index 41fd9e933..d1f7eaf87 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb @@ -1,4 +1,4 @@ -require 'sentry/sidekiq/context_filter' +require "sentry/sidekiq/context_filter" module Sentry module Sidekiq diff --git a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb index 748ca0155..e43acb653 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'sentry/sidekiq/context_filter' +require "sentry/sidekiq/context_filter" module Sentry module Sidekiq From 22f2a3a2275c046e30f4a901d5286f09355d6d8a Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Fri, 16 Aug 2024 17:28:58 +0100 Subject: [PATCH 28/96] feat: Add support for $SENTRY_DEBUG and $SENTRY_SPOTLIGHT (#2374) * feat: Add support for $SENTRY_DEBUG and $SENTRY_SPOTLIGHT Part of getsentry/spotlight#482. Similar to sentry-python#3443 but it also adds support for `$SENTRY_DEBUG` which was lacking in the Ruby SDK. * rubocop power! * add changelog entry * changelog with pr ref * try again * now? * maybe now? * fix typo * default to false rather than nil * use `self.` instead of module name Co-authored-by: Neel Shah * add tests --------- Co-authored-by: Burak Yigit Kaya Co-authored-by: Neel Shah --- CHANGELOG.md | 37 +++++++----- sentry-ruby/lib/sentry/configuration.rb | 12 ++-- sentry-ruby/lib/sentry/utils/env_helper.rb | 21 +++++++ sentry-ruby/spec/sentry/configuration_spec.rb | 58 +++++++++++++++++++ 4 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 sentry-ruby/lib/sentry/utils/env_helper.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cfdbbc5f..8937d0134 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## Unreleased + +- Add support for $SENTRY_DEBUG and $SENTRY_SPOTLIGHT ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) + ## 5.19.0 ### Features @@ -6,7 +10,7 @@ - Support for tracing Faraday requests ([#2345](https://github.com/getsentry/sentry-ruby/pull/2345)) - Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795) - - Please note that the Faraday instrumentation has some limitations in case of async requests: https://github.com/lostisland/faraday/issues/1381 + - Please note that the Faraday instrumentation has some limitations in case of async requests: Usage: @@ -32,6 +36,7 @@ - Inject Sentry meta tags in the Rails application layout automatically in the generator ([#2369](https://github.com/getsentry/sentry-ruby/pull/2369)) To turn this behavior off, use + ```bash bin/rails generate sentry --inject-meta false ``` @@ -256,6 +261,7 @@ config.cron.default_timezone = 'America/New_York' end ``` + - Clean up logging [#2216](https://github.com/getsentry/sentry-ruby/pull/2216) - Pick up config.cron.default_timezone from Rails config [#2213](https://github.com/getsentry/sentry-ruby/pull/2213) - Don't add most scope data (tags/extra/breadcrumbs) to `CheckInEvent` [#2217](https://github.com/getsentry/sentry-ruby/pull/2217) @@ -303,6 +309,7 @@ ```rb config.enabled_patches += [:sidekiq_cron] ``` + - Add support for [`sidekiq-scheduler`](https://github.com/sidekiq-scheduler/sidekiq-scheduler) [#2172](https://github.com/getsentry/sentry-ruby/pull/2172) You can opt in to the `sidekiq-scheduler` patch and we will automatically monitor check-ins for all repeating jobs (i.e. `cron`, `every`, and `interval`) specified in the config. @@ -331,6 +338,7 @@ config.rails.active_support_logger_subscription_items.delete("sql.active_record") config.rails.active_support_logger_subscription_items["foo"] = :bar ``` + - Enable opting out of patches [#2151](https://github.com/getsentry/sentry-ruby/pull/2151) ### Bug Fixes @@ -358,6 +366,7 @@ # do job stuff Sentry.capture_check_in('job_name', :ok, check_in_id: check_in_id) ``` + - Add `Sentry::Cron::MonitorCheckIns` module for automatic monitoring of jobs [#2130](https://github.com/getsentry/sentry-ruby/pull/2130) Standard job frameworks such as `ActiveJob` and `Sidekiq` can now use this module to automatically capture check ins. @@ -388,6 +397,7 @@ ``` You can pass in optional attributes to `sentry_monitor_check_ins` as follows. + ```rb # slug defaults to the job class name sentry_monitor_check_ins slug: 'custom_slug' @@ -427,6 +437,7 @@ config.trace_propagation_targets = [/.*/] # default is to all targets config.trace_propagation_targets = [/example.com/, 'foobar.org/api/v2'] ``` + - Tracing without Performance - Implement `PropagationContext` on `Scope` and add `Sentry.get_trace_propagation_headers` API [#2084](https://github.com/getsentry/sentry-ruby/pull/2084) - Implement `Sentry.continue_trace` API [#2089](https://github.com/getsentry/sentry-ruby/pull/2089) @@ -466,7 +477,6 @@ - Use allowlist to filter `ActiveSupport` breadcrumbs' data [#2048](https://github.com/getsentry/sentry-ruby/pull/2048) - ErrorHandler should cleanup the scope ([#2059](https://github.com/getsentry/sentry-ruby/pull/2059)) - ## 5.9.0 ### Features @@ -484,6 +494,7 @@ Sentry.capture_exception(ignored_exception) # won't be sent to Sentry Sentry.capture_exception(ignored_exception, hint: { ignore_exclusions: true }) # will be sent to Sentry ``` + - Support capturing low-level errors propagated to Puma [#2026](https://github.com/getsentry/sentry-ruby/pull/2026) - Add `spec` to `Backtrace::APP_DIRS_PATTERN` [#2029](https://github.com/getsentry/sentry-ruby/pull/2029) @@ -522,7 +533,7 @@ > **Warning** > Profiling is currently in beta. Beta features are still in-progress and may have bugs. We recognize the irony. - > If you have any questions or feedback, please email us at profiling@sentry.io, reach out via Discord (#profiling), or open an issue. + > If you have any questions or feedback, please email us at , reach out via Discord (#profiling), or open an issue. ### Bug Fixes @@ -617,8 +628,8 @@ ``` - Use `Sentry.with_child_span` in redis and net/http instead of `span.start_child` [#1920](https://github.com/getsentry/sentry-ruby/pull/1920) - - This might change the nesting of some spans and make it more accurate - - Followup fix to set the sentry-trace header in the correct place [#1922](https://github.com/getsentry/sentry-ruby/pull/1922) + - This might change the nesting of some spans and make it more accurate + - Followup fix to set the sentry-trace header in the correct place [#1922](https://github.com/getsentry/sentry-ruby/pull/1922) - Use `Exception#detailed_message` when generating exception message if applicable [#1924](https://github.com/getsentry/sentry-ruby/pull/1924) - Make `sentry-sidekiq` compatible with Sidekiq 7 [#1930](https://github.com/getsentry/sentry-ruby/pull/1930) @@ -626,10 +637,10 @@ ### Bug Fixes - `Sentry::BackgroundWorker` will release `ActiveRecord` connection pool only when the `ActiveRecord` connection is established -- Remove bad encoding arguments in redis span descriptions [#1914](https://github.com/getsentry/sentry-ruby/pull/1914) - - Fixes [#1911](https://github.com/getsentry/sentry-ruby/issues/1911) +- Remove bad encoding arguments in redis span descriptions [#1914](https://github.com/getsentry/sentry-ruby/pull/1914) + - Fixes [#1911](https://github.com/getsentry/sentry-ruby/issues/1911) - Add missing `initialized?` checks to `sentry-rails` [#1919](https://github.com/getsentry/sentry-ruby/pull/1919) - - Fixes [#1885](https://github.com/getsentry/sentry-ruby/issues/1885) + - Fixes [#1885](https://github.com/getsentry/sentry-ruby/issues/1885) - Update Tracing Span's op names [#1923](https://github.com/getsentry/sentry-ruby/pull/1923) Currently, Ruby integrations' Span op names aren't aligned with the core specification's convention, so we decided to update them altogether in this PR. @@ -706,6 +717,7 @@ 1/0 #=> ZeroDivisionError will be reported and re-raised end ``` + - Prepare for Rails 7.1's error reporter API change [#1834](https://github.com/getsentry/sentry-ruby/pull/1834) - Set `sentry.error_event_id` in request env if the middleware captures errors [#1849](https://github.com/getsentry/sentry-ruby/pull/1849) @@ -858,7 +870,6 @@ end This will help users report size-related issues in the future. - - Automatic session tracking [#1715](https://github.com/getsentry/sentry-ruby/pull/1715) **Example**: @@ -877,7 +888,6 @@ end To disable this feature, set `config.auto_session_tracking` to `false`. - ### Bug Fixes - Require set library [#1753](https://github.com/getsentry/sentry-ruby/pull/1753) @@ -892,7 +902,6 @@ end - Avoid duplicated capturing on the same exception object [#1738](https://github.com/getsentry/sentry-ruby/pull/1738) - Fixes [#1731](https://github.com/getsentry/sentry-ruby/issues/1731) - ### Refactoring - Encapsulate extension helpers [#1725](https://github.com/getsentry/sentry-ruby/pull/1725) @@ -957,7 +966,6 @@ end This version removes the dependency of [faraday](https://github.com/lostisland/faraday) and replaces related implementation with the `Net::HTTP` standard library. - #### Why? Since the old `sentry-raven` SDK, we've been using `faraday` as the HTTP client for years (see [HTTPTransport](https://github.com/getsentry/sentry-ruby/blob/4-9/sentry-ruby/lib/sentry/transport/http_transport.rb)). It's an amazing tool that saved us many work and allowed us to focus on SDK features. @@ -972,10 +980,8 @@ And with the release of [faraday 2.0](https://github.com/lostisland/faraday/rele So we think it's time to say goodbye to it with this release. - #### What's changed? - By default, the SDK used `faraday`'s `net_http` adapter, which is also built on top of `Net::HTTP`. So this change shouldn't impact most of the users. The only noticeable changes are the removal of 2 faraday-specific transport configurations: @@ -1076,7 +1082,6 @@ end 2. Set `config.transport.transport = FaradayTransport` - **Please keep in mind that this may not work in the future when the SDK changes its `HTTPTransport` implementation.** ## 4.9.2 @@ -1216,7 +1221,6 @@ When `config.send_default_pii` is set as `true`, `:http_logger` will include que - Start Testing Against Rails 7.0 [#1581](https://github.com/getsentry/sentry-ruby/pull/1581) - ## 4.7.3 - Avoid leaking tracing timestamp to breadcrumbs [#1575](https://github.com/getsentry/sentry-ruby/pull/1575) @@ -1235,6 +1239,7 @@ When `config.send_default_pii` is set as `true`, `:http_logger` will include que ## 4.7.1 ### Bug Fixes + - Send events when report_after_job_retries is true and a job is configured with retry: 0 [#1557](https://github.com/getsentry/sentry-ruby/pull/1557) - Fixes [#1556](https://github.com/getsentry/sentry-ruby/issues/1556) diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index 44ea574b4..4fb927cb4 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -3,7 +3,8 @@ require "concurrent/utility/processor_counter" require "sentry/utils/exception_cause_chain" -require "sentry/utils/custom_inspection" +require 'sentry/utils/custom_inspection' +require 'sentry/utils/env_helper' require "sentry/dsn" require "sentry/release_detector" require "sentry/transport/configuration" @@ -350,7 +351,7 @@ def add_post_initialization_callback(&block) def initialize self.app_dirs_pattern = nil - self.debug = false + self.debug = Sentry::Utils::EnvHelper.env_to_bool(ENV["SENTRY_DEBUG"]) self.background_worker_threads = (processor_count / 2.0).ceil self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE self.backtrace_cleanup_callback = nil @@ -376,8 +377,11 @@ def initialize self.auto_session_tracking = true self.enable_backpressure_handling = false self.trusted_proxies = [] - self.dsn = ENV["SENTRY_DSN"] - self.spotlight = false + self.dsn = ENV['SENTRY_DSN'] + + spotlight_env = ENV['SENTRY_SPOTLIGHT'] + spotlight_bool = Sentry::Utils::EnvHelper.env_to_bool(spotlight_env, strict: true) + self.spotlight = spotlight_bool.nil? ? (spotlight_env || false) : spotlight_bool self.server_name = server_name_from_env self.instrumenter = :sentry self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL] diff --git a/sentry-ruby/lib/sentry/utils/env_helper.rb b/sentry-ruby/lib/sentry/utils/env_helper.rb new file mode 100644 index 000000000..a1a143d61 --- /dev/null +++ b/sentry-ruby/lib/sentry/utils/env_helper.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Sentry + module Utils + module EnvHelper + TRUTHY_ENV_VALUES = %w[t true yes y 1 on].freeze + FALSY_ENV_VALUES = %w[f false no n 0 off].freeze + + def self.env_to_bool(value, strict: false) + value = value.to_s + normalized = value.downcase + + return false if FALSY_ENV_VALUES.include?(normalized) + + return true if TRUTHY_ENV_VALUES.include?(normalized) + + strict ? nil : !(value.nil? || value.empty?) + end + end + end +end diff --git a/sentry-ruby/spec/sentry/configuration_spec.rb b/sentry-ruby/spec/sentry/configuration_spec.rb index 92926836a..7ebd32920 100644 --- a/sentry-ruby/spec/sentry/configuration_spec.rb +++ b/sentry-ruby/spec/sentry/configuration_spec.rb @@ -278,9 +278,67 @@ end describe "#spotlight" do + before do + ENV.delete('SENTRY_SPOTLIGHT') + end + + after do + ENV.delete('SENTRY_SPOTLIGHT') + end + it "false by default" do expect(subject.spotlight).to eq(false) end + + it 'uses `SENTRY_SPOTLIGHT` env variable for truthy' do + ENV['SENTRY_SPOTLIGHT'] = 'on' + + expect(subject.spotlight).to eq(true) + end + + it 'uses `SENTRY_SPOTLIGHT` env variable for falsy' do + ENV['SENTRY_SPOTLIGHT'] = '0' + + expect(subject.spotlight).to eq(false) + end + + it 'uses `SENTRY_SPOTLIGHT` env variable for custom value' do + ENV['SENTRY_SPOTLIGHT'] = 'https://my.remote.server:8080/stream' + + expect(subject.spotlight).to eq('https://my.remote.server:8080/stream') + end + end + + describe "#debug" do + before do + ENV.delete('SENTRY_DEBUG') + end + + after do + ENV.delete('SENTRY_DEBUG') + end + + it "false by default" do + expect(subject.debug).to eq(false) + end + + it 'uses `SENTRY_DEBUG` env variable for truthy' do + ENV['SENTRY_DEBUG'] = 'on' + + expect(subject.debug).to eq(true) + end + + it 'uses `SENTRY_DEBUG` env variable for falsy' do + ENV['SENTRY_DEBUG'] = '0' + + expect(subject.debug).to eq(false) + end + + it 'uses `SENTRY_DEBUG` env variable to turn on random value' do + ENV['SENTRY_DEBUG'] = 'yabadabadoo' + + expect(subject.debug).to eq(true) + end end describe "#sending_allowed?" do From 6181b7bab798cdf3b846d853de5d4b00b706dfee Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Mon, 19 Aug 2024 21:12:18 +0100 Subject: [PATCH 29/96] Support Rails 7.2 on CI (#2382) * Support Rails 7.2 on CI * Use Rails config to silence deprecation --- .github/workflows/sentry_rails_test.yml | 3 +++ sentry-rails/Gemfile | 6 ++++-- sentry-rails/spec/dummy/test_rails_app/app.rb | 9 ++++++++- .../spec/isolated/active_job_activation.rb | 2 ++ sentry-rails/spec/sentry/generator_spec.rb | 8 +++++++- sentry-rails/spec/sentry/rails/client_spec.rb | 14 +++++++++++--- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index ceabdc6af..9e1e55d8a 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -43,6 +43,9 @@ jobs: - { ruby_version: "2.7", rails_version: 5.2.0 } - { ruby_version: "2.7", rails_version: 6.0.0 } - { ruby_version: "2.7", rails_version: 6.1.0 } + - { ruby_version: "3.1", rails_version: 7.2.0 } + - { ruby_version: "3.2", rails_version: 7.2.0 } + - { ruby_version: "3.3", rails_version: 7.2.0 } - { ruby_version: "jruby", rails_version: 6.1.0 } - { ruby_version: "3.2", diff --git a/sentry-rails/Gemfile b/sentry-rails/Gemfile index c67dbefce..e203e41a1 100644 --- a/sentry-rails/Gemfile +++ b/sentry-rails/Gemfile @@ -24,11 +24,14 @@ else end end -if rails_version >= Gem::Version.new("7.2.0.alpha") +if rails_version >= Gem::Version.new("8.0.0.alpha") gem "rails", github: "rails/rails" + gem "rspec-rails" elsif rails_version >= Gem::Version.new("7.1.0") gem "rails", "~> #{rails_version}" + gem "rspec-rails" else + gem "rspec-rails", "~> 4.0" gem "rails", "~> #{rails_version}" gem "psych", "~> 3.0.0" end @@ -39,7 +42,6 @@ gem "sprockets-rails" gem "sidekiq" -gem "rspec-rails", "~> 4.0" ruby_version = Gem::Version.new(RUBY_VERSION) diff --git a/sentry-rails/spec/dummy/test_rails_app/app.rb b/sentry-rails/spec/dummy/test_rails_app/app.rb index af5a54400..302723863 100644 --- a/sentry-rails/spec/dummy/test_rails_app/app.rb +++ b/sentry-rails/spec/dummy/test_rails_app/app.rb @@ -9,7 +9,6 @@ require 'sentry/rails' -ActiveSupport::Deprecation.silenced = true ActiveRecord::Base.logger = Logger.new(nil) ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: "db") @@ -50,6 +49,7 @@ def self.name end end + app.config.active_support.deprecation = :silence app.config.action_controller.view_paths = "spec/dummy/test_rails_app" app.config.hosts = nil app.config.secret_key_base = "test" @@ -57,6 +57,13 @@ def self.name app.config.eager_load = true app.config.active_job.queue_adapter = :test + # Eager load namespaces can be accumulated after repeated initializations and make initialization + # slower after each run + # This is especially obvious in Rails 7.2, because of https://github.com/rails/rails/pull/49987, but other constants's + # accumulation can also cause slowdown + # Because this is not necessary for the test, we can simply clear it here + app.config.eager_load_namespaces.clear + configure_app(app) app.routes.append do diff --git a/sentry-rails/spec/isolated/active_job_activation.rb b/sentry-rails/spec/isolated/active_job_activation.rb index e4ab3f358..e8c8cb571 100644 --- a/sentry-rails/spec/isolated/active_job_activation.rb +++ b/sentry-rails/spec/isolated/active_job_activation.rb @@ -2,6 +2,8 @@ # for https://github.com/getsentry/sentry-ruby/issues/1249 require "active_job/railtie" +# Rails 7.2 added HealthCheckController, which requires ActionController +require "action_controller/railtie" require "active_support/all" require "sentry/rails" require "minitest/autorun" diff --git a/sentry-rails/spec/sentry/generator_spec.rb b/sentry-rails/spec/sentry/generator_spec.rb index 7da9e12a7..0e1f6856f 100644 --- a/sentry-rails/spec/sentry/generator_spec.rb +++ b/sentry-rails/spec/sentry/generator_spec.rb @@ -4,8 +4,14 @@ require "rails/generators/test_case" require "generators/sentry_generator" +behavior_module = if defined?(Rails::Generators::Testing::Behaviour) + Rails::Generators::Testing::Behaviour +else + Rails::Generators::Testing::Behavior +end + RSpec.describe SentryGenerator do - include ::Rails::Generators::Testing::Behaviour + include behavior_module include FileUtils self.destination File.expand_path('../../tmp', __dir__) self.generator_class = described_class diff --git a/sentry-rails/spec/sentry/rails/client_spec.rb b/sentry-rails/spec/sentry/rails/client_spec.rb index 6c6403f16..81c847b9d 100644 --- a/sentry-rails/spec/sentry/rails/client_spec.rb +++ b/sentry-rails/spec/sentry/rails/client_spec.rb @@ -5,8 +5,16 @@ Sentry.get_current_client.transport end + let(:expected_initial_active_record_connections_count) do + if Gem::Version.new(Rails.version) < Gem::Version.new('7.2.0') + 1 + else + 0 + end + end + before do - expect(ActiveRecord::Base.connection_pool.stat[:busy]).to eq(1) + expect(ActiveRecord::Base.connection_pool.stat[:busy]).to eq(expected_initial_active_record_connections_count) end def send_events @@ -35,7 +43,7 @@ def send_events expect(transport.events.count).to eq(5) - expect(ActiveRecord::Base.connection_pool.stat[:busy]).to eq(1) + expect(ActiveRecord::Base.connection_pool.stat[:busy]).to eq(expected_initial_active_record_connections_count) end end @@ -53,7 +61,7 @@ def send_events expect(transport.events.count).to eq(5) - expect(ActiveRecord::Base.connection_pool.stat[:busy]).to eq(1) + expect(ActiveRecord::Base.connection_pool.stat[:busy]).to eq(expected_initial_active_record_connections_count) end end end From 9d23b6faba2101fd3b7fc81570f73548c5fb131e Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 22 Aug 2024 13:09:40 +0200 Subject: [PATCH 30/96] Add a generic way for skipping specs (#2385) --- sentry-ruby/spec/sentry/event_spec.rb | 2 +- sentry-ruby/spec/sentry/profiler_spec.rb | 4 +--- .../spec/sentry/rack/capture_exceptions_spec.rb | 4 +--- sentry-ruby/spec/sentry/scope/setters_spec.rb | 2 +- sentry-ruby/spec/sentry/scope_spec.rb | 2 +- sentry-ruby/spec/spec_helper.rb | 16 ++++++++++++++-- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/sentry-ruby/spec/sentry/event_spec.rb b/sentry-ruby/spec/sentry/event_spec.rb index 5eeb232f9..ea59f95e1 100644 --- a/sentry-ruby/spec/sentry/event_spec.rb +++ b/sentry-ruby/spec/sentry/event_spec.rb @@ -66,7 +66,7 @@ end end - context 'rack context specified', rack: true do + context 'rack context specified', when: :rack_available? do require 'stringio' before do diff --git a/sentry-ruby/spec/sentry/profiler_spec.rb b/sentry-ruby/spec/sentry/profiler_spec.rb index 215e739be..e0cba8177 100644 --- a/sentry-ruby/spec/sentry/profiler_spec.rb +++ b/sentry-ruby/spec/sentry/profiler_spec.rb @@ -1,8 +1,6 @@ require "spec_helper" -return unless defined?(StackProf) - -RSpec.describe Sentry::Profiler do +RSpec.describe Sentry::Profiler, when: :stack_prof_installed? do before do perform_basic_setup do |config| config.traces_sample_rate = 1.0 diff --git a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb index e03984cdf..e2a226f77 100644 --- a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb +++ b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -return unless defined?(Rack) - -RSpec.describe Sentry::Rack::CaptureExceptions, rack: true do +RSpec.describe Sentry::Rack::CaptureExceptions, when: :rack_available? do let(:exception) { ZeroDivisionError.new("divided by 0") } let(:additional_headers) { {} } let(:env) { Rack::MockRequest.env_for("/test", additional_headers) } diff --git a/sentry-ruby/spec/sentry/scope/setters_spec.rb b/sentry-ruby/spec/sentry/scope/setters_spec.rb index 3ca240488..6a5378194 100644 --- a/sentry-ruby/spec/sentry/scope/setters_spec.rb +++ b/sentry-ruby/spec/sentry/scope/setters_spec.rb @@ -7,7 +7,7 @@ new_breadcrumb end - describe "#set_rack_env", rack: true do + describe "#set_rack_env", when: :rack_available? do let(:env) do Rack::MockRequest.env_for("/test", {}) end diff --git a/sentry-ruby/spec/sentry/scope_spec.rb b/sentry-ruby/spec/sentry/scope_spec.rb index 5de4d8d6d..9b52244a8 100644 --- a/sentry-ruby/spec/sentry/scope_spec.rb +++ b/sentry-ruby/spec/sentry/scope_spec.rb @@ -309,7 +309,7 @@ expect(event.dynamic_sampling_context).to eq(subject.propagation_context.get_dynamic_sampling_context) end - context "with Rack", rack: true do + context "with Rack", when: :rack_available? do let(:env) do Rack::MockRequest.env_for("/test", {}) end diff --git a/sentry-ruby/spec/spec_helper.rb b/sentry-ruby/spec/spec_helper.rb index 611205163..2758a0a1f 100644 --- a/sentry-ruby/spec/spec_helper.rb +++ b/sentry-ruby/spec/spec_helper.rb @@ -46,8 +46,10 @@ ENV.delete('RACK_ENV') end - config.before(:each, rack: true) do - skip("skip rack related tests") unless defined?(Rack) + config.before(:each, when: true) do |example| + meth = example.metadata[:when] + + skip("Skipping because `when: #{meth}` returned false") unless TestHelpers.public_send(meth, example) end RSpec::Matchers.define :have_recorded_lost_event do |reason, data_category, num: 1| @@ -57,6 +59,16 @@ end end +module TestHelpers + def self.stack_prof_installed?(_example) + defined?(StackProf) + end + + def self.rack_available?(_example) + defined?(Rack) + end +end + def fixtures_root @fixtures_root ||= Pathname(__dir__).join("fixtures") end From 51299fa3b188a0fbc2e47cb6f892c91a777ca66e Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Mon, 26 Aug 2024 10:04:05 +0200 Subject: [PATCH 31/96] Improve CI (#2388) * Remove rubocop from the bundle when running tests on CI * Measure coverage under ruby 3.3 * Test against latest rack and redis-rb * Fix rack spec when rack is not present --- .github/workflows/sentry_ruby_test.yml | 11 +++-- Gemfile | 6 ++- .../sentry/rack/capture_exceptions_spec.rb | 48 +++++++++---------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index a154df326..688b54042 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -29,7 +29,7 @@ jobs: fail-fast: false matrix: ruby_version: ${{ fromJson(needs.ruby-versions.outputs.versions) }} - rack_version: [2.0, 3.0] + rack_version: [2.0, 3.0, 3.1] redis_rb_version: [4.0] include: - { ruby_version: 3.2, rack_version: 0, redis_rb_version: 5.0 } @@ -45,8 +45,12 @@ jobs: } - { ruby_version: 3.2, - rack_version: 3.0, - redis_rb_version: 5.0, + rack_version: 3.0 + } + - { + ruby_version: 3.3, + rack_version: 3.1, + redis_rb_version: 5.3, options: { codecov: 1 }, } steps: @@ -69,6 +73,7 @@ jobs: RACK_VERSION: ${{ matrix.rack_version }} REDIS_RB_VERSION: ${{ matrix.redis_rb_version }} run: | + bundle config set without 'rubocop' bundle install --jobs 4 --retry 3 bundle exec rake diff --git a/Gemfile b/Gemfile index c42bc20c6..c897e543f 100644 --- a/Gemfile +++ b/Gemfile @@ -19,5 +19,7 @@ gem "simplecov" gem "simplecov-cobertura", "~> 1.4" gem "rexml" -gem "rubocop-rails-omakase" -gem "rubocop-packaging" +group :rubocop do + gem "rubocop-rails-omakase" + gem "rubocop-packaging" +end diff --git a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb index e2a226f77..dfd42ab33 100644 --- a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb +++ b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -RSpec.describe Sentry::Rack::CaptureExceptions, when: :rack_available? do +RSpec.describe 'Sentry::Rack::CaptureExceptions', when: :rack_available? do let(:exception) { ZeroDivisionError.new("divided by 0") } let(:additional_headers) { {} } let(:env) { Rack::MockRequest.env_for("/test", additional_headers) } @@ -12,7 +12,7 @@ it 'captures the exception from direct raise' do app = ->(_e) { raise exception } - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect { stack.call(env) }.to raise_error(ZeroDivisionError) @@ -25,7 +25,7 @@ it 'has the correct mechanism' do app = ->(_e) { raise exception } - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect { stack.call(env) }.to raise_error(ZeroDivisionError) @@ -39,7 +39,7 @@ e['rack.exception'] = exception [200, {}, ['okay']] end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect do stack.call(env) @@ -55,7 +55,7 @@ e['sinatra.error'] = exception [200, {}, ['okay']] end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect do stack.call(env) @@ -70,7 +70,7 @@ e['rack.exception'] = exception [200, {}, ['okay']] end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) stack.call(env) @@ -86,7 +86,7 @@ [200, { 'content-type' => 'text/plain' }, ['OK']] end - stack = described_class.new(Rack::Lint.new(app)) + stack = Sentry::Rack::CaptureExceptions.new(Rack::Lint.new(app)) expect { stack.call(env) }.to_not raise_error expect(env.key?("sentry.error_event_id")).to eq(false) end @@ -109,7 +109,7 @@ a / b end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect { stack.call(env) }.to raise_error(ZeroDivisionError) @@ -133,7 +133,7 @@ def inspect a / b end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect { stack.call(env) }.to raise_error(ZeroDivisionError) @@ -151,7 +151,7 @@ def inspect a / b end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect { stack.call(env) }.to raise_error(ZeroDivisionError) @@ -179,7 +179,7 @@ def inspect [200, {}, ["ok"]] end - app_1 = described_class.new(request_1) + app_1 = Sentry::Rack::CaptureExceptions.new(request_1) app_1.call(env) @@ -193,7 +193,7 @@ def inspect Sentry.capture_message("test") [200, {}, ["ok"]] end - app_1 = described_class.new(request_1) + app_1 = Sentry::Rack::CaptureExceptions.new(request_1) app_1.call(env) @@ -207,7 +207,7 @@ def inspect e['rack.exception'] = Exception.new [200, {}, ["ok"]] end - app_1 = described_class.new(request_1) + app_1 = Sentry::Rack::CaptureExceptions.new(request_1) app_1.call(env) event = last_sentry_event @@ -219,7 +219,7 @@ def inspect e['rack.exception'] = Exception.new [200, {}, ["ok"]] end - app_2 = described_class.new(request_2) + app_2 = Sentry::Rack::CaptureExceptions.new(request_2) app_2.call(env) event = last_sentry_event @@ -248,7 +248,7 @@ def inspect end let(:stack) do - described_class.new( + Sentry::Rack::CaptureExceptions.new( ->(_) do [200, {}, ["ok"]] end @@ -436,7 +436,7 @@ def will_be_sampled_by_sdk [200, {}, ["ok"]] end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) stack.call(env) @@ -460,7 +460,7 @@ def will_be_sampled_by_sdk end end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) stack.call(env) @@ -494,7 +494,7 @@ def will_be_sampled_by_sdk [200, {}, ["ok"]] end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) stack.call(env) @@ -512,7 +512,7 @@ def will_be_sampled_by_sdk raise "foo" end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect do stack.call(env) @@ -539,7 +539,7 @@ def will_be_sampled_by_sdk end let(:stack) do - described_class.new( + Sentry::Rack::CaptureExceptions.new( ->(_) do [200, {}, ["ok"]] end @@ -586,7 +586,7 @@ def will_be_sampled_by_sdk let(:stack) do app = ->(_e) { raise exception } - described_class.new(app) + Sentry::Rack::CaptureExceptions.new(app) end before { perform_basic_setup } @@ -618,7 +618,7 @@ def will_be_sampled_by_sdk expect_any_instance_of(Sentry::Hub).not_to receive(:start_session) expect(Sentry.session_flusher).to be_nil - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) stack.call(env) expect(sentry_envelopes.count).to eq(0) @@ -644,7 +644,7 @@ def will_be_sampled_by_sdk end end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) expect(Sentry.session_flusher).not_to be_nil @@ -707,7 +707,7 @@ def will_be_sampled_by_sdk [200, {}, "ok"] end - stack = described_class.new(app) + stack = Sentry::Rack::CaptureExceptions.new(app) stack.call(env) event = last_sentry_event From adf38eb7545f946118756d5ce5a21818ad29e47d Mon Sep 17 00:00:00 2001 From: y-yagi Date: Tue, 27 Aug 2024 22:34:42 +0900 Subject: [PATCH 32/96] Fix a typo of the issue number in CHANGELOG (#2375) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8937d0134..0aa3ea8c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ ``` - Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365)) - - Closes [#2364](https://github.com/getsentry/sentry-ruby/issues/2363) + - Closes [#2363](https://github.com/getsentry/sentry-ruby/issues/2363) - Inject Sentry meta tags in the Rails application layout automatically in the generator ([#2369](https://github.com/getsentry/sentry-ruby/pull/2369)) From 7b69425af24c1d70c968b9a460f0b022ac945db8 Mon Sep 17 00:00:00 2001 From: joshuarli Date: Tue, 27 Aug 2024 06:36:05 -0700 Subject: [PATCH 33/96] all-repos: update actions/upload-artifact to v4 (#2359) Committed via https://github.com/asottile/all-repos --- .github/workflows/build_batch_release.yml | 2 +- .github/workflows/build_release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_batch_release.yml b/.github/workflows/build_batch_release.yml index ffc30fcbd..ff584e14d 100644 --- a/.github/workflows/build_batch_release.yml +++ b/.github/workflows/build_batch_release.yml @@ -17,7 +17,7 @@ jobs: - name: Build gem source run: ruby .scripts/batch_build.rb - name: Archive Artifacts - uses: actions/upload-artifact@v3.1.1 + uses: actions/upload-artifact@v4 with: name: ${{ github.sha }} path: sentry*/*.gem diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml index f9cad4c6e..3dfe24f81 100644 --- a/.github/workflows/build_release.yml +++ b/.github/workflows/build_release.yml @@ -27,7 +27,7 @@ jobs: working-directory: ${{env.sdk-directory}} run: make build - name: Archive Artifacts - uses: actions/upload-artifact@v3.1.1 + uses: actions/upload-artifact@v4 with: name: ${{ github.sha }} path: ${{env.sdk-directory}}/*.gem From 4db5f7469cb7b8897e363454a2183a55d08d879d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zapa=C5=9Bnik?= <9281806+adamzapasnik@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:38:30 +0200 Subject: [PATCH 34/96] Improve sidekiq-cron patch (#2387) --- CHANGELOG.md | 3 +++ sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb | 4 ++-- .../spec/fixtures/sidekiq-cron-schedule.yml | 4 ++++ .../spec/sentry/sidekiq/cron/job_spec.rb | 18 ++++++++++++++++++ sentry-sidekiq/spec/spec_helper.rb | 2 ++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa3ea8c7..4430e9fb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## Unreleased +### Features + - Add support for $SENTRY_DEBUG and $SENTRY_SPOTLIGHT ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) +- Support human readable intervals in `sidekiq-cron` ([#2387](https://github.com/getsentry/sentry-ruby/pull/2387)) ## 5.19.0 diff --git a/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb b/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb index 4098d7564..937fd797c 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb @@ -28,8 +28,8 @@ def save unless klass_const.send(:ancestors).include?(Sentry::Cron::MonitorCheckIns) klass_const.send(:include, Sentry::Cron::MonitorCheckIns) klass_const.send(:sentry_monitor_check_ins, - slug: name, - monitor_config: Sentry::Cron::MonitorConfig.from_crontab(cron)) + slug: name.to_s, + monitor_config: Sentry::Cron::MonitorConfig.from_crontab(parsed_cron.original)) end true diff --git a/sentry-sidekiq/spec/fixtures/sidekiq-cron-schedule.yml b/sentry-sidekiq/spec/fixtures/sidekiq-cron-schedule.yml index 65b5945a6..fe2798262 100644 --- a/sentry-sidekiq/spec/fixtures/sidekiq-cron-schedule.yml +++ b/sentry-sidekiq/spec/fixtures/sidekiq-cron-schedule.yml @@ -6,6 +6,10 @@ manual: cron: "* * * * *" class: "SadWorkerWithCron" +human_readable_cron: + cron: "every 5 minutes" + class: HappyWorkerWithHumanReadableCron + invalid_cron: cron: "not a crontab" class: "ReportingWorker" diff --git a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb index 44f02f86e..c0f223096 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb @@ -10,6 +10,7 @@ before do schedule_file = 'spec/fixtures/sidekiq-cron-schedule.yml' schedule = Sidekiq::Cron::Support.load_yaml(ERB.new(IO.read(schedule_file)).result) + schedule = schedule.merge(symbol_name: { cron: '* * * * *', class: HappyWorkerWithSymbolName }) # sidekiq-cron 2.0+ accepts second argument to `load_from_hash!` with options, # such as {source: 'schedule'}, but sidekiq-cron 1.9.1 (last version to support Ruby 2.6) does not. # Since we're not using the source option in our code anyway, it's safe to not pass the 2nd arg. @@ -48,6 +49,23 @@ expect(HappyWorkerForCron.sentry_monitor_config.schedule.value).to eq('* * * * *') end + it 'patches HappyWorkerWithHumanReadableCron' do + expect(HappyWorkerWithHumanReadableCron.ancestors).to include(Sentry::Cron::MonitorCheckIns) + expect(HappyWorkerWithHumanReadableCron.sentry_monitor_slug).to eq('human_readable_cron') + expect(HappyWorkerWithHumanReadableCron.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig) + expect(HappyWorkerWithHumanReadableCron.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab) + expect(HappyWorkerWithHumanReadableCron.sentry_monitor_config.schedule.value).to eq('*/5 * * * *') + end + + it 'patches HappyWorkerWithSymbolName' do + expect(HappyWorkerWithSymbolName.ancestors).to include(Sentry::Cron::MonitorCheckIns) + expect(HappyWorkerWithSymbolName.sentry_monitor_slug).to eq('symbol_name') + expect(HappyWorkerWithSymbolName.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig) + expect(HappyWorkerWithSymbolName.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab) + expect(HappyWorkerWithSymbolName.sentry_monitor_config.schedule.value).to eq('* * * * *') + end + + it 'does not override SadWorkerWithCron manually set values' do expect(SadWorkerWithCron.ancestors).to include(Sentry::Cron::MonitorCheckIns) expect(SadWorkerWithCron.sentry_monitor_slug).to eq('failed_job') diff --git a/sentry-sidekiq/spec/spec_helper.rb b/sentry-sidekiq/spec/spec_helper.rb index 83e55d7da..6b2287957 100644 --- a/sentry-sidekiq/spec/spec_helper.rb +++ b/sentry-sidekiq/spec/spec_helper.rb @@ -139,6 +139,8 @@ class HappyWorkerForCron < HappyWorker; end class HappyWorkerForScheduler < HappyWorker; end class HappyWorkerForSchedulerWithTimezone < HappyWorker; end class EveryHappyWorker < HappyWorker; end +class HappyWorkerWithHumanReadableCron < HappyWorker; end +class HappyWorkerWithSymbolName < HappyWorker; end class HappyWorkerWithCron < HappyWorker include Sentry::Cron::MonitorCheckIns From 5980531cf582797046a21f3d1e91fcaa4c1b56e3 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sun, 1 Sep 2024 22:54:45 +0100 Subject: [PATCH 35/96] Set default app dirs pattern (#2390) * Set default app dirs pattern Instead of falling back to the default app dirs pattern when `config.app_dirs_pattern` is `nil`, we can simply set it to `APP_DIRS_PATTERN` by default. This means we don't need to always check if `config.app_dirs_pattern` is set and can simply use it. * Update changelog --- CHANGELOG.md | 1 + sentry-ruby/lib/sentry/backtrace.rb | 4 +--- sentry-ruby/lib/sentry/configuration.rb | 6 +++++- sentry-ruby/lib/sentry/profiler.rb | 2 +- sentry-ruby/spec/sentry/backtrace/lines_spec.rb | 2 +- sentry-ruby/spec/sentry/transport_spec.rb | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4430e9fb7..01ca61028 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Add support for $SENTRY_DEBUG and $SENTRY_SPOTLIGHT ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) - Support human readable intervals in `sidekiq-cron` ([#2387](https://github.com/getsentry/sentry-ruby/pull/2387)) +- Set default app dirs pattern ([#2390](https://github.com/getsentry/sentry-ruby/pull/2390)) ## 5.19.0 diff --git a/sentry-ruby/lib/sentry/backtrace.rb b/sentry-ruby/lib/sentry/backtrace.rb index b7ebb2159..c5ab16d39 100644 --- a/sentry-ruby/lib/sentry/backtrace.rb +++ b/sentry-ruby/lib/sentry/backtrace.rb @@ -80,8 +80,6 @@ def inspect end end - APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze - # holder for an Array of Backtrace::Line instances attr_reader :lines @@ -91,7 +89,7 @@ def self.parse(backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_cal ruby_lines = backtrace_cleanup_callback.call(ruby_lines) if backtrace_cleanup_callback in_app_pattern ||= begin - Regexp.new("^(#{project_root}/)?#{app_dirs_pattern || APP_DIRS_PATTERN}") + Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}") end lines = ruby_lines.to_a.map do |unparsed_line| diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index 4fb927cb4..9b119b508 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -23,6 +23,8 @@ class Configuration # have an `engines` dir at the root of your project, you may want # to set this to something like /(app|config|engines|lib)/ # + # The default is value is /(bin|exe|app|config|lib|test|spec)/ + # # @return [Regexp, nil] attr_accessor :app_dirs_pattern @@ -336,6 +338,8 @@ def capture_exception_frame_locals=(value) DEFAULT_PATCHES = %i[redis puma http].freeze + APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze + class << self # Post initialization callbacks are called at the end of initialization process # allowing extending the configuration of sentry-ruby by multiple extensions @@ -350,7 +354,7 @@ def add_post_initialization_callback(&block) end def initialize - self.app_dirs_pattern = nil + self.app_dirs_pattern = APP_DIRS_PATTERN self.debug = Sentry::Utils::EnvHelper.env_to_bool(ENV["SENTRY_DEBUG"]) self.background_worker_threads = (processor_count / 2.0).ceil self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE diff --git a/sentry-ruby/lib/sentry/profiler.rb b/sentry-ruby/lib/sentry/profiler.rb index cec7c70ce..ee6590357 100644 --- a/sentry-ruby/lib/sentry/profiler.rb +++ b/sentry-ruby/lib/sentry/profiler.rb @@ -21,7 +21,7 @@ def initialize(configuration) @profiling_enabled = defined?(StackProf) && configuration.profiling_enabled? @profiles_sample_rate = configuration.profiles_sample_rate @project_root = configuration.project_root - @app_dirs_pattern = configuration.app_dirs_pattern || Backtrace::APP_DIRS_PATTERN + @app_dirs_pattern = configuration.app_dirs_pattern @in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}") end diff --git a/sentry-ruby/spec/sentry/backtrace/lines_spec.rb b/sentry-ruby/spec/sentry/backtrace/lines_spec.rb index cdcb9809d..92dc48e6d 100644 --- a/sentry-ruby/spec/sentry/backtrace/lines_spec.rb +++ b/sentry-ruby/spec/sentry/backtrace/lines_spec.rb @@ -13,7 +13,7 @@ let(:in_app_pattern) do project_root = Sentry.configuration.project_root&.to_s - Regexp.new("^(#{project_root}/)?#{Sentry::Backtrace::APP_DIRS_PATTERN}") + Regexp.new("^(#{project_root}/)?#{Sentry::Configuration::APP_DIRS_PATTERN}") end describe ".parse" do diff --git a/sentry-ruby/spec/sentry/transport_spec.rb b/sentry-ruby/spec/sentry/transport_spec.rb index b78dc7878..9eb5de9dc 100644 --- a/sentry-ruby/spec/sentry/transport_spec.rb +++ b/sentry-ruby/spec/sentry/transport_spec.rb @@ -250,7 +250,7 @@ let(:in_app_pattern) do project_root = "/fake/project_root" - Regexp.new("^(#{project_root}/)?#{Sentry::Backtrace::APP_DIRS_PATTERN}") + Regexp.new("^(#{project_root}/)?#{Sentry::Configuration::APP_DIRS_PATTERN}") end let(:frame_list_limit) { 500 } let(:frame_list_size) { frame_list_limit * 20 } From c3bcfa0401856d9ee7616c95ab9dfe988a89da30 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Mon, 2 Sep 2024 15:59:02 +0100 Subject: [PATCH 36/96] Minor refactors (#2392) * Simplify Attachment#infer_filename * Small refactor on Profiler's frames collection --- sentry-ruby/lib/sentry/attachment.rb | 6 ++---- sentry-ruby/lib/sentry/profiler.rb | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/sentry-ruby/lib/sentry/attachment.rb b/sentry-ruby/lib/sentry/attachment.rb index 71a2b2b76..847d58c47 100644 --- a/sentry-ruby/lib/sentry/attachment.rb +++ b/sentry-ruby/lib/sentry/attachment.rb @@ -8,7 +8,7 @@ class Attachment def initialize(bytes: nil, filename: nil, content_type: nil, path: nil) @bytes = bytes - @filename = infer_filename(filename, path) + @filename = filename || infer_filename(path) @path = path @content_type = content_type end @@ -29,9 +29,7 @@ def payload private - def infer_filename(filename, path) - return filename if filename - + def infer_filename(path) if path File.basename(path) else diff --git a/sentry-ruby/lib/sentry/profiler.rb b/sentry-ruby/lib/sentry/profiler.rb index ee6590357..400cab5da 100644 --- a/sentry-ruby/lib/sentry/profiler.rb +++ b/sentry-ruby/lib/sentry/profiler.rb @@ -90,13 +90,12 @@ def to_hash frame_map = {} - frames = results[:frames].to_enum.with_index.map do |frame, idx| - frame_id, frame_data = frame - + frames = results[:frames].map.with_index do |(frame_id, frame_data), idx| # need to map over stackprof frame ids to ours frame_map[frame_id] = idx file_path = frame_data[:file] + lineno = frame_data[:line] in_app = in_app?(file_path) filename = compute_filename(file_path, in_app) function, mod = split_module(frame_data[:name]) @@ -109,7 +108,7 @@ def to_hash } frame_hash[:module] = mod if mod - frame_hash[:lineno] = frame_data[:line] if frame_data[:line] && frame_data[:line] >= 0 + frame_hash[:lineno] = lineno if lineno && lineno >= 0 frame_hash end From 0c56e1c5cce5eb3475d04d5de7092252c11f56a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Luarte=20Gonz=C3=A1lez?= Date: Mon, 16 Sep 2024 15:08:05 -0300 Subject: [PATCH 37/96] Verifies that client is available before sending breadcrumbs (#2394) During build, we have encountered situations where Sentry wants to send a `breadcrumb` but it fails to accomplish the task because of `NoMethodError: undefined method `configuration' for nil:NilClass`. After one of this error is triggered, Sentry fails to work at all, passing from 0 to several hundred errors in our pipeline, and then back to zero once we start rebuilding. Our pipeline tests using parallelism and there is a ton of concurrency, so we believe that has something to do with it. The backtrace points out to `Hub#add_breadcrumb` and inside of it to `configuration`. It is possible that while the new "local" hub is available, the client is not and fails to work. We have observed that several other method have checks in place to verify that the client is really available but not on `add_breadcrumb` so we added a verification before starting the rest of the process. --- CHANGELOG.md | 1 + sentry-ruby/lib/sentry/hub.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ca61028..a4086f0b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Add support for $SENTRY_DEBUG and $SENTRY_SPOTLIGHT ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) - Support human readable intervals in `sidekiq-cron` ([#2387](https://github.com/getsentry/sentry-ruby/pull/2387)) - Set default app dirs pattern ([#2390](https://github.com/getsentry/sentry-ruby/pull/2390)) +- Verifies presence of client before adding a breadcrumb ([#2394](https://github.com/getsentry/sentry-ruby/pull/2394)) ## 5.19.0 diff --git a/sentry-ruby/lib/sentry/hub.rb b/sentry-ruby/lib/sentry/hub.rb index 66d0b379a..8553fec7b 100644 --- a/sentry-ruby/lib/sentry/hub.rb +++ b/sentry-ruby/lib/sentry/hub.rb @@ -214,6 +214,7 @@ def capture_event(event, **options, &block) end def add_breadcrumb(breadcrumb, hint: {}) + return unless current_client return unless configuration.enabled_in_current_env? if before_breadcrumb = current_client.configuration.before_breadcrumb From 05c4675be6b2cad2b7fbc75116e88bcfa32ea5f8 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Thu, 19 Sep 2024 16:11:47 +0200 Subject: [PATCH 38/96] Fix error events missing a DSC when there's an active span (#2408) --- CHANGELOG.md | 4 +++ sentry-ruby/lib/sentry/propagation_context.rb | 2 +- sentry-ruby/lib/sentry/scope.rb | 1 + sentry-ruby/lib/sentry/span.rb | 6 ++++ sentry-ruby/spec/sentry/scope_spec.rb | 3 +- sentry-ruby/spec/sentry/span_spec.rb | 29 +++++++++++++++++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4086f0b5..566757024 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Set default app dirs pattern ([#2390](https://github.com/getsentry/sentry-ruby/pull/2390)) - Verifies presence of client before adding a breadcrumb ([#2394](https://github.com/getsentry/sentry-ruby/pull/2394)) +### Bug Fixes + +- Fix error events missing a DSC when there's an active span ([#2408](https://github.com/getsentry/sentry-ruby/pull/2408)) + ## 5.19.0 ### Features diff --git a/sentry-ruby/lib/sentry/propagation_context.rb b/sentry-ruby/lib/sentry/propagation_context.rb index 12ce55540..db2f58b8f 100644 --- a/sentry-ruby/lib/sentry/propagation_context.rb +++ b/sentry-ruby/lib/sentry/propagation_context.rb @@ -108,7 +108,7 @@ def get_baggage end # Returns the Dynamic Sampling Context from the baggage. - # @return [String, nil] + # @return [Hash, nil] def get_dynamic_sampling_context get_baggage&.dynamic_sampling_context end diff --git a/sentry-ruby/lib/sentry/scope.rb b/sentry-ruby/lib/sentry/scope.rb index 73e873f43..4feb6ecdd 100644 --- a/sentry-ruby/lib/sentry/scope.rb +++ b/sentry-ruby/lib/sentry/scope.rb @@ -62,6 +62,7 @@ def apply_to_event(event, hint = nil) if span event.contexts[:trace] ||= span.get_trace_context + event.dynamic_sampling_context ||= span.get_dynamic_sampling_context else event.contexts[:trace] ||= propagation_context.get_trace_context event.dynamic_sampling_context ||= propagation_context.get_dynamic_sampling_context diff --git a/sentry-ruby/lib/sentry/span.rb b/sentry-ruby/lib/sentry/span.rb index da7232d9a..3dd2158ea 100644 --- a/sentry-ruby/lib/sentry/span.rb +++ b/sentry-ruby/lib/sentry/span.rb @@ -160,6 +160,12 @@ def to_baggage transaction.get_baggage&.serialize end + # Returns the Dynamic Sampling Context from the transaction baggage. + # @return [Hash, nil] + def get_dynamic_sampling_context + transaction.get_baggage&.dynamic_sampling_context + end + # @return [Hash] def to_hash hash = { diff --git a/sentry-ruby/spec/sentry/scope_spec.rb b/sentry-ruby/spec/sentry/scope_spec.rb index 9b52244a8..6b4b4c168 100644 --- a/sentry-ruby/spec/sentry/scope_spec.rb +++ b/sentry-ruby/spec/sentry/scope_spec.rb @@ -293,7 +293,7 @@ end end - it "sets trace context from span if there's a span" do + it "sets trace context and dynamic_sampling_context from span if there's a span" do transaction = Sentry::Transaction.new(op: "foo", hub: hub) subject.set_span(transaction) @@ -301,6 +301,7 @@ expect(event.contexts[:trace]).to eq(transaction.get_trace_context) expect(event.contexts.dig(:trace, :op)).to eq("foo") + expect(event.dynamic_sampling_context).to eq(transaction.get_dynamic_sampling_context) end it "sets trace context and dynamic_sampling_context from propagation context if there's no span" do diff --git a/sentry-ruby/spec/sentry/span_spec.rb b/sentry-ruby/spec/sentry/span_spec.rb index d890dfa25..f24876d7f 100644 --- a/sentry-ruby/spec/sentry/span_spec.rb +++ b/sentry-ruby/spec/sentry/span_spec.rb @@ -136,6 +136,35 @@ end end + describe "#get_dynamic_sampling_context" do + before do + # because initializing transactions requires an active hub + perform_basic_setup + end + + subject do + baggage = Sentry::Baggage.from_incoming_header( + "other-vendor-value-1=foo;bar;baz, "\ + "sentry-trace_id=771a43a4192642f0b136d5159a501700, "\ + "sentry-public_key=49d0f7386ad645858ae85020e393bef3, "\ + "sentry-sample_rate=0.01337, "\ + "sentry-user_id=Am%C3%A9lie, "\ + "other-vendor-value-2=foo;bar;" + ) + + Sentry::Transaction.new(hub: Sentry.get_current_hub, baggage: baggage).start_child + end + + it "propagates sentry dynamic_sampling_context" do + expect(subject.get_dynamic_sampling_context).to eq({ + "sample_rate" => "0.01337", + "public_key" => "49d0f7386ad645858ae85020e393bef3", + "trace_id" => "771a43a4192642f0b136d5159a501700", + "user_id" => "Amélie" + }) + end + end + describe "#start_child" do before do # because initializing transactions requires an active hub From ab8361f67dde0cb0928da97a015fada37ca0b6d8 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Fri, 20 Sep 2024 19:24:55 +0200 Subject: [PATCH 39/96] Add new `strip_backtrace_load_path` boolean config (default true) to enable disabling load path stripping (#2409) --- .gitignore | 1 + CHANGELOG.md | 1 + sentry-ruby/lib/sentry/configuration.rb | 9 ++++++++- sentry-ruby/lib/sentry/interfaces/stacktrace.rb | 4 +++- .../lib/sentry/interfaces/stacktrace_builder.rb | 17 +++++++++++++++-- .../interfaces/stacktrace_builder_spec.rb | 15 +++++++++++++++ .../spec/sentry/interfaces/stacktrace_spec.rb | 10 ++++++++++ 7 files changed, 53 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 0b513cc74..7e3c680b2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,6 @@ Gemfile.lock .ruby-gemset .idea *.rdb +.rgignore examples/**/node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index 566757024..7737b195f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Support human readable intervals in `sidekiq-cron` ([#2387](https://github.com/getsentry/sentry-ruby/pull/2387)) - Set default app dirs pattern ([#2390](https://github.com/getsentry/sentry-ruby/pull/2390)) - Verifies presence of client before adding a breadcrumb ([#2394](https://github.com/getsentry/sentry-ruby/pull/2394)) +- Add new `strip_backtrace_load_path` boolean config (default true) to enable disabling load path stripping ([#2409](https://github.com/getsentry/sentry-ruby/pull/2409)) ### Bug Fixes diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index 9b119b508..e02e1533c 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -190,6 +190,11 @@ def capture_exception_frame_locals=(value) # @return [String] attr_accessor :project_root + # Whether to strip the load path while constructing the backtrace frame filename. + # Defaults to true. + # @return [Boolean] + attr_accessor :strip_backtrace_load_path + # Insert sentry-trace to outgoing requests' headers # @return [Boolean] attr_accessor :propagate_traces @@ -359,6 +364,7 @@ def initialize self.background_worker_threads = (processor_count / 2.0).ceil self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE self.backtrace_cleanup_callback = nil + self.strip_backtrace_load_path = true self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE self.breadcrumbs_logger = [] self.context_lines = 3 @@ -563,7 +569,8 @@ def stacktrace_builder app_dirs_pattern: @app_dirs_pattern, linecache: @linecache, context_lines: @context_lines, - backtrace_cleanup_callback: @backtrace_cleanup_callback + backtrace_cleanup_callback: @backtrace_cleanup_callback, + strip_backtrace_load_path: @strip_backtrace_load_path ) end diff --git a/sentry-ruby/lib/sentry/interfaces/stacktrace.rb b/sentry-ruby/lib/sentry/interfaces/stacktrace.rb index eadf01188..5f4be3719 100644 --- a/sentry-ruby/lib/sentry/interfaces/stacktrace.rb +++ b/sentry-ruby/lib/sentry/interfaces/stacktrace.rb @@ -27,8 +27,9 @@ class Frame < Interface attr_accessor :abs_path, :context_line, :function, :in_app, :filename, :lineno, :module, :pre_context, :post_context, :vars - def initialize(project_root, line) + def initialize(project_root, line, strip_backtrace_load_path = true) @project_root = project_root + @strip_backtrace_load_path = strip_backtrace_load_path @abs_path = line.file @function = line.method if line.method @@ -44,6 +45,7 @@ def to_s def compute_filename return if abs_path.nil? + return abs_path unless @strip_backtrace_load_path prefix = if under_project_root? && in_app diff --git a/sentry-ruby/lib/sentry/interfaces/stacktrace_builder.rb b/sentry-ruby/lib/sentry/interfaces/stacktrace_builder.rb index 5edac90c5..d2d0758ec 100644 --- a/sentry-ruby/lib/sentry/interfaces/stacktrace_builder.rb +++ b/sentry-ruby/lib/sentry/interfaces/stacktrace_builder.rb @@ -17,22 +17,35 @@ class StacktraceBuilder # @return [Proc, nil] attr_reader :backtrace_cleanup_callback + # @return [Boolean] + attr_reader :strip_backtrace_load_path + # @param project_root [String] # @param app_dirs_pattern [Regexp, nil] # @param linecache [LineCache] # @param context_lines [Integer, nil] # @param backtrace_cleanup_callback [Proc, nil] + # @param strip_backtrace_load_path [Boolean] # @see Configuration#project_root # @see Configuration#app_dirs_pattern # @see Configuration#linecache # @see Configuration#context_lines # @see Configuration#backtrace_cleanup_callback - def initialize(project_root:, app_dirs_pattern:, linecache:, context_lines:, backtrace_cleanup_callback: nil) + # @see Configuration#strip_backtrace_load_path + def initialize( + project_root:, + app_dirs_pattern:, + linecache:, + context_lines:, + backtrace_cleanup_callback: nil, + strip_backtrace_load_path: true + ) @project_root = project_root @app_dirs_pattern = app_dirs_pattern @linecache = linecache @context_lines = context_lines @backtrace_cleanup_callback = backtrace_cleanup_callback + @strip_backtrace_load_path = strip_backtrace_load_path end # Generates a StacktraceInterface with the given backtrace. @@ -73,7 +86,7 @@ def metrics_code_location(unparsed_line) private def convert_parsed_line_into_frame(line) - frame = StacktraceInterface::Frame.new(project_root, line) + frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path) frame.set_context(linecache, context_lines) if context_lines frame end diff --git a/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb b/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb index 637aff2ad..e7c05d6ad 100644 --- a/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb +++ b/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb @@ -51,6 +51,21 @@ expect(second_frame.post_context).to eq(["end\n", nil, nil]) end + context "when strip_backtrace_load_path is false" do + let(:configuration) do + Sentry::Configuration.new.tap do |config| + config.project_root = fixture_root + config.strip_backtrace_load_path = false + end + end + + it "does not strip load paths for filenames" do + interface = subject.build(backtrace: backtrace) + expect(interface.frames.first.filename).to eq(fixture_file) + expect(interface.frames.last.filename).to eq(fixture_file) + end + end + context "with block argument" do it "removes the frame if it's evaluated as nil" do interface = subject.build(backtrace: backtrace) do |frame| diff --git a/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb b/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb index 143dc369c..3236af606 100644 --- a/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb +++ b/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb @@ -28,5 +28,15 @@ expect(second_frame.function).to eq("save_user") expect(second_frame.lineno).to eq(5) end + + it "does not strip load path when strip_backtrace_load_path is false" do + first_frame = Sentry::StacktraceInterface::Frame.new(configuration.project_root, lines.first, false) + expect(first_frame.filename).to eq(first_frame.abs_path) + expect(first_frame.filename).to eq(raw_lines.first.split(':').first) + + second_frame = Sentry::StacktraceInterface::Frame.new(configuration.project_root, lines.last, false) + expect(second_frame.filename).to eq(second_frame.abs_path) + expect(second_frame.filename).to eq(raw_lines.last.split(':').first) + end end end From 04e030f974558aa750e26afc458c48e663ddcfcc Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 20 Sep 2024 19:42:04 +0200 Subject: [PATCH 40/96] Add 5 min timeout to sentry_ruby_test workflow (#2410) --- .github/workflows/sentry_ruby_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index 688b54042..c5228c8a1 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -25,6 +25,7 @@ jobs: working-directory: sentry-ruby name: Ruby ${{ matrix.ruby_version }} & Rack ${{ matrix.rack_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest + timeout-minutes: 5 strategy: fail-fast: false matrix: From 23fe6f5511f26c460a8ea82ecf345648d5b4d5a3 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Mon, 23 Sep 2024 17:08:58 +0200 Subject: [PATCH 41/96] changelog for 5.20.0 (#2412) --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7737b195f..fa9987b79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,16 @@ ## Unreleased -### Features +### 5.20.0 -- Add support for $SENTRY_DEBUG and $SENTRY_SPOTLIGHT ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) +- Add support for `$SENTRY_DEBUG` and `$SENTRY_SPOTLIGHT` ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) - Support human readable intervals in `sidekiq-cron` ([#2387](https://github.com/getsentry/sentry-ruby/pull/2387)) - Set default app dirs pattern ([#2390](https://github.com/getsentry/sentry-ruby/pull/2390)) -- Verifies presence of client before adding a breadcrumb ([#2394](https://github.com/getsentry/sentry-ruby/pull/2394)) - Add new `strip_backtrace_load_path` boolean config (default true) to enable disabling load path stripping ([#2409](https://github.com/getsentry/sentry-ruby/pull/2409)) ### Bug Fixes - Fix error events missing a DSC when there's an active span ([#2408](https://github.com/getsentry/sentry-ruby/pull/2408)) +- Verifies presence of client before adding a breadcrumb ([#2394](https://github.com/getsentry/sentry-ruby/pull/2394)) ## 5.19.0 From 246e9268f91d64cc0252f88b789d711af6ba8ba1 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Mon, 23 Sep 2024 17:34:27 +0200 Subject: [PATCH 42/96] Change timeout to 10 min since 5 is not enough (#2414) --- .github/workflows/sentry_ruby_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index c5228c8a1..bc6a1ad64 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -25,7 +25,7 @@ jobs: working-directory: sentry-ruby name: Ruby ${{ matrix.ruby_version }} & Rack ${{ matrix.rack_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 strategy: fail-fast: false matrix: From 0c875e4305f4e51f4ba356d698d7386ecc92b29c Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Mon, 23 Sep 2024 17:59:49 +0200 Subject: [PATCH 43/96] Skip concurrent threaded test on jruby (#2415) --- .../sentry/breadcrumb/sentry_logger_spec.rb | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb b/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb index baf180922..aafcf6f96 100644 --- a/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb +++ b/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb @@ -69,33 +69,35 @@ end # see https://github.com/getsentry/sentry-ruby/issues/1858 - it "noops on thread with cloned hub" do - mutex = Mutex.new - cv = ConditionVariable.new - - a = Thread.new do - expect(Sentry.get_current_hub).to be_a(Sentry::Hub) + unless RUBY_PLATFORM == "java" + it "noops on thread with cloned hub" do + mutex = Mutex.new + cv = ConditionVariable.new + + a = Thread.new do + expect(Sentry.get_current_hub).to be_a(Sentry::Hub) + + # close in another thread + b = Thread.new do + mutex.synchronize do + Sentry.close + cv.signal + end + end - # close in another thread - b = Thread.new do mutex.synchronize do - Sentry.close - cv.signal - end - end + # wait for other thread to close SDK + cv.wait(mutex) - mutex.synchronize do - # wait for other thread to close SDK - cv.wait(mutex) + expect(Sentry).not_to receive(:add_breadcrumb) + logger.info("foo") + end - expect(Sentry).not_to receive(:add_breadcrumb) - logger.info("foo") + b.join end - b.join + a.join end - - a.join end end end From 399c97d5b7340355dbe467bc9831229ff46ddc99 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 24 Sep 2024 17:23:19 +0200 Subject: [PATCH 44/96] fix changelog (#2416) --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa9987b79..ae6d070ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,3 @@ -## Unreleased - ### 5.20.0 - Add support for `$SENTRY_DEBUG` and `$SENTRY_SPOTLIGHT` ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) From 152eb5e823b14500169166f7a83d96a739064094 Mon Sep 17 00:00:00 2001 From: Raul Ascencio <106978264+rascencio-kraft@users.noreply.github.com> Date: Fri, 27 Sep 2024 20:50:01 +0200 Subject: [PATCH 45/96] fix: Unable to use sentry when URI contains non-ascii symbols on Net::HTTP traces. (#2417) Signed-off-by: Raul Ascencio Co-authored-by: Neel Shah --- CHANGELOG.md | 1 + sentry-ruby/lib/sentry/net/http.rb | 2 +- sentry-ruby/spec/sentry/net/http_spec.rb | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae6d070ce..a90ac995a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fix error events missing a DSC when there's an active span ([#2408](https://github.com/getsentry/sentry-ruby/pull/2408)) - Verifies presence of client before adding a breadcrumb ([#2394](https://github.com/getsentry/sentry-ruby/pull/2394)) +- Fix `Net:HTTP` integration for non-ASCII URI's ([#2417](https://github.com/getsentry/sentry-ruby/pull/2417)) ## 5.19.0 diff --git a/sentry-ruby/lib/sentry/net/http.rb b/sentry-ruby/lib/sentry/net/http.rb index c769b4c3d..04820f3d5 100644 --- a/sentry-ruby/lib/sentry/net/http.rb +++ b/sentry-ruby/lib/sentry/net/http.rb @@ -66,7 +66,7 @@ def extract_request_info(req) # IPv6 url could look like '::1/path', and that won't parse without # wrapping it in square brackets. hostname = address =~ Resolv::IPv6::Regex ? "[#{address}]" : address - uri = req.uri || URI.parse("#{use_ssl? ? 'https' : 'http'}://#{hostname}#{req.path}") + uri = req.uri || URI.parse(URI::DEFAULT_PARSER.escape("#{use_ssl? ? 'https' : 'http'}://#{hostname}#{req.path}")) url = "#{uri.scheme}://#{uri.host}#{uri.path}" rescue uri.to_s result = { method: req.method, url: url } diff --git a/sentry-ruby/spec/sentry/net/http_spec.rb b/sentry-ruby/spec/sentry/net/http_spec.rb index 064c4f36c..6a6dbbf73 100644 --- a/sentry-ruby/spec/sentry/net/http_spec.rb +++ b/sentry-ruby/spec/sentry/net/http_spec.rb @@ -107,6 +107,22 @@ end end + it "supports non-ascii characters in the path" do + stub_normal_response + + uri = URI('http://example.com') + http = Net::HTTP.new(uri.host, uri.port) + request = Net::HTTP::Get.new('/path?q=øgreyfoss&å=vær') + + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + + response = http.request(request) + + expect(response.code).to eq("200") + end + it "adds sentry-trace header to the request header" do uri = URI("http://example.com/path") http = Net::HTTP.new(uri.host, uri.port) From af8fcdd395eb4ba1a4c0e86691ab5d682c1adc2a Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Fri, 27 Sep 2024 15:00:15 -0400 Subject: [PATCH 46/96] Prevent Hub from having nil scope and client (#2402) * Prevent Hub from having nil scope and client `Hub#pop_scope` currently can cause a Hub to have a nil scope and client, which would highly likely lead of errors. For example, `Hub#configuration` would simply cause `NoMethodError`. This commit prevents that from ever happening by making sure that `Hub#pop_scope` would at least leave a brand new scope and the old client on the stack. --- CHANGELOG.md | 3 ++- sentry-ruby/lib/sentry/hub.rb | 8 ++++++- sentry-ruby/spec/sentry/hub_spec.rb | 33 +++++++++++++++-------------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a90ac995a..5ae41c951 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 5.20.0 +## 5.20.0 - Add support for `$SENTRY_DEBUG` and `$SENTRY_SPOTLIGHT` ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) - Support human readable intervals in `sidekiq-cron` ([#2387](https://github.com/getsentry/sentry-ruby/pull/2387)) @@ -10,6 +10,7 @@ - Fix error events missing a DSC when there's an active span ([#2408](https://github.com/getsentry/sentry-ruby/pull/2408)) - Verifies presence of client before adding a breadcrumb ([#2394](https://github.com/getsentry/sentry-ruby/pull/2394)) - Fix `Net:HTTP` integration for non-ASCII URI's ([#2417](https://github.com/getsentry/sentry-ruby/pull/2417)) +- Prevent Hub from having nil scope and client ([#2402](https://github.com/getsentry/sentry-ruby/pull/2402)) ## 5.19.0 diff --git a/sentry-ruby/lib/sentry/hub.rb b/sentry-ruby/lib/sentry/hub.rb index 8553fec7b..b9b58638d 100644 --- a/sentry-ruby/lib/sentry/hub.rb +++ b/sentry-ruby/lib/sentry/hub.rb @@ -73,7 +73,13 @@ def push_scope end def pop_scope - @stack.pop + if @stack.size > 1 + @stack.pop + else + # We never want to enter a situation where we have no scope and no client + client = current_client + @stack = [Layer.new(client, Scope.new)] + end end def start_transaction(transaction: nil, custom_sampling_context: {}, instrumenter: :sentry, **options) diff --git a/sentry-ruby/spec/sentry/hub_spec.rb b/sentry-ruby/spec/sentry/hub_spec.rb index 6d06595aa..c7ada3ae6 100644 --- a/sentry-ruby/spec/sentry/hub_spec.rb +++ b/sentry-ruby/spec/sentry/hub_spec.rb @@ -519,9 +519,25 @@ describe "#pop_scope" do it "pops the current scope" do + prev_scope = subject.current_scope + subject.push_scope + scope = subject.current_scope expect(subject.current_scope).to eq(scope) subject.pop_scope - expect(subject.current_scope).to eq(nil) + expect(subject.current_scope).to eq(prev_scope) + end + + it "doesn't pop the last layer" do + expect(subject.instance_variable_get(:@stack).count).to eq(1) + + subject.pop_scope + + expect(subject.instance_variable_get(:@stack).count).to eq(1) + + # It should be a completely new scope + expect(subject.current_scope).not_to eq(scope) + # But it should be the same client + expect(subject.current_client).to eq(client) end end @@ -543,21 +559,6 @@ expect(subject.current_scope).not_to eq(scope) expect(subject.current_scope.tags).to eq({ foo: "bar" }) end - - context "when the current_scope is nil" do - before do - subject.pop_scope - expect(subject.current_scope).to eq(nil) - end - it "creates a new scope" do - scope.set_tags({ foo: "bar" }) - - subject.push_scope - - expect(subject.current_scope).not_to eq(scope) - expect(subject.current_scope.tags).to eq({}) - end - end end describe '#configure_scope' do From 34ba320098faa0c8b99fc455e0769942dad847b6 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Fri, 27 Sep 2024 19:09:28 +0000 Subject: [PATCH 47/96] release: 5.20.0 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index 95d3630b0..b7283d65d 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -1,5 +1,5 @@ module Sentry module DelayedJob - VERSION = "5.19.0" + VERSION = "5.20.0" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index e97096bcb..80196f2fb 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.19.0" + spec.add_dependency "sentry-ruby", "~> 5.20.0" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index ddc0cbe67..0f3e54408 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.19.0" + VERSION = "5.20.0" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index aaee606be..886bc610d 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.19.0" + spec.add_dependency "sentry-ruby", "~> 5.20.0" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index ac6bcb23b..205096dd5 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -1,5 +1,5 @@ module Sentry module Rails - VERSION = "5.19.0" + VERSION = "5.20.0" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 7cfdd0e70..d0433ef02 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -29,5 +29,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.19.0" + spec.add_dependency "sentry-ruby", "~> 5.20.0" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index 9e6a6ec4f..103921ec7 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -1,5 +1,5 @@ module Sentry module Resque - VERSION = "5.19.0" + VERSION = "5.20.0" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 36d777b00..1f36b9111 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.19.0" + spec.add_dependency "sentry-ruby", "~> 5.20.0" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index a06f8cebc..032719ca0 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.19.0" + VERSION = "5.20.0" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index b127d83ba..460207d2c 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -1,5 +1,5 @@ module Sentry module Sidekiq - VERSION = "5.19.0" + VERSION = "5.20.0" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index 56f737887..ecbd4e8cc 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.19.0" + spec.add_dependency "sentry-ruby", "~> 5.20.0" spec.add_dependency "sidekiq", ">= 3.0" end From d96e8e14f7bbc784aab242804e84394c68a92b8f Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Fri, 27 Sep 2024 23:08:12 +0200 Subject: [PATCH 48/96] Ignore rubocop file in spec files (#2420) --- CHANGELOG.md | 6 ++++++ sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/sentry-ruby-core.gemspec | 2 +- sentry-ruby/sentry-ruby.gemspec | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 8 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ae41c951..919d304b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 5.20.1 + +### Bug Fixes + +- Skip `rubocop.yml` in `spec.files` ([#2420](https://github.com/getsentry/sentry-ruby/pull/2420)) + ## 5.20.0 - Add support for `$SENTRY_DEBUG` and `$SENTRY_SPOTLIGHT` ([#2374](https://github.com/getsentry/sentry-ruby/pull/2374)) diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index 80196f2fb..ba5a62216 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] - spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") + spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n") github_root_uri = 'https://github.com/getsentry/sentry-ruby' spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 886bc610d..4e026d2ba 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -13,7 +13,7 @@ Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] - spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") + spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n") github_root_uri = 'https://github.com/getsentry/sentry-ruby' spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index d0433ef02..7c4cfac47 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] - spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") + spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n") github_root_uri = 'https://github.com/getsentry/sentry-ruby' spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 1f36b9111..732ae4c3a 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] - spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") + spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n") github_root_uri = 'https://github.com/getsentry/sentry-ruby' spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" diff --git a/sentry-ruby/sentry-ruby-core.gemspec b/sentry-ruby/sentry-ruby-core.gemspec index 76a343c28..a676fe126 100644 --- a/sentry-ruby/sentry-ruby-core.gemspec +++ b/sentry-ruby/sentry-ruby-core.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] - spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") + spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n") spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/sentry-ruby/sentry-ruby.gemspec b/sentry-ruby/sentry-ruby.gemspec index 52cbcc180..44fcfceaa 100644 --- a/sentry-ruby/sentry-ruby.gemspec +++ b/sentry-ruby/sentry-ruby.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] - spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") + spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n") github_root_uri = 'https://github.com/getsentry/sentry-ruby' spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index ecbd4e8cc..210485b12 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.required_ruby_version = '>= 2.4' spec.extra_rdoc_files = ["README.md", "LICENSE.txt"] - spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") + spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n") github_root_uri = 'https://github.com/getsentry/sentry-ruby' spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}" From 84bf2cf6f2e9256f7fe7527cc2bc164252a85ff2 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Fri, 27 Sep 2024 21:23:59 +0000 Subject: [PATCH 49/96] release: 5.20.1 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index b7283d65d..e5c1c5e5f 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -1,5 +1,5 @@ module Sentry module DelayedJob - VERSION = "5.20.0" + VERSION = "5.20.1" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index ba5a62216..e9c004738 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.0" + spec.add_dependency "sentry-ruby", "~> 5.20.1" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index 0f3e54408..2caed2fa7 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.20.0" + VERSION = "5.20.1" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 4e026d2ba..2418bd47d 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.0" + spec.add_dependency "sentry-ruby", "~> 5.20.1" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index 205096dd5..e62a1de60 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -1,5 +1,5 @@ module Sentry module Rails - VERSION = "5.20.0" + VERSION = "5.20.1" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 7c4cfac47..67a545a36 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -29,5 +29,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.20.0" + spec.add_dependency "sentry-ruby", "~> 5.20.1" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index 103921ec7..3bac872bc 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -1,5 +1,5 @@ module Sentry module Resque - VERSION = "5.20.0" + VERSION = "5.20.1" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 732ae4c3a..6d198dcab 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.0" + spec.add_dependency "sentry-ruby", "~> 5.20.1" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index 032719ca0..212678965 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.20.0" + VERSION = "5.20.1" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index 460207d2c..46cb74dbe 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -1,5 +1,5 @@ module Sentry module Sidekiq - VERSION = "5.20.0" + VERSION = "5.20.1" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index 210485b12..69a4689de 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -28,6 +28,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.0" + spec.add_dependency "sentry-ruby", "~> 5.20.1" spec.add_dependency "sidekiq", ">= 3.0" end From a070e08c58f66e2c629b975a25144588a01901f9 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Mon, 30 Sep 2024 14:24:25 +0200 Subject: [PATCH 50/96] Generalize size limits based on envelope item type (#2421) * Fix spec file location * Extract Envelope::Item to its own file * Add Envelope::Item#size_limit * Make Envelope::Item#{headers,payload} just readers We don't set headers and payloads after initializing an item, so these accessors were not needed. * Memoize Envelope::Item#type in the constructor It's faster like that given that we rely on type value in multiple places * Memoize Envelope::Item#data_category Same as with type, we rely on this value in multiple places so it makes no sense to keep calculating it multiple times * Add custom size limit for profile items * Update CHANGELOG --- CHANGELOG.md | 6 ++ sentry-ruby/lib/sentry/envelope.rb | 87 +----------------- sentry-ruby/lib/sentry/envelope/item.rb | 88 +++++++++++++++++++ .../item_spec.rb} | 0 sentry-ruby/spec/sentry/transport_spec.rb | 31 +++++++ 5 files changed, 127 insertions(+), 85 deletions(-) create mode 100644 sentry-ruby/lib/sentry/envelope/item.rb rename sentry-ruby/spec/sentry/{envelope_spec.rb => envelope/item_spec.rb} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 919d304b4..4307dabc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Internal + +- Profile items have bigger size limit now ([#2421](https://github.com/getsentry/sentry-ruby/pull/2421)) + ## 5.20.1 ### Bug Fixes diff --git a/sentry-ruby/lib/sentry/envelope.rb b/sentry-ruby/lib/sentry/envelope.rb index 4e1d8acb2..d60e79ba7 100644 --- a/sentry-ruby/lib/sentry/envelope.rb +++ b/sentry-ruby/lib/sentry/envelope.rb @@ -3,91 +3,6 @@ module Sentry # @api private class Envelope - class Item - STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD = 500 - MAX_SERIALIZED_PAYLOAD_SIZE = 1024 * 1000 - - attr_accessor :headers, :payload - - def initialize(headers, payload) - @headers = headers - @payload = payload - end - - def type - @headers[:type] || "event" - end - - # rate limits and client reports use the data_category rather than envelope item type - def self.data_category(type) - case type - when "session", "attachment", "transaction", "profile", "span" then type - when "sessions" then "session" - when "check_in" then "monitor" - when "statsd", "metric_meta" then "metric_bucket" - when "event" then "error" - when "client_report" then "internal" - else "default" - end - end - - def data_category - self.class.data_category(type) - end - - def to_s - [JSON.generate(@headers), @payload.is_a?(String) ? @payload : JSON.generate(@payload)].join("\n") - end - - def serialize - result = to_s - - if result.bytesize > MAX_SERIALIZED_PAYLOAD_SIZE - remove_breadcrumbs! - result = to_s - end - - if result.bytesize > MAX_SERIALIZED_PAYLOAD_SIZE - reduce_stacktrace! - result = to_s - end - - [result, result.bytesize > MAX_SERIALIZED_PAYLOAD_SIZE] - end - - def size_breakdown - payload.map do |key, value| - "#{key}: #{JSON.generate(value).bytesize}" - end.join(", ") - end - - private - - def remove_breadcrumbs! - if payload.key?(:breadcrumbs) - payload.delete(:breadcrumbs) - elsif payload.key?("breadcrumbs") - payload.delete("breadcrumbs") - end - end - - def reduce_stacktrace! - if exceptions = payload.dig(:exception, :values) || payload.dig("exception", "values") - exceptions.each do |exception| - # in most cases there is only one exception (2 or 3 when have multiple causes), so we won't loop through this double condition much - traces = exception.dig(:stacktrace, :frames) || exception.dig("stacktrace", "frames") - - if traces && traces.size > STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD - size_on_both_ends = STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD / 2 - traces.replace( - traces[0..(size_on_both_ends - 1)] + traces[-size_on_both_ends..-1], - ) - end - end - end - end - end - attr_accessor :headers, :items def initialize(headers = {}) @@ -108,3 +23,5 @@ def event_id end end end + +require_relative "envelope/item" diff --git a/sentry-ruby/lib/sentry/envelope/item.rb b/sentry-ruby/lib/sentry/envelope/item.rb new file mode 100644 index 000000000..e1539bf6c --- /dev/null +++ b/sentry-ruby/lib/sentry/envelope/item.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module Sentry + # @api private + class Envelope::Item + STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD = 500 + MAX_SERIALIZED_PAYLOAD_SIZE = 1024 * 1000 + + SIZE_LIMITS = Hash.new(MAX_SERIALIZED_PAYLOAD_SIZE).update( + "profile" => 1024 * 1000 * 50 + ) + + attr_reader :size_limit, :headers, :payload, :type, :data_category + + # rate limits and client reports use the data_category rather than envelope item type + def self.data_category(type) + case type + when "session", "attachment", "transaction", "profile", "span" then type + when "sessions" then "session" + when "check_in" then "monitor" + when "statsd", "metric_meta" then "metric_bucket" + when "event" then "error" + when "client_report" then "internal" + else "default" + end + end + + def initialize(headers, payload) + @headers = headers + @payload = payload + @type = headers[:type] || "event" + @data_category = self.class.data_category(type) + @size_limit = SIZE_LIMITS[type] + end + + def to_s + [JSON.generate(@headers), @payload.is_a?(String) ? @payload : JSON.generate(@payload)].join("\n") + end + + def serialize + result = to_s + + if result.bytesize > size_limit + remove_breadcrumbs! + result = to_s + end + + if result.bytesize > size_limit + reduce_stacktrace! + result = to_s + end + + [result, result.bytesize > size_limit] + end + + def size_breakdown + payload.map do |key, value| + "#{key}: #{JSON.generate(value).bytesize}" + end.join(", ") + end + + private + + def remove_breadcrumbs! + if payload.key?(:breadcrumbs) + payload.delete(:breadcrumbs) + elsif payload.key?("breadcrumbs") + payload.delete("breadcrumbs") + end + end + + def reduce_stacktrace! + if exceptions = payload.dig(:exception, :values) || payload.dig("exception", "values") + exceptions.each do |exception| + # in most cases there is only one exception (2 or 3 when have multiple causes), so we won't loop through this double condition much + traces = exception.dig(:stacktrace, :frames) || exception.dig("stacktrace", "frames") + + if traces && traces.size > STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD + size_on_both_ends = STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD / 2 + traces.replace( + traces[0..(size_on_both_ends - 1)] + traces[-size_on_both_ends..-1], + ) + end + end + end + end + end +end diff --git a/sentry-ruby/spec/sentry/envelope_spec.rb b/sentry-ruby/spec/sentry/envelope/item_spec.rb similarity index 100% rename from sentry-ruby/spec/sentry/envelope_spec.rb rename to sentry-ruby/spec/sentry/envelope/item_spec.rb diff --git a/sentry-ruby/spec/sentry/transport_spec.rb b/sentry-ruby/spec/sentry/transport_spec.rb index 9eb5de9dc..079aa8709 100644 --- a/sentry-ruby/spec/sentry/transport_spec.rb +++ b/sentry-ruby/spec/sentry/transport_spec.rb @@ -145,6 +145,37 @@ expect(profile_payload).to eq(profile.to_json) end end + + context "allows bigger item size" do + let(:profile) do + { + environment: "test", + release: "release", + profile: { + frames: Array.new(10000) { |i| { function: "function_#{i}", filename: "file_#{i}", lineno: i } }, + stacks: Array.new(10000) { |i| [i] }, + samples: Array.new(10000) { |i| { stack_id: i, elapsed_since_start_ns: i * 1000, thread_id: i % 10 } } + } + } + end + + let(:event_with_profile) do + event.profile = profile + event + end + + let(:envelope) { subject.envelope_from_event(event_with_profile) } + + it "adds profile item to envelope" do + result, _ = subject.serialize_envelope(envelope) + + _profile_header, profile_payload_json = result.split("\n").last(2) + + profile_payload = JSON.parse(profile_payload_json) + + expect(profile_payload["profile"]).to_not be(nil) + end + end end context "client report" do From 8dc3d2d8aa296fc84f0e9e09d40f7901233152d7 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 4 Oct 2024 15:17:54 +0200 Subject: [PATCH 51/96] Experimental support for multi-threaded profiling using Vernier (#2372) * Add support for Vernier profiler - Introduce `Sentry::Vernier::Profiler` - Introduce `Sentry.config.profiler_class` that can be set to a class that should be used for profiling. By default it's set to `Sentry::Profiler` --- CHANGELOG.md | 4 + sentry-ruby/Gemfile | 1 + sentry-ruby/lib/sentry-ruby.rb | 1 + sentry-ruby/lib/sentry/configuration.rb | 26 +- sentry-ruby/lib/sentry/profiler.rb | 44 +- sentry-ruby/lib/sentry/profiler/helpers.rb | 46 ++ sentry-ruby/lib/sentry/transaction.rb | 2 +- sentry-ruby/lib/sentry/transaction_event.rb | 3 +- sentry-ruby/lib/sentry/vernier/output.rb | 89 +++ sentry-ruby/lib/sentry/vernier/profiler.rb | 125 +++ sentry-ruby/spec/sentry/configuration_spec.rb | 17 + sentry-ruby/spec/sentry/profiler_spec.rb | 3 +- .../sentry/rack/capture_exceptions_spec.rb | 143 ++-- .../spec/sentry/vernier/profiler_spec.rb | 309 ++++++++ sentry-ruby/spec/spec_helper.rb | 31 +- sentry-ruby/spec/support/profiler.rb | 14 + .../spec/support/stackprof_results.json | 719 +++++++++++++++++- 17 files changed, 1472 insertions(+), 105 deletions(-) create mode 100644 sentry-ruby/lib/sentry/profiler/helpers.rb create mode 100644 sentry-ruby/lib/sentry/vernier/output.rb create mode 100644 sentry-ruby/lib/sentry/vernier/profiler.rb create mode 100644 sentry-ruby/spec/sentry/vernier/profiler_spec.rb create mode 100644 sentry-ruby/spec/support/profiler.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 4307dabc5..9f0aa6444 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased +### Features + +- Experimental support for multi-threaded profiling using Vernier ([#2372](https://github.com/getsentry/sentry-ruby/pull/2372)) + ### Internal - Profile items have bigger size limit now ([#2421](https://github.com/getsentry/sentry-ruby/pull/2421)) diff --git a/sentry-ruby/Gemfile b/sentry-ruby/Gemfile index c6e1db011..f13a6fe48 100644 --- a/sentry-ruby/Gemfile +++ b/sentry-ruby/Gemfile @@ -14,6 +14,7 @@ gem "puma" gem "timecop" gem "stackprof" unless RUBY_PLATFORM == "java" +gem "vernier", platforms: :ruby if RUBY_VERSION >= "3.2.1" gem "graphql", ">= 2.2.6" if RUBY_VERSION.to_f >= 2.7 diff --git a/sentry-ruby/lib/sentry-ruby.rb b/sentry-ruby/lib/sentry-ruby.rb index 734bc2cc9..db3420aba 100644 --- a/sentry-ruby/lib/sentry-ruby.rb +++ b/sentry-ruby/lib/sentry-ruby.rb @@ -25,6 +25,7 @@ require "sentry/backpressure_monitor" require "sentry/cron/monitor_check_ins" require "sentry/metrics" +require "sentry/vernier/profiler" [ "sentry/rake", diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index e02e1533c..505e46a2a 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -3,8 +3,8 @@ require "concurrent/utility/processor_counter" require "sentry/utils/exception_cause_chain" -require 'sentry/utils/custom_inspection' -require 'sentry/utils/env_helper' +require "sentry/utils/custom_inspection" +require "sentry/utils/env_helper" require "sentry/dsn" require "sentry/release_detector" require "sentry/transport/configuration" @@ -291,6 +291,10 @@ def capture_exception_frame_locals=(value) # @return [Symbol] attr_reader :instrumenter + # The profiler class + # @return [Class] + attr_reader :profiler_class + # Take a float between 0.0 and 1.0 as the sample rate for capturing profiles. # Note that this rate is relative to traces_sample_rate / traces_sampler, # i.e. the profile is sampled by this rate after the transaction is sampled. @@ -387,9 +391,9 @@ def initialize self.auto_session_tracking = true self.enable_backpressure_handling = false self.trusted_proxies = [] - self.dsn = ENV['SENTRY_DSN'] + self.dsn = ENV["SENTRY_DSN"] - spotlight_env = ENV['SENTRY_SPOTLIGHT'] + spotlight_env = ENV["SENTRY_SPOTLIGHT"] spotlight_bool = Sentry::Utils::EnvHelper.env_to_bool(spotlight_env, strict: true) self.spotlight = spotlight_bool.nil? ? (spotlight_env || false) : spotlight_bool self.server_name = server_name_from_env @@ -403,6 +407,8 @@ def initialize self.traces_sampler = nil self.enable_tracing = nil + self.profiler_class = Sentry::Profiler + @transport = Transport::Configuration.new @cron = Cron::Configuration.new @metrics = Metrics::Configuration.new @@ -498,6 +504,18 @@ def profiles_sample_rate=(profiles_sample_rate) @profiles_sample_rate = profiles_sample_rate end + def profiler_class=(profiler_class) + if profiler_class == Sentry::Vernier::Profiler + begin + require "vernier" + rescue LoadError + raise ArgumentError, "Please add the 'vernier' gem to your Gemfile to use the Vernier profiler with Sentry." + end + end + + @profiler_class = profiler_class + end + def sending_allowed? spotlight || sending_to_dsn_allowed? end diff --git a/sentry-ruby/lib/sentry/profiler.rb b/sentry-ruby/lib/sentry/profiler.rb index 400cab5da..d81e46024 100644 --- a/sentry-ruby/lib/sentry/profiler.rb +++ b/sentry-ruby/lib/sentry/profiler.rb @@ -1,9 +1,12 @@ # frozen_string_literal: true require "securerandom" +require_relative "profiler/helpers" module Sentry class Profiler + include Profiler::Helpers + VERSION = "1" PLATFORM = "ruby" # 101 Hz in microseconds @@ -44,6 +47,10 @@ def stop log("Stopped") end + def active_thread_id + "0" + end + # Sets initial sampling decision of the profile. # @return [void] def set_initial_sample_decision(transaction_sampled) @@ -188,43 +195,6 @@ def log(message) Sentry.logger.debug(LOGGER_PROGNAME) { "[Profiler] #{message}" } end - def in_app?(abs_path) - abs_path.match?(@in_app_pattern) - end - - # copied from stacktrace.rb since I don't want to touch existing code - # TODO-neel-profiler try to fetch this from stackprof once we patch - # the native extension - def compute_filename(abs_path, in_app) - return nil if abs_path.nil? - - under_project_root = @project_root && abs_path.start_with?(@project_root) - - prefix = - if under_project_root && in_app - @project_root - else - longest_load_path = $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size) - - if under_project_root - longest_load_path || @project_root - else - longest_load_path - end - end - - prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path - end - - def split_module(name) - # last module plus class/instance method - i = name.rindex("::") - function = i ? name[(i + 2)..-1] : name - mod = i ? name[0...i] : nil - - [function, mod] - end - def record_lost_event(reason) Sentry.get_current_client&.transport&.record_lost_event(reason, "profile") end diff --git a/sentry-ruby/lib/sentry/profiler/helpers.rb b/sentry-ruby/lib/sentry/profiler/helpers.rb new file mode 100644 index 000000000..3c446fba0 --- /dev/null +++ b/sentry-ruby/lib/sentry/profiler/helpers.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require "securerandom" + +module Sentry + class Profiler + module Helpers + def in_app?(abs_path) + abs_path.match?(@in_app_pattern) + end + + # copied from stacktrace.rb since I don't want to touch existing code + # TODO-neel-profiler try to fetch this from stackprof once we patch + # the native extension + def compute_filename(abs_path, in_app) + return nil if abs_path.nil? + + under_project_root = @project_root && abs_path.start_with?(@project_root) + + prefix = + if under_project_root && in_app + @project_root + else + longest_load_path = $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size) + + if under_project_root + longest_load_path || @project_root + else + longest_load_path + end + end + + prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path + end + + def split_module(name) + # last module plus class/instance method + i = name.rindex("::") + function = i ? name[(i + 2)..-1] : name + mod = i ? name[0...i] : nil + + [function, mod] + end + end + end +end diff --git a/sentry-ruby/lib/sentry/transaction.rb b/sentry-ruby/lib/sentry/transaction.rb index ac6256555..ad9447061 100644 --- a/sentry-ruby/lib/sentry/transaction.rb +++ b/sentry-ruby/lib/sentry/transaction.rb @@ -85,7 +85,7 @@ def initialize( @effective_sample_rate = nil @contexts = {} @measurements = {} - @profiler = Profiler.new(@configuration) + @profiler = @configuration.profiler_class.new(@configuration) init_span_recorder end diff --git a/sentry-ruby/lib/sentry/transaction_event.rb b/sentry-ruby/lib/sentry/transaction_event.rb index 4136ac6aa..a1a8767d1 100644 --- a/sentry-ruby/lib/sentry/transaction_event.rb +++ b/sentry-ruby/lib/sentry/transaction_event.rb @@ -74,8 +74,7 @@ def populate_profile(transaction) id: event_id, name: transaction.name, trace_id: transaction.trace_id, - # TODO-neel-profiler stubbed for now, see thread_id note in profiler.rb - active_thead_id: "0" + active_thread_id: transaction.profiler.active_thread_id.to_s } ) diff --git a/sentry-ruby/lib/sentry/vernier/output.rb b/sentry-ruby/lib/sentry/vernier/output.rb new file mode 100644 index 000000000..7002f82a1 --- /dev/null +++ b/sentry-ruby/lib/sentry/vernier/output.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require "json" +require "rbconfig" + +module Sentry + module Vernier + class Output + include Profiler::Helpers + + attr_reader :profile + + def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:) + @profile = profile + @project_root = project_root + @in_app_pattern = in_app_pattern + @app_dirs_pattern = app_dirs_pattern + end + + def to_h + @to_h ||= { + frames: frames, + stacks: stacks, + samples: samples, + thread_metadata: thread_metadata + } + end + + private + + def thread_metadata + profile.threads.map { |thread_id, thread_info| + [thread_id, { name: thread_info[:name] }] + }.to_h + end + + def samples + profile.threads.flat_map { |thread_id, thread_info| + started_at = thread_info[:started_at] + samples, timestamps = thread_info.values_at(:samples, :timestamps) + + samples.zip(timestamps).map { |stack_id, timestamp| + elapsed_since_start_ns = timestamp - started_at + + next if elapsed_since_start_ns < 0 + + { + thread_id: thread_id.to_s, + stack_id: stack_id, + elapsed_since_start_ns: elapsed_since_start_ns.to_s + } + }.compact + } + end + + def frames + funcs = stack_table_hash[:frame_table].fetch(:func) + lines = stack_table_hash[:func_table].fetch(:first_line) + + funcs.map do |idx| + function, mod = split_module(stack_table_hash[:func_table][:name][idx]) + + abs_path = stack_table_hash[:func_table][:filename][idx] + in_app = in_app?(abs_path) + filename = compute_filename(abs_path, in_app) + + { + function: function, + module: mod, + filename: filename, + abs_path: abs_path, + lineno: (lineno = lines[idx]) > 0 ? lineno : nil, + in_app: in_app + }.compact + end + end + + def stacks + profile._stack_table.stack_count.times.map do |stack_id| + profile.stack(stack_id).frames.map(&:idx) + end + end + + def stack_table_hash + @stack_table_hash ||= profile._stack_table.to_h + end + end + end +end diff --git a/sentry-ruby/lib/sentry/vernier/profiler.rb b/sentry-ruby/lib/sentry/vernier/profiler.rb new file mode 100644 index 000000000..0ca8c0f39 --- /dev/null +++ b/sentry-ruby/lib/sentry/vernier/profiler.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +require "securerandom" +require_relative "../profiler/helpers" +require_relative "output" + +module Sentry + module Vernier + class Profiler + EMPTY_RESULT = {}.freeze + + attr_reader :started, :event_id, :result + + def initialize(configuration) + @event_id = SecureRandom.uuid.delete("-") + + @started = false + @sampled = nil + + @profiling_enabled = defined?(Vernier) && configuration.profiling_enabled? + @profiles_sample_rate = configuration.profiles_sample_rate + @project_root = configuration.project_root + @app_dirs_pattern = configuration.app_dirs_pattern + @in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}") + end + + def set_initial_sample_decision(transaction_sampled) + unless @profiling_enabled + @sampled = false + return + end + + unless transaction_sampled + @sampled = false + log("Discarding profile because transaction not sampled") + return + end + + case @profiles_sample_rate + when 0.0 + @sampled = false + log("Discarding profile because sample_rate is 0") + return + when 1.0 + @sampled = true + return + else + @sampled = Random.rand < @profiles_sample_rate + end + + log("Discarding profile due to sampling decision") unless @sampled + end + + def start + return unless @sampled + return if @started + + ::Vernier.start_profile + @started = true + + log("Started") + + @started + rescue RuntimeError => e + # TODO: once Vernier raises something more dedicated, we should catch that instead + if e.message.include?("Profile already started") + log("Not started since running elsewhere") + else + log("Failed to start: #{e.message}") + end + end + + def stop + return unless @sampled + return unless @started + + @result = ::Vernier.stop_profile + + log("Stopped") + end + + def active_thread_id + Thread.current.object_id + end + + def to_hash + return EMPTY_RESULT unless @started + + unless @sampled + record_lost_event(:sample_rate) + return EMPTY_RESULT + end + + { **profile_meta, profile: output.to_h } + end + + private + + def log(message) + Sentry.logger.debug(LOGGER_PROGNAME) { "[Profiler::Vernier] #{message}" } + end + + def record_lost_event(reason) + Sentry.get_current_client&.transport&.record_lost_event(reason, "profile") + end + + def profile_meta + { + event_id: @event_id, + version: "1", + platform: "ruby" + } + end + + def output + @output ||= Output.new( + result, + project_root: @project_root, + app_dirs_pattern: @app_dirs_pattern, + in_app_pattern: @in_app_pattern + ) + end + end + end +end diff --git a/sentry-ruby/spec/sentry/configuration_spec.rb b/sentry-ruby/spec/sentry/configuration_spec.rb index 7ebd32920..f910712ad 100644 --- a/sentry-ruby/spec/sentry/configuration_spec.rb +++ b/sentry-ruby/spec/sentry/configuration_spec.rb @@ -693,4 +693,21 @@ class SentryConfigurationSample < Sentry::Configuration expect(subject.enabled_patches).to eq(%i[redis http]) end end + + describe "#profiler_class=" do + it "sets the profiler class to Vernier when it's available", when: :vernier_installed? do + subject.profiler_class = Sentry::Vernier::Profiler + expect(subject.profiler_class).to eq(Sentry::Vernier::Profiler) + end + + it "sets the profiler class to StackProf when Vernier is not available", when: { ruby_version?: [:<, "3.2"] } do + expect { subject.profiler_class = Sentry::Vernier::Profiler } + .to raise_error( + ArgumentError, + /Please add the 'vernier' gem to your Gemfile/ + ) + + expect(subject.profiler_class).to eq(Sentry::Profiler) + end + end end diff --git a/sentry-ruby/spec/sentry/profiler_spec.rb b/sentry-ruby/spec/sentry/profiler_spec.rb index e0cba8177..9100a3441 100644 --- a/sentry-ruby/spec/sentry/profiler_spec.rb +++ b/sentry-ruby/spec/sentry/profiler_spec.rb @@ -174,10 +174,11 @@ subject.set_initial_sample_decision(true) subject.start subject.stop + + allow(StackProf).to receive(:results).and_return([]) end it 'returns empty' do - expect(StackProf).to receive(:results).and_call_original expect(subject.to_hash).to eq({}) end diff --git a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb index dfd42ab33..83095d842 100644 --- a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb +++ b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'sentry/vernier/profiler' RSpec.describe 'Sentry::Rack::CaptureExceptions', when: :rack_available? do let(:exception) { ZeroDivisionError.new("divided by 0") } @@ -679,74 +680,106 @@ def will_be_sampled_by_sdk end end - if defined?(StackProf) - describe "profiling" do - context "when profiling is enabled" do - before do - perform_basic_setup do |config| - config.traces_sample_rate = 1.0 - config.profiles_sample_rate = 1.0 - config.release = "test-release" - end - end + shared_examples "a profiled transaction" do + it "collects a profile", retry: 3 do + stack = Sentry::Rack::CaptureExceptions.new(app) + stack.call(env) + event = last_sentry_event - let(:stackprof_results) do - data = StackProf::Report.from_file('spec/support/stackprof_results.json').data - # relative dir differs on each machine - data[:frames].each { |_id, fra| fra[:file].gsub!(//, Dir.pwd) } - data - end + profile = event.profile + expect(profile).not_to be_nil - before do - StackProf.stop - allow(StackProf).to receive(:results).and_return(stackprof_results) - end + expect(profile[:event_id]).not_to be_nil + expect(profile[:platform]).to eq("ruby") + expect(profile[:version]).to eq("1") + expect(profile[:environment]).to eq("development") + expect(profile[:release]).to eq("test-release") + expect { Time.parse(profile[:timestamp]) }.not_to raise_error - it "collects a profile" do - app = ->(_) do - [200, {}, "ok"] - end + expect(profile[:device]).to include(:architecture) + expect(profile[:os]).to include(:name, :version) + expect(profile[:runtime]).to include(:name, :version) - stack = Sentry::Rack::CaptureExceptions.new(app) - stack.call(env) - event = last_sentry_event + expect(profile[:transaction]).to include(:id, :name, :trace_id, :active_thread_id) + expect(profile[:transaction][:id]).to eq(event.event_id) + expect(profile[:transaction][:name]).to eq(event.transaction) + expect(profile[:transaction][:trace_id]).to eq(event.contexts[:trace][:trace_id]) + + thread_id_mapping = { + Sentry::Profiler => "0", + Sentry::Vernier::Profiler => Thread.current.object_id.to_s + } + + expect(profile[:transaction][:active_thread_id]).to eq(thread_id_mapping[Sentry.configuration.profiler_class]) + + # detailed checking of content is done in profiler_spec, + # just check basic structure here + frames = profile[:profile][:frames] + expect(frames).to be_a(Array) + expect(frames.first).to include(:function, :filename, :abs_path, :in_app) + + stacks = profile[:profile][:stacks] + expect(stacks).to be_a(Array) + expect(stacks.first).to be_a(Array) + expect(stacks.first.first).to be_a(Integer) - profile = event.profile - expect(profile).not_to be_nil + samples = profile[:profile][:samples] + expect(samples).to be_a(Array) + expect(samples.first).to include(:stack_id, :thread_id, :elapsed_since_start_ns) + end + end + + describe "profiling with StackProf", when: [:stack_prof_installed?, :rack_available?] do + context "when profiling is enabled" do + let(:app) do + ->(_) do + [200, {}, "ok"] + end + end - expect(profile[:event_id]).not_to be_nil - expect(profile[:platform]).to eq("ruby") - expect(profile[:version]).to eq("1") - expect(profile[:environment]).to eq("development") - expect(profile[:release]).to eq("test-release") - expect { Time.parse(profile[:timestamp]) }.not_to raise_error + let(:stackprof_results) do + data = StackProf::Report.from_file('spec/support/stackprof_results.json').data + # relative dir differs on each machine + data[:frames].each { |_id, fra| fra[:file].gsub!(//, Dir.pwd) } + data + end + + before do + perform_basic_setup do |config| + config.traces_sample_rate = 1.0 + config.profiles_sample_rate = 1.0 + config.release = "test-release" + end - expect(profile[:device]).to include(:architecture) - expect(profile[:os]).to include(:name, :version) - expect(profile[:runtime]).to include(:name, :version) + StackProf.stop - expect(profile[:transaction]).to include(:id, :name, :trace_id, :active_thead_id) - expect(profile[:transaction][:id]).to eq(event.event_id) - expect(profile[:transaction][:name]).to eq(event.transaction) - expect(profile[:transaction][:trace_id]).to eq(event.contexts[:trace][:trace_id]) - expect(profile[:transaction][:active_thead_id]).to eq("0") + allow(StackProf).to receive(:results).and_return(stackprof_results) + end - # detailed checking of content is done in profiler_spec, - # just check basic structure here - frames = profile[:profile][:frames] - expect(frames).to be_a(Array) - expect(frames.first).to include(:function, :filename, :abs_path, :in_app) + include_examples "a profiled transaction" + end + end - stacks = profile[:profile][:stacks] - expect(stacks).to be_a(Array) - expect(stacks.first).to be_a(Array) - expect(stacks.first.first).to be_a(Integer) + describe "profiling with vernier", when: [:vernier_installed?, :rack_available?] do + context "when profiling is enabled" do + let(:app) do + ->(_) do + ProfilerTest::Bar.bar + [200, {}, "ok"] + end + end - samples = profile[:profile][:samples] - expect(samples).to be_a(Array) - expect(samples.first).to include(:stack_id, :thread_id, :elapsed_since_start_ns) + before do + perform_basic_setup do |config| + config.traces_sample_rate = 1.0 + config.profiles_sample_rate = 1.0 + config.release = "test-release" + config.profiler_class = Sentry::Vernier::Profiler + config.project_root = Dir.pwd end end + + include_examples "a profiled transaction" end end end diff --git a/sentry-ruby/spec/sentry/vernier/profiler_spec.rb b/sentry-ruby/spec/sentry/vernier/profiler_spec.rb new file mode 100644 index 000000000..645ddcada --- /dev/null +++ b/sentry-ruby/spec/sentry/vernier/profiler_spec.rb @@ -0,0 +1,309 @@ +require "spec_helper" + +require "sentry/vernier/profiler" + +RSpec.describe Sentry::Vernier::Profiler, when: { ruby_version?: [:>=, "3.2.1"] } do + subject(:profiler) { described_class.new(Sentry.configuration) } + + before do + # TODO: replace with some public API once available + Vernier.stop_profile if Vernier.instance_variable_get(:@collector) + + perform_basic_setup do |config| + config.traces_sample_rate = traces_sample_rate + config.profiles_sample_rate = profiles_sample_rate + config.app_dirs_pattern = %r{spec/support} + end + end + + let(:profiles_sample_rate) { 1.0 } + let(:traces_sample_rate) { 1.0 } + + describe '#start' do + context "when profiles_sample_rate is 0" do + let(:profiles_sample_rate) { 0.0 } + + it "does not start Vernier" do + profiler.set_initial_sample_decision(true) + + expect(Vernier).not_to receive(:start_profile) + profiler.start + expect(profiler.started).to eq(false) + end + end + + context "when profiles_sample_rate is between 0.0 and 1.0" do + let(:profiles_sample_rate) { 0.4 } + + it "randomizes profiling" do + profiler.set_initial_sample_decision(true) + + expect([nil, true]).to include(profiler.start) + end + end + + context "when traces_sample_rate is nil" do + let(:traces_sample_rate) { nil } + + it "does not start Vernier" do + profiler.set_initial_sample_decision(true) + + expect(Vernier).not_to receive(:start_profile) + profiler.start + expect(profiler.started).to eq(false) + end + end + + context 'without sampling decision' do + it 'does not start Vernier' do + expect(Vernier).not_to receive(:start_profile) + profiler.start + expect(profiler.started).to eq(false) + end + + it 'does not start Vernier if not sampled' do + expect(Vernier).not_to receive(:start_profile) + profiler.start + expect(profiler.started).to eq(false) + end + end + + context 'with sampling decision' do + before do + profiler.set_initial_sample_decision(true) + end + + it 'starts Vernier if sampled' do + expect(Vernier).to receive(:start_profile).and_return(true) + + profiler.start + + expect(profiler.started).to eq(true) + end + + it 'does not start Vernier again if already started' do + expect(Vernier).to receive(:start_profile).and_return(true).once + + profiler.start + profiler.start + + expect(profiler.started).to be(true) + end + end + + context "when Vernier crashes" do + it "logs the error and does not raise" do + profiler.set_initial_sample_decision(true) + + expect(Vernier).to receive(:start_profile).and_raise("boom") + + expect { profiler.start }.to_not raise_error("boom") + end + + it "doesn't start if Vernier raises that it already started" do + profiler.set_initial_sample_decision(true) + + expect(Vernier).to receive(:start_profile).and_raise(RuntimeError.new("Profile already started")) + + profiler.start + + expect(profiler.started).to eq(false) + end + end + end + + describe '#stop' do + it 'does not stop Vernier if not sampled' do + profiler.set_initial_sample_decision(false) + expect(Vernier).not_to receive(:stop_profile) + profiler.stop + end + + it 'does not stop Vernier if sampled but not started' do + profiler.set_initial_sample_decision(true) + expect(Vernier).not_to receive(:stop_profile) + profiler.stop + end + + it 'stops Vernier if sampled and started' do + profiler.set_initial_sample_decision(true) + profiler.start + expect(Vernier).to receive(:stop_profile) + profiler.stop + end + end + + describe "#to_hash" do + let (:transport) { Sentry.get_current_client.transport } + + + it "records lost event if not sampled" do + expect(transport).to receive(:record_lost_event).with(:sample_rate, "profile") + + profiler.set_initial_sample_decision(true) + profiler.start + profiler.set_initial_sample_decision(false) + + expect(profiler.to_hash).to eq({}) + end + end + + context 'with sampling decision' do + before do + profiler.set_initial_sample_decision(true) + end + + describe '#to_hash' do + it "returns empty hash if not started" do + expect(profiler.to_hash).to eq({}) + end + + context 'with single-thread profiled code' do + before do + profiler.start + ProfilerTest::Bar.bar + profiler.stop + end + + it 'has correct frames' do + frames = profiler.to_hash[:profile][:frames] + + foo_frame = frames.find { |f| f[:function] =~ /foo/ } + + expect(foo_frame[:function]).to eq('Foo.foo') + expect(foo_frame[:module]).to eq('ProfilerTest::Bar') + expect(foo_frame[:in_app]).to eq(true) + expect(foo_frame[:lineno]).to eq(4) + expect(foo_frame[:filename]).to eq('spec/support/profiler.rb') + expect(foo_frame[:abs_path]).to include('sentry-ruby/sentry-ruby/spec/support/profiler.rb') + end + + it 'has correct stacks' do + profile = profiler.to_hash[:profile] + frames = profile[:frames] + stacks = profile[:stacks] + + stack_tops = stacks.map { |s| s.take(3) }.map { |s| s.map { |i| frames[i][:function] } } + + expect(stack_tops.any? { |tops| tops.include?("Foo.foo") }).to be(true) + expect(stack_tops.any? { |tops| tops.include?("Bar.bar") }).to be(true) + expect(stack_tops.any? { |tops| tops.include?("Integer#times") }).to be(true) + + stacks.each do |stack| + stack.each do |frame_idx| + expect(frames[frame_idx][:function]).to be_a(String) + end + end + end + + it 'has correct samples' do + profile = profiler.to_hash[:profile] + samples = profile[:samples] + last_elapsed = 0 + + samples.group_by { |sample| sample[:thread_id] }.each do |thread_id, thread_samples| + expect(thread_id.to_i).to be > 0 + + last_elapsed = 0 + + thread_samples.each do |sample| + expect(sample[:stack_id]).to be > 0 + + elapsed = sample[:elapsed_since_start_ns].to_i + + expect(elapsed).to be > 0.0 + expect(elapsed).to be > last_elapsed + + last_elapsed = elapsed + end + end + end + end + + context 'with multi-thread profiled code' do + before do + profiler.start + + 2.times.map do |i| + Thread.new do + Thread.current.name = "thread-bar-#{i}" + + ProfilerTest::Bar.bar + end + end.map(&:join) + + profiler.stop + end + + it "has correct thread metadata" do + thread_metadata = profiler.to_hash[:profile][:thread_metadata] + + main_thread = thread_metadata.values.find { |metadata| metadata[:name].include?("rspec") } + thread1 = thread_metadata.values.find { |metadata| metadata[:name] == "thread-bar-0" } + thread2 = thread_metadata.values.find { |metadata| metadata[:name] == "thread-bar-1" } + + thread_metadata.each do |thread_id, metadata| + expect(thread_id.to_i).to be > 0 + end + + expect(main_thread[:name]).to include("rspec") + expect(thread1[:name]).to eq("thread-bar-0") + expect(thread2[:name]).to eq("thread-bar-1") + end + + it 'has correct frames', when: { ruby_version?: [:>=, "3.3"] } do + frames = profiler.to_hash[:profile][:frames] + + foo_frame = frames.find { |f| f[:function] =~ /foo/ } + + expect(foo_frame[:function]).to eq('Foo.foo') + expect(foo_frame[:module]).to eq('ProfilerTest::Bar') + expect(foo_frame[:in_app]).to eq(true) + expect(foo_frame[:lineno]).to eq(4) + expect(foo_frame[:filename]).to eq('spec/support/profiler.rb') + expect(foo_frame[:abs_path]).to include('sentry-ruby/sentry-ruby/spec/support/profiler.rb') + end + + it 'has correct stacks', when: { ruby_version?: [:>=, "3.3"] } do + profile = profiler.to_hash[:profile] + frames = profile[:frames] + stacks = profile[:stacks] + + stack_tops = stacks.map { |s| s.take(3) }.map { |s| s.map { |i| frames[i][:function] } } + + expect(stack_tops.any? { |tops| tops.include?("Foo.foo") }).to be(true) + expect(stack_tops.any? { |tops| tops.include?("Bar.bar") }).to be(true) + expect(stack_tops.any? { |tops| tops.include?("Integer#times") }).to be(true) + + stacks.each do |stack| + stack.each do |frame_idx| + expect(frames[frame_idx][:function]).to be_a(String) + end + end + end + + it 'has correct samples' do + profile = profiler.to_hash[:profile] + samples = profile[:samples] + + samples.group_by { |sample| sample[:thread_id] }.each do |thread_id, thread_samples| + expect(thread_id.to_i).to be > 0 + + last_elapsed = 0 + + thread_samples.each do |sample| + expect(sample[:stack_id]).to be > 0 + + elapsed = sample[:elapsed_since_start_ns].to_i + + expect(elapsed).to be > 0.0 + expect(elapsed).to be > last_elapsed + + last_elapsed = elapsed + end + end + end + end + end + end +end diff --git a/sentry-ruby/spec/spec_helper.rb b/sentry-ruby/spec/spec_helper.rb index 2758a0a1f..1bceb1070 100644 --- a/sentry-ruby/spec/spec_helper.rb +++ b/sentry-ruby/spec/spec_helper.rb @@ -8,6 +8,7 @@ require "rspec/retry" require "redis" require "stackprof" unless RUBY_PLATFORM == "java" +require "vernier" unless RUBY_PLATFORM == "java" || RUBY_VERSION < "3.2" SimpleCov.start do project_name "sentry-ruby" @@ -23,6 +24,8 @@ require "sentry-ruby" require "sentry/test_helper" +Dir[Pathname(__dir__).join("support/**/*.rb")].sort.each { |f| require f } + RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" @@ -47,9 +50,20 @@ end config.before(:each, when: true) do |example| - meth = example.metadata[:when] + guards = + case value = example.metadata[:when] + when Symbol then [value] + when Array then value + when Hash then value.map { |k, v| [k, v].flatten } + else + raise ArgumentError, "Invalid `when` metadata: #{value.inspect}" + end + + skip_examples = guards.any? do |meth, *args| + !TestHelpers.public_send(meth, *args) + end - skip("Skipping because `when: #{meth}` returned false") unless TestHelpers.public_send(meth, example) + skip("Skipping because one or more guards `#{guards.inspect}` returned false") if skip_examples end RSpec::Matchers.define :have_recorded_lost_event do |reason, data_category, num: 1| @@ -60,13 +74,22 @@ end module TestHelpers - def self.stack_prof_installed?(_example) + def self.stack_prof_installed? defined?(StackProf) end - def self.rack_available?(_example) + def self.vernier_installed? + require "sentry/vernier/profiler" + defined?(::Vernier) + end + + def self.rack_available? defined?(Rack) end + + def self.ruby_version?(op, version) + RUBY_VERSION.public_send(op, version) + end end def fixtures_root diff --git a/sentry-ruby/spec/support/profiler.rb b/sentry-ruby/spec/support/profiler.rb new file mode 100644 index 000000000..7f048b8a5 --- /dev/null +++ b/sentry-ruby/spec/support/profiler.rb @@ -0,0 +1,14 @@ +module ProfilerTest + module Bar + module Foo + def self.foo + 1e6.to_i.times { 2**2 } + end + end + + def self.bar + Foo.foo + sleep 0.1 + end + end +end diff --git a/sentry-ruby/spec/support/stackprof_results.json b/sentry-ruby/spec/support/stackprof_results.json index 1527df8cd..712c3b768 100644 --- a/sentry-ruby/spec/support/stackprof_results.json +++ b/sentry-ruby/spec/support/stackprof_results.json @@ -1 +1,718 @@ -{"version":1.2,"mode":"wall","interval":9900.990099009901,"samples":15,"gc_samples":0,"missed_samples":0,"metadata":{},"frames":{"140370219074600":{"name":"Integer#times","file":"","line":null,"total_samples":5,"samples":2},"140370222379560":{"name":"Bar::Foo.foo","file":"/spec/sentry/profiler_spec.rb","line":7,"total_samples":5,"samples":2},"140370222379480":{"name":"Bar.bar","file":"/spec/sentry/profiler_spec.rb","line":12,"total_samples":15,"samples":0},"140370262463760":{"name":"block (4 levels) in ","file":"/spec/sentry/profiler_spec.rb","line":169,"total_samples":15,"samples":0},"140370219081000":{"name":"BasicObject#instance_exec","file":"","line":null,"total_samples":15,"samples":0},"140369934628760":{"name":"RSpec::Core::Example#instance_exec","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb","line":456,"total_samples":15,"samples":0},"140370262209000":{"name":"RSpec::Core::Hooks::BeforeHook#run","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb","line":364,"total_samples":15,"samples":0},"140370262206960":{"name":"RSpec::Core::Hooks::HookCollections#run_owned_hooks_for","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb","line":527,"total_samples":15,"samples":0},"140370219016480":{"name":"Array#each","file":"","line":null,"total_samples":15,"samples":0},"140370262206440":{"name":"RSpec::Core::Hooks::HookCollections#run_example_hooks_for","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb","line":613,"total_samples":15,"samples":0},"140370219016360":{"name":"Array#reverse_each","file":"","line":null,"total_samples":15,"samples":0},"140370262207720":{"name":"RSpec::Core::Hooks::HookCollections#run","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb","line":475,"total_samples":15,"samples":0},"140369934628120":{"name":"RSpec::Core::Example#run_before_example","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb","line":503,"total_samples":15,"samples":0},"140369934656240":{"name":"RSpec::Core::Example#run","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb","line":246,"total_samples":15,"samples":0},"140369934628080":{"name":"RSpec::Core::Example#with_around_and_singleton_context_hooks","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb","line":508,"total_samples":15,"samples":0},"140369934628640":{"name":"RSpec::Core::Example#with_around_example_hooks","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb","line":466,"total_samples":15,"samples":0},"140370262206400":{"name":"RSpec::Core::Hooks::HookCollections#run_around_example_hooks_for","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb","line":619,"total_samples":15,"samples":0},"140369934629600":{"name":"RSpec::Core::Example::Procsy#call","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb","line":350,"total_samples":15,"samples":0},"140369936132760":{"name":"RSpec::Retry#run","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-retry-0.6.2/lib/rspec/retry.rb","line":107,"total_samples":15,"samples":0},"140370203515000":{"name":"Kernel#loop","file":"","line":null,"total_samples":15,"samples":0},"140369936134000":{"name":"RSpec::Core::Example::Procsy#run_with_retry","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-retry-0.6.2/lib/rspec_ext/rspec_ext.rb","line":11,"total_samples":15,"samples":0},"140369936133560":{"name":"RSpec::Retry.setup","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-retry-0.6.2/lib/rspec/retry.rb","line":7,"total_samples":15,"samples":0},"140370262208320":{"name":"RSpec::Core::Hooks::AroundHook#execute_with","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb","line":389,"total_samples":15,"samples":0},"140369934629640":{"name":"RSpec::Core::Example::Procsy#call","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb","line":350,"total_samples":15,"samples":0},"140370221599800":{"name":"RSpec::Core::ExampleGroup.run_examples","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example_group.rb","line":641,"total_samples":15,"samples":0},"140370219015440":{"name":"Array#map","file":"","line":null,"total_samples":15,"samples":0},"140370221599880":{"name":"RSpec::Core::ExampleGroup.run","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example_group.rb","line":599,"total_samples":15,"samples":0},"140369934821040":{"name":"RSpec::Core::Runner#run_specs","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb","line":113,"total_samples":15,"samples":0},"140370221475080":{"name":"RSpec::Core::Configuration#with_suite_hooks","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/configuration.rb","line":2062,"total_samples":15,"samples":0},"140370262307680":{"name":"RSpec::Core::Reporter#report","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/reporter.rb","line":71,"total_samples":15,"samples":0},"140369934821120":{"name":"RSpec::Core::Runner#run","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb","line":85,"total_samples":15,"samples":0},"140369934821200":{"name":"RSpec::Core::Runner.run","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb","line":64,"total_samples":15,"samples":0},"140369934821320":{"name":"RSpec::Core::Runner.invoke","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb","line":43,"total_samples":15,"samples":0},"140369934947600":{"name":"","file":"/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/exe/rspec","total_samples":15,"samples":0},"140370220922120":{"name":"Kernel#load","file":"","line":null,"total_samples":15,"samples":0},"140369934788840":{"name":"
","file":"/Users/neel/.rvm/gems/ruby-3.0.0/bin/rspec","line":1,"total_samples":15,"samples":0},"140370219331600":{"name":"Kernel#eval","file":"","line":null,"total_samples":15,"samples":0},"140369933326520":{"name":"
","file":"/Users/neel/.rvm/gems/ruby-3.0.0/bin/ruby_executable_hooks","total_samples":15,"samples":0},"140370218844600":{"name":"
","file":"/Users/neel/.rvm/gems/ruby-3.0.0/bin/ruby_executable_hooks","total_samples":15,"samples":0},"140370219073720":{"name":"Integer#**","file":"","line":null,"total_samples":1,"samples":1},"140370265410040":{"name":"Kernel#sleep","file":"","line":null,"total_samples":10,"samples":10}},"raw":[62,140370218844600,140369933326520,140370219331600,140369934788840,140370220922120,140369934947600,140369934821320,140369934821200,140369934821120,140369934821040,140370262307680,140369934821040,140370221475080,140369934821040,140370219015440,140369934821040,140370221599880,140370219015440,140370221599880,140370221599880,140370219015440,140370221599880,140370221599880,140370221599800,140370219015440,140370221599800,140369934656240,140369934628080,140369934628640,140370262207720,140370262206400,140369934629640,140370262206400,140370262208320,140369934628760,140370219081000,140369936133560,140369936134000,140369936132760,140370203515000,140369936132760,140369934629600,140370262206400,140370262207720,140369934628640,140369934628080,140369934656240,140369934628120,140370262207720,140370262206440,140370219016360,140370262206440,140370262206960,140370219016480,140370262206960,140370262209000,140369934628760,140370219081000,140370262463760,140370222379480,140370222379560,140370219074600,1,63,140370218844600,140369933326520,140370219331600,140369934788840,140370220922120,140369934947600,140369934821320,140369934821200,140369934821120,140369934821040,140370262307680,140369934821040,140370221475080,140369934821040,140370219015440,140369934821040,140370221599880,140370219015440,140370221599880,140370221599880,140370219015440,140370221599880,140370221599880,140370221599800,140370219015440,140370221599800,140369934656240,140369934628080,140369934628640,140370262207720,140370262206400,140369934629640,140370262206400,140370262208320,140369934628760,140370219081000,140369936133560,140369936134000,140369936132760,140370203515000,140369936132760,140369934629600,140370262206400,140370262207720,140369934628640,140369934628080,140369934656240,140369934628120,140370262207720,140370262206440,140370219016360,140370262206440,140370262206960,140370219016480,140370262206960,140370262209000,140369934628760,140370219081000,140370262463760,140370222379480,140370222379560,140370219074600,140370222379560,1,62,140370218844600,140369933326520,140370219331600,140369934788840,140370220922120,140369934947600,140369934821320,140369934821200,140369934821120,140369934821040,140370262307680,140369934821040,140370221475080,140369934821040,140370219015440,140369934821040,140370221599880,140370219015440,140370221599880,140370221599880,140370219015440,140370221599880,140370221599880,140370221599800,140370219015440,140370221599800,140369934656240,140369934628080,140369934628640,140370262207720,140370262206400,140369934629640,140370262206400,140370262208320,140369934628760,140370219081000,140369936133560,140369936134000,140369936132760,140370203515000,140369936132760,140369934629600,140370262206400,140370262207720,140369934628640,140369934628080,140369934656240,140369934628120,140370262207720,140370262206440,140370219016360,140370262206440,140370262206960,140370219016480,140370262206960,140370262209000,140369934628760,140370219081000,140370262463760,140370222379480,140370222379560,140370219074600,1,64,140370218844600,140369933326520,140370219331600,140369934788840,140370220922120,140369934947600,140369934821320,140369934821200,140369934821120,140369934821040,140370262307680,140369934821040,140370221475080,140369934821040,140370219015440,140369934821040,140370221599880,140370219015440,140370221599880,140370221599880,140370219015440,140370221599880,140370221599880,140370221599800,140370219015440,140370221599800,140369934656240,140369934628080,140369934628640,140370262207720,140370262206400,140369934629640,140370262206400,140370262208320,140369934628760,140370219081000,140369936133560,140369936134000,140369936132760,140370203515000,140369936132760,140369934629600,140370262206400,140370262207720,140369934628640,140369934628080,140369934656240,140369934628120,140370262207720,140370262206440,140370219016360,140370262206440,140370262206960,140370219016480,140370262206960,140370262209000,140369934628760,140370219081000,140370262463760,140370222379480,140370222379560,140370219074600,140370222379560,140370219073720,1,63,140370218844600,140369933326520,140370219331600,140369934788840,140370220922120,140369934947600,140369934821320,140369934821200,140369934821120,140369934821040,140370262307680,140369934821040,140370221475080,140369934821040,140370219015440,140369934821040,140370221599880,140370219015440,140370221599880,140370221599880,140370219015440,140370221599880,140370221599880,140370221599800,140370219015440,140370221599800,140369934656240,140369934628080,140369934628640,140370262207720,140370262206400,140369934629640,140370262206400,140370262208320,140369934628760,140370219081000,140369936133560,140369936134000,140369936132760,140370203515000,140369936132760,140369934629600,140370262206400,140370262207720,140369934628640,140369934628080,140369934656240,140369934628120,140370262207720,140370262206440,140370219016360,140370262206440,140370262206960,140370219016480,140370262206960,140370262209000,140369934628760,140370219081000,140370262463760,140370222379480,140370222379560,140370219074600,140370222379560,1,61,140370218844600,140369933326520,140370219331600,140369934788840,140370220922120,140369934947600,140369934821320,140369934821200,140369934821120,140369934821040,140370262307680,140369934821040,140370221475080,140369934821040,140370219015440,140369934821040,140370221599880,140370219015440,140370221599880,140370221599880,140370219015440,140370221599880,140370221599880,140370221599800,140370219015440,140370221599800,140369934656240,140369934628080,140369934628640,140370262207720,140370262206400,140369934629640,140370262206400,140370262208320,140369934628760,140370219081000,140369936133560,140369936134000,140369936132760,140370203515000,140369936132760,140369934629600,140370262206400,140370262207720,140369934628640,140369934628080,140369934656240,140369934628120,140370262207720,140370262206440,140370219016360,140370262206440,140370262206960,140370219016480,140370262206960,140370262209000,140369934628760,140370219081000,140370262463760,140370222379480,140370265410040,10],"raw_sample_timestamps":[1295905330989,1295905338595,1295905348330,1295905358336,1295905368777,1295905379129,1295905388495,1295905398492,1295905407835,1295905418826,1295905428669,1295905438609,1295905447579,1295905458008,1295905468407],"raw_timestamp_deltas":[12403,7531,9689,9986,10420,10338,9320,9949,9269,10920,9770,9864,8899,10354,10323]} +{ + "version": 1.2, + "mode": "wall", + "interval": 9900.990099009901, + "samples": 15, + "gc_samples": 0, + "missed_samples": 0, + "metadata": {}, + "frames": { + "140370219074600": { + "name": "Integer#times", + "file": "", + "line": null, + "total_samples": 5, + "samples": 2 + }, + "140370222379560": { + "name": "Bar::Foo.foo", + "file": "/spec/sentry/profiler_spec.rb", + "line": 7, + "total_samples": 5, + "samples": 2 + }, + "140370222379480": { + "name": "Bar.bar", + "file": "/spec/sentry/profiler_spec.rb", + "line": 12, + "total_samples": 15, + "samples": 0 + }, + "140370262463760": { + "name": "block (4 levels) in ", + "file": "/spec/sentry/profiler_spec.rb", + "line": 169, + "total_samples": 15, + "samples": 0 + }, + "140370219081000": { + "name": "BasicObject#instance_exec", + "file": "", + "line": null, + "total_samples": 15, + "samples": 0 + }, + "140369934628760": { + "name": "RSpec::Core::Example#instance_exec", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb", + "line": 456, + "total_samples": 15, + "samples": 0 + }, + "140370262209000": { + "name": "RSpec::Core::Hooks::BeforeHook#run", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb", + "line": 364, + "total_samples": 15, + "samples": 0 + }, + "140370262206960": { + "name": "RSpec::Core::Hooks::HookCollections#run_owned_hooks_for", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb", + "line": 527, + "total_samples": 15, + "samples": 0 + }, + "140370219016480": { + "name": "Array#each", + "file": "", + "line": null, + "total_samples": 15, + "samples": 0 + }, + "140370262206440": { + "name": "RSpec::Core::Hooks::HookCollections#run_example_hooks_for", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb", + "line": 613, + "total_samples": 15, + "samples": 0 + }, + "140370219016360": { + "name": "Array#reverse_each", + "file": "", + "line": null, + "total_samples": 15, + "samples": 0 + }, + "140370262207720": { + "name": "RSpec::Core::Hooks::HookCollections#run", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb", + "line": 475, + "total_samples": 15, + "samples": 0 + }, + "140369934628120": { + "name": "RSpec::Core::Example#run_before_example", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb", + "line": 503, + "total_samples": 15, + "samples": 0 + }, + "140369934656240": { + "name": "RSpec::Core::Example#run", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb", + "line": 246, + "total_samples": 15, + "samples": 0 + }, + "140369934628080": { + "name": "RSpec::Core::Example#with_around_and_singleton_context_hooks", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb", + "line": 508, + "total_samples": 15, + "samples": 0 + }, + "140369934628640": { + "name": "RSpec::Core::Example#with_around_example_hooks", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb", + "line": 466, + "total_samples": 15, + "samples": 0 + }, + "140370262206400": { + "name": "RSpec::Core::Hooks::HookCollections#run_around_example_hooks_for", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb", + "line": 619, + "total_samples": 15, + "samples": 0 + }, + "140369934629600": { + "name": "RSpec::Core::Example::Procsy#call", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb", + "line": 350, + "total_samples": 15, + "samples": 0 + }, + "140369936132760": { + "name": "RSpec::Retry#run", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-retry-0.6.2/lib/rspec/retry.rb", + "line": 107, + "total_samples": 15, + "samples": 0 + }, + "140370203515000": { + "name": "Kernel#loop", + "file": "", + "line": null, + "total_samples": 15, + "samples": 0 + }, + "140369936134000": { + "name": "RSpec::Core::Example::Procsy#run_with_retry", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-retry-0.6.2/lib/rspec_ext/rspec_ext.rb", + "line": 11, + "total_samples": 15, + "samples": 0 + }, + "140369936133560": { + "name": "RSpec::Retry.setup", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-retry-0.6.2/lib/rspec/retry.rb", + "line": 7, + "total_samples": 15, + "samples": 0 + }, + "140370262208320": { + "name": "RSpec::Core::Hooks::AroundHook#execute_with", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb", + "line": 389, + "total_samples": 15, + "samples": 0 + }, + "140369934629640": { + "name": "RSpec::Core::Example::Procsy#call", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example.rb", + "line": 350, + "total_samples": 15, + "samples": 0 + }, + "140370221599800": { + "name": "RSpec::Core::ExampleGroup.run_examples", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example_group.rb", + "line": 641, + "total_samples": 15, + "samples": 0 + }, + "140370219015440": { + "name": "Array#map", + "file": "", + "line": null, + "total_samples": 15, + "samples": 0 + }, + "140370221599880": { + "name": "RSpec::Core::ExampleGroup.run", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/example_group.rb", + "line": 599, + "total_samples": 15, + "samples": 0 + }, + "140369934821040": { + "name": "RSpec::Core::Runner#run_specs", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb", + "line": 113, + "total_samples": 15, + "samples": 0 + }, + "140370221475080": { + "name": "RSpec::Core::Configuration#with_suite_hooks", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/configuration.rb", + "line": 2062, + "total_samples": 15, + "samples": 0 + }, + "140370262307680": { + "name": "RSpec::Core::Reporter#report", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/reporter.rb", + "line": 71, + "total_samples": 15, + "samples": 0 + }, + "140369934821120": { + "name": "RSpec::Core::Runner#run", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb", + "line": 85, + "total_samples": 15, + "samples": 0 + }, + "140369934821200": { + "name": "RSpec::Core::Runner.run", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb", + "line": 64, + "total_samples": 15, + "samples": 0 + }, + "140369934821320": { + "name": "RSpec::Core::Runner.invoke", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/lib/rspec/core/runner.rb", + "line": 43, + "total_samples": 15, + "samples": 0 + }, + "140369934947600": { + "name": "", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/gems/rspec-core-3.11.0/exe/rspec", + "total_samples": 15, + "samples": 0 + }, + "140370220922120": { + "name": "Kernel#load", + "file": "", + "line": null, + "total_samples": 15, + "samples": 0 + }, + "140369934788840": { + "name": "
", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/bin/rspec", + "line": 1, + "total_samples": 15, + "samples": 0 + }, + "140370219331600": { + "name": "Kernel#eval", + "file": "", + "line": null, + "total_samples": 15, + "samples": 0 + }, + "140369933326520": { + "name": "
", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/bin/ruby_executable_hooks", + "total_samples": 15, + "samples": 0 + }, + "140370218844600": { + "name": "
", + "file": "/Users/neel/.rvm/gems/ruby-3.0.0/bin/ruby_executable_hooks", + "total_samples": 15, + "samples": 0 + }, + "140370219073720": { + "name": "Integer#**", + "file": "", + "line": null, + "total_samples": 1, + "samples": 1 + }, + "140370265410040": { + "name": "Kernel#sleep", + "file": "", + "line": null, + "total_samples": 10, + "samples": 10 + } + }, + "raw": [ + 62, + 140370218844600, + 140369933326520, + 140370219331600, + 140369934788840, + 140370220922120, + 140369934947600, + 140369934821320, + 140369934821200, + 140369934821120, + 140369934821040, + 140370262307680, + 140369934821040, + 140370221475080, + 140369934821040, + 140370219015440, + 140369934821040, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370221599800, + 140370219015440, + 140370221599800, + 140369934656240, + 140369934628080, + 140369934628640, + 140370262207720, + 140370262206400, + 140369934629640, + 140370262206400, + 140370262208320, + 140369934628760, + 140370219081000, + 140369936133560, + 140369936134000, + 140369936132760, + 140370203515000, + 140369936132760, + 140369934629600, + 140370262206400, + 140370262207720, + 140369934628640, + 140369934628080, + 140369934656240, + 140369934628120, + 140370262207720, + 140370262206440, + 140370219016360, + 140370262206440, + 140370262206960, + 140370219016480, + 140370262206960, + 140370262209000, + 140369934628760, + 140370219081000, + 140370262463760, + 140370222379480, + 140370222379560, + 140370219074600, + 1, + 63, + 140370218844600, + 140369933326520, + 140370219331600, + 140369934788840, + 140370220922120, + 140369934947600, + 140369934821320, + 140369934821200, + 140369934821120, + 140369934821040, + 140370262307680, + 140369934821040, + 140370221475080, + 140369934821040, + 140370219015440, + 140369934821040, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370221599800, + 140370219015440, + 140370221599800, + 140369934656240, + 140369934628080, + 140369934628640, + 140370262207720, + 140370262206400, + 140369934629640, + 140370262206400, + 140370262208320, + 140369934628760, + 140370219081000, + 140369936133560, + 140369936134000, + 140369936132760, + 140370203515000, + 140369936132760, + 140369934629600, + 140370262206400, + 140370262207720, + 140369934628640, + 140369934628080, + 140369934656240, + 140369934628120, + 140370262207720, + 140370262206440, + 140370219016360, + 140370262206440, + 140370262206960, + 140370219016480, + 140370262206960, + 140370262209000, + 140369934628760, + 140370219081000, + 140370262463760, + 140370222379480, + 140370222379560, + 140370219074600, + 140370222379560, + 1, + 62, + 140370218844600, + 140369933326520, + 140370219331600, + 140369934788840, + 140370220922120, + 140369934947600, + 140369934821320, + 140369934821200, + 140369934821120, + 140369934821040, + 140370262307680, + 140369934821040, + 140370221475080, + 140369934821040, + 140370219015440, + 140369934821040, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370221599800, + 140370219015440, + 140370221599800, + 140369934656240, + 140369934628080, + 140369934628640, + 140370262207720, + 140370262206400, + 140369934629640, + 140370262206400, + 140370262208320, + 140369934628760, + 140370219081000, + 140369936133560, + 140369936134000, + 140369936132760, + 140370203515000, + 140369936132760, + 140369934629600, + 140370262206400, + 140370262207720, + 140369934628640, + 140369934628080, + 140369934656240, + 140369934628120, + 140370262207720, + 140370262206440, + 140370219016360, + 140370262206440, + 140370262206960, + 140370219016480, + 140370262206960, + 140370262209000, + 140369934628760, + 140370219081000, + 140370262463760, + 140370222379480, + 140370222379560, + 140370219074600, + 1, + 64, + 140370218844600, + 140369933326520, + 140370219331600, + 140369934788840, + 140370220922120, + 140369934947600, + 140369934821320, + 140369934821200, + 140369934821120, + 140369934821040, + 140370262307680, + 140369934821040, + 140370221475080, + 140369934821040, + 140370219015440, + 140369934821040, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370221599800, + 140370219015440, + 140370221599800, + 140369934656240, + 140369934628080, + 140369934628640, + 140370262207720, + 140370262206400, + 140369934629640, + 140370262206400, + 140370262208320, + 140369934628760, + 140370219081000, + 140369936133560, + 140369936134000, + 140369936132760, + 140370203515000, + 140369936132760, + 140369934629600, + 140370262206400, + 140370262207720, + 140369934628640, + 140369934628080, + 140369934656240, + 140369934628120, + 140370262207720, + 140370262206440, + 140370219016360, + 140370262206440, + 140370262206960, + 140370219016480, + 140370262206960, + 140370262209000, + 140369934628760, + 140370219081000, + 140370262463760, + 140370222379480, + 140370222379560, + 140370219074600, + 140370222379560, + 140370219073720, + 1, + 63, + 140370218844600, + 140369933326520, + 140370219331600, + 140369934788840, + 140370220922120, + 140369934947600, + 140369934821320, + 140369934821200, + 140369934821120, + 140369934821040, + 140370262307680, + 140369934821040, + 140370221475080, + 140369934821040, + 140370219015440, + 140369934821040, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370221599800, + 140370219015440, + 140370221599800, + 140369934656240, + 140369934628080, + 140369934628640, + 140370262207720, + 140370262206400, + 140369934629640, + 140370262206400, + 140370262208320, + 140369934628760, + 140370219081000, + 140369936133560, + 140369936134000, + 140369936132760, + 140370203515000, + 140369936132760, + 140369934629600, + 140370262206400, + 140370262207720, + 140369934628640, + 140369934628080, + 140369934656240, + 140369934628120, + 140370262207720, + 140370262206440, + 140370219016360, + 140370262206440, + 140370262206960, + 140370219016480, + 140370262206960, + 140370262209000, + 140369934628760, + 140370219081000, + 140370262463760, + 140370222379480, + 140370222379560, + 140370219074600, + 140370222379560, + 1, + 61, + 140370218844600, + 140369933326520, + 140370219331600, + 140369934788840, + 140370220922120, + 140369934947600, + 140369934821320, + 140369934821200, + 140369934821120, + 140369934821040, + 140370262307680, + 140369934821040, + 140370221475080, + 140369934821040, + 140370219015440, + 140369934821040, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370219015440, + 140370221599880, + 140370221599880, + 140370221599800, + 140370219015440, + 140370221599800, + 140369934656240, + 140369934628080, + 140369934628640, + 140370262207720, + 140370262206400, + 140369934629640, + 140370262206400, + 140370262208320, + 140369934628760, + 140370219081000, + 140369936133560, + 140369936134000, + 140369936132760, + 140370203515000, + 140369936132760, + 140369934629600, + 140370262206400, + 140370262207720, + 140369934628640, + 140369934628080, + 140369934656240, + 140369934628120, + 140370262207720, + 140370262206440, + 140370219016360, + 140370262206440, + 140370262206960, + 140370219016480, + 140370262206960, + 140370262209000, + 140369934628760, + 140370219081000, + 140370262463760, + 140370222379480, + 140370265410040, + 10 + ], + "raw_sample_timestamps": [ + 1295905330989, + 1295905338595, + 1295905348330, + 1295905358336, + 1295905368777, + 1295905379129, + 1295905388495, + 1295905398492, + 1295905407835, + 1295905418826, + 1295905428669, + 1295905438609, + 1295905447579, + 1295905458008, + 1295905468407 + ], + "raw_timestamp_deltas": [ + 12403, + 7531, + 9689, + 9986, + 10420, + 10338, + 9320, + 9949, + 9269, + 10920, + 9770, + 9864, + 8899, + 10354, + 10323 + ] +} From 5b1b558a5aa4bcf5aa15af78e508dc3cfb74ccc7 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Mon, 7 Oct 2024 20:39:24 +0800 Subject: [PATCH 52/96] Consistent string freezing (#2422) --- .rubocop.yml | 10 ++++++++++ CHANGELOG.md | 1 + Gemfile | 2 ++ sentry-delayed_job/Gemfile | 2 ++ sentry-delayed_job/Rakefile | 2 ++ sentry-delayed_job/bin/console | 1 + sentry-delayed_job/example/Gemfile | 2 ++ sentry-delayed_job/example/app.rb | 2 ++ sentry-delayed_job/lib/sentry-delayed_job.rb | 2 ++ .../lib/sentry/delayed_job/configuration.rb | 2 ++ .../lib/sentry/delayed_job/version.rb | 2 ++ sentry-delayed_job/sentry-delayed_job.gemspec | 2 ++ .../sentry/delayed_job/configuration_spec.rb | 2 ++ .../spec/sentry/delayed_job_spec.rb | 2 ++ sentry-delayed_job/spec/spec_helper.rb | 2 ++ sentry-opentelemetry/Gemfile | 2 ++ sentry-opentelemetry/Rakefile | 2 ++ sentry-rails/Gemfile | 2 ++ sentry-rails/Rakefile | 2 ++ sentry-rails/app/jobs/sentry/send_event_job.rb | 2 ++ sentry-rails/benchmarks/allocation_comparison.rb | 2 ++ sentry-rails/benchmarks/allocation_report.rb | 2 ++ sentry-rails/benchmarks/application.rb | 2 ++ sentry-rails/bin/console | 1 + sentry-rails/lib/generators/sentry_generator.rb | 2 ++ sentry-rails/lib/sentry-rails.rb | 2 ++ sentry-rails/lib/sentry/rails.rb | 2 ++ sentry-rails/lib/sentry/rails/action_cable.rb | 4 +++- sentry-rails/lib/sentry/rails/active_job.rb | 6 ++++-- .../lib/sentry/rails/background_worker.rb | 2 ++ .../lib/sentry/rails/backtrace_cleaner.rb | 6 ++++-- .../rails/breadcrumb/active_support_logger.rb | 2 ++ .../monotonic_active_support_logger.rb | 2 ++ .../lib/sentry/rails/capture_exceptions.rb | 6 ++++-- sentry-rails/lib/sentry/rails/configuration.rb | 2 ++ .../lib/sentry/rails/controller_methods.rb | 2 ++ .../lib/sentry/rails/controller_transaction.rb | 4 +++- sentry-rails/lib/sentry/rails/engine.rb | 2 ++ .../lib/sentry/rails/error_subscriber.rb | 2 ++ .../rails/instrument_payload_cleanup_helper.rb | 2 ++ .../sentry/rails/overrides/streaming_reporter.rb | 2 ++ sentry-rails/lib/sentry/rails/railtie.rb | 2 ++ .../rails/rescued_exception_interceptor.rb | 2 ++ sentry-rails/lib/sentry/rails/tracing.rb | 2 ++ .../sentry/rails/tracing/abstract_subscriber.rb | 2 ++ .../tracing/action_controller_subscriber.rb | 6 ++++-- .../rails/tracing/action_view_subscriber.rb | 6 ++++-- .../rails/tracing/active_storage_subscriber.rb | 6 ++++-- sentry-rails/lib/sentry/rails/version.rb | 2 ++ sentry-rails/sentry-rails.gemspec | 2 ++ sentry-rails/spec/dummy/test_rails_app/app.rb | 2 ++ .../spec/dummy/test_rails_app/apps/5-0.rb | 2 ++ .../spec/dummy/test_rails_app/apps/5-2.rb | 2 ++ .../spec/dummy/test_rails_app/apps/6-0.rb | 2 ++ .../spec/dummy/test_rails_app/apps/6-1.rb | 2 ++ .../spec/dummy/test_rails_app/apps/7-0.rb | 2 ++ .../spec/dummy/test_rails_app/apps/7-1.rb | 2 ++ .../spec/dummy/test_rails_app/configs/5-0.rb | 2 ++ .../spec/dummy/test_rails_app/configs/5-2.rb | 2 ++ .../spec/dummy/test_rails_app/configs/6-0.rb | 2 ++ .../spec/dummy/test_rails_app/configs/6-1.rb | 2 ++ .../spec/dummy/test_rails_app/configs/7-0.rb | 2 ++ .../spec/dummy/test_rails_app/configs/7-1.rb | 2 ++ .../spec/dummy/test_rails_app/configs/7-2.rb | 2 ++ .../spec/sentry/rails/action_cable_spec.rb | 2 ++ sentry-rails/spec/sentry/rails/activejob_spec.rb | 2 ++ .../breadcrumbs/active_support_logger_spec.rb | 2 ++ .../monotonic_active_support_logger_spec.rb | 2 ++ sentry-rails/spec/sentry/rails/client_spec.rb | 2 ++ .../spec/sentry/rails/configuration_spec.rb | 2 ++ .../spec/sentry/rails/controller_methods_spec.rb | 2 ++ .../spec/sentry/rails/error_subscriber_spec.rb | 2 ++ sentry-rails/spec/sentry/rails/event_spec.rb | 2 ++ .../tracing/action_controller_subscriber_spec.rb | 2 ++ .../rails/tracing/action_view_subscriber_spec.rb | 2 ++ .../tracing/active_record_subscriber_spec.rb | 2 ++ .../tracing/active_storage_subscriber_spec.rb | 2 ++ sentry-rails/spec/sentry/rails/tracing_spec.rb | 2 ++ sentry-rails/spec/sentry/rails_spec.rb | 2 ++ sentry-rails/spec/sentry/send_event_job_spec.rb | 2 ++ sentry-rails/spec/spec_helper.rb | 2 ++ sentry-resque/Gemfile | 2 ++ sentry-resque/Gemfile_with_rails.rb | 2 ++ sentry-resque/Rakefile | 2 ++ sentry-resque/bin/console | 1 + sentry-resque/example/Gemfile | 2 ++ sentry-resque/example/app.rb | 2 ++ sentry-resque/lib/sentry-resque.rb | 2 ++ sentry-resque/lib/sentry/resque/configuration.rb | 2 ++ sentry-resque/lib/sentry/resque/version.rb | 2 ++ sentry-resque/sentry-resque.gemspec | 2 ++ .../spec/sentry/resque/configuration_spec.rb | 2 ++ sentry-resque/spec/sentry/resque_spec.rb | 2 ++ sentry-resque/spec/sentry/tracing_spec.rb | 2 ++ sentry-resque/spec/spec_helper.rb | 2 ++ sentry-ruby/.rubocop.yml | 1 + sentry-ruby/Gemfile | 2 ++ sentry-ruby/Rakefile | 2 ++ sentry-ruby/benchmarks/allocation_comparison.rb | 2 ++ sentry-ruby/benchmarks/allocation_report.rb | 2 ++ .../benchmarks/exception_locals_capturing.rb | 2 ++ sentry-ruby/bin/console | 1 + sentry-ruby/lib/sentry-ruby.rb | 6 +++--- sentry-ruby/lib/sentry/backtrace.rb | 4 ++-- sentry-ruby/lib/sentry/baggage.rb | 2 +- sentry-ruby/lib/sentry/configuration.rb | 10 +++++----- sentry-ruby/lib/sentry/cron/monitor_check_ins.rb | 2 ++ .../lib/sentry/interfaces/single_exception.rb | 4 ++-- .../lib/sentry/rack/capture_exceptions.rb | 2 +- sentry-ruby/lib/sentry/test_helper.rb | 2 ++ sentry-ruby/lib/sentry/transaction.rb | 2 +- sentry-ruby/sentry-ruby-core.gemspec | 2 ++ sentry-ruby/sentry-ruby.gemspec | 2 ++ sentry-ruby/spec/contexts/with_request_mock.rb | 2 ++ sentry-ruby/spec/initialization_check_spec.rb | 2 ++ sentry-ruby/spec/isolated/puma_spec.rb | 2 ++ .../spec/sentry/background_worker_spec.rb | 2 ++ .../spec/sentry/backpressure_monitor_spec.rb | 2 ++ sentry-ruby/spec/sentry/backtrace/lines_spec.rb | 2 ++ sentry-ruby/spec/sentry/backtrace_spec.rb | 2 ++ sentry-ruby/spec/sentry/baggage_spec.rb | 2 ++ .../spec/sentry/breadcrumb/http_logger_spec.rb | 2 ++ .../spec/sentry/breadcrumb/redis_logger_spec.rb | 2 ++ .../spec/sentry/breadcrumb/sentry_logger_spec.rb | 2 ++ .../spec/sentry/breadcrumb_buffer_spec.rb | 2 ++ sentry-ruby/spec/sentry/breadcrumb_spec.rb | 2 ++ .../spec/sentry/client/event_sending_spec.rb | 2 ++ sentry-ruby/spec/sentry/client_spec.rb | 9 ++++++++- sentry-ruby/spec/sentry/configuration_spec.rb | 2 ++ .../spec/sentry/cron/monitor_check_ins_spec.rb | 2 ++ .../spec/sentry/cron/monitor_config_spec.rb | 2 ++ .../spec/sentry/cron/monitor_schedule_spec.rb | 2 ++ sentry-ruby/spec/sentry/dsn_spec.rb | 2 ++ sentry-ruby/spec/sentry/envelope/item_spec.rb | 2 ++ sentry-ruby/spec/sentry/event_spec.rb | 2 ++ sentry-ruby/spec/sentry/faraday_spec.rb | 2 ++ sentry-ruby/spec/sentry/graphql_spec.rb | 2 ++ sentry-ruby/spec/sentry/hub_spec.rb | 2 ++ sentry-ruby/spec/sentry/integrable_spec.rb | 2 ++ sentry-ruby/spec/sentry/interface_spec.rb | 2 ++ .../sentry/interfaces/request_interface_spec.rb | 2 ++ .../sentry/interfaces/stacktrace_builder_spec.rb | 16 +++++++++------- .../spec/sentry/interfaces/stacktrace_spec.rb | 2 ++ sentry-ruby/spec/sentry/linecache_spec.rb | 2 ++ .../spec/sentry/metrics/aggregator_spec.rb | 2 ++ .../spec/sentry/metrics/configuration_spec.rb | 2 ++ .../spec/sentry/metrics/counter_metric_spec.rb | 2 ++ .../sentry/metrics/distribution_metric_spec.rb | 2 ++ .../spec/sentry/metrics/gauge_metric_spec.rb | 2 ++ .../spec/sentry/metrics/local_aggregator_spec.rb | 2 ++ sentry-ruby/spec/sentry/metrics/metric_spec.rb | 2 ++ .../spec/sentry/metrics/set_metric_spec.rb | 2 ++ sentry-ruby/spec/sentry/metrics/timing_spec.rb | 2 ++ sentry-ruby/spec/sentry/metrics_spec.rb | 2 ++ sentry-ruby/spec/sentry/net/http_spec.rb | 2 ++ sentry-ruby/spec/sentry/profiler_spec.rb | 2 ++ .../spec/sentry/propagation_context_spec.rb | 2 ++ .../spec/sentry/rack/capture_exceptions_spec.rb | 2 ++ sentry-ruby/spec/sentry/rake_spec.rb | 2 ++ sentry-ruby/spec/sentry/redis_spec.rb | 2 ++ sentry-ruby/spec/sentry/scope/setters_spec.rb | 2 ++ sentry-ruby/spec/sentry/scope_spec.rb | 2 ++ sentry-ruby/spec/sentry/session_flusher_spec.rb | 2 ++ sentry-ruby/spec/sentry/span_spec.rb | 2 ++ sentry-ruby/spec/sentry/test_helper_spec.rb | 2 ++ sentry-ruby/spec/sentry/transaction_spec.rb | 2 ++ .../spec/sentry/transport/configuration_spec.rb | 2 ++ .../http_transport_rate_limiting_spec.rb | 2 ++ .../spec/sentry/transport/http_transport_spec.rb | 2 ++ .../sentry/transport/spotlight_transport_spec.rb | 2 ++ sentry-ruby/spec/sentry/transport_spec.rb | 2 ++ sentry-ruby/spec/sentry/utils/real_ip_spec.rb | 2 ++ sentry-ruby/spec/sentry/utils/request_id_spec.rb | 2 ++ sentry-ruby/spec/sentry/vernier/profiler_spec.rb | 6 ++++-- sentry-ruby/spec/sentry_spec.rb | 2 ++ sentry-ruby/spec/spec_helper.rb | 2 ++ sentry-ruby/spec/support/Rakefile.rb | 2 ++ sentry-ruby/spec/support/profiler.rb | 2 ++ .../spec/support/stacktrace_test_fixture.rb | 2 ++ sentry-sidekiq/Gemfile | 2 ++ sentry-sidekiq/Rakefile | 2 ++ sentry-sidekiq/bin/console | 1 + sentry-sidekiq/example/Gemfile | 2 ++ sentry-sidekiq/example/error_worker.rb | 2 ++ sentry-sidekiq/lib/sentry-sidekiq.rb | 2 ++ .../lib/sentry/sidekiq/configuration.rb | 2 ++ .../lib/sentry/sidekiq/context_filter.rb | 6 ++++-- .../lib/sentry/sidekiq/error_handler.rb | 2 ++ sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 ++ sentry-sidekiq/sentry-sidekiq.gemspec | 2 ++ sentry-sidekiq/spec/sentry/rails_spec.rb | 2 ++ .../sentry/sidekiq-scheduler/scheduler_spec.rb | 2 ++ .../spec/sentry/sidekiq/configuration_spec.rb | 2 ++ .../spec/sentry/sidekiq/context_filter_spec.rb | 2 ++ .../spec/sentry/sidekiq/cron/job_spec.rb | 2 ++ .../spec/sentry/sidekiq/error_handler_spec.rb | 2 ++ .../sidekiq/sentry_context_middleware_spec.rb | 2 ++ sentry-sidekiq/spec/sentry/sidekiq_spec.rb | 2 ++ sentry-sidekiq/spec/spec_helper.rb | 2 ++ 199 files changed, 431 insertions(+), 41 deletions(-) create mode 120000 sentry-ruby/.rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml index 451fd8589..9286a27d3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,7 +4,17 @@ inherit_gem: Layout/SpaceInsideArrayLiteralBrackets: Enabled: false +Layout/EmptyLineAfterMagicComment: + Enabled: true + +Style/FrozenStringLiteralComment: + Enabled: true + +Style/RedundantFreeze: + Enabled: true + AllCops: Exclude: - "sentry-raven/**/*" - "sentry-*/tmp/**/*" + - "sentry-*/examples/**/*" diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f0aa6444..35975b8dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Internal - Profile items have bigger size limit now ([#2421](https://github.com/getsentry/sentry-ruby/pull/2421)) +- Consistent string freezing ([#2422](https://github.com/getsentry/sentry-ruby/pull/2422)) ## 5.20.1 diff --git a/Gemfile b/Gemfile index c897e543f..9847a55e8 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" git_source(:github) { |name| "https://github.com/#{name}.git" } diff --git a/sentry-delayed_job/Gemfile b/sentry-delayed_job/Gemfile index 936bec48a..48e80fbdc 100644 --- a/sentry-delayed_job/Gemfile +++ b/sentry-delayed_job/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" git_source(:github) { |name| "https://github.com/#{name}.git" } diff --git a/sentry-delayed_job/Rakefile b/sentry-delayed_job/Rakefile index 7b2756854..13afab191 100644 --- a/sentry-delayed_job/Rakefile +++ b/sentry-delayed_job/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/gem_tasks" require "rspec/core/rake_task" diff --git a/sentry-delayed_job/bin/console b/sentry-delayed_job/bin/console index 660c7a889..f0f5a7b6a 100755 --- a/sentry-delayed_job/bin/console +++ b/sentry-delayed_job/bin/console @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require "bundler/setup" require "sentry/ruby" diff --git a/sentry-delayed_job/example/Gemfile b/sentry-delayed_job/example/Gemfile index 2ed843ab1..d138c16d5 100644 --- a/sentry-delayed_job/example/Gemfile +++ b/sentry-delayed_job/example/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" gem "rails" diff --git a/sentry-delayed_job/example/app.rb b/sentry-delayed_job/example/app.rb index bcec27c52..04f391468 100644 --- a/sentry-delayed_job/example/app.rb +++ b/sentry-delayed_job/example/app.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_job" require "active_record" require "delayed_job" diff --git a/sentry-delayed_job/lib/sentry-delayed_job.rb b/sentry-delayed_job/lib/sentry-delayed_job.rb index f96b03b6a..bc961259f 100644 --- a/sentry-delayed_job/lib/sentry-delayed_job.rb +++ b/sentry-delayed_job/lib/sentry-delayed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "delayed_job" require "sentry-ruby" require "sentry/integrable" diff --git a/sentry-delayed_job/lib/sentry/delayed_job/configuration.rb b/sentry-delayed_job/lib/sentry/delayed_job/configuration.rb index 4408b37af..42ee8e63c 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/configuration.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry class Configuration attr_reader :delayed_job diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index e5c1c5e5f..69dc33410 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module DelayedJob VERSION = "5.20.1" diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index e9c004738..cd55d35dd 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "lib/sentry/delayed_job/version" Gem::Specification.new do |spec| diff --git a/sentry-delayed_job/spec/sentry/delayed_job/configuration_spec.rb b/sentry-delayed_job/spec/sentry/delayed_job/configuration_spec.rb index fdde5b4f5..a785f53c3 100644 --- a/sentry-delayed_job/spec/sentry/delayed_job/configuration_spec.rb +++ b/sentry-delayed_job/spec/sentry/delayed_job/configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::DelayedJob::Configuration do diff --git a/sentry-delayed_job/spec/sentry/delayed_job_spec.rb b/sentry-delayed_job/spec/sentry/delayed_job_spec.rb index ac2d31fb1..24a1de77d 100644 --- a/sentry-delayed_job/spec/sentry/delayed_job_spec.rb +++ b/sentry-delayed_job/spec/sentry/delayed_job_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::DelayedJob do diff --git a/sentry-delayed_job/spec/spec_helper.rb b/sentry-delayed_job/spec/spec_helper.rb index 2d8bf6d10..3e07723bb 100644 --- a/sentry-delayed_job/spec/spec_helper.rb +++ b/sentry-delayed_job/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/setup" begin require "debug/prelude" diff --git a/sentry-opentelemetry/Gemfile b/sentry-opentelemetry/Gemfile index e084c17c6..b30d36d42 100644 --- a/sentry-opentelemetry/Gemfile +++ b/sentry-opentelemetry/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" git_source(:github) { |name| "https://github.com/#{name}.git" } diff --git a/sentry-opentelemetry/Rakefile b/sentry-opentelemetry/Rakefile index 7b2756854..13afab191 100644 --- a/sentry-opentelemetry/Rakefile +++ b/sentry-opentelemetry/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/gem_tasks" require "rspec/core/rake_task" diff --git a/sentry-rails/Gemfile b/sentry-rails/Gemfile index e203e41a1..7695eff15 100644 --- a/sentry-rails/Gemfile +++ b/sentry-rails/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" git_source(:github) { |name| "https://github.com/#{name}.git" } diff --git a/sentry-rails/Rakefile b/sentry-rails/Rakefile index 2624fb72e..d58f59ad2 100644 --- a/sentry-rails/Rakefile +++ b/sentry-rails/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/gem_tasks" require "rspec/core/rake_task" diff --git a/sentry-rails/app/jobs/sentry/send_event_job.rb b/sentry-rails/app/jobs/sentry/send_event_job.rb index 75ac80529..06ca59172 100644 --- a/sentry-rails/app/jobs/sentry/send_event_job.rb +++ b/sentry-rails/app/jobs/sentry/send_event_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + if defined?(ActiveJob) module Sentry parent_job = diff --git a/sentry-rails/benchmarks/allocation_comparison.rb b/sentry-rails/benchmarks/allocation_comparison.rb index f2499d937..15b1e3c4a 100644 --- a/sentry-rails/benchmarks/allocation_comparison.rb +++ b/sentry-rails/benchmarks/allocation_comparison.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'benchmark/memory' require "sentry-ruby" require "sentry/benchmarks/benchmark_transport" diff --git a/sentry-rails/benchmarks/allocation_report.rb b/sentry-rails/benchmarks/allocation_report.rb index 13fee1513..9bc691a26 100644 --- a/sentry-rails/benchmarks/allocation_report.rb +++ b/sentry-rails/benchmarks/allocation_report.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'benchmark/ipsa' require "sentry-ruby" require "sentry/benchmarks/benchmark_transport" diff --git a/sentry-rails/benchmarks/application.rb b/sentry-rails/benchmarks/application.rb index fa4d3f5e8..0ef435cee 100644 --- a/sentry-rails/benchmarks/application.rb +++ b/sentry-rails/benchmarks/application.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_support/all" require "action_controller" require_relative "../spec/support/test_rails_app/app" diff --git a/sentry-rails/bin/console b/sentry-rails/bin/console index 660c7a889..f0f5a7b6a 100755 --- a/sentry-rails/bin/console +++ b/sentry-rails/bin/console @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require "bundler/setup" require "sentry/ruby" diff --git a/sentry-rails/lib/generators/sentry_generator.rb b/sentry-rails/lib/generators/sentry_generator.rb index de694e40d..e293dae95 100644 --- a/sentry-rails/lib/generators/sentry_generator.rb +++ b/sentry-rails/lib/generators/sentry_generator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails/generators/base" class SentryGenerator < ::Rails::Generators::Base diff --git a/sentry-rails/lib/sentry-rails.rb b/sentry-rails/lib/sentry-rails.rb index c436e1dfa..a8d6499b1 100644 --- a/sentry-rails/lib/sentry-rails.rb +++ b/sentry-rails/lib/sentry-rails.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + require "sentry/rails/version" require "sentry/rails" diff --git a/sentry-rails/lib/sentry/rails.rb b/sentry-rails/lib/sentry/rails.rb index 14c8e1b80..b4b79dd85 100644 --- a/sentry-rails/lib/sentry/rails.rb +++ b/sentry-rails/lib/sentry/rails.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails" require "sentry-ruby" require "sentry/integrable" diff --git a/sentry-rails/lib/sentry/rails/action_cable.rb b/sentry-rails/lib/sentry/rails/action_cable.rb index 06833a68b..222aab1b8 100644 --- a/sentry-rails/lib/sentry/rails/action_cable.rb +++ b/sentry-rails/lib/sentry/rails/action_cable.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + module Sentry module Rails module ActionCableExtensions class ErrorHandler - OP_NAME = "websocket.server".freeze + OP_NAME = "websocket.server" SPAN_ORIGIN = "auto.http.rails.actioncable" class << self diff --git a/sentry-rails/lib/sentry/rails/active_job.rb b/sentry-rails/lib/sentry/rails/active_job.rb index afdf87cd7..953af632b 100644 --- a/sentry-rails/lib/sentry/rails/active_job.rb +++ b/sentry-rails/lib/sentry/rails/active_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails module ActiveJobExtensions @@ -16,8 +18,8 @@ def already_supported_by_sentry_integration? end class SentryReporter - OP_NAME = "queue.active_job".freeze - SPAN_ORIGIN = "auto.queue.active_job".freeze + OP_NAME = "queue.active_job" + SPAN_ORIGIN = "auto.queue.active_job" class << self def record(job, &block) diff --git a/sentry-rails/lib/sentry/rails/background_worker.rb b/sentry-rails/lib/sentry/rails/background_worker.rb index 56dcd6609..2c0cc7a71 100644 --- a/sentry-rails/lib/sentry/rails/background_worker.rb +++ b/sentry-rails/lib/sentry/rails/background_worker.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry class BackgroundWorker def _perform(&block) diff --git a/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb b/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb index 25812b97a..57030f733 100644 --- a/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb +++ b/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb @@ -1,11 +1,13 @@ +# frozen_string_literal: true + require "active_support/backtrace_cleaner" require "active_support/core_ext/string/access" module Sentry module Rails class BacktraceCleaner < ActiveSupport::BacktraceCleaner - APP_DIRS_PATTERN = /\A(?:\.\/)?(?:app|config|lib|test|\(\w*\))/.freeze - RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/.freeze + APP_DIRS_PATTERN = /\A(?:\.\/)?(?:app|config|lib|test|\(\w*\))/ + RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/ def initialize super diff --git a/sentry-rails/lib/sentry/rails/breadcrumb/active_support_logger.rb b/sentry-rails/lib/sentry/rails/breadcrumb/active_support_logger.rb index 9dfdd1d26..a301cb960 100644 --- a/sentry-rails/lib/sentry/rails/breadcrumb/active_support_logger.rb +++ b/sentry-rails/lib/sentry/rails/breadcrumb/active_support_logger.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails module Breadcrumb diff --git a/sentry-rails/lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb b/sentry-rails/lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb index 71785d256..541f9bea3 100644 --- a/sentry-rails/lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb +++ b/sentry-rails/lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/rails/instrument_payload_cleanup_helper" module Sentry diff --git a/sentry-rails/lib/sentry/rails/capture_exceptions.rb b/sentry-rails/lib/sentry/rails/capture_exceptions.rb index 3216d2a3a..f571bd689 100644 --- a/sentry-rails/lib/sentry/rails/capture_exceptions.rb +++ b/sentry-rails/lib/sentry/rails/capture_exceptions.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + module Sentry module Rails class CaptureExceptions < Sentry::Rack::CaptureExceptions RAILS_7_1 = Gem::Version.new(::Rails.version) >= Gem::Version.new("7.1.0.alpha") - SPAN_ORIGIN = "auto.http.rails".freeze + SPAN_ORIGIN = "auto.http.rails" def initialize(_) super @@ -20,7 +22,7 @@ def collect_exception(env) end def transaction_op - "http.server".freeze + "http.server" end def capture_exception(exception, env) diff --git a/sentry-rails/lib/sentry/rails/configuration.rb b/sentry-rails/lib/sentry/rails/configuration.rb index 609e03ca4..2e4591947 100644 --- a/sentry-rails/lib/sentry/rails/configuration.rb +++ b/sentry-rails/lib/sentry/rails/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/rails/tracing/action_controller_subscriber" require "sentry/rails/tracing/action_view_subscriber" require "sentry/rails/tracing/active_record_subscriber" diff --git a/sentry-rails/lib/sentry/rails/controller_methods.rb b/sentry-rails/lib/sentry/rails/controller_methods.rb index 90330e946..aa8b4f3e4 100644 --- a/sentry-rails/lib/sentry/rails/controller_methods.rb +++ b/sentry-rails/lib/sentry/rails/controller_methods.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails module ControllerMethods diff --git a/sentry-rails/lib/sentry/rails/controller_transaction.rb b/sentry-rails/lib/sentry/rails/controller_transaction.rb index cd3ffa38b..8f19bb63d 100644 --- a/sentry-rails/lib/sentry/rails/controller_transaction.rb +++ b/sentry-rails/lib/sentry/rails/controller_transaction.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + module Sentry module Rails module ControllerTransaction - SPAN_ORIGIN = "auto.view.rails".freeze + SPAN_ORIGIN = "auto.view.rails" def self.included(base) base.prepend_around_action(:sentry_around_action) diff --git a/sentry-rails/lib/sentry/rails/engine.rb b/sentry-rails/lib/sentry/rails/engine.rb index 12ac173a7..dc50819cd 100644 --- a/sentry-rails/lib/sentry/rails/engine.rb +++ b/sentry-rails/lib/sentry/rails/engine.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry class Engine < ::Rails::Engine isolate_namespace Sentry diff --git a/sentry-rails/lib/sentry/rails/error_subscriber.rb b/sentry-rails/lib/sentry/rails/error_subscriber.rb index fac675dbf..dad598c51 100644 --- a/sentry-rails/lib/sentry/rails/error_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/error_subscriber.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails # This is not a user-facing class. You should use it with Rails 7.0's error reporter feature and its interfaces. diff --git a/sentry-rails/lib/sentry/rails/instrument_payload_cleanup_helper.rb b/sentry-rails/lib/sentry/rails/instrument_payload_cleanup_helper.rb index 343d2d41c..07422c5e8 100644 --- a/sentry-rails/lib/sentry/rails/instrument_payload_cleanup_helper.rb +++ b/sentry-rails/lib/sentry/rails/instrument_payload_cleanup_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails module InstrumentPayloadCleanupHelper diff --git a/sentry-rails/lib/sentry/rails/overrides/streaming_reporter.rb b/sentry-rails/lib/sentry/rails/overrides/streaming_reporter.rb index 5ce0c637b..1fdd4ad60 100644 --- a/sentry-rails/lib/sentry/rails/overrides/streaming_reporter.rb +++ b/sentry-rails/lib/sentry/rails/overrides/streaming_reporter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails module Overrides diff --git a/sentry-rails/lib/sentry/rails/railtie.rb b/sentry-rails/lib/sentry/rails/railtie.rb index e4926cc0f..0a0cdf213 100644 --- a/sentry-rails/lib/sentry/rails/railtie.rb +++ b/sentry-rails/lib/sentry/rails/railtie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/rails/capture_exceptions" require "sentry/rails/rescued_exception_interceptor" require "sentry/rails/backtrace_cleaner" diff --git a/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb b/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb index 2c977dba4..43cb69db1 100644 --- a/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb +++ b/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails class RescuedExceptionInterceptor diff --git a/sentry-rails/lib/sentry/rails/tracing.rb b/sentry-rails/lib/sentry/rails/tracing.rb index 3c5ae2222..82509ab8b 100644 --- a/sentry-rails/lib/sentry/rails/tracing.rb +++ b/sentry-rails/lib/sentry/rails/tracing.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails module Tracing diff --git a/sentry-rails/lib/sentry/rails/tracing/abstract_subscriber.rb b/sentry-rails/lib/sentry/rails/tracing/abstract_subscriber.rb index fec3f7bde..7ba338c6b 100644 --- a/sentry-rails/lib/sentry/rails/tracing/abstract_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/tracing/abstract_subscriber.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails module Tracing diff --git a/sentry-rails/lib/sentry/rails/tracing/action_controller_subscriber.rb b/sentry-rails/lib/sentry/rails/tracing/action_controller_subscriber.rb index 11e9eadf2..42b89ce32 100644 --- a/sentry-rails/lib/sentry/rails/tracing/action_controller_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/tracing/action_controller_subscriber.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/rails/tracing/abstract_subscriber" require "sentry/rails/instrument_payload_cleanup_helper" @@ -8,8 +10,8 @@ class ActionControllerSubscriber < AbstractSubscriber extend InstrumentPayloadCleanupHelper EVENT_NAMES = ["process_action.action_controller"].freeze - OP_NAME = "view.process_action.action_controller".freeze - SPAN_ORIGIN = "auto.view.rails".freeze + OP_NAME = "view.process_action.action_controller" + SPAN_ORIGIN = "auto.view.rails" def self.subscribe! Sentry.logger.warn <<~MSG diff --git a/sentry-rails/lib/sentry/rails/tracing/action_view_subscriber.rb b/sentry-rails/lib/sentry/rails/tracing/action_view_subscriber.rb index baed2c7e5..3f56d72ac 100644 --- a/sentry-rails/lib/sentry/rails/tracing/action_view_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/tracing/action_view_subscriber.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/rails/tracing/abstract_subscriber" module Sentry @@ -5,8 +7,8 @@ module Rails module Tracing class ActionViewSubscriber < AbstractSubscriber EVENT_NAMES = ["render_template.action_view"].freeze - SPAN_PREFIX = "template.".freeze - SPAN_ORIGIN = "auto.template.rails".freeze + SPAN_PREFIX = "template." + SPAN_ORIGIN = "auto.template.rails" def self.subscribe! subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload| diff --git a/sentry-rails/lib/sentry/rails/tracing/active_storage_subscriber.rb b/sentry-rails/lib/sentry/rails/tracing/active_storage_subscriber.rb index 5d62bad22..50ee0d703 100644 --- a/sentry-rails/lib/sentry/rails/tracing/active_storage_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/tracing/active_storage_subscriber.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/rails/tracing/abstract_subscriber" module Sentry @@ -19,12 +21,12 @@ class ActiveStorageSubscriber < AbstractSubscriber analyze.active_storage ].freeze - SPAN_ORIGIN = "auto.file.rails".freeze + SPAN_ORIGIN = "auto.file.rails" def self.subscribe! subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload| record_on_current_span( - op: "file.#{event_name}".freeze, + op: "file.#{event_name}", origin: SPAN_ORIGIN, start_timestamp: payload[START_TIMESTAMP_NAME], description: payload[:service], diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index e62a1de60..3d1dc210e 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Rails VERSION = "5.20.1" diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 67a545a36..8c47f981d 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "lib/sentry/rails/version" Gem::Specification.new do |spec| diff --git a/sentry-rails/spec/dummy/test_rails_app/app.rb b/sentry-rails/spec/dummy/test_rails_app/app.rb index 302723863..95309fbaa 100644 --- a/sentry-rails/spec/dummy/test_rails_app/app.rb +++ b/sentry-rails/spec/dummy/test_rails_app/app.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ENV["RAILS_ENV"] = "test" require "rails" diff --git a/sentry-rails/spec/dummy/test_rails_app/apps/5-0.rb b/sentry-rails/spec/dummy/test_rails_app/apps/5-0.rb index f1b3a2758..a68a68358 100644 --- a/sentry-rails/spec/dummy/test_rails_app/apps/5-0.rb +++ b/sentry-rails/spec/dummy/test_rails_app/apps/5-0.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ActiveRecord::Schema.define do create_table :posts, force: true do |t| end diff --git a/sentry-rails/spec/dummy/test_rails_app/apps/5-2.rb b/sentry-rails/spec/dummy/test_rails_app/apps/5-2.rb index e7b1f2180..9dfcf0d62 100644 --- a/sentry-rails/spec/dummy/test_rails_app/apps/5-2.rb +++ b/sentry-rails/spec/dummy/test_rails_app/apps/5-2.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ActiveRecord::Schema.define do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false diff --git a/sentry-rails/spec/dummy/test_rails_app/apps/6-0.rb b/sentry-rails/spec/dummy/test_rails_app/apps/6-0.rb index e7b1f2180..9dfcf0d62 100644 --- a/sentry-rails/spec/dummy/test_rails_app/apps/6-0.rb +++ b/sentry-rails/spec/dummy/test_rails_app/apps/6-0.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ActiveRecord::Schema.define do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false diff --git a/sentry-rails/spec/dummy/test_rails_app/apps/6-1.rb b/sentry-rails/spec/dummy/test_rails_app/apps/6-1.rb index ac504704e..a9148a3ee 100644 --- a/sentry-rails/spec/dummy/test_rails_app/apps/6-1.rb +++ b/sentry-rails/spec/dummy/test_rails_app/apps/6-1.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ActiveRecord::Schema.define do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false diff --git a/sentry-rails/spec/dummy/test_rails_app/apps/7-0.rb b/sentry-rails/spec/dummy/test_rails_app/apps/7-0.rb index ac504704e..a9148a3ee 100644 --- a/sentry-rails/spec/dummy/test_rails_app/apps/7-0.rb +++ b/sentry-rails/spec/dummy/test_rails_app/apps/7-0.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ActiveRecord::Schema.define do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false diff --git a/sentry-rails/spec/dummy/test_rails_app/apps/7-1.rb b/sentry-rails/spec/dummy/test_rails_app/apps/7-1.rb index ac504704e..a9148a3ee 100644 --- a/sentry-rails/spec/dummy/test_rails_app/apps/7-1.rb +++ b/sentry-rails/spec/dummy/test_rails_app/apps/7-1.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ActiveRecord::Schema.define do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false diff --git a/sentry-rails/spec/dummy/test_rails_app/configs/5-0.rb b/sentry-rails/spec/dummy/test_rails_app/configs/5-0.rb index 70cb662b3..d291ac8f8 100644 --- a/sentry-rails/spec/dummy/test_rails_app/configs/5-0.rb +++ b/sentry-rails/spec/dummy/test_rails_app/configs/5-0.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + def run_pre_initialize_cleanup; end def configure_app(app); end diff --git a/sentry-rails/spec/dummy/test_rails_app/configs/5-2.rb b/sentry-rails/spec/dummy/test_rails_app/configs/5-2.rb index f6b4f39e5..d5d88d8b6 100644 --- a/sentry-rails/spec/dummy/test_rails_app/configs/5-2.rb +++ b/sentry-rails/spec/dummy/test_rails_app/configs/5-2.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_storage/engine" def run_pre_initialize_cleanup; end diff --git a/sentry-rails/spec/dummy/test_rails_app/configs/6-0.rb b/sentry-rails/spec/dummy/test_rails_app/configs/6-0.rb index 7b0673b3c..bab5746a8 100644 --- a/sentry-rails/spec/dummy/test_rails_app/configs/6-0.rb +++ b/sentry-rails/spec/dummy/test_rails_app/configs/6-0.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_storage/engine" require "action_cable/engine" diff --git a/sentry-rails/spec/dummy/test_rails_app/configs/6-1.rb b/sentry-rails/spec/dummy/test_rails_app/configs/6-1.rb index 4532be7ca..e36c83344 100644 --- a/sentry-rails/spec/dummy/test_rails_app/configs/6-1.rb +++ b/sentry-rails/spec/dummy/test_rails_app/configs/6-1.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_storage/engine" require "action_cable/engine" diff --git a/sentry-rails/spec/dummy/test_rails_app/configs/7-0.rb b/sentry-rails/spec/dummy/test_rails_app/configs/7-0.rb index dd5d0716c..84652ae04 100644 --- a/sentry-rails/spec/dummy/test_rails_app/configs/7-0.rb +++ b/sentry-rails/spec/dummy/test_rails_app/configs/7-0.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_storage/engine" require "action_cable/engine" diff --git a/sentry-rails/spec/dummy/test_rails_app/configs/7-1.rb b/sentry-rails/spec/dummy/test_rails_app/configs/7-1.rb index d17545fe0..d0126d985 100644 --- a/sentry-rails/spec/dummy/test_rails_app/configs/7-1.rb +++ b/sentry-rails/spec/dummy/test_rails_app/configs/7-1.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_storage/engine" require "action_cable/engine" require "sentry/rails/error_subscriber" diff --git a/sentry-rails/spec/dummy/test_rails_app/configs/7-2.rb b/sentry-rails/spec/dummy/test_rails_app/configs/7-2.rb index d17545fe0..d0126d985 100644 --- a/sentry-rails/spec/dummy/test_rails_app/configs/7-2.rb +++ b/sentry-rails/spec/dummy/test_rails_app/configs/7-2.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_storage/engine" require "action_cable/engine" require "sentry/rails/error_subscriber" diff --git a/sentry-rails/spec/sentry/rails/action_cable_spec.rb b/sentry-rails/spec/sentry/rails/action_cable_spec.rb index 4b353adff..e47ad2efa 100644 --- a/sentry-rails/spec/sentry/rails/action_cable_spec.rb +++ b/sentry-rails/spec/sentry/rails/action_cable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + if defined?(ActionCable) && ActionCable.version >= Gem::Version.new('6.0.0') require "spec_helper" require "action_cable/engine" diff --git a/sentry-rails/spec/sentry/rails/activejob_spec.rb b/sentry-rails/spec/sentry/rails/activejob_spec.rb index f5892d944..9e9e0ce36 100644 --- a/sentry-rails/spec/sentry/rails/activejob_spec.rb +++ b/sentry-rails/spec/sentry/rails/activejob_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "active_job/railtie" diff --git a/sentry-rails/spec/sentry/rails/breadcrumbs/active_support_logger_spec.rb b/sentry-rails/spec/sentry/rails/breadcrumbs/active_support_logger_spec.rb index b156eaf59..e6a0ae6e3 100644 --- a/sentry-rails/spec/sentry/rails/breadcrumbs/active_support_logger_spec.rb +++ b/sentry-rails/spec/sentry/rails/breadcrumbs/active_support_logger_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe "Sentry::Breadcrumbs::ActiveSupportLogger", type: :request do diff --git a/sentry-rails/spec/sentry/rails/breadcrumbs/monotonic_active_support_logger_spec.rb b/sentry-rails/spec/sentry/rails/breadcrumbs/monotonic_active_support_logger_spec.rb index 0334531f6..031443c25 100644 --- a/sentry-rails/spec/sentry/rails/breadcrumbs/monotonic_active_support_logger_spec.rb +++ b/sentry-rails/spec/sentry/rails/breadcrumbs/monotonic_active_support_logger_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" diff --git a/sentry-rails/spec/sentry/rails/client_spec.rb b/sentry-rails/spec/sentry/rails/client_spec.rb index 81c847b9d..86ef1e110 100644 --- a/sentry-rails/spec/sentry/rails/client_spec.rb +++ b/sentry-rails/spec/sentry/rails/client_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Client, type: :request, retry: 3, skip: Gem::Version.new(Rails.version) < Gem::Version.new('5.1.0') do diff --git a/sentry-rails/spec/sentry/rails/configuration_spec.rb b/sentry-rails/spec/sentry/rails/configuration_spec.rb index f27ee99a9..76a8c7546 100644 --- a/sentry-rails/spec/sentry/rails/configuration_spec.rb +++ b/sentry-rails/spec/sentry/rails/configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Rails::Configuration do diff --git a/sentry-rails/spec/sentry/rails/controller_methods_spec.rb b/sentry-rails/spec/sentry/rails/controller_methods_spec.rb index a751e1366..6254dc290 100644 --- a/sentry-rails/spec/sentry/rails/controller_methods_spec.rb +++ b/sentry-rails/spec/sentry/rails/controller_methods_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require "sentry/rails/controller_methods" diff --git a/sentry-rails/spec/sentry/rails/error_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/error_subscriber_spec.rb index 1bce4baca..1dcc1a0f4 100644 --- a/sentry-rails/spec/sentry/rails/error_subscriber_spec.rb +++ b/sentry-rails/spec/sentry/rails/error_subscriber_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'sentry/rails/error_subscriber' diff --git a/sentry-rails/spec/sentry/rails/event_spec.rb b/sentry-rails/spec/sentry/rails/event_spec.rb index 674615f3a..6c3f7b661 100644 --- a/sentry-rails/spec/sentry/rails/event_spec.rb +++ b/sentry-rails/spec/sentry/rails/event_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Event do diff --git a/sentry-rails/spec/sentry/rails/tracing/action_controller_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/tracing/action_controller_subscriber_spec.rb index f147e1b8e..9d0a4df4e 100644 --- a/sentry-rails/spec/sentry/rails/tracing/action_controller_subscriber_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing/action_controller_subscriber_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Rails::Tracing::ActionControllerSubscriber, :subscriber, type: :request do diff --git a/sentry-rails/spec/sentry/rails/tracing/action_view_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/tracing/action_view_subscriber_spec.rb index aa2473312..555584024 100644 --- a/sentry-rails/spec/sentry/rails/tracing/action_view_subscriber_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing/action_view_subscriber_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Rails::Tracing::ActionViewSubscriber, :subscriber, type: :request do diff --git a/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb index aa29b82d2..2441a63d3 100644 --- a/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Rails::Tracing::ActiveRecordSubscriber, :subscriber do diff --git a/sentry-rails/spec/sentry/rails/tracing/active_storage_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/tracing/active_storage_subscriber_spec.rb index 5d34db1e3..a5e186d7e 100644 --- a/sentry-rails/spec/sentry/rails/tracing/active_storage_subscriber_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing/active_storage_subscriber_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Rails::Tracing::ActiveStorageSubscriber, :subscriber, type: :request, skip: Rails.version.to_f <= 5.2 do diff --git a/sentry-rails/spec/sentry/rails/tracing_spec.rb b/sentry-rails/spec/sentry/rails/tracing_spec.rb index 287bd8acc..927e11c8e 100644 --- a/sentry-rails/spec/sentry/rails/tracing_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Rails::Tracing, type: :request do diff --git a/sentry-rails/spec/sentry/rails_spec.rb b/sentry-rails/spec/sentry/rails_spec.rb index 88c1dae1f..dd069db81 100644 --- a/sentry-rails/spec/sentry/rails_spec.rb +++ b/sentry-rails/spec/sentry/rails_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Rails, type: :request do diff --git a/sentry-rails/spec/sentry/send_event_job_spec.rb b/sentry-rails/spec/sentry/send_event_job_spec.rb index c50130f65..00f89b2ed 100644 --- a/sentry-rails/spec/sentry/send_event_job_spec.rb +++ b/sentry-rails/spec/sentry/send_event_job_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_job" require "spec_helper" diff --git a/sentry-rails/spec/spec_helper.rb b/sentry-rails/spec/spec_helper.rb index 55d3334d3..68b7d5a04 100644 --- a/sentry-rails/spec/spec_helper.rb +++ b/sentry-rails/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/setup" begin require "debug/prelude" diff --git a/sentry-resque/Gemfile b/sentry-resque/Gemfile index 58c13cada..96f47a3a5 100644 --- a/sentry-resque/Gemfile +++ b/sentry-resque/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" git_source(:github) { |name| "https://github.com/#{name}.git" } diff --git a/sentry-resque/Gemfile_with_rails.rb b/sentry-resque/Gemfile_with_rails.rb index bceb75350..306b36624 100644 --- a/sentry-resque/Gemfile_with_rails.rb +++ b/sentry-resque/Gemfile_with_rails.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + eval_gemfile File.expand_path("Gemfile", __dir__) gem "sentry-rails", path: "../sentry-rails" diff --git a/sentry-resque/Rakefile b/sentry-resque/Rakefile index 7b2756854..13afab191 100644 --- a/sentry-resque/Rakefile +++ b/sentry-resque/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/gem_tasks" require "rspec/core/rake_task" diff --git a/sentry-resque/bin/console b/sentry-resque/bin/console index 660c7a889..f0f5a7b6a 100755 --- a/sentry-resque/bin/console +++ b/sentry-resque/bin/console @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require "bundler/setup" require "sentry/ruby" diff --git a/sentry-resque/example/Gemfile b/sentry-resque/example/Gemfile index b9432d218..20d98ac4a 100644 --- a/sentry-resque/example/Gemfile +++ b/sentry-resque/example/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" gem "rails" diff --git a/sentry-resque/example/app.rb b/sentry-resque/example/app.rb index 843e8c028..2e85eca19 100644 --- a/sentry-resque/example/app.rb +++ b/sentry-resque/example/app.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "active_job" require "resque" require "sentry-resque" diff --git a/sentry-resque/lib/sentry-resque.rb b/sentry-resque/lib/sentry-resque.rb index 10af757c0..1d499af8a 100644 --- a/sentry-resque/lib/sentry-resque.rb +++ b/sentry-resque/lib/sentry-resque.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "resque" require "sentry-ruby" require "sentry/integrable" diff --git a/sentry-resque/lib/sentry/resque/configuration.rb b/sentry-resque/lib/sentry/resque/configuration.rb index f0d7ffae8..126d6f7eb 100644 --- a/sentry-resque/lib/sentry/resque/configuration.rb +++ b/sentry-resque/lib/sentry/resque/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry class Configuration attr_reader :resque diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index 3bac872bc..8ecd6cfe4 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Resque VERSION = "5.20.1" diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 6d198dcab..4ce4a7ea8 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "lib/sentry/resque/version" Gem::Specification.new do |spec| diff --git a/sentry-resque/spec/sentry/resque/configuration_spec.rb b/sentry-resque/spec/sentry/resque/configuration_spec.rb index abde7c4d4..af2f464d9 100644 --- a/sentry-resque/spec/sentry/resque/configuration_spec.rb +++ b/sentry-resque/spec/sentry/resque/configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Resque::Configuration do diff --git a/sentry-resque/spec/sentry/resque_spec.rb b/sentry-resque/spec/sentry/resque_spec.rb index 2a4739b6f..7239284e3 100644 --- a/sentry-resque/spec/sentry/resque_spec.rb +++ b/sentry-resque/spec/sentry/resque_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" def process_job(worker) diff --git a/sentry-resque/spec/sentry/tracing_spec.rb b/sentry-resque/spec/sentry/tracing_spec.rb index e77b84f4e..bf81f9006 100644 --- a/sentry-resque/spec/sentry/tracing_spec.rb +++ b/sentry-resque/spec/sentry/tracing_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Resque do diff --git a/sentry-resque/spec/spec_helper.rb b/sentry-resque/spec/spec_helper.rb index dd212aab3..73b3baefe 100644 --- a/sentry-resque/spec/spec_helper.rb +++ b/sentry-resque/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/setup" begin require "debug/prelude" diff --git a/sentry-ruby/.rubocop.yml b/sentry-ruby/.rubocop.yml new file mode 120000 index 000000000..7cc18e076 --- /dev/null +++ b/sentry-ruby/.rubocop.yml @@ -0,0 +1 @@ +../.rubocop.yml \ No newline at end of file diff --git a/sentry-ruby/Gemfile b/sentry-ruby/Gemfile index f13a6fe48..5ca0f99c2 100644 --- a/sentry-ruby/Gemfile +++ b/sentry-ruby/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" git_source(:github) { |name| "https://github.com/#{name}.git" } diff --git a/sentry-ruby/Rakefile b/sentry-ruby/Rakefile index c199ef8f8..fb7a8c183 100644 --- a/sentry-ruby/Rakefile +++ b/sentry-ruby/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rake/clean" CLOBBER.include "pkg" diff --git a/sentry-ruby/benchmarks/allocation_comparison.rb b/sentry-ruby/benchmarks/allocation_comparison.rb index 90c7b2b19..c765b2ff6 100644 --- a/sentry-ruby/benchmarks/allocation_comparison.rb +++ b/sentry-ruby/benchmarks/allocation_comparison.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'benchmark/memory' require "sentry-ruby" require "sentry/benchmarks/benchmark_transport" diff --git a/sentry-ruby/benchmarks/allocation_report.rb b/sentry-ruby/benchmarks/allocation_report.rb index 3e0359d72..54fbd4139 100644 --- a/sentry-ruby/benchmarks/allocation_report.rb +++ b/sentry-ruby/benchmarks/allocation_report.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'benchmark/ipsa' require "sentry-ruby" require "sentry/benchmarks/benchmark_transport" diff --git a/sentry-ruby/benchmarks/exception_locals_capturing.rb b/sentry-ruby/benchmarks/exception_locals_capturing.rb index 00c05f9e9..6ebc46ee9 100644 --- a/sentry-ruby/benchmarks/exception_locals_capturing.rb +++ b/sentry-ruby/benchmarks/exception_locals_capturing.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'benchmark/ips' def raise_n_exceptions(n, with_sleep: false) diff --git a/sentry-ruby/bin/console b/sentry-ruby/bin/console index 57a532604..6ab9e0413 100755 --- a/sentry-ruby/bin/console +++ b/sentry-ruby/bin/console @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require "bundler/setup" require "debug" diff --git a/sentry-ruby/lib/sentry-ruby.rb b/sentry-ruby/lib/sentry-ruby.rb index db3420aba..6dcf99671 100644 --- a/sentry-ruby/lib/sentry-ruby.rb +++ b/sentry-ruby/lib/sentry-ruby.rb @@ -42,11 +42,11 @@ module Sentry CAPTURED_SIGNATURE = :@__sentry_captured - LOGGER_PROGNAME = "sentry".freeze + LOGGER_PROGNAME = "sentry" - SENTRY_TRACE_HEADER_NAME = "sentry-trace".freeze + SENTRY_TRACE_HEADER_NAME = "sentry-trace" - BAGGAGE_HEADER_NAME = "baggage".freeze + BAGGAGE_HEADER_NAME = "baggage" THREAD_LOCAL = :sentry_hub diff --git a/sentry-ruby/lib/sentry/backtrace.rb b/sentry-ruby/lib/sentry/backtrace.rb index c5ab16d39..5fd2aadff 100644 --- a/sentry-ruby/lib/sentry/backtrace.rb +++ b/sentry-ruby/lib/sentry/backtrace.rb @@ -13,10 +13,10 @@ class Line ^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>): (\d+) (?: :in\s('|`)([^']+)')?$ - /x.freeze + /x # org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170) - JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze + JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/ # The file portion of the line (such as app/models/user.rb) attr_reader :file diff --git a/sentry-ruby/lib/sentry/baggage.rb b/sentry-ruby/lib/sentry/baggage.rb index 2b375a846..dc02dd8e6 100644 --- a/sentry-ruby/lib/sentry/baggage.rb +++ b/sentry-ruby/lib/sentry/baggage.rb @@ -6,7 +6,7 @@ module Sentry # A {https://www.w3.org/TR/baggage W3C Baggage Header} implementation. class Baggage SENTRY_PREFIX = "sentry-" - SENTRY_PREFIX_REGEX = /^sentry-/.freeze + SENTRY_PREFIX_REGEX = /^sentry-/ # @return [Hash] attr_reader :items diff --git a/sentry-ruby/lib/sentry/configuration.rb b/sentry-ruby/lib/sentry/configuration.rb index 505e46a2a..b13c81c49 100644 --- a/sentry-ruby/lib/sentry/configuration.rb +++ b/sentry-ruby/lib/sentry/configuration.rb @@ -335,19 +335,19 @@ def capture_exception_frame_locals=(value) ].freeze HEROKU_DYNO_METADATA_MESSAGE = "You are running on Heroku but haven't enabled Dyno Metadata. For Sentry's "\ - "release detection to work correctly, please run `heroku labs:enable runtime-dyno-metadata`".freeze + "release detection to work correctly, please run `heroku labs:enable runtime-dyno-metadata`" - LOG_PREFIX = "** [Sentry] ".freeze - MODULE_SEPARATOR = "::".freeze + LOG_PREFIX = "** [Sentry] " + MODULE_SEPARATOR = "::" SKIP_INSPECTION_ATTRIBUTES = [:@linecache, :@stacktrace_builder] INSTRUMENTERS = [:sentry, :otel] - PROPAGATION_TARGETS_MATCH_ALL = /.*/.freeze + PROPAGATION_TARGETS_MATCH_ALL = /.*/ DEFAULT_PATCHES = %i[redis puma http].freeze - APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze + APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/ class << self # Post initialization callbacks are called at the end of initialization process diff --git a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb index ac7e35d81..835ae84ad 100644 --- a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb +++ b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Cron module MonitorCheckIns diff --git a/sentry-ruby/lib/sentry/interfaces/single_exception.rb b/sentry-ruby/lib/sentry/interfaces/single_exception.rb index f7126e702..db2d54e7b 100644 --- a/sentry-ruby/lib/sentry/interfaces/single_exception.rb +++ b/sentry-ruby/lib/sentry/interfaces/single_exception.rb @@ -7,8 +7,8 @@ class SingleExceptionInterface < Interface include CustomInspection SKIP_INSPECTION_ATTRIBUTES = [:@stacktrace] - PROBLEMATIC_LOCAL_VALUE_REPLACEMENT = "[ignored due to error]".freeze - OMISSION_MARK = "...".freeze + PROBLEMATIC_LOCAL_VALUE_REPLACEMENT = "[ignored due to error]" + OMISSION_MARK = "..." MAX_LOCAL_BYTES = 1024 attr_reader :type, :module, :thread_id, :stacktrace, :mechanism diff --git a/sentry-ruby/lib/sentry/rack/capture_exceptions.rb b/sentry-ruby/lib/sentry/rack/capture_exceptions.rb index 5bb8eda67..40cdfb4f8 100644 --- a/sentry-ruby/lib/sentry/rack/capture_exceptions.rb +++ b/sentry-ruby/lib/sentry/rack/capture_exceptions.rb @@ -54,7 +54,7 @@ def collect_exception(env) end def transaction_op - "http.server".freeze + "http.server" end def capture_exception(exception, env) diff --git a/sentry-ruby/lib/sentry/test_helper.rb b/sentry-ruby/lib/sentry/test_helper.rb index 212c35db5..d36dc0be0 100644 --- a/sentry-ruby/lib/sentry/test_helper.rb +++ b/sentry-ruby/lib/sentry/test_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module TestHelper DUMMY_DSN = "http://12345:67890@sentry.localdomain/sentry/42" diff --git a/sentry-ruby/lib/sentry/transaction.rb b/sentry-ruby/lib/sentry/transaction.rb index ad9447061..5e3ceb982 100644 --- a/sentry-ruby/lib/sentry/transaction.rb +++ b/sentry-ruby/lib/sentry/transaction.rb @@ -9,7 +9,7 @@ class Transaction < Span # @deprecated Use Sentry::PropagationContext::SENTRY_TRACE_REGEXP instead. SENTRY_TRACE_REGEXP = PropagationContext::SENTRY_TRACE_REGEXP - UNLABELD_NAME = "".freeze + UNLABELD_NAME = "" MESSAGE_PREFIX = "[Tracing]" # https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations diff --git a/sentry-ruby/sentry-ruby-core.gemspec b/sentry-ruby/sentry-ruby-core.gemspec index a676fe126..4bd423750 100644 --- a/sentry-ruby/sentry-ruby-core.gemspec +++ b/sentry-ruby/sentry-ruby-core.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "lib/sentry/version" Gem::Specification.new do |spec| diff --git a/sentry-ruby/sentry-ruby.gemspec b/sentry-ruby/sentry-ruby.gemspec index 44fcfceaa..ba183705c 100644 --- a/sentry-ruby/sentry-ruby.gemspec +++ b/sentry-ruby/sentry-ruby.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "lib/sentry/version" Gem::Specification.new do |spec| diff --git a/sentry-ruby/spec/contexts/with_request_mock.rb b/sentry-ruby/spec/contexts/with_request_mock.rb index bc103f7dc..e6c480256 100644 --- a/sentry-ruby/spec/contexts/with_request_mock.rb +++ b/sentry-ruby/spec/contexts/with_request_mock.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # because our patch on Net::HTTP is relatively low-level, we need to stub methods on socket level # which is not supported by most of the http mocking library # so we need to put something together ourselves diff --git a/sentry-ruby/spec/initialization_check_spec.rb b/sentry-ruby/spec/initialization_check_spec.rb index 039384c1d..129d5fdff 100644 --- a/sentry-ruby/spec/initialization_check_spec.rb +++ b/sentry-ruby/spec/initialization_check_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe "with uninitialized SDK" do diff --git a/sentry-ruby/spec/isolated/puma_spec.rb b/sentry-ruby/spec/isolated/puma_spec.rb index 0e2082519..6f416d6e9 100644 --- a/sentry-ruby/spec/isolated/puma_spec.rb +++ b/sentry-ruby/spec/isolated/puma_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "puma" require_relative "../spec_helper" diff --git a/sentry-ruby/spec/sentry/background_worker_spec.rb b/sentry-ruby/spec/sentry/background_worker_spec.rb index e1b900094..9e15b43ec 100644 --- a/sentry-ruby/spec/sentry/background_worker_spec.rb +++ b/sentry-ruby/spec/sentry/background_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::BackgroundWorker do diff --git a/sentry-ruby/spec/sentry/backpressure_monitor_spec.rb b/sentry-ruby/spec/sentry/backpressure_monitor_spec.rb index 1419cffdb..e0147d87c 100644 --- a/sentry-ruby/spec/sentry/backpressure_monitor_spec.rb +++ b/sentry-ruby/spec/sentry/backpressure_monitor_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::BackpressureMonitor do diff --git a/sentry-ruby/spec/sentry/backtrace/lines_spec.rb b/sentry-ruby/spec/sentry/backtrace/lines_spec.rb index 92dc48e6d..8a49ea1d8 100644 --- a/sentry-ruby/spec/sentry/backtrace/lines_spec.rb +++ b/sentry-ruby/spec/sentry/backtrace/lines_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Backtrace::Line do diff --git a/sentry-ruby/spec/sentry/backtrace_spec.rb b/sentry-ruby/spec/sentry/backtrace_spec.rb index b373c45f4..648e4ee8e 100644 --- a/sentry-ruby/spec/sentry/backtrace_spec.rb +++ b/sentry-ruby/spec/sentry/backtrace_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Backtrace do diff --git a/sentry-ruby/spec/sentry/baggage_spec.rb b/sentry-ruby/spec/sentry/baggage_spec.rb index 3d72a5687..a9cc44873 100644 --- a/sentry-ruby/spec/sentry/baggage_spec.rb +++ b/sentry-ruby/spec/sentry/baggage_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Baggage do diff --git a/sentry-ruby/spec/sentry/breadcrumb/http_logger_spec.rb b/sentry-ruby/spec/sentry/breadcrumb/http_logger_spec.rb index 66146ef64..a4fab84ed 100644 --- a/sentry-ruby/spec/sentry/breadcrumb/http_logger_spec.rb +++ b/sentry-ruby/spec/sentry/breadcrumb/http_logger_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require 'contexts/with_request_mock' diff --git a/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb b/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb index 4d0d541df..4285a43f4 100644 --- a/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb +++ b/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe :redis_logger do diff --git a/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb b/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb index aafcf6f96..da3cd97c7 100644 --- a/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb +++ b/sentry-ruby/spec/sentry/breadcrumb/sentry_logger_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe "Sentry::Breadcrumbs::SentryLogger" do diff --git a/sentry-ruby/spec/sentry/breadcrumb_buffer_spec.rb b/sentry-ruby/spec/sentry/breadcrumb_buffer_spec.rb index 04a76fe3c..f68e223b3 100644 --- a/sentry-ruby/spec/sentry/breadcrumb_buffer_spec.rb +++ b/sentry-ruby/spec/sentry/breadcrumb_buffer_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::BreadcrumbBuffer do diff --git a/sentry-ruby/spec/sentry/breadcrumb_spec.rb b/sentry-ruby/spec/sentry/breadcrumb_spec.rb index 66c2d1112..2eddb7101 100644 --- a/sentry-ruby/spec/sentry/breadcrumb_spec.rb +++ b/sentry-ruby/spec/sentry/breadcrumb_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Breadcrumb do diff --git a/sentry-ruby/spec/sentry/client/event_sending_spec.rb b/sentry-ruby/spec/sentry/client/event_sending_spec.rb index b1b1a041c..86b4b6c67 100644 --- a/sentry-ruby/spec/sentry/client/event_sending_spec.rb +++ b/sentry-ruby/spec/sentry/client/event_sending_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Client do diff --git a/sentry-ruby/spec/sentry/client_spec.rb b/sentry-ruby/spec/sentry/client_spec.rb index bd1debcf2..e069ccc5b 100644 --- a/sentry-ruby/spec/sentry/client_spec.rb +++ b/sentry-ruby/spec/sentry/client_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' class ExceptionWithContext < StandardError @@ -341,7 +343,12 @@ def detailed_message(*) event = subject.event_from_exception(NonStringMessageError.new) hash = event.to_hash expect(event).to be_a(Sentry::ErrorEvent) - expect(hash[:exception][:values][0][:value]).to eq("{:foo=>\"bar\"}") + + if RUBY_VERSION >= "3.4" + expect(hash[:exception][:values][0][:value]).to eq("{foo: \"bar\"}") + else + expect(hash[:exception][:values][0][:value]).to eq("{:foo=>\"bar\"}") + end end end diff --git a/sentry-ruby/spec/sentry/configuration_spec.rb b/sentry-ruby/spec/sentry/configuration_spec.rb index f910712ad..afd78625b 100644 --- a/sentry-ruby/spec/sentry/configuration_spec.rb +++ b/sentry-ruby/spec/sentry/configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Configuration do diff --git a/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb b/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb index fb8212df6..48cd3e044 100644 --- a/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb +++ b/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Cron::MonitorCheckIns do diff --git a/sentry-ruby/spec/sentry/cron/monitor_config_spec.rb b/sentry-ruby/spec/sentry/cron/monitor_config_spec.rb index 68bbbe95a..1c934e8cc 100644 --- a/sentry-ruby/spec/sentry/cron/monitor_config_spec.rb +++ b/sentry-ruby/spec/sentry/cron/monitor_config_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Cron::MonitorConfig do diff --git a/sentry-ruby/spec/sentry/cron/monitor_schedule_spec.rb b/sentry-ruby/spec/sentry/cron/monitor_schedule_spec.rb index 8e1b422d1..909a9b4fa 100644 --- a/sentry-ruby/spec/sentry/cron/monitor_schedule_spec.rb +++ b/sentry-ruby/spec/sentry/cron/monitor_schedule_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Cron::MonitorSchedule::Crontab do diff --git a/sentry-ruby/spec/sentry/dsn_spec.rb b/sentry-ruby/spec/sentry/dsn_spec.rb index 24256f291..0a0eaecb4 100644 --- a/sentry-ruby/spec/sentry/dsn_spec.rb +++ b/sentry-ruby/spec/sentry/dsn_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::DSN do diff --git a/sentry-ruby/spec/sentry/envelope/item_spec.rb b/sentry-ruby/spec/sentry/envelope/item_spec.rb index 8936c7707..ea9cf1019 100644 --- a/sentry-ruby/spec/sentry/envelope/item_spec.rb +++ b/sentry-ruby/spec/sentry/envelope/item_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Envelope::Item do diff --git a/sentry-ruby/spec/sentry/event_spec.rb b/sentry-ruby/spec/sentry/event_spec.rb index ea59f95e1..90acb4da8 100644 --- a/sentry-ruby/spec/sentry/event_spec.rb +++ b/sentry-ruby/spec/sentry/event_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Event do diff --git a/sentry-ruby/spec/sentry/faraday_spec.rb b/sentry-ruby/spec/sentry/faraday_spec.rb index f4632032f..0cb69fe39 100644 --- a/sentry-ruby/spec/sentry/faraday_spec.rb +++ b/sentry-ruby/spec/sentry/faraday_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "faraday" require_relative "../spec_helper" diff --git a/sentry-ruby/spec/sentry/graphql_spec.rb b/sentry-ruby/spec/sentry/graphql_spec.rb index 5820b73d2..a90dfe6b0 100644 --- a/sentry-ruby/spec/sentry/graphql_spec.rb +++ b/sentry-ruby/spec/sentry/graphql_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' with_graphql = begin diff --git a/sentry-ruby/spec/sentry/hub_spec.rb b/sentry-ruby/spec/sentry/hub_spec.rb index c7ada3ae6..735bc6acd 100644 --- a/sentry-ruby/spec/sentry/hub_spec.rb +++ b/sentry-ruby/spec/sentry/hub_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Hub do diff --git a/sentry-ruby/spec/sentry/integrable_spec.rb b/sentry-ruby/spec/sentry/integrable_spec.rb index 269ba821e..6e7a03a07 100644 --- a/sentry-ruby/spec/sentry/integrable_spec.rb +++ b/sentry-ruby/spec/sentry/integrable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "sentry/integrable" diff --git a/sentry-ruby/spec/sentry/interface_spec.rb b/sentry-ruby/spec/sentry/interface_spec.rb index 7d95d5263..2d70cdc9b 100644 --- a/sentry-ruby/spec/sentry/interface_spec.rb +++ b/sentry-ruby/spec/sentry/interface_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'sentry/interface' diff --git a/sentry-ruby/spec/sentry/interfaces/request_interface_spec.rb b/sentry-ruby/spec/sentry/interfaces/request_interface_spec.rb index 580a610d3..a7a2225d0 100644 --- a/sentry-ruby/spec/sentry/interfaces/request_interface_spec.rb +++ b/sentry-ruby/spec/sentry/interfaces/request_interface_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' return unless defined?(Rack) diff --git a/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb b/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb index e7c05d6ad..fd89360a9 100644 --- a/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb +++ b/sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::StacktraceBuilder do @@ -11,8 +13,8 @@ let(:backtrace) do [ - "#{fixture_file}:6:in `bar'", - "#{fixture_file}:2:in `foo'" + "#{fixture_file}:8:in `bar'", + "#{fixture_file}:4:in `foo'" ] end @@ -36,8 +38,8 @@ expect(first_frame.filename).to match(/stacktrace_test_fixture.rb/) expect(first_frame.function).to eq("foo") - expect(first_frame.lineno).to eq(2) - expect(first_frame.pre_context).to eq([nil, nil, "def foo\n"]) + expect(first_frame.lineno).to eq(4) + expect(first_frame.pre_context).to eq(["# frozen_string_literal: true\n", "\n", "def foo\n"]) expect(first_frame.context_line).to eq(" bar\n") expect(first_frame.post_context).to eq(["end\n", "\n", "def bar\n"]) @@ -45,7 +47,7 @@ expect(second_frame.filename).to match(/stacktrace_test_fixture.rb/) expect(second_frame.function).to eq("bar") - expect(second_frame.lineno).to eq(6) + expect(second_frame.lineno).to eq(8) expect(second_frame.pre_context).to eq(["end\n", "\n", "def bar\n"]) expect(second_frame.context_line).to eq(" baz\n") expect(second_frame.post_context).to eq(["end\n", nil, nil]) @@ -92,7 +94,7 @@ expect(second_frame.filename).to match(/stacktrace_test_fixture.rb/) expect(second_frame.function).to eq("bar") - expect(second_frame.lineno).to eq(6) + expect(second_frame.lineno).to eq(8) expect(second_frame.vars).to eq({ foo: "bar" }) end end @@ -104,7 +106,7 @@ expect(hash[:filename]).to match(/stacktrace_test_fixture.rb/) expect(hash[:function]).to eq("bar") - expect(hash[:lineno]).to eq(6) + expect(hash[:lineno]).to eq(8) expect(hash[:pre_context]).to eq(["end\n", "\n", "def bar\n"]) expect(hash[:context_line]).to eq(" baz\n") expect(hash[:post_context]).to eq(["end\n", nil, nil]) diff --git a/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb b/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb index 3236af606..6ceb0b1d0 100644 --- a/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb +++ b/sentry-ruby/spec/sentry/interfaces/stacktrace_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::StacktraceInterface::Frame do diff --git a/sentry-ruby/spec/sentry/linecache_spec.rb b/sentry-ruby/spec/sentry/linecache_spec.rb index 56c9e086b..097b3ed56 100644 --- a/sentry-ruby/spec/sentry/linecache_spec.rb +++ b/sentry-ruby/spec/sentry/linecache_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' # rubocop:disable Style/WordArray RSpec.describe Sentry::LineCache do diff --git a/sentry-ruby/spec/sentry/metrics/aggregator_spec.rb b/sentry-ruby/spec/sentry/metrics/aggregator_spec.rb index dcd78ab86..b54c6a0d9 100644 --- a/sentry-ruby/spec/sentry/metrics/aggregator_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/aggregator_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::Aggregator do diff --git a/sentry-ruby/spec/sentry/metrics/configuration_spec.rb b/sentry-ruby/spec/sentry/metrics/configuration_spec.rb index 2c7e22fbe..3d04ad3ea 100644 --- a/sentry-ruby/spec/sentry/metrics/configuration_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::Configuration do diff --git a/sentry-ruby/spec/sentry/metrics/counter_metric_spec.rb b/sentry-ruby/spec/sentry/metrics/counter_metric_spec.rb index f92a0135f..f1c480b45 100644 --- a/sentry-ruby/spec/sentry/metrics/counter_metric_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/counter_metric_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::CounterMetric do diff --git a/sentry-ruby/spec/sentry/metrics/distribution_metric_spec.rb b/sentry-ruby/spec/sentry/metrics/distribution_metric_spec.rb index 7e5b2f2d4..e8ac709f3 100644 --- a/sentry-ruby/spec/sentry/metrics/distribution_metric_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/distribution_metric_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::DistributionMetric do diff --git a/sentry-ruby/spec/sentry/metrics/gauge_metric_spec.rb b/sentry-ruby/spec/sentry/metrics/gauge_metric_spec.rb index 44be08465..fce3141c6 100644 --- a/sentry-ruby/spec/sentry/metrics/gauge_metric_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/gauge_metric_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::GaugeMetric do diff --git a/sentry-ruby/spec/sentry/metrics/local_aggregator_spec.rb b/sentry-ruby/spec/sentry/metrics/local_aggregator_spec.rb index 5c5ab0583..3056808da 100644 --- a/sentry-ruby/spec/sentry/metrics/local_aggregator_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/local_aggregator_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::LocalAggregator do diff --git a/sentry-ruby/spec/sentry/metrics/metric_spec.rb b/sentry-ruby/spec/sentry/metrics/metric_spec.rb index a5ed3fd93..ccb4fa222 100644 --- a/sentry-ruby/spec/sentry/metrics/metric_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/metric_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::Metric do diff --git a/sentry-ruby/spec/sentry/metrics/set_metric_spec.rb b/sentry-ruby/spec/sentry/metrics/set_metric_spec.rb index fdf74dd0d..2cd01da83 100644 --- a/sentry-ruby/spec/sentry/metrics/set_metric_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/set_metric_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::SetMetric do diff --git a/sentry-ruby/spec/sentry/metrics/timing_spec.rb b/sentry-ruby/spec/sentry/metrics/timing_spec.rb index 8142fbb4d..3b2ee2235 100644 --- a/sentry-ruby/spec/sentry/metrics/timing_spec.rb +++ b/sentry-ruby/spec/sentry/metrics/timing_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics::Timing do diff --git a/sentry-ruby/spec/sentry/metrics_spec.rb b/sentry-ruby/spec/sentry/metrics_spec.rb index 335c31e5a..e50c55074 100644 --- a/sentry-ruby/spec/sentry/metrics_spec.rb +++ b/sentry-ruby/spec/sentry/metrics_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Metrics do diff --git a/sentry-ruby/spec/sentry/net/http_spec.rb b/sentry-ruby/spec/sentry/net/http_spec.rb index 6a6dbbf73..9de0a6f76 100644 --- a/sentry-ruby/spec/sentry/net/http_spec.rb +++ b/sentry-ruby/spec/sentry/net/http_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require 'contexts/with_request_mock' diff --git a/sentry-ruby/spec/sentry/profiler_spec.rb b/sentry-ruby/spec/sentry/profiler_spec.rb index 9100a3441..883fac025 100644 --- a/sentry-ruby/spec/sentry/profiler_spec.rb +++ b/sentry-ruby/spec/sentry/profiler_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Profiler, when: :stack_prof_installed? do diff --git a/sentry-ruby/spec/sentry/propagation_context_spec.rb b/sentry-ruby/spec/sentry/propagation_context_spec.rb index 644fc9530..7e16404b6 100644 --- a/sentry-ruby/spec/sentry/propagation_context_spec.rb +++ b/sentry-ruby/spec/sentry/propagation_context_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::PropagationContext do diff --git a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb index 83095d842..21e1786ef 100644 --- a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb +++ b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'sentry/vernier/profiler' diff --git a/sentry-ruby/spec/sentry/rake_spec.rb b/sentry-ruby/spec/sentry/rake_spec.rb index a1eb22998..904f19170 100644 --- a/sentry-ruby/spec/sentry/rake_spec.rb +++ b/sentry-ruby/spec/sentry/rake_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe "rake auto-reporting" do diff --git a/sentry-ruby/spec/sentry/redis_spec.rb b/sentry-ruby/spec/sentry/redis_spec.rb index 2722e0498..50e86ac55 100644 --- a/sentry-ruby/spec/sentry/redis_spec.rb +++ b/sentry-ruby/spec/sentry/redis_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Redis do diff --git a/sentry-ruby/spec/sentry/scope/setters_spec.rb b/sentry-ruby/spec/sentry/scope/setters_spec.rb index 6a5378194..39a2e25c1 100644 --- a/sentry-ruby/spec/sentry/scope/setters_spec.rb +++ b/sentry-ruby/spec/sentry/scope/setters_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Scope do diff --git a/sentry-ruby/spec/sentry/scope_spec.rb b/sentry-ruby/spec/sentry/scope_spec.rb index 6b4b4c168..4bacae275 100644 --- a/sentry-ruby/spec/sentry/scope_spec.rb +++ b/sentry-ruby/spec/sentry/scope_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Scope do diff --git a/sentry-ruby/spec/sentry/session_flusher_spec.rb b/sentry-ruby/spec/sentry/session_flusher_spec.rb index 0c0fbb4eb..376f71dd4 100644 --- a/sentry-ruby/spec/sentry/session_flusher_spec.rb +++ b/sentry-ruby/spec/sentry/session_flusher_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::SessionFlusher do diff --git a/sentry-ruby/spec/sentry/span_spec.rb b/sentry-ruby/spec/sentry/span_spec.rb index f24876d7f..0d1fd225c 100644 --- a/sentry-ruby/spec/sentry/span_spec.rb +++ b/sentry-ruby/spec/sentry/span_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Span do diff --git a/sentry-ruby/spec/sentry/test_helper_spec.rb b/sentry-ruby/spec/sentry/test_helper_spec.rb index 2753b9b64..8303464c8 100644 --- a/sentry-ruby/spec/sentry/test_helper_spec.rb +++ b/sentry-ruby/spec/sentry/test_helper_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::TestHelper do diff --git a/sentry-ruby/spec/sentry/transaction_spec.rb b/sentry-ruby/spec/sentry/transaction_spec.rb index effb249f1..7cc83aa64 100644 --- a/sentry-ruby/spec/sentry/transaction_spec.rb +++ b/sentry-ruby/spec/sentry/transaction_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Transaction do diff --git a/sentry-ruby/spec/sentry/transport/configuration_spec.rb b/sentry-ruby/spec/sentry/transport/configuration_spec.rb index 676a4800c..fa3edd87b 100644 --- a/sentry-ruby/spec/sentry/transport/configuration_spec.rb +++ b/sentry-ruby/spec/sentry/transport/configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Transport::Configuration do diff --git a/sentry-ruby/spec/sentry/transport/http_transport_rate_limiting_spec.rb b/sentry-ruby/spec/sentry/transport/http_transport_rate_limiting_spec.rb index ac83e3b16..30dc42bbb 100644 --- a/sentry-ruby/spec/sentry/transport/http_transport_rate_limiting_spec.rb +++ b/sentry-ruby/spec/sentry/transport/http_transport_rate_limiting_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'contexts/with_request_mock' diff --git a/sentry-ruby/spec/sentry/transport/http_transport_spec.rb b/sentry-ruby/spec/sentry/transport/http_transport_spec.rb index 3c7b1b051..a0973ef75 100644 --- a/sentry-ruby/spec/sentry/transport/http_transport_spec.rb +++ b/sentry-ruby/spec/sentry/transport/http_transport_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'contexts/with_request_mock' diff --git a/sentry-ruby/spec/sentry/transport/spotlight_transport_spec.rb b/sentry-ruby/spec/sentry/transport/spotlight_transport_spec.rb index 04de57af6..fc095efeb 100644 --- a/sentry-ruby/spec/sentry/transport/spotlight_transport_spec.rb +++ b/sentry-ruby/spec/sentry/transport/spotlight_transport_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::SpotlightTransport do diff --git a/sentry-ruby/spec/sentry/transport_spec.rb b/sentry-ruby/spec/sentry/transport_spec.rb index 079aa8709..059a8109b 100644 --- a/sentry-ruby/spec/sentry/transport_spec.rb +++ b/sentry-ruby/spec/sentry/transport_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Transport do diff --git a/sentry-ruby/spec/sentry/utils/real_ip_spec.rb b/sentry-ruby/spec/sentry/utils/real_ip_spec.rb index 7aa6c7559..42197b9f2 100644 --- a/sentry-ruby/spec/sentry/utils/real_ip_spec.rb +++ b/sentry-ruby/spec/sentry/utils/real_ip_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Utils::RealIp do diff --git a/sentry-ruby/spec/sentry/utils/request_id_spec.rb b/sentry-ruby/spec/sentry/utils/request_id_spec.rb index 7fa7a7301..955bd8894 100644 --- a/sentry-ruby/spec/sentry/utils/request_id_spec.rb +++ b/sentry-ruby/spec/sentry/utils/request_id_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Utils::RequestId do diff --git a/sentry-ruby/spec/sentry/vernier/profiler_spec.rb b/sentry-ruby/spec/sentry/vernier/profiler_spec.rb index 645ddcada..03fe7ebde 100644 --- a/sentry-ruby/spec/sentry/vernier/profiler_spec.rb +++ b/sentry-ruby/spec/sentry/vernier/profiler_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require "sentry/vernier/profiler" @@ -173,7 +175,7 @@ expect(foo_frame[:function]).to eq('Foo.foo') expect(foo_frame[:module]).to eq('ProfilerTest::Bar') expect(foo_frame[:in_app]).to eq(true) - expect(foo_frame[:lineno]).to eq(4) + expect(foo_frame[:lineno]).to eq(6) expect(foo_frame[:filename]).to eq('spec/support/profiler.rb') expect(foo_frame[:abs_path]).to include('sentry-ruby/sentry-ruby/spec/support/profiler.rb') end @@ -259,7 +261,7 @@ expect(foo_frame[:function]).to eq('Foo.foo') expect(foo_frame[:module]).to eq('ProfilerTest::Bar') expect(foo_frame[:in_app]).to eq(true) - expect(foo_frame[:lineno]).to eq(4) + expect(foo_frame[:lineno]).to eq(6) expect(foo_frame[:filename]).to eq('spec/support/profiler.rb') expect(foo_frame[:abs_path]).to include('sentry-ruby/sentry-ruby/spec/support/profiler.rb') end diff --git a/sentry-ruby/spec/sentry_spec.rb b/sentry-ruby/spec/sentry_spec.rb index dd3f85c93..dabdcd07e 100644 --- a/sentry-ruby/spec/sentry_spec.rb +++ b/sentry-ruby/spec/sentry_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require 'contexts/with_request_mock' diff --git a/sentry-ruby/spec/spec_helper.rb b/sentry-ruby/spec/spec_helper.rb index 1bceb1070..e0d1c9a1e 100644 --- a/sentry-ruby/spec/spec_helper.rb +++ b/sentry-ruby/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/setup" begin require "debug/prelude" diff --git a/sentry-ruby/spec/support/Rakefile.rb b/sentry-ruby/spec/support/Rakefile.rb index 2304ba3a4..77b245297 100644 --- a/sentry-ruby/spec/support/Rakefile.rb +++ b/sentry-ruby/spec/support/Rakefile.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rake" require "sentry-ruby" diff --git a/sentry-ruby/spec/support/profiler.rb b/sentry-ruby/spec/support/profiler.rb index 7f048b8a5..ee83cc4dd 100644 --- a/sentry-ruby/spec/support/profiler.rb +++ b/sentry-ruby/spec/support/profiler.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ProfilerTest module Bar module Foo diff --git a/sentry-ruby/spec/support/stacktrace_test_fixture.rb b/sentry-ruby/spec/support/stacktrace_test_fixture.rb index 7921fb53b..0c8d7933e 100644 --- a/sentry-ruby/spec/support/stacktrace_test_fixture.rb +++ b/sentry-ruby/spec/support/stacktrace_test_fixture.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + def foo bar end diff --git a/sentry-sidekiq/Gemfile b/sentry-sidekiq/Gemfile index 5ce453b72..c158e85dc 100644 --- a/sentry-sidekiq/Gemfile +++ b/sentry-sidekiq/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" git_source(:github) { |name| "https://github.com/#{name}.git" } diff --git a/sentry-sidekiq/Rakefile b/sentry-sidekiq/Rakefile index 7b2756854..13afab191 100644 --- a/sentry-sidekiq/Rakefile +++ b/sentry-sidekiq/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/gem_tasks" require "rspec/core/rake_task" diff --git a/sentry-sidekiq/bin/console b/sentry-sidekiq/bin/console index 660c7a889..f0f5a7b6a 100755 --- a/sentry-sidekiq/bin/console +++ b/sentry-sidekiq/bin/console @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require "bundler/setup" require "sentry/ruby" diff --git a/sentry-sidekiq/example/Gemfile b/sentry-sidekiq/example/Gemfile index d038af521..9834edf07 100644 --- a/sentry-sidekiq/example/Gemfile +++ b/sentry-sidekiq/example/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" gem "sidekiq" diff --git a/sentry-sidekiq/example/error_worker.rb b/sentry-sidekiq/example/error_worker.rb index 220d80f63..8782dd2d7 100644 --- a/sentry-sidekiq/example/error_worker.rb +++ b/sentry-sidekiq/example/error_worker.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sidekiq" require "sentry-sidekiq" diff --git a/sentry-sidekiq/lib/sentry-sidekiq.rb b/sentry-sidekiq/lib/sentry-sidekiq.rb index b7318b9f9..a126782f2 100644 --- a/sentry-sidekiq/lib/sentry-sidekiq.rb +++ b/sentry-sidekiq/lib/sentry-sidekiq.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sidekiq" require "sentry-ruby" require "sentry/integrable" diff --git a/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb b/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb index cc71908b5..b6ef3856c 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry class Configuration attr_reader :sidekiq diff --git a/sentry-sidekiq/lib/sentry/sidekiq/context_filter.rb b/sentry-sidekiq/lib/sentry/sidekiq/context_filter.rb index 8512b5ab5..ff9f014c3 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/context_filter.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/context_filter.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + module Sentry module Sidekiq class ContextFilter - ACTIVEJOB_RESERVED_PREFIX_REGEX = /^_aj_/.freeze - SIDEKIQ_NAME = "Sidekiq".freeze + ACTIVEJOB_RESERVED_PREFIX_REGEX = /^_aj_/ + SIDEKIQ_NAME = "Sidekiq" attr_reader :context diff --git a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb index d1f7eaf87..50c720929 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "sentry/sidekiq/context_filter" module Sentry diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index 46cb74dbe..7fd496062 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Sentry module Sidekiq VERSION = "5.20.1" diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index 69a4689de..fe8a94595 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "lib/sentry/sidekiq/version" Gem::Specification.new do |spec| diff --git a/sentry-sidekiq/spec/sentry/rails_spec.rb b/sentry-sidekiq/spec/sentry/rails_spec.rb index 87518ea06..36c6fdd31 100644 --- a/sentry-sidekiq/spec/sentry/rails_spec.rb +++ b/sentry-sidekiq/spec/sentry/rails_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + return unless ENV["WITH_SENTRY_RAILS"] require "rails" diff --git a/sentry-sidekiq/spec/sentry/sidekiq-scheduler/scheduler_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq-scheduler/scheduler_spec.rb index 879e34a55..02efd1ccc 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq-scheduler/scheduler_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq-scheduler/scheduler_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' return unless defined?(SidekiqScheduler::Scheduler) diff --git a/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb index 2fdcdfbc5..7e9066ffe 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Sidekiq::Configuration do diff --git a/sentry-sidekiq/spec/sentry/sidekiq/context_filter_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/context_filter_spec.rb index dc5354b9c..099ce329b 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/context_filter_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/context_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.describe Sentry::Sidekiq::ContextFilter do diff --git a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb index c0f223096..4e4f65202 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' return unless defined?(Sidekiq::Cron::Job) diff --git a/sentry-sidekiq/spec/sentry/sidekiq/error_handler_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/error_handler_spec.rb index 15053609e..5e144bf9a 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/error_handler_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/error_handler_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe Sentry::Sidekiq::ErrorHandler do diff --git a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb index 8d28577e7..de5e9416f 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" RSpec.shared_context "sidekiq", shared_context: :metadata do diff --git a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb index 2e7cfb99a..64fdec5c1 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" require 'sidekiq/manager' require 'sidekiq/api' diff --git a/sentry-sidekiq/spec/spec_helper.rb b/sentry-sidekiq/spec/spec_helper.rb index 6b2287957..5e1e6a6e9 100644 --- a/sentry-sidekiq/spec/spec_helper.rb +++ b/sentry-sidekiq/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "bundler/setup" begin require "debug/prelude" From 46a539561f868ff98391d5143cc9f66e031ff77e Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Mon, 7 Oct 2024 14:56:39 +0200 Subject: [PATCH 53/96] Changelog for 5.21.0 (#2423) --- CHANGELOG.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35975b8dd..eaff67e9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,30 @@ -## Unreleased +## 5.21.0 ### Features -- Experimental support for multi-threaded profiling using Vernier ([#2372](https://github.com/getsentry/sentry-ruby/pull/2372)) +- Experimental support for multi-threaded profiling using [Vernier](https://github.com/jhawthorn/vernier) ([#2372](https://github.com/getsentry/sentry-ruby/pull/2372)) + + You can have much better profiles if you're using multi-threaded servers like Puma now by leveraging Vernier. + To use it, first add `vernier` to your `Gemfile` and make sure it is loaded before `sentry-ruby`. + + ```ruby + # Gemfile + + gem 'vernier' + gem 'sentry-ruby' + ``` + + Then, set a `profiles_sample_rate` and the new `profiler_class` configuration in your sentry initializer to use the new profiler. + + ```ruby + # config/initializers/sentry.rb + + Sentry.init do |config| + # ... + config.profiles_sample_rate = 1.0 + config.profiler_class = Sentry::Vernier::Profiler + end + ``` ### Internal From d56c2bbb481d0a0956c4d7dc47b75c23b93301ee Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Mon, 7 Oct 2024 13:00:17 +0000 Subject: [PATCH 54/96] release: 5.21.0 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index 69dc33410..e9d6999c6 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -2,6 +2,6 @@ module Sentry module DelayedJob - VERSION = "5.20.1" + VERSION = "5.21.0" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index cd55d35dd..fc6a50341 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.1" + spec.add_dependency "sentry-ruby", "~> 5.21.0" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index 2caed2fa7..d9e8b1083 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.20.1" + VERSION = "5.21.0" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 2418bd47d..516908891 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.1" + spec.add_dependency "sentry-ruby", "~> 5.21.0" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index 3d1dc210e..f234ea7ea 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -2,6 +2,6 @@ module Sentry module Rails - VERSION = "5.20.1" + VERSION = "5.21.0" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 8c47f981d..ebb19c1b0 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -31,5 +31,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.20.1" + spec.add_dependency "sentry-ruby", "~> 5.21.0" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index 8ecd6cfe4..e8e9d7466 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -2,6 +2,6 @@ module Sentry module Resque - VERSION = "5.20.1" + VERSION = "5.21.0" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 4ce4a7ea8..1f5dd7085 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.1" + spec.add_dependency "sentry-ruby", "~> 5.21.0" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index 212678965..cb7b82b61 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.20.1" + VERSION = "5.21.0" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index 7fd496062..5028b6c59 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -2,6 +2,6 @@ module Sentry module Sidekiq - VERSION = "5.20.1" + VERSION = "5.21.0" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index fe8a94595..375ec153c 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.20.1" + spec.add_dependency "sentry-ruby", "~> 5.21.0" spec.add_dependency "sidekiq", ">= 3.0" end From 499cbac2cf7a22c4f0607abeb77b2f658e677fd4 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 10 Oct 2024 17:48:52 +0200 Subject: [PATCH 55/96] RSpec matchers (#2424) --- CHANGELOG.md | 6 + sentry-ruby/lib/sentry/rspec.rb | 91 +++++++++++++ .../spec/sentry/rspec/matchers_spec.rb | 123 ++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 sentry-ruby/lib/sentry/rspec.rb create mode 100644 sentry-ruby/spec/sentry/rspec/matchers_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index eaff67e9a..7c7c3e2c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Features + +- Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) + ## 5.21.0 ### Features diff --git a/sentry-ruby/lib/sentry/rspec.rb b/sentry-ruby/lib/sentry/rspec.rb new file mode 100644 index 000000000..9c7c49730 --- /dev/null +++ b/sentry-ruby/lib/sentry/rspec.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +RSpec::Matchers.define :include_sentry_event do |event_message = "", **opts| + match do |sentry_events| + @expected_exception = expected_exception(**opts) + @context = context(**opts) + @tags = tags(**opts) + + @expected_event = expected_event(event_message) + @matched_event = find_matched_event(event_message, sentry_events) + + return false unless @matched_event + + [verify_context(), verify_tags()].all? + end + + chain :with_context do |context| + @context = context + end + + chain :with_tags do |tags| + @tags = tags + end + + failure_message do |sentry_events| + info = ["Failed to find event matching:\n"] + info << " message: #{@expected_event.message.inspect}" + info << " exception: #{@expected_exception.inspect}" + info << " context: #{@context.inspect}" + info << " tags: #{@tags.inspect}" + info << "\n" + info << "Captured events:\n" + info << dump_events(sentry_events) + info.join("\n") + end + + def expected_event(event_message) + if @expected_exception + Sentry.get_current_client.event_from_exception(@expected_exception) + else + Sentry.get_current_client.event_from_message(event_message) + end + end + + def expected_exception(**opts) + opts[:exception].new(opts[:message]) if opts[:exception] + end + + def context(**opts) + opts.fetch(:context, @context || {}) + end + + def tags(**opts) + opts.fetch(:tags, @tags || {}) + end + + def find_matched_event(event_message, sentry_events) + @matched_event ||= sentry_events + .find { |event| + if @expected_exception + # Is it OK that we only compare the first exception? + event_exception = event.exception.values.first + expected_event_exception = @expected_event.exception.values.first + + event_exception.type == expected_event_exception.type && event_exception.value == expected_event_exception.value + else + event.message == @expected_event.message + end + } + end + + def dump_events(sentry_events) + sentry_events.map(&Kernel.method(:Hash)).map do |hash| + hash.select { |k, _| [:message, :contexts, :tags, :exception].include?(k) } + end.map do |hash| + JSON.pretty_generate(hash) + end.join("\n\n") + end + + def verify_context + return true if @context.empty? + + @matched_event.contexts.any? { |key, value| value == @context[key] } + end + + def verify_tags + return true if @tags.empty? + + @tags.all? { |key, value| @matched_event.tags.include?(key) && @matched_event.tags[key] == value } + end +end diff --git a/sentry-ruby/spec/sentry/rspec/matchers_spec.rb b/sentry-ruby/spec/sentry/rspec/matchers_spec.rb new file mode 100644 index 000000000..45e914f52 --- /dev/null +++ b/sentry-ruby/spec/sentry/rspec/matchers_spec.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +require "spec_helper" +require "sentry/rspec" + +RSpec.describe "Sentry RSpec Matchers" do + include Sentry::TestHelper + + before do + # simulate normal user setup + Sentry.init do |config| + config.dsn = 'https://2fb45f003d054a7ea47feb45898f7649@o447951.ingest.sentry.io/5434472' + config.enabled_environments = ["production"] + config.environment = :test + end + + setup_sentry_test + end + + after do + teardown_sentry_test + end + + let(:exception) { StandardError.new("Gaah!") } + + describe "include_sentry_event" do + it "matches events with the given message" do + Sentry.capture_message("Ooops") + + expect(sentry_events).to include_sentry_event("Ooops") + end + + it "does not match events with a different message" do + Sentry.capture_message("Ooops") + + expect(sentry_events).not_to include_sentry_event("Different message") + end + + it "matches events with exception" do + Sentry.capture_exception(exception) + + expect(sentry_events).to include_sentry_event(exception: exception.class, message: exception.message) + end + + it "does not match events with different exception" do + exception = StandardError.new("Gaah!") + + Sentry.capture_exception(exception) + + expect(sentry_events).not_to include_sentry_event(exception: StandardError, message: "Oops!") + end + + it "matches events with context" do + Sentry.set_context("rails.error", { some: "stuff" }) + Sentry.capture_message("Ooops") + + expect(sentry_events).to include_sentry_event("Ooops") + .with_context("rails.error" => { some: "stuff" }) + end + + it "does not match events with different context" do + Sentry.set_context("rails.error", { some: "stuff" }) + Sentry.capture_message("Ooops") + + expect(sentry_events).not_to include_sentry_event("Ooops") + .with_context("rails.error" => { other: "data" }) + end + + it "matches events with tags" do + Sentry.set_tags(foo: "bar", baz: "qux") + Sentry.capture_message("Ooops") + + expect(sentry_events).to include_sentry_event("Ooops") + .with_tags({ foo: "bar", baz: "qux" }) + end + + it "does not match events with missing tags" do + Sentry.set_tags(foo: "bar") + Sentry.capture_message("Ooops") + + expect(sentry_events).not_to include_sentry_event("Ooops") + .with_tags({ foo: "bar", baz: "qux" }) + end + + it "matches error events with tags and context" do + Sentry.set_tags(foo: "bar", baz: "qux") + Sentry.set_context("rails.error", { some: "stuff" }) + + Sentry.capture_exception(exception) + + expect(sentry_events).to include_sentry_event(exception: exception.class, message: exception.message) + .with_tags({ foo: "bar", baz: "qux" }) + .with_context("rails.error" => { some: "stuff" }) + end + + it "matches error events with tags and context provided as arguments" do + Sentry.set_tags(foo: "bar", baz: "qux") + Sentry.set_context("rails.error", { some: "stuff" }) + + Sentry.capture_exception(exception) + + expect(sentry_events).to include_sentry_event( + exception: exception.class, + message: exception.message, + tags: { foo: "bar", baz: "qux" }, + context: { "rails.error" => { some: "stuff" } } + ) + end + + it "produces a useful failure message" do + Sentry.capture_message("Actual message") + + expect { + expect(sentry_events).to include_sentry_event("Expected message") + }.to raise_error(RSpec::Expectations::ExpectationNotMetError) do |error| + expect(error.message).to include("Failed to find event matching:") + expect(error.message).to include("message: \"Expected message\"") + expect(error.message).to include("Captured events:") + expect(error.message).to include("\"message\": \"Actual message\"") + end + end + end +end From f3ed31e4a1189d20ec761af79f82f002d85f328e Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 11 Oct 2024 16:21:05 +0200 Subject: [PATCH 56/96] Fix issues with stopping Vernier (#2429) --- CHANGELOG.md | 4 ++++ sentry-ruby/lib/sentry/vernier/profiler.rb | 9 +++++++-- sentry-ruby/spec/sentry/vernier/profiler_spec.rb | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c7c3e2c7..4adbcb093 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) +### Bug Fixes + +- Fix Vernier profiler not stopping when already stopped [#2429](https://github.com/getsentry/sentry-ruby/pull/2429) + ## 5.21.0 ### Features diff --git a/sentry-ruby/lib/sentry/vernier/profiler.rb b/sentry-ruby/lib/sentry/vernier/profiler.rb index 0ca8c0f39..6ee6b6ced 100644 --- a/sentry-ruby/lib/sentry/vernier/profiler.rb +++ b/sentry-ruby/lib/sentry/vernier/profiler.rb @@ -55,8 +55,7 @@ def start return unless @sampled return if @started - ::Vernier.start_profile - @started = true + @started = ::Vernier.start_profile log("Started") @@ -77,6 +76,12 @@ def stop @result = ::Vernier.stop_profile log("Stopped") + rescue RuntimeError => e + if e.message.include?("Profile not started") + log("Not stopped since not started") + else + log("Failed to stop Vernier: #{e.message}") + end end def active_thread_id diff --git a/sentry-ruby/spec/sentry/vernier/profiler_spec.rb b/sentry-ruby/spec/sentry/vernier/profiler_spec.rb index 03fe7ebde..46a696fee 100644 --- a/sentry-ruby/spec/sentry/vernier/profiler_spec.rb +++ b/sentry-ruby/spec/sentry/vernier/profiler_spec.rb @@ -133,6 +133,20 @@ expect(Vernier).to receive(:stop_profile) profiler.stop end + + it 'does not crash when Vernier was already stopped' do + profiler.set_initial_sample_decision(true) + profiler.start + Vernier.stop_profile + profiler.stop + end + + it 'does not crash when stopping Vernier crashed' do + profiler.set_initial_sample_decision(true) + profiler.start + expect(Vernier).to receive(:stop_profile).and_raise(RuntimeError.new("Profile not started")) + profiler.stop + end end describe "#to_hash" do From d134d9ec1276143517ded6351701f44257506911 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Wed, 16 Oct 2024 12:07:37 +0200 Subject: [PATCH 57/96] Fix bundle cache on CI (#2432) * Fix bundle cache on CI * [sidekiq] remove test run step from Makefile + restore bundle install * [resque] simplify running specs with/without Rails on CI --- .github/workflows/sentry_delayed_job_test.yml | 12 +++++++----- .github/workflows/sentry_opentelemetry_test.yml | 13 +++++++------ .github/workflows/sentry_rails_test.yml | 12 ++++++------ .github/workflows/sentry_resque_test.yml | 16 ++++++++-------- .github/workflows/sentry_ruby_test.yml | 15 +++++++-------- .github/workflows/sentry_sidekiq_test.yml | 13 ++++++++----- sentry-resque/Gemfile | 5 +++++ sentry-resque/Gemfile_with_rails.rb | 6 ------ sentry-sidekiq/Makefile | 4 ---- 9 files changed, 48 insertions(+), 48 deletions(-) delete mode 100644 sentry-resque/Gemfile_with_rails.rb diff --git a/.github/workflows/sentry_delayed_job_test.yml b/.github/workflows/sentry_delayed_job_test.yml index 206c6eeb7..d40cdfaa1 100644 --- a/.github/workflows/sentry_delayed_job_test.yml +++ b/.github/workflows/sentry_delayed_job_test.yml @@ -25,7 +25,12 @@ jobs: working-directory: sentry-delayed_job name: Ruby ${{ matrix.ruby_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest + env: + RUBYOPT: ${{ matrix.options.rubyopt }} + BUNDLE_GEMFILE: ${{ github.workspace }}/sentry-delayed_job/Gemfile + BUNDLE_WITHOUT: rubocop strategy: + fail-fast: false matrix: ruby_version: ${{ fromJson(needs.ruby-versions.outputs.versions) }} include: @@ -55,13 +60,10 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} + bundler-cache: true - name: Run specs - env: - RUBYOPT: ${{ matrix.options.rubyopt }} - run: | - bundle install --jobs 4 --retry 3 - bundle exec rake + run: bundle exec rake - name: Upload Coverage if: ${{ matrix.options.codecov }} diff --git a/.github/workflows/sentry_opentelemetry_test.yml b/.github/workflows/sentry_opentelemetry_test.yml index 1aba897ba..ddf480f2d 100644 --- a/.github/workflows/sentry_opentelemetry_test.yml +++ b/.github/workflows/sentry_opentelemetry_test.yml @@ -25,7 +25,13 @@ jobs: working-directory: sentry-opentelemetry name: Ruby ${{ matrix.ruby_version }} & OpenTelemetry ${{ matrix.opentelemetry_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest + env: + RUBYOPT: ${{ matrix.options.rubyopt }} + BUNDLE_GEMFILE: ${{ github.workspace }}/sentry-opentelemetry/Gemfile + BUNDLE_WITHOUT: rubocop + OPENTELEMETRY_VERSION: ${{ matrix.opentelemetry_version }} strategy: + fail-fast: false matrix: ruby_version: ${{ fromJson(needs.ruby-versions.outputs.versions) }} # opentelemetry_version: [1.2.0] @@ -48,12 +54,7 @@ jobs: bundler-cache: true - name: Run specs - env: - RUBYOPT: ${{ matrix.options.rubyopt }} - OPENTELEMETRY_VERSION: ${{ matrix.opentelemetry_version }} - run: | - bundle install --jobs 4 --retry 3 - bundle exec rake + run: bundle exec rake - name: Upload Coverage if: ${{ matrix.options.codecov }} diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index 9e1e55d8a..a38c7c398 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -19,6 +19,11 @@ jobs: working-directory: sentry-rails name: Ruby ${{ matrix.ruby_version }} & Rails ${{ matrix.rails_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest + env: + RUBYOPT: ${{ matrix.options.rubyopt }} + BUNDLE_GEMFILE: ${{ github.workspace }}/sentry-rails/Gemfile + BUNDLE_WITHOUT: rubocop + RAILS_VERSION: ${{ matrix.rails_version }} strategy: fail-fast: false matrix: @@ -75,12 +80,7 @@ jobs: bundler-cache: true - name: Build with Rails ${{ matrix.rails_version }} - env: - RAILS_VERSION: ${{ matrix.rails_version }} - RUBYOPT: ${{ matrix.options.rubyopt }} - run: | - bundle install --jobs 4 --retry 3 - bundle exec rake + run: bundle exec rake - name: Upload Coverage if: ${{ matrix.options.codecov }} diff --git a/.github/workflows/sentry_resque_test.yml b/.github/workflows/sentry_resque_test.yml index bdd71e6ce..548410413 100644 --- a/.github/workflows/sentry_resque_test.yml +++ b/.github/workflows/sentry_resque_test.yml @@ -25,7 +25,12 @@ jobs: working-directory: sentry-resque name: Ruby ${{ matrix.ruby_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest + env: + RUBYOPT: ${{ matrix.options.rubyopt }} + BUNDLE_GEMFILE: ${{ github.workspace }}/sentry-resque/Gemfile + BUNDLE_WITHOUT: rubocop strategy: + fail-fast: false matrix: ruby_version: ${{ fromJson(needs.ruby-versions.outputs.versions) }} include: @@ -50,20 +55,15 @@ jobs: with: redis-version: 5 - - name: Run specs + - name: Run specs without Rails env: RUBYOPT: ${{ matrix.options.rubyopt }} - run: | - bundle install --jobs 4 --retry 3 - bundle exec rake + run: BUNDLE_WITHOUT="rubocop rails" bundle exec rake - name: Run specs with Rails env: - BUNDLE_GEMFILE: Gemfile_with_rails.rb RUBYOPT: ${{ matrix.options.rubyopt }} - run: | - bundle install --jobs 4 --retry 3 - bundle exec rake + run: bundle exec rake - name: Upload Coverage if: ${{ matrix.options.codecov }} diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index bc6a1ad64..51fa25493 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -26,6 +26,12 @@ jobs: name: Ruby ${{ matrix.ruby_version }} & Rack ${{ matrix.rack_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest timeout-minutes: 10 + env: + RUBYOPT: ${{ matrix.options.rubyopt }} + BUNDLE_GEMFILE: ${{ github.workspace }}/sentry-ruby/Gemfile + BUNDLE_WITHOUT: rubocop + RACK_VERSION: ${{ matrix.rack_version }} + REDIS_RB_VERSION: ${{ matrix.redis_rb_version }} strategy: fail-fast: false matrix: @@ -69,14 +75,7 @@ jobs: redis-version: 6 - name: Run specs with Rack ${{ matrix.rack_version }} and redis-rb ${{ matrix.redis_rb_version }} - env: - RUBYOPT: ${{ matrix.options.rubyopt }} - RACK_VERSION: ${{ matrix.rack_version }} - REDIS_RB_VERSION: ${{ matrix.redis_rb_version }} - run: | - bundle config set without 'rubocop' - bundle install --jobs 4 --retry 3 - bundle exec rake + run: bundle exec rake - name: Upload Coverage if: ${{ matrix.options.codecov }} diff --git a/.github/workflows/sentry_sidekiq_test.yml b/.github/workflows/sentry_sidekiq_test.yml index 06bb45a9d..d472492f0 100644 --- a/.github/workflows/sentry_sidekiq_test.yml +++ b/.github/workflows/sentry_sidekiq_test.yml @@ -19,7 +19,13 @@ jobs: working-directory: sentry-sidekiq name: Ruby ${{ matrix.ruby_version }} & Sidekiq ${{ matrix.sidekiq_version }}, options - ${{ toJson(matrix.options) }} runs-on: ubuntu-latest + env: + RUBYOPT: ${{ matrix.options.rubyopt }} + BUNDLE_GEMFILE: ${{ github.workspace }}/sentry-sidekiq/Gemfile + BUNDLE_WITHOUT: rubocop + SIDEKIQ_VERSION: ${{ matrix.sidekiq_version }} strategy: + fail-fast: false matrix: sidekiq_version: ["5.0", "6.5", "7.0"] ruby_version: ["2.7", "3.0", "3.1", "3.2", "3.3", jruby] @@ -61,11 +67,8 @@ jobs: - name: Run specs with Sidekiq ${{ matrix.sidekiq_version }} env: - SIDEKIQ_VERSION: ${{ matrix.sidekiq_version }} - RUBYOPT: ${{ matrix.options.rubyopt }} - run: | - bundle install --jobs 4 --retry 3 - make test + WITH_SENTRY_RAILS: 1 + run: bundle exec rake - name: Upload Coverage if: ${{ matrix.options.codecov }} diff --git a/sentry-resque/Gemfile b/sentry-resque/Gemfile index 96f47a3a5..5819261e7 100644 --- a/sentry-resque/Gemfile +++ b/sentry-resque/Gemfile @@ -10,3 +10,8 @@ gem "sentry-ruby", path: "../sentry-ruby" gem "resque-retry", "~> 1.8" eval_gemfile File.expand_path("../Gemfile", __dir__) + +group :rails do + gem "sentry-rails", path: "../sentry-rails" + gem "rails" +end diff --git a/sentry-resque/Gemfile_with_rails.rb b/sentry-resque/Gemfile_with_rails.rb deleted file mode 100644 index 306b36624..000000000 --- a/sentry-resque/Gemfile_with_rails.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -eval_gemfile File.expand_path("Gemfile", __dir__) - -gem "sentry-rails", path: "../sentry-rails" -gem "rails" diff --git a/sentry-sidekiq/Makefile b/sentry-sidekiq/Makefile index 63010b098..62ad039eb 100644 --- a/sentry-sidekiq/Makefile +++ b/sentry-sidekiq/Makefile @@ -1,7 +1,3 @@ build: bundle install gem build sentry-sidekiq.gemspec - -test: - WITH_SENTRY_RAILS=1 bundle exec rspec spec/sentry/rails_spec.rb - bundle exec rspec From 76ede8735759e3f3312b61e09f58df0f97400f97 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 17 Oct 2024 11:40:59 +0200 Subject: [PATCH 58/96] Upload coverage from all test runs (#2430) --- .github/workflows/sentry_opentelemetry_test.yml | 2 -- .github/workflows/sentry_rails_test.yml | 4 +--- .github/workflows/sentry_resque_test.yml | 2 -- .github/workflows/sentry_ruby_test.yml | 4 +--- .github/workflows/sentry_sidekiq_test.yml | 4 +--- 5 files changed, 3 insertions(+), 13 deletions(-) diff --git a/.github/workflows/sentry_opentelemetry_test.yml b/.github/workflows/sentry_opentelemetry_test.yml index ddf480f2d..2f377894f 100644 --- a/.github/workflows/sentry_opentelemetry_test.yml +++ b/.github/workflows/sentry_opentelemetry_test.yml @@ -43,7 +43,6 @@ jobs: rubyopt: "--enable-frozen-string-literal --debug=frozen-string-literal", }, } - - { ruby_version: 3.2, options: { codecov: 1 } } steps: - uses: actions/checkout@v1 @@ -57,7 +56,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - if: ${{ matrix.options.codecov }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index a38c7c398..ed32ab477 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -62,8 +62,7 @@ jobs: } - { ruby_version: "3.2", - rails_version: 7.1.0, - options: { codecov: 1 }, + rails_version: 7.1.0 } steps: - uses: actions/checkout@v1 @@ -83,7 +82,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - if: ${{ matrix.options.codecov }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_resque_test.yml b/.github/workflows/sentry_resque_test.yml index 548410413..015a1bcce 100644 --- a/.github/workflows/sentry_resque_test.yml +++ b/.github/workflows/sentry_resque_test.yml @@ -41,7 +41,6 @@ jobs: rubyopt: "--enable-frozen-string-literal --debug=frozen-string-literal", }, } - - { ruby_version: "3.2", options: { codecov: 1 } } steps: - uses: actions/checkout@v1 - name: Set up Ruby ${{ matrix.ruby_version }} @@ -66,7 +65,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - if: ${{ matrix.options.codecov }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index 51fa25493..60fa831f5 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -57,8 +57,7 @@ jobs: - { ruby_version: 3.3, rack_version: 3.1, - redis_rb_version: 5.3, - options: { codecov: 1 }, + redis_rb_version: 5.3 } steps: - uses: actions/checkout@v1 @@ -78,7 +77,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - if: ${{ matrix.options.codecov }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_sidekiq_test.yml b/.github/workflows/sentry_sidekiq_test.yml index d472492f0..7b7768069 100644 --- a/.github/workflows/sentry_sidekiq_test.yml +++ b/.github/workflows/sentry_sidekiq_test.yml @@ -48,8 +48,7 @@ jobs: } - { ruby_version: "3.2", - sidekiq_version: 7.0, - options: { codecov: 1 }, + sidekiq_version: 7.0 } steps: - uses: actions/checkout@v1 @@ -71,7 +70,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - if: ${{ matrix.options.codecov }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} From 03293ef68db2fabfec61d04d8c3df5d8c4141222 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 17 Oct 2024 12:13:28 +0200 Subject: [PATCH 59/96] [rails] disable eager loading in make_basic_app (#2434) --- sentry-rails/spec/dummy/test_rails_app/app.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-rails/spec/dummy/test_rails_app/app.rb b/sentry-rails/spec/dummy/test_rails_app/app.rb index 95309fbaa..7b7e926ba 100644 --- a/sentry-rails/spec/dummy/test_rails_app/app.rb +++ b/sentry-rails/spec/dummy/test_rails_app/app.rb @@ -56,7 +56,7 @@ def self.name app.config.hosts = nil app.config.secret_key_base = "test" app.config.logger = ActiveSupport::Logger.new(nil) - app.config.eager_load = true + app.config.eager_load = false app.config.active_job.queue_adapter = :test # Eager load namespaces can be accumulated after repeated initializations and make initialization From 2ff68a791ffca5c08fbcfb01993757920f46484c Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 18 Oct 2024 13:58:03 +0200 Subject: [PATCH 60/96] Fix ignoring spec files in codecov (#2437) --- codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 3dd8085c8..03096bfb1 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,7 +1,7 @@ codecov: disable_default_path_fixes: true ignore: - - "**/spec" + - "**/spec/**" comment: layout: "header, diff, flags, components, tree" component_management: From ee37a4a6bfa1b8ad2c5536a399995b92b451a4ba Mon Sep 17 00:00:00 2001 From: Frederik Spang Date: Fri, 18 Oct 2024 23:27:23 +0200 Subject: [PATCH 61/96] Add ActiveSupport for cache module (#2380) --- CHANGELOG.md | 2 + .../lib/sentry/rails/configuration.rb | 2 + .../tracing/active_support_subscriber.rb | 63 +++++++ sentry-rails/spec/dummy/test_rails_app/app.rb | 2 + .../spec/sentry/rails/configuration_spec.rb | 4 +- .../tracing/active_support_subscriber_spec.rb | 176 ++++++++++++++++++ 6 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 sentry-rails/lib/sentry/rails/tracing/active_support_subscriber.rb create mode 100644 sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 4adbcb093..b8b49da70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ### Features - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) +- Add support for Sentry Cache instrumentation, when using Rails.cache ([#2380](https://github.com/getsentry/sentry-ruby/pull/2380)) (MemoryStore and FileStore require Rails 8.0+) + ### Bug Fixes diff --git a/sentry-rails/lib/sentry/rails/configuration.rb b/sentry-rails/lib/sentry/rails/configuration.rb index 2e4591947..a28a07f69 100644 --- a/sentry-rails/lib/sentry/rails/configuration.rb +++ b/sentry-rails/lib/sentry/rails/configuration.rb @@ -4,6 +4,7 @@ require "sentry/rails/tracing/action_view_subscriber" require "sentry/rails/tracing/active_record_subscriber" require "sentry/rails/tracing/active_storage_subscriber" +require "sentry/rails/tracing/active_support_subscriber" module Sentry class Configuration @@ -164,6 +165,7 @@ def initialize end @tracing_subscribers = Set.new([ Sentry::Rails::Tracing::ActionViewSubscriber, + Sentry::Rails::Tracing::ActiveSupportSubscriber, Sentry::Rails::Tracing::ActiveRecordSubscriber, Sentry::Rails::Tracing::ActiveStorageSubscriber ]) diff --git a/sentry-rails/lib/sentry/rails/tracing/active_support_subscriber.rb b/sentry-rails/lib/sentry/rails/tracing/active_support_subscriber.rb new file mode 100644 index 000000000..e19c22245 --- /dev/null +++ b/sentry-rails/lib/sentry/rails/tracing/active_support_subscriber.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require "sentry/rails/tracing/abstract_subscriber" + +module Sentry + module Rails + module Tracing + class ActiveSupportSubscriber < AbstractSubscriber + READ_EVENT_NAMES = %w[ + cache_read.active_support + ].freeze + + WRITE_EVENT_NAMES = %w[ + cache_write.active_support + cache_increment.active_support + cache_decrement.active_support + ].freeze + + REMOVE_EVENT_NAMES = %w[ + cache_delete.active_support + ].freeze + + FLUSH_EVENT_NAMES = %w[ + cache_prune.active_support + ].freeze + + EVENT_NAMES = READ_EVENT_NAMES + WRITE_EVENT_NAMES + REMOVE_EVENT_NAMES + FLUSH_EVENT_NAMES + + SPAN_ORIGIN = "auto.cache.rails" + + def self.subscribe! + subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload| + record_on_current_span( + op: operation_name(event_name), + origin: SPAN_ORIGIN, + start_timestamp: payload[START_TIMESTAMP_NAME], + description: payload[:store], + duration: duration + ) do |span| + span.set_data("cache.key", [*payload[:key]].select { |key| Utils::EncodingHelper.valid_utf_8?(key) }) + span.set_data("cache.hit", payload[:hit] == true) # Handle nil case + end + end + end + + def self.operation_name(event_name) + case + when READ_EVENT_NAMES.include?(event_name) + "cache.get" + when WRITE_EVENT_NAMES.include?(event_name) + "cache.put" + when REMOVE_EVENT_NAMES.include?(event_name) + "cache.remove" + when FLUSH_EVENT_NAMES.include?(event_name) + "cache.flush" + else + "other" + end + end + end + end + end +end diff --git a/sentry-rails/spec/dummy/test_rails_app/app.rb b/sentry-rails/spec/dummy/test_rails_app/app.rb index 7b7e926ba..4a807f587 100644 --- a/sentry-rails/spec/dummy/test_rails_app/app.rb +++ b/sentry-rails/spec/dummy/test_rails_app/app.rb @@ -58,6 +58,8 @@ def self.name app.config.logger = ActiveSupport::Logger.new(nil) app.config.eager_load = false app.config.active_job.queue_adapter = :test + app.config.cache_store = :memory_store + app.config.action_controller.perform_caching = true # Eager load namespaces can be accumulated after repeated initializations and make initialization # slower after each run diff --git a/sentry-rails/spec/sentry/rails/configuration_spec.rb b/sentry-rails/spec/sentry/rails/configuration_spec.rb index 76a8c7546..37c5a41d6 100644 --- a/sentry-rails/spec/sentry/rails/configuration_spec.rb +++ b/sentry-rails/spec/sentry/rails/configuration_spec.rb @@ -25,12 +25,12 @@ class MySubscriber; end it "returns the default subscribers" do - expect(subject.tracing_subscribers.size).to eq(3) + expect(subject.tracing_subscribers.size).to eq(4) end it "is customizable" do subject.tracing_subscribers << MySubscriber - expect(subject.tracing_subscribers.size).to eq(4) + expect(subject.tracing_subscribers.size).to eq(5) end it "is replaceable" do diff --git a/sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb new file mode 100644 index 000000000..951ebb212 --- /dev/null +++ b/sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb @@ -0,0 +1,176 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe Sentry::Rails::Tracing::ActiveSupportSubscriber, :subscriber, type: :request do + let(:transport) do + Sentry.get_current_client.transport + end + + context "when transaction is sampled" do + before do + make_basic_app do |config, app| + config.traces_sample_rate = 1.0 + config.rails.tracing_subscribers = [described_class] + end + end + + it "tracks cache write" do + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + + Rails.cache.write("my_cache_key", "my_cache_value") + transaction.finish + + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + + expect(cache_transaction[:spans].count).to eq(1) + expect(cache_transaction[:spans][0][:op]).to eq("cache.put") + expect(cache_transaction[:spans][0][:origin]).to eq("auto.cache.rails") + end + + # + it "tracks cache increment" do + skip("Tracks on Rails 8.0 for all Cache Stores; Until then only MemCached and Redis Stores.") if Rails.version.to_f < 8.0 + + Rails.cache.write("my_cache_key", 0) + + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + Rails.cache.increment("my_cache_key") + + transaction.finish + + expect(Rails.cache.read("my_cache_key")).to eq(1) + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + expect(cache_transaction[:spans].count).to eq(2) + expect(cache_transaction[:spans][1][:op]).to eq("cache.put") + expect(cache_transaction[:spans][1][:origin]).to eq("auto.cache.rails") + end + + # + it "tracks cache decrement" do + skip("Tracks on Rails 8.0 for all Cache Stores; Until then only MemCached and Redis Stores.") if Rails.version.to_f < 8.0 + + Rails.cache.write("my_cache_key", 0) + + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + Rails.cache.decrement("my_cache_key") + + transaction.finish + + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + expect(cache_transaction[:spans].count).to eq(2) + expect(cache_transaction[:spans][1][:op]).to eq("cache.put") + expect(cache_transaction[:spans][1][:origin]).to eq("auto.cache.rails") + end + + it "tracks cache read" do + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + Rails.cache.read("my_cache_key") + + transaction.finish + + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + expect(cache_transaction[:spans].count).to eq(1) + expect(cache_transaction[:spans][0][:op]).to eq("cache.get") + expect(cache_transaction[:spans][0][:origin]).to eq("auto.cache.rails") + end + + it "tracks cache delete" do + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + + Rails.cache.read("my_cache_key") + + transaction.finish + + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + expect(cache_transaction[:spans].count).to eq(1) + expect(cache_transaction[:spans][0][:op]).to eq("cache.get") + expect(cache_transaction[:spans][0][:origin]).to eq("auto.cache.rails") + end + it "tracks cache prune" do + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + + Rails.cache.write("my_cache_key", 123, expires_in: 0.seconds) + + Rails.cache.prune(0) + + transaction.finish + + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + expect(cache_transaction[:spans].count).to eq(2) + expect(cache_transaction[:spans][1][:op]).to eq("cache.flush") + expect(cache_transaction[:spans][1][:origin]).to eq("auto.cache.rails") + end + + it "tracks sets cache hit" do + skip("cache.hit is unset on Rails 6.0.x.") if Rails.version.to_i == 6 + + Rails.cache.write("my_cache_key", "my_cache_value") + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + Rails.cache.read("my_cache_key") + Rails.cache.read("my_cache_key_non_existing") + + transaction.finish + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + expect(cache_transaction[:spans].count).to eq(2) + expect(cache_transaction[:spans][0][:op]).to eq("cache.get") + expect(cache_transaction[:spans][0][:origin]).to eq("auto.cache.rails") + expect(cache_transaction[:spans][0][:data]['cache.key']).to eq(["my_cache_key"]) + expect(cache_transaction[:spans][0][:data]['cache.hit']).to eq(true) + + expect(cache_transaction[:spans][1][:op]).to eq("cache.get") + expect(cache_transaction[:spans][1][:origin]).to eq("auto.cache.rails") + expect(cache_transaction[:spans][1][:data]['cache.key']).to eq(["my_cache_key_non_existing"]) + expect(cache_transaction[:spans][1][:data]['cache.hit']).to eq(false) + end + + it "tracks cache delete" do + Rails.cache.write("my_cache_key", "my_cache_value") + transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) + Sentry.get_current_scope.set_span(transaction) + Rails.cache.delete("my_cache_key") + + transaction.finish + expect(transport.events.count).to eq(1) + cache_transaction = transport.events.first.to_hash + expect(cache_transaction[:type]).to eq("transaction") + expect(cache_transaction[:spans].count).to eq(1) + expect(cache_transaction[:spans][0][:op]).to eq("cache.remove") + expect(cache_transaction[:spans][0][:origin]).to eq("auto.cache.rails") + expect(cache_transaction[:spans][0][:data]['cache.key']).to eq(["my_cache_key"]) + end + end + + context "when transaction is not sampled" do + before do + make_basic_app + end + + it "doesn't record spans" do + Rails.cache.write("my_cache_key", "my_cache_value") + + expect(transport.events.count).to eq(0) + end + end +end From b4bbed225a3e7ec0607629909896eb5d14e6bda3 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Sun, 20 Oct 2024 22:55:59 +0200 Subject: [PATCH 62/96] Enforce latest rubygems on CI (#2439) --- .github/workflows/sentry_delayed_job_test.yml | 1 + .github/workflows/sentry_opentelemetry_test.yml | 1 + .github/workflows/sentry_rails_test.yml | 1 + .github/workflows/sentry_resque_test.yml | 1 + .github/workflows/sentry_ruby_test.yml | 1 + .github/workflows/sentry_sidekiq_test.yml | 3 ++- sentry-sidekiq/spec/spec_helper.rb | 2 ++ 7 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sentry_delayed_job_test.yml b/.github/workflows/sentry_delayed_job_test.yml index d40cdfaa1..4f0e9c27e 100644 --- a/.github/workflows/sentry_delayed_job_test.yml +++ b/.github/workflows/sentry_delayed_job_test.yml @@ -60,6 +60,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} + rubygems: latest bundler-cache: true - name: Run specs diff --git a/.github/workflows/sentry_opentelemetry_test.yml b/.github/workflows/sentry_opentelemetry_test.yml index 2f377894f..dd464cb41 100644 --- a/.github/workflows/sentry_opentelemetry_test.yml +++ b/.github/workflows/sentry_opentelemetry_test.yml @@ -50,6 +50,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} + rubygems: latest bundler-cache: true - name: Run specs diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index ed32ab477..228e6b03f 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -76,6 +76,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} + rubygems: latest bundler-cache: true - name: Build with Rails ${{ matrix.rails_version }} diff --git a/.github/workflows/sentry_resque_test.yml b/.github/workflows/sentry_resque_test.yml index 015a1bcce..2507cbdcd 100644 --- a/.github/workflows/sentry_resque_test.yml +++ b/.github/workflows/sentry_resque_test.yml @@ -47,6 +47,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} + rubygems: latest bundler-cache: true - name: Start Redis diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index 60fa831f5..dc7292f38 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -66,6 +66,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} + rubygems: latest bundler-cache: true - name: Start Redis diff --git a/.github/workflows/sentry_sidekiq_test.yml b/.github/workflows/sentry_sidekiq_test.yml index 7b7768069..5dd8b1011 100644 --- a/.github/workflows/sentry_sidekiq_test.yml +++ b/.github/workflows/sentry_sidekiq_test.yml @@ -36,7 +36,7 @@ jobs: - { ruby_version: 2.6, sidekiq_version: 5.0 } - { ruby_version: 2.6, sidekiq_version: 6.0 } - { ruby_version: jruby, sidekiq_version: 5.0 } - - { ruby_version: jruby, sidekiq_version: 6.0 } + - { ruby_version: jruby, sidekiq_version: 6.5 } - { ruby_version: jruby, sidekiq_version: 7.0 } - { ruby_version: "3.2", @@ -57,6 +57,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} + rubygems: latest bundler-cache: true - name: Start Redis diff --git a/sentry-sidekiq/spec/spec_helper.rb b/sentry-sidekiq/spec/spec_helper.rb index 5e1e6a6e9..9d6b122b6 100644 --- a/sentry-sidekiq/spec/spec_helper.rb +++ b/sentry-sidekiq/spec/spec_helper.rb @@ -6,6 +6,8 @@ rescue LoadError end +require "sidekiq" + # this enables sidekiq's server mode require "sidekiq/cli" From 957c8d6280567865e9155d30a6a9f4e7e5945645 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Sun, 20 Oct 2024 23:45:24 +0200 Subject: [PATCH 63/96] Make Sentry.{close,get_main_hub} thread-safe (#2436) --- sentry-ruby/lib/sentry-ruby.rb | 10 +++++++--- sentry-sidekiq/Gemfile | 3 --- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sentry-ruby/lib/sentry-ruby.rb b/sentry-ruby/lib/sentry-ruby.rb index 6dcf99671..4ebf5b299 100644 --- a/sentry-ruby/lib/sentry-ruby.rb +++ b/sentry-ruby/lib/sentry-ruby.rb @@ -50,6 +50,8 @@ module Sentry THREAD_LOCAL = :sentry_hub + MUTEX = Mutex.new + class << self # @!visibility private def exception_locals_tp @@ -275,8 +277,10 @@ def close @background_worker.shutdown - @main_hub = nil - Thread.current.thread_variable_set(THREAD_LOCAL, nil) + MUTEX.synchronize do + @main_hub = nil + Thread.current.thread_variable_set(THREAD_LOCAL, nil) + end end # Returns true if the SDK is initialized. @@ -303,7 +307,7 @@ def csp_report_uri # # @return [Hub] def get_main_hub - @main_hub + MUTEX.synchronize { @main_hub } end # Takes an instance of Sentry::Breadcrumb and stores it to the current active scope. diff --git a/sentry-sidekiq/Gemfile b/sentry-sidekiq/Gemfile index c158e85dc..c860cb206 100644 --- a/sentry-sidekiq/Gemfile +++ b/sentry-sidekiq/Gemfile @@ -12,9 +12,6 @@ gem "sentry-rails", path: "../sentry-rails" # loofah changed the required ruby version in a patch so we need to explicitly pin it gem "loofah", "2.20.0" if RUBY_VERSION.to_f < 2.5 -# For https://github.com/ruby/psych/issues/655 -gem "psych", "5.1.0" - sidekiq_version = ENV["SIDEKIQ_VERSION"] sidekiq_version = "7.0" if sidekiq_version.nil? sidekiq_version = Gem::Version.new(sidekiq_version) From 1c431f07f489be355e081cd2f78b6f5cbf98a9ea Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Tue, 22 Oct 2024 16:33:31 +0200 Subject: [PATCH 64/96] Revert "Enforce latest rubygems on CI (#2439)" (#2441) This reverts commit b4bbed225a3e7ec0607629909896eb5d14e6bda3. --- .github/workflows/sentry_delayed_job_test.yml | 1 - .github/workflows/sentry_opentelemetry_test.yml | 1 - .github/workflows/sentry_rails_test.yml | 1 - .github/workflows/sentry_resque_test.yml | 1 - .github/workflows/sentry_ruby_test.yml | 1 - .github/workflows/sentry_sidekiq_test.yml | 3 +-- sentry-sidekiq/spec/spec_helper.rb | 2 -- 7 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/sentry_delayed_job_test.yml b/.github/workflows/sentry_delayed_job_test.yml index 4f0e9c27e..d40cdfaa1 100644 --- a/.github/workflows/sentry_delayed_job_test.yml +++ b/.github/workflows/sentry_delayed_job_test.yml @@ -60,7 +60,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} - rubygems: latest bundler-cache: true - name: Run specs diff --git a/.github/workflows/sentry_opentelemetry_test.yml b/.github/workflows/sentry_opentelemetry_test.yml index dd464cb41..2f377894f 100644 --- a/.github/workflows/sentry_opentelemetry_test.yml +++ b/.github/workflows/sentry_opentelemetry_test.yml @@ -50,7 +50,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} - rubygems: latest bundler-cache: true - name: Run specs diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index 228e6b03f..ed32ab477 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -76,7 +76,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} - rubygems: latest bundler-cache: true - name: Build with Rails ${{ matrix.rails_version }} diff --git a/.github/workflows/sentry_resque_test.yml b/.github/workflows/sentry_resque_test.yml index 2507cbdcd..015a1bcce 100644 --- a/.github/workflows/sentry_resque_test.yml +++ b/.github/workflows/sentry_resque_test.yml @@ -47,7 +47,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} - rubygems: latest bundler-cache: true - name: Start Redis diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index dc7292f38..60fa831f5 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -66,7 +66,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} - rubygems: latest bundler-cache: true - name: Start Redis diff --git a/.github/workflows/sentry_sidekiq_test.yml b/.github/workflows/sentry_sidekiq_test.yml index 5dd8b1011..7b7768069 100644 --- a/.github/workflows/sentry_sidekiq_test.yml +++ b/.github/workflows/sentry_sidekiq_test.yml @@ -36,7 +36,7 @@ jobs: - { ruby_version: 2.6, sidekiq_version: 5.0 } - { ruby_version: 2.6, sidekiq_version: 6.0 } - { ruby_version: jruby, sidekiq_version: 5.0 } - - { ruby_version: jruby, sidekiq_version: 6.5 } + - { ruby_version: jruby, sidekiq_version: 6.0 } - { ruby_version: jruby, sidekiq_version: 7.0 } - { ruby_version: "3.2", @@ -57,7 +57,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} - rubygems: latest bundler-cache: true - name: Start Redis diff --git a/sentry-sidekiq/spec/spec_helper.rb b/sentry-sidekiq/spec/spec_helper.rb index 9d6b122b6..5e1e6a6e9 100644 --- a/sentry-sidekiq/spec/spec_helper.rb +++ b/sentry-sidekiq/spec/spec_helper.rb @@ -6,8 +6,6 @@ rescue LoadError end -require "sidekiq" - # this enables sidekiq's server mode require "sidekiq/cli" From 9bba2ef0a8ef14fa6df8a8a1e5f61e5589375b16 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 22 Oct 2024 17:27:10 +0200 Subject: [PATCH 65/96] Fix send_default_pii handling in rails controller spans (#2443) The change in #1793 accidentally exposed params always in the controller action span. This change now respects both `Rails.config.filter_parameters` and `Sentry.coniguration.send_default_pii` together to decide what to send. --- CHANGELOG.md | 5 +- .../sentry/rails/controller_transaction.rb | 6 ++- sentry-rails/spec/dummy/test_rails_app/app.rb | 1 + .../spec/sentry/rails/tracing_spec.rb | 46 +++++++++++++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8b49da70..a9dc18876 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,15 @@ ### Features - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) -- Add support for Sentry Cache instrumentation, when using Rails.cache ([#2380](https://github.com/getsentry/sentry-ruby/pull/2380)) (MemoryStore and FileStore require Rails 8.0+) +- Add support for Sentry Cache instrumentation, when using Rails.cache [#2380](https://github.com/getsentry/sentry-ruby/pull/2380) + Note: MemoryStore and FileStore require Rails 8.0+ ### Bug Fixes - Fix Vernier profiler not stopping when already stopped [#2429](https://github.com/getsentry/sentry-ruby/pull/2429) +- Fix `send_default_pii` handling in rails controller spans [#2443](https://github.com/getsentry/sentry-ruby/pull/2443) + - Fixes [#2438](https://github.com/getsentry/sentry-ruby/issues/2438) ## 5.21.0 diff --git a/sentry-rails/lib/sentry/rails/controller_transaction.rb b/sentry-rails/lib/sentry/rails/controller_transaction.rb index 8f19bb63d..a753f06d7 100644 --- a/sentry-rails/lib/sentry/rails/controller_transaction.rb +++ b/sentry-rails/lib/sentry/rails/controller_transaction.rb @@ -23,8 +23,10 @@ def sentry_around_action child_span.set_http_status(response.status) child_span.set_data(:format, request.format) child_span.set_data(:method, request.method) - child_span.set_data(:path, request.path) - child_span.set_data(:params, request.params) + + pii = Sentry.configuration.send_default_pii + child_span.set_data(:path, pii ? request.fullpath : request.filtered_path) + child_span.set_data(:params, pii ? request.params : request.filtered_parameters) end result diff --git a/sentry-rails/spec/dummy/test_rails_app/app.rb b/sentry-rails/spec/dummy/test_rails_app/app.rb index 4a807f587..5b1bd82a9 100644 --- a/sentry-rails/spec/dummy/test_rails_app/app.rb +++ b/sentry-rails/spec/dummy/test_rails_app/app.rb @@ -60,6 +60,7 @@ def self.name app.config.active_job.queue_adapter = :test app.config.cache_store = :memory_store app.config.action_controller.perform_caching = true + app.config.filter_parameters += [:password, :secret] # Eager load namespaces can be accumulated after repeated initializations and make initialization # slower after each run diff --git a/sentry-rails/spec/sentry/rails/tracing_spec.rb b/sentry-rails/spec/sentry/rails/tracing_spec.rb index 927e11c8e..36063f39d 100644 --- a/sentry-rails/spec/sentry/rails/tracing_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing_spec.rb @@ -106,6 +106,52 @@ end end + describe "filtering pii data" do + context "with send_default_pii = false" do + before do + make_basic_app do |config| + config.traces_sample_rate = 1.0 + config.send_default_pii = false + end + end + + it "does not record sensitive params" do + get "/posts?foo=bar&password=42&secret=baz" + transaction = transport.events.last.to_hash + + params = transaction[:spans][0][:data][:params] + expect(params["foo"]).to eq("bar") + expect(params["password"]).to eq("[FILTERED]") + expect(params["secret"]).to eq("[FILTERED]") + + path = transaction[:spans][0][:data][:path] + expect(path).to eq("/posts?foo=bar&password=[FILTERED]&secret=[FILTERED]") + end + end + + context "with send_default_pii = true" do + before do + make_basic_app do |config| + config.traces_sample_rate = 1.0 + config.send_default_pii = true + end + end + + it "records all params" do + get "/posts?foo=bar&password=42&secret=baz" + transaction = transport.events.last.to_hash + + params = transaction[:spans][0][:data][:params] + expect(params["foo"]).to eq("bar") + expect(params["password"]).to eq("42") + expect(params["secret"]).to eq("baz") + + path = transaction[:spans][0][:data][:path] + expect(path).to eq("/posts?foo=bar&password=42&secret=baz") + end + end + end + context "with instrumenter :otel" do before do make_basic_app do |config| From e384446fa102a5fab03c17ced22d0076eaf075ea Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Mon, 28 Oct 2024 19:42:28 +0800 Subject: [PATCH 66/96] Test sentry-rails against Rails 8.0.0 (#2444) * Simplify ActiveJob specs setup We don't need to use Sidekiq for ActiveJob specs, we can use Rails' default adapters instead. * Update sentry-rails' Gemfile conditions to support Rails 7.2 * Test against Rails 8.0 on CI * Update Rails 8 related tests --- .github/workflows/sentry_rails_test.yml | 2 + sentry-rails/Gemfile | 46 ++++++++++--------- .../spec/sentry/rails/activejob_spec.rb | 18 +++----- .../tracing/active_support_subscriber_spec.rb | 13 +++--- 4 files changed, 39 insertions(+), 40 deletions(-) diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index ed32ab477..06a5867c0 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -51,6 +51,8 @@ jobs: - { ruby_version: "3.1", rails_version: 7.2.0 } - { ruby_version: "3.2", rails_version: 7.2.0 } - { ruby_version: "3.3", rails_version: 7.2.0 } + - { ruby_version: "3.2", rails_version: "8.0.0.rc1" } + - { ruby_version: "3.3", rails_version: "8.0.0.rc1" } - { ruby_version: "jruby", rails_version: 6.1.0 } - { ruby_version: "3.2", diff --git a/sentry-rails/Gemfile b/sentry-rails/Gemfile index 7695eff15..53f632539 100644 --- a/sentry-rails/Gemfile +++ b/sentry-rails/Gemfile @@ -12,40 +12,38 @@ platform :jruby do gem "jdbc-sqlite3" end +ruby_version = Gem::Version.new(RUBY_VERSION) + rails_version = ENV["RAILS_VERSION"] -rails_version = "7.1.0" if rails_version.nil? +rails_version = "7.2.0" if rails_version.nil? rails_version = Gem::Version.new(rails_version) -if rails_version < Gem::Version.new("6.0.0") - gem "sqlite3", "~> 1.3.0", platform: :ruby -else - if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0") - gem "sqlite3", "~> 1.7.3", platform: :ruby - else - gem "sqlite3", "~> 1.6.9", platform: :ruby - end -end +gem "rails", "~> #{rails_version}" if rails_version >= Gem::Version.new("8.0.0.alpha") - gem "rails", github: "rails/rails" gem "rspec-rails" + gem "sqlite3", platform: :ruby elsif rails_version >= Gem::Version.new("7.1.0") - gem "rails", "~> #{rails_version}" gem "rspec-rails" + gem "sqlite3", "~> 1.7.3", platform: :ruby +elsif rails_version >= Gem::Version.new("6.1.0") + gem "rspec-rails", "~> 4.0" + + if ruby_version >= Gem::Version.new("2.7.0") + gem "sqlite3", "~> 1.7.3", platform: :ruby + else + gem "sqlite3", "~> 1.6.9", platform: :ruby + end else gem "rspec-rails", "~> 4.0" - gem "rails", "~> #{rails_version}" gem "psych", "~> 3.0.0" -end -gem "mini_magick" - -gem "sprockets-rails" - -gem "sidekiq" - - -ruby_version = Gem::Version.new(RUBY_VERSION) + if rails_version >= Gem::Version.new("6.0.0") + gem "sqlite3", "~> 1.4.0", platform: :ruby + else + gem "sqlite3", "~> 1.3.0", platform: :ruby + end +end if ruby_version < Gem::Version.new("2.5.0") # https://github.com/flavorjones/loofah/pull/267 @@ -53,6 +51,10 @@ if ruby_version < Gem::Version.new("2.5.0") gem "loofah", "2.20.0" end +gem "mini_magick" + +gem "sprockets-rails" + gem "benchmark-ips" gem "benchmark_driver" gem "benchmark-ipsa" diff --git a/sentry-rails/spec/sentry/rails/activejob_spec.rb b/sentry-rails/spec/sentry/rails/activejob_spec.rb index 9e9e0ce36..cf986d937 100644 --- a/sentry-rails/spec/sentry/rails/activejob_spec.rb +++ b/sentry-rails/spec/sentry/rails/activejob_spec.rb @@ -309,21 +309,17 @@ def perform(event, hint) context "when we are using an adapter which has a specific integration" do before do - Sentry.configuration.rails.skippable_job_adapters = ["ActiveJob::QueueAdapters::SidekiqAdapter"] + Sentry.configuration.rails.skippable_job_adapters = ["ActiveJob::QueueAdapters::TestAdapter"] end - it "does not trigger sentry and re-raises" do - begin - original_queue_adapter = FailedJob.queue_adapter - FailedJob.queue_adapter = :sidekiq + after do + Sentry.configuration.rails.skippable_job_adapters = [] + end - expect { FailedJob.perform_now }.to raise_error(FailedJob::TestError) + it "does not trigger sentry and re-raises" do + expect { FailedJob.perform_now }.to raise_error(FailedJob::TestError) - expect(transport.events.size).to eq(0) - ensure - # this doesn't affect test result, but we shouldn't change it anyway - FailedJob.queue_adapter = original_queue_adapter - end + expect(transport.events.size).to eq(0) end end diff --git a/sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb index 951ebb212..c276063da 100644 --- a/sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing/active_support_subscriber_spec.rb @@ -47,12 +47,11 @@ expect(transport.events.count).to eq(1) cache_transaction = transport.events.first.to_hash expect(cache_transaction[:type]).to eq("transaction") - expect(cache_transaction[:spans].count).to eq(2) - expect(cache_transaction[:spans][1][:op]).to eq("cache.put") - expect(cache_transaction[:spans][1][:origin]).to eq("auto.cache.rails") + expect(cache_transaction[:spans].count).to eq(1) + expect(cache_transaction[:spans][0][:op]).to eq("cache.put") + expect(cache_transaction[:spans][0][:origin]).to eq("auto.cache.rails") end - # it "tracks cache decrement" do skip("Tracks on Rails 8.0 for all Cache Stores; Until then only MemCached and Redis Stores.") if Rails.version.to_f < 8.0 @@ -67,9 +66,9 @@ expect(transport.events.count).to eq(1) cache_transaction = transport.events.first.to_hash expect(cache_transaction[:type]).to eq("transaction") - expect(cache_transaction[:spans].count).to eq(2) - expect(cache_transaction[:spans][1][:op]).to eq("cache.put") - expect(cache_transaction[:spans][1][:origin]).to eq("auto.cache.rails") + expect(cache_transaction[:spans].count).to eq(1) + expect(cache_transaction[:spans][0][:op]).to eq("cache.put") + expect(cache_transaction[:spans][0][:origin]).to eq("auto.cache.rails") end it "tracks cache read" do From 27d7384919b41c607f92ead49333bd307e49c9ca Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Mon, 28 Oct 2024 19:21:52 +0100 Subject: [PATCH 67/96] RescuedExceptionInterceptor: Handle empty configuration (#2428) Previously, it could happen that `Sentry.configuration` was `nil`. In this case, calling `rails` would produce a `NoMethodError`. We fix this issue by using safe navigation. Furthermore, this commit ensures we use a reasonable default in case the configuration couldn't be loaded. Since the config `report_rescued_exceptions` defaults to `true`, we assume this value here, too. Fixes #2386 --- CHANGELOG.md | 1 + .../lib/sentry/rails/rescued_exception_interceptor.rb | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9dc18876..a11809b02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Fix Vernier profiler not stopping when already stopped [#2429](https://github.com/getsentry/sentry-ruby/pull/2429) - Fix `send_default_pii` handling in rails controller spans [#2443](https://github.com/getsentry/sentry-ruby/pull/2443) - Fixes [#2438](https://github.com/getsentry/sentry-ruby/issues/2438) +- Fix `RescuedExceptionInterceptor` to handle an empty configuration [#2428](https://github.com/getsentry/sentry-ruby/pull/2428) ## 5.21.0 diff --git a/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb b/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb index 43cb69db1..757377298 100644 --- a/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb +++ b/sentry-rails/lib/sentry/rails/rescued_exception_interceptor.rb @@ -19,7 +19,16 @@ def call(env) end def report_rescued_exceptions? - Sentry.configuration.rails.report_rescued_exceptions + # In rare edge cases, `Sentry.configuration` might be `nil` here. + # Hence, we use a safe navigation and fallback to a reasonable default + # of `true` in case the configuration couldn't be loaded. + # See https://github.com/getsentry/sentry-ruby/issues/2386 + report_rescued_exceptions = Sentry.configuration&.rails&.report_rescued_exceptions + return report_rescued_exceptions unless report_rescued_exceptions.nil? + + # `true` is the default for `report_rescued_exceptions`, as specified in + # `sentry-rails/lib/sentry/rails/configuration.rb`. + true end end end From 9446a30e56d16dff04c98593a251cecbe872e147 Mon Sep 17 00:00:00 2001 From: Frederik Spang Date: Tue, 29 Oct 2024 14:05:22 +0100 Subject: [PATCH 68/96] Add child_spans for Sidekiq Queue instrumentation (#2403) * Add childspan for Sidekiq Queue instrumentation * Add basic specs * Remove unneeded exception alloc * Add CHANGELOG entry * Set root op instead of nested spans * Adjust feedback * Remove timecop_delay from options hash * Fix 1 day * Fix 1.day * Dont use .day helper --- CHANGELOG.md | 3 +- sentry-sidekiq/Gemfile | 2 + .../sidekiq/sentry_context_middleware.rb | 35 ++++++++++++++--- .../sidekiq/sentry_context_middleware_spec.rb | 39 +++++++++++++++++++ sentry-sidekiq/spec/sentry/sidekiq_spec.rb | 2 +- sentry-sidekiq/spec/spec_helper.rb | 9 ++++- 6 files changed, 81 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a11809b02..7d2360ffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### Features - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) -- Add support for Sentry Cache instrumentation, when using Rails.cache [#2380](https://github.com/getsentry/sentry-ruby/pull/2380) +- Add support for Sentry Cache instrumentation, when using Rails.cache ([#2380](https://github.com/getsentry/sentry-ruby/pull/2380)) +- Add support for Queue Instrumentation for Sidekiq. [#2403](https://github.com/getsentry/sentry-ruby/pull/2403) Note: MemoryStore and FileStore require Rails 8.0+ diff --git a/sentry-sidekiq/Gemfile b/sentry-sidekiq/Gemfile index c860cb206..8448e3b77 100644 --- a/sentry-sidekiq/Gemfile +++ b/sentry-sidekiq/Gemfile @@ -25,4 +25,6 @@ end gem "rails", "> 5.0.0" +gem "timecop" + eval_gemfile File.expand_path("../Gemfile", __dir__) diff --git a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb index e43acb653..690f26ade 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb @@ -4,11 +4,24 @@ module Sentry module Sidekiq + module Helpers + def set_span_data(span, id:, queue:, latency: nil, retry_count: nil) + if span + span.set_data("messaging.message.id", id) + span.set_data("messaging.destination.name", queue) + span.set_data("messaging.message.receive.latency", latency) if latency + span.set_data("messaging.message.retry.count", retry_count) if retry_count + end + end + end + class SentryContextServerMiddleware - OP_NAME = "queue.sidekiq" + include Sentry::Sidekiq::Helpers + + OP_NAME = "queue.process" SPAN_ORIGIN = "auto.queue.sidekiq" - def call(_worker, job, queue) + def call(worker, job, queue) return yield unless Sentry.initialized? context_filter = Sentry::Sidekiq::ContextFilter.new(job) @@ -23,7 +36,12 @@ def call(_worker, job, queue) scope.set_contexts(sidekiq: job.merge("queue" => queue)) scope.set_transaction_name(context_filter.transaction_name, source: :task) transaction = start_transaction(scope, job["trace_propagation_headers"]) - scope.set_span(transaction) if transaction + + if transaction + scope.set_span(transaction) + + set_span_data(transaction, id: job["jid"], queue: queue, latency: ((Time.now.to_f - job["enqueued_at"]) * 1000).to_i, retry_count: job["retry_count"] || 0) + end begin yield @@ -63,13 +81,20 @@ def finish_transaction(transaction, status) end class SentryContextClientMiddleware - def call(_worker_class, job, _queue, _redis_pool) + include Sentry::Sidekiq::Helpers + + def call(worker_class, job, queue, _redis_pool) return yield unless Sentry.initialized? user = Sentry.get_current_scope.user job["sentry_user"] = user unless user.empty? job["trace_propagation_headers"] ||= Sentry.get_trace_propagation_headers - yield + + Sentry.with_child_span(op: "queue.publish", description: worker_class.to_s) do |span| + set_span_data(span, id: job["jid"], queue: queue) + + yield + end end end end diff --git a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb index de5e9416f..ea930ee4e 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "spec_helper" +require "timecop" RSpec.shared_context "sidekiq", shared_context: :metadata do let(:user) { { "id" => rand(10_000) } } @@ -65,6 +66,30 @@ expect(transaction.contexts.dig(:trace, :origin)).to eq('auto.queue.sidekiq') end + it "adds a queue.process spans" do + Timecop.freeze do + execute_worker(processor, HappyWorker) + execute_worker(processor, HappyWorker, jid: '123456', timecop_delay: Time.now + 86400) + + expect(transport.events.count).to eq(2) + + transaction = transport.events[0] + expect(transaction).not_to be_nil + expect(transaction.spans.count).to eq(0) + expect(transaction.contexts[:trace][:data]['messaging.message.id']).to eq('123123') # Default defined in #execute_worker + expect(transaction.contexts[:trace][:data]['messaging.destination.name']).to eq('default') + expect(transaction.contexts[:trace][:data]['messaging.message.retry.count']).to eq(0) + expect(transaction.contexts[:trace][:data]['messaging.message.receive.latency']).to eq(0) + + transaction = transport.events[1] + expect(transaction).not_to be_nil + expect(transaction.spans.count).to eq(0) + expect(transaction.contexts[:trace][:data]['messaging.message.id']).to eq('123456') # Explicitly set above. + expect(transaction.contexts[:trace][:data]['messaging.destination.name']).to eq('default') + expect(transaction.contexts[:trace][:data]['messaging.message.receive.latency']).to eq(86400000) + end + end + context "with trace_propagation_headers" do let(:parent_transaction) { Sentry.start_transaction(op: "sidekiq") } @@ -73,6 +98,7 @@ execute_worker(processor, HappyWorker, trace_propagation_headers: trace_propagation_headers) expect(transport.events.count).to eq(1) + transaction = transport.events[0] expect(transaction).not_to be_nil expect(transaction.contexts.dig(:trace, :trace_id)).to eq(parent_transaction.trace_id) @@ -156,5 +182,18 @@ expect(second_headers["sentry-trace"]).to eq(transaction.to_sentry_trace) expect(second_headers["baggage"]).to eq(transaction.to_baggage) end + + it "has a queue.publish span" do + message_id = client.push('queue' => 'default', 'class' => HappyWorker, 'args' => []) + + transaction.finish + + expect(transport.events.count).to eq(1) + event = transport.events.last + expect(event.spans.count).to eq(1) + expect(event.spans[0][:op]).to eq("queue.publish") + expect(event.spans[0][:data]['messaging.message.id']).to eq(message_id) + expect(event.spans[0][:data]['messaging.destination.name']).to eq('default') + end end end diff --git a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb index 64fdec5c1..4c788c9ce 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb @@ -223,7 +223,7 @@ def retry_last_failed_job expect(transaction.contexts.dig(:trace, :trace_id)).to be_a(String) expect(transaction.contexts.dig(:trace, :span_id)).to be_a(String) expect(transaction.contexts.dig(:trace, :status)).to eq("ok") - expect(transaction.contexts.dig(:trace, :op)).to eq("queue.sidekiq") + expect(transaction.contexts.dig(:trace, :op)).to eq("queue.process") end it "records transaction with exception" do diff --git a/sentry-sidekiq/spec/spec_helper.rb b/sentry-sidekiq/spec/spec_helper.rb index 5e1e6a6e9..e712a6a0f 100644 --- a/sentry-sidekiq/spec/spec_helper.rb +++ b/sentry-sidekiq/spec/spec_helper.rb @@ -229,15 +229,20 @@ def sidekiq_config(opts) def execute_worker(processor, klass, **options) klass_options = klass.sidekiq_options_hash || {} - # for Ruby < 2.6 klass_options.each do |k, v| options[k.to_sym] = v end - msg = Sidekiq.dump_json(jid: "123123", class: klass, args: [], **options) + jid = options.delete(:jid) || "123123" + timecop_delay = options.delete(:timecop_delay) + + msg = Sidekiq.dump_json(created_at: Time.now.to_f, enqueued_at: Time.now.to_f, jid: jid, class: klass, args: [], **options) + Timecop.freeze(timecop_delay) if timecop_delay work = Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg) process_work(processor, work) +ensure + Timecop.return if timecop_delay end def process_work(processor, work) From ceba0da67755c6168729027b84cb2eaac9179902 Mon Sep 17 00:00:00 2001 From: Frederik Spang Date: Tue, 5 Nov 2024 16:55:15 +0100 Subject: [PATCH 69/96] Reset trace and transaction for sidekiq-cron Fixes #2391 --- CHANGELOG.md | 1 + sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb | 42 ++++++++++++++++ .../spec/sentry/sidekiq/cron/job_spec.rb | 48 ++++++++++++++++++- 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d2360ffd..af25e2044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) - Add support for Sentry Cache instrumentation, when using Rails.cache ([#2380](https://github.com/getsentry/sentry-ruby/pull/2380)) - Add support for Queue Instrumentation for Sidekiq. [#2403](https://github.com/getsentry/sentry-ruby/pull/2403) +- Reset trace_id and add root transaction for sidekiq-cron [#2446](https://github.com/getsentry/sentry-ruby/pull/2446) Note: MemoryStore and FileStore require Rails 8.0+ diff --git a/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb b/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb index 937fd797c..954e98311 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb @@ -12,6 +12,32 @@ module Sentry module Sidekiq module Cron module Job + def self.enqueueing_method + ::Sidekiq::Cron::Job.instance_methods.include?(:enque!) ? :enque! : :enqueue! + end + + define_method(enqueueing_method) do |*args| + # make sure the current thread has a clean hub + Sentry.clone_hub_to_current_thread + + Sentry.with_scope do |scope| + Sentry.with_session_tracking do + begin + scope.set_transaction_name("#{name} (#{klass})") + + transaction = start_transaction(scope) + scope.set_span(transaction) if transaction + super(*args) + + finish_transaction(transaction, 200) + rescue + finish_transaction(transaction, 500) + raise + end + end + end + end + def save # validation failed, do nothing return false unless super @@ -34,6 +60,22 @@ def save true end + + def start_transaction(scope) + Sentry.start_transaction( + name: scope.transaction_name, + source: scope.transaction_source, + op: "queue.sidekiq-cron", + origin: "auto.queue.sidekiq.cron" + ) + end + + def finish_transaction(transaction, status_code) + return unless transaction + + transaction.set_http_status(status_code) + transaction.finish + end end end end diff --git a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb index 4e4f65202..85fcaeb99 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb @@ -5,11 +5,24 @@ return unless defined?(Sidekiq::Cron::Job) RSpec.describe Sentry::Sidekiq::Cron::Job do + let(:processor) do + new_processor + end + + let(:transport) do + Sentry.get_current_client.transport + end + before do - perform_basic_setup { |c| c.enabled_patches += [:sidekiq_cron] } + perform_basic_setup do |c| + c.enabled_patches += [:sidekiq_cron] + c.traces_sample_rate = 1.0 + end end before do + Sidekiq::Cron::Job.destroy_all! + Sidekiq::Queue.all.each(&:clear) schedule_file = 'spec/fixtures/sidekiq-cron-schedule.yml' schedule = Sidekiq::Cron::Support.load_yaml(ERB.new(IO.read(schedule_file)).result) schedule = schedule.merge(symbol_name: { cron: '* * * * *', class: HappyWorkerWithSymbolName }) @@ -79,4 +92,37 @@ it 'does not patch ReportingWorker because of invalid schedule' do expect(ReportingWorker.ancestors).not_to include(Sentry::Cron::MonitorSchedule) end + + describe 'sidekiq-cron' do + it 'adds job to sidekiq within transaction' do + job = Sidekiq::Cron::Job.new(name: 'test', cron: 'not a crontab', class: 'HappyWorkerForCron') + job.send(Sentry::Sidekiq::Cron::Job.enqueueing_method) + + expect(::Sidekiq::Queue.new.size).to eq(1) + expect(transport.events.count).to eq(1) + event = transport.events.last + expect(event.spans.count).to eq(1) + expect(event.spans[0][:op]).to eq("queue.publish") + expect(event.spans[0][:data]['messaging.destination.name']).to eq('default') + end + + it 'adds job to sidekiq within transaction' do + job = Sidekiq::Cron::Job.new(name: 'test', cron: 'not a crontab', class: 'HappyWorkerForCron') + job.send(Sentry::Sidekiq::Cron::Job.enqueueing_method) + # Time passes. + job.send(Sentry::Sidekiq::Cron::Job.enqueueing_method) + + expect(::Sidekiq::Queue.new.size).to eq(2) + expect(transport.events.count).to eq(2) + events = transport.events + expect(events[0].spans.count).to eq(1) + expect(events[0].spans[0][:op]).to eq("queue.publish") + expect(events[0].spans[0][:data]['messaging.destination.name']).to eq('default') + expect(events[1].spans.count).to eq(1) + expect(events[1].spans[0][:op]).to eq("queue.publish") + expect(events[1].spans[0][:data]['messaging.destination.name']).to eq('default') + + expect(events[0].dynamic_sampling_context['trace_id']).to_not eq(events[1].dynamic_sampling_context['trace_id']) + end + end end From 5de4ebc62d3a64015f206a7fd53534deb22e5730 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 14 Nov 2024 11:54:21 +0100 Subject: [PATCH 70/96] Fix the build (#2463) * [delayed_job] pin activerecord-jdbcmysql-adapter to a specific sha for now They bumped it to 9.1.0 and we need < 9 https://github.com/jruby/activerecord-jdbc-adapter/commit/0a959b87b313b1e4740fd1639c11f89b87842d9f * [delayed_job] update sqlite for older rubies this fixes the spec suite * [sidekiq] fix specs --- sentry-delayed_job/Gemfile | 14 ++++++++++---- .../spec/sentry/client/event_sending_spec.rb | 2 +- .../spec/sentry/sidekiq/cron/job_spec.rb | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/sentry-delayed_job/Gemfile b/sentry-delayed_job/Gemfile index 48e80fbdc..d32b3f24e 100644 --- a/sentry-delayed_job/Gemfile +++ b/sentry-delayed_job/Gemfile @@ -18,14 +18,20 @@ gem "rails", "> 5.0.0" platform :jruby do # See https://github.com/jruby/activerecord-jdbc-adapter/issues/1139 - gem "activerecord-jdbcmysql-adapter", github: "jruby/activerecord-jdbc-adapter" + gem "activerecord-jdbcmysql-adapter", github: "jruby/activerecord-jdbc-adapter", ref: "6b3983bbbfda75ee2a1f5bc4c8d35efd7b71d84b" gem "jdbc-sqlite3" end -if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0") +ruby_version = Gem::Version.new(RUBY_VERSION) + +if ruby_version < Gem::Version.new("2.5.0") gem "sqlite3", "~> 1.3.0", platform: :ruby -else - gem "sqlite3", "~> 1.6.9", platform: :ruby +elsif ruby_version < Gem::Version.new("3.0.0") + gem "sqlite3", "~> 1.6.0", platform: :ruby +elsif ruby_version >= Gem::Version.new("3.0.0") && ruby_version < Gem::Version.new("3.1.0") + gem "sqlite3", "~> 1.7.0", platform: :ruby +elsif ruby_version >= Gem::Version.new("3.1.0") + gem "sqlite3", "~> 2.2", platform: :ruby end eval_gemfile File.expand_path("../Gemfile", __dir__) diff --git a/sentry-ruby/spec/sentry/client/event_sending_spec.rb b/sentry-ruby/spec/sentry/client/event_sending_spec.rb index 86b4b6c67..e66926758 100644 --- a/sentry-ruby/spec/sentry/client/event_sending_spec.rb +++ b/sentry-ruby/spec/sentry/client/event_sending_spec.rb @@ -101,7 +101,7 @@ client.capture_event(event, scope) - expect(string_io.string).to include("Converting event (#{event.event_id}) to JSON compatible hash failed: source sequence is illegal/malformed utf-8") + expect(string_io.string).to match(/Converting event \(#{event.event_id}\) to JSON compatible hash failed:.*illegal\/malformed utf-8/i) end end diff --git a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb index 85fcaeb99..d5d637a7c 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb @@ -33,7 +33,7 @@ end before do - stub_const('Job', Class.new { def perform; end }) + stub_const('Job', Class.new { include Sidekiq::Worker; def perform; end }) end it 'patches class' do From b31f0f395af16953287e7154b383919c55d7a927 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Sat, 16 Nov 2024 23:03:38 +0100 Subject: [PATCH 71/96] [rails] support string errors in error reporter (#2464) * [rails] support string errors in error reporter * Update CHANGELOG * [rails] log instead of raising when ErrorSubscriber fails * [rails] fix spec --- CHANGELOG.md | 1 + .../lib/sentry/rails/error_subscriber.rb | 15 ++++++++++- sentry-rails/spec/sentry/rails_spec.rb | 26 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af25e2044..ff1163894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) - Add support for Sentry Cache instrumentation, when using Rails.cache ([#2380](https://github.com/getsentry/sentry-ruby/pull/2380)) - Add support for Queue Instrumentation for Sidekiq. [#2403](https://github.com/getsentry/sentry-ruby/pull/2403) +- Add support for string errors in error reporter ([#2464](https://github.com/getsentry/sentry-ruby/pull/2464)) - Reset trace_id and add root transaction for sidekiq-cron [#2446](https://github.com/getsentry/sentry-ruby/pull/2446) Note: MemoryStore and FileStore require Rails 8.0+ diff --git a/sentry-rails/lib/sentry/rails/error_subscriber.rb b/sentry-rails/lib/sentry/rails/error_subscriber.rb index dad598c51..161b8793b 100644 --- a/sentry-rails/lib/sentry/rails/error_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/error_subscriber.rb @@ -27,7 +27,20 @@ def report(error, handled:, severity:, context:, source: nil) hint.merge!(context.delete(:hint)) end - Sentry::Rails.capture_exception(error, level: severity, contexts: { "rails.error" => context }, tags: tags, hint: hint) + options = { level: severity, contexts: { "rails.error" => context }, tags: tags, hint: hint } + + case error + when String + Sentry::Rails.capture_message(error, **options) + when Exception + Sentry::Rails.capture_exception(error, **options) + else + log_debug("Expected an Exception or a String, got: #{error.inspect}") + end + end + + def log_debug(message) + Sentry.configuration.logger.debug(message) end end end diff --git a/sentry-rails/spec/sentry/rails_spec.rb b/sentry-rails/spec/sentry/rails_spec.rb index dd069db81..7a2f3ec15 100644 --- a/sentry-rails/spec/sentry/rails_spec.rb +++ b/sentry-rails/spec/sentry/rails_spec.rb @@ -356,6 +356,32 @@ def capture_in_separate_process(exit_code:) expect(transport.events.count).to eq(0) end + + it "captures string messages through error reporter" do + Rails.error.report("Test message", severity: :info, handled: true, context: { foo: "bar" }) + + expect(transport.events.count).to eq(1) + event = transport.events.first + + expect(event.message).to eq("Test message") + expect(event.level).to eq(:info) + expect(event.contexts).to include({ "rails.error" => { foo: "bar" } }) + expect(event.tags).to include({ handled: true }) + end + + it "skips non-string and non-exception errors" do + expect { + Sentry.init do |config| + config.logger = Logger.new($stdout) + end + + Sentry.logger.debug("Expected an Exception or a String, got: #{312.inspect}") + + Rails.error.report(312, severity: :info, handled: true, context: { foo: "bar" }) + }.to output(/Expected an Exception or a String, got: 312/).to_stdout + + expect(transport.events.count).to eq(0) + end end end end From a9b3687d3ce5d00d5586ef3fe76ae8233d8405f1 Mon Sep 17 00:00:00 2001 From: Frederik Spang Date: Tue, 19 Nov 2024 13:47:36 +0100 Subject: [PATCH 72/96] Add Excon instrumentation (#2383) * Add Excon instrumentation * Add missing specs * Add CHANGELOG * Fix Rubocop * Fix spec support for Ruby < 3 * Update sentry-ruby/lib/sentry/excon/middleware.rb Co-authored-by: Peter Solnica * Handle case for Excon 1+ with Hash as query * Borrow Rack::Utils for building nested query * Add one more specs for more advanced query building in Excon * Fixes changelog * Add new specs using the query parameter encoding --------- Co-authored-by: Peter Solnica --- CHANGELOG.md | 3 +- sentry-ruby/Gemfile | 1 + sentry-ruby/lib/sentry-ruby.rb | 1 + sentry-ruby/lib/sentry/excon.rb | 10 + sentry-ruby/lib/sentry/excon/middleware.rb | 77 ++++++ sentry-ruby/lib/sentry/utils/http_tracing.rb | 21 +- sentry-ruby/spec/sentry/excon_spec.rb | 251 +++++++++++++++++++ sentry-ruby/spec/sentry_spec.rb | 10 + 8 files changed, 372 insertions(+), 2 deletions(-) create mode 100644 sentry-ruby/lib/sentry/excon.rb create mode 100644 sentry-ruby/lib/sentry/excon/middleware.rb create mode 100644 sentry-ruby/spec/sentry/excon_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index ff1163894..49d11bda1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ### Features - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) -- Add support for Sentry Cache instrumentation, when using Rails.cache ([#2380](https://github.com/getsentry/sentry-ruby/pull/2380)) +- Add support for Sentry Cache instrumentation, when using Rails.cache [#2380](https://github.com/getsentry/sentry-ruby/pull/2380) - Add support for Queue Instrumentation for Sidekiq. [#2403](https://github.com/getsentry/sentry-ruby/pull/2403) - Add support for string errors in error reporter ([#2464](https://github.com/getsentry/sentry-ruby/pull/2464)) - Reset trace_id and add root transaction for sidekiq-cron [#2446](https://github.com/getsentry/sentry-ruby/pull/2446) +- Add support for Excon HTTP client instrumentation ([#2383](https://github.com/getsentry/sentry-ruby/pull/2383)) Note: MemoryStore and FileStore require Rails 8.0+ diff --git a/sentry-ruby/Gemfile b/sentry-ruby/Gemfile index 5ca0f99c2..5371ddbf2 100644 --- a/sentry-ruby/Gemfile +++ b/sentry-ruby/Gemfile @@ -28,5 +28,6 @@ gem "benchmark-memory" gem "yard", github: "lsegal/yard" gem "webrick" gem "faraday" +gem "excon" eval_gemfile File.expand_path("../Gemfile", __dir__) diff --git a/sentry-ruby/lib/sentry-ruby.rb b/sentry-ruby/lib/sentry-ruby.rb index 4ebf5b299..b7ecdea53 100644 --- a/sentry-ruby/lib/sentry-ruby.rb +++ b/sentry-ruby/lib/sentry-ruby.rb @@ -614,3 +614,4 @@ def utc_now require "sentry/puma" require "sentry/graphql" require "sentry/faraday" +require "sentry/excon" diff --git a/sentry-ruby/lib/sentry/excon.rb b/sentry-ruby/lib/sentry/excon.rb new file mode 100644 index 000000000..39559a992 --- /dev/null +++ b/sentry-ruby/lib/sentry/excon.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +Sentry.register_patch(:excon) do + if defined?(::Excon) + require "sentry/excon/middleware" + if Excon.defaults[:middlewares] + Excon.defaults[:middlewares] << Sentry::Excon::Middleware unless Excon.defaults[:middlewares].include?(Sentry::Excon::Middleware) + end + end +end diff --git a/sentry-ruby/lib/sentry/excon/middleware.rb b/sentry-ruby/lib/sentry/excon/middleware.rb new file mode 100644 index 000000000..9c6e59467 --- /dev/null +++ b/sentry-ruby/lib/sentry/excon/middleware.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +module Sentry + module Excon + OP_NAME = "http.client" + + class Middleware < ::Excon::Middleware::Base + def initialize(stack) + super + @instrumenter = Instrumenter.new + end + + def request_call(datum) + @instrumenter.start_transaction(datum) + @stack.request_call(datum) + end + + def response_call(datum) + @instrumenter.finish_transaction(datum) + @stack.response_call(datum) + end + end + + class Instrumenter + SPAN_ORIGIN = "auto.http.excon" + BREADCRUMB_CATEGORY = "http" + + include Utils::HttpTracing + + def start_transaction(env) + return unless Sentry.initialized? + + current_span = Sentry.get_current_scope&.span + @span = current_span&.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) + + request_info = extract_request_info(env) + + if propagate_trace?(request_info[:url]) + set_propagation_headers(env[:headers]) + end + end + + def finish_transaction(response) + return unless @span + + response_status = response[:response][:status] + request_info = extract_request_info(response) + + if record_sentry_breadcrumb? + record_sentry_breadcrumb(request_info, response_status) + end + + set_span_info(@span, request_info, response_status) + ensure + @span&.finish + end + + private + + def extract_request_info(env) + url = env[:scheme] + "://" + env[:hostname] + env[:path] + result = { method: env[:method].to_s.upcase, url: url } + + if Sentry.configuration.send_default_pii + result[:query] = env[:query] + + # Handle excon 1.0.0+ + result[:query] = build_nested_query(result[:query]) unless result[:query].is_a?(String) + + result[:body] = env[:body] + end + + result + end + end + end +end diff --git a/sentry-ruby/lib/sentry/utils/http_tracing.rb b/sentry-ruby/lib/sentry/utils/http_tracing.rb index abf6a9141..136e78d99 100644 --- a/sentry-ruby/lib/sentry/utils/http_tracing.rb +++ b/sentry-ruby/lib/sentry/utils/http_tracing.rb @@ -19,7 +19,7 @@ def record_sentry_breadcrumb(request_info, response_status) crumb = Sentry::Breadcrumb.new( level: :info, category: self.class::BREADCRUMB_CATEGORY, - type: :info, + type: "info", data: { status: response_status, **request_info } ) @@ -36,6 +36,25 @@ def propagate_trace?(url) Sentry.configuration.propagate_traces && Sentry.configuration.trace_propagation_targets.any? { |target| url.match?(target) } end + + # Kindly borrowed from Rack::Utils + def build_nested_query(value, prefix = nil) + case value + when Array + value.map { |v| + build_nested_query(v, "#{prefix}[]") + }.join("&") + when Hash + value.map { |k, v| + build_nested_query(v, prefix ? "#{prefix}[#{k}]" : k) + }.delete_if(&:empty?).join("&") + when nil + URI.encode_www_form_component(prefix) + else + raise ArgumentError, "value must be a Hash" if prefix.nil? + "#{URI.encode_www_form_component(prefix)}=#{URI.encode_www_form_component(value)}" + end + end end end end diff --git a/sentry-ruby/spec/sentry/excon_spec.rb b/sentry-ruby/spec/sentry/excon_spec.rb new file mode 100644 index 000000000..96574622a --- /dev/null +++ b/sentry-ruby/spec/sentry/excon_spec.rb @@ -0,0 +1,251 @@ +# frozen_string_literal: true + +require "spec_helper" +require "contexts/with_request_mock" +require "excon" + +RSpec.describe "Sentry::Excon" do + include Sentry::Utils::HttpTracing + include_context "with request mock" + + before do + Excon.defaults[:mock] = true + end + + after(:each) do + Excon.stubs.clear + end + + let(:string_io) { StringIO.new } + let(:logger) do + ::Logger.new(string_io) + end + + context "with IPv6 addresses" do + before do + perform_basic_setup do |config| + config.traces_sample_rate = 1.0 + config.enabled_patches += [:excon] unless config.enabled_patches.include?(:excon) + end + end + + it "correctly parses the short-hand IPv6 addresses" do + Excon.stub({}, { body: "", status: 200 }) + + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + _ = Excon.get("http://[::1]:8080/path", mock: true) + + expect(transaction.span_recorder.spans.count).to eq(2) + + request_span = transaction.span_recorder.spans.last + expect(request_span.data).to eq( + { "url" => "http://::1/path", "http.request.method" => "GET", "http.response.status_code" => 200 } + ) + end + end + + context "with tracing enabled" do + before do + perform_basic_setup do |config| + config.traces_sample_rate = 1.0 + config.transport.transport_class = Sentry::HTTPTransport + config.logger = logger + # the dsn needs to have a real host so we can make a real connection before sending a failed request + config.dsn = "http://foobarbaz@o447951.ingest.sentry.io/5434472" + config.enabled_patches += [:excon] unless config.enabled_patches.include?(:excon) + end + end + + context "with config.send_default_pii = true" do + before do + Sentry.configuration.send_default_pii = true + Sentry.configuration.breadcrumbs_logger = [:http_logger] + end + + it "records the request's span with query string in data" do + Excon.stub({}, { body: "", status: 200 }) + + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + response = Excon.get("http://example.com/path?foo=bar", mock: true) + + expect(response.status).to eq(200) + expect(transaction.span_recorder.spans.count).to eq(2) + + request_span = transaction.span_recorder.spans.last + expect(request_span.op).to eq("http.client") + expect(request_span.origin).to eq("auto.http.excon") + expect(request_span.start_timestamp).not_to be_nil + expect(request_span.timestamp).not_to be_nil + expect(request_span.start_timestamp).not_to eq(request_span.timestamp) + expect(request_span.description).to eq("GET http://example.com/path") + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "http://example.com/path", + "http.request.method" => "GET", + "http.query" => "foo=bar" + }) + end + + it "records the request's span with advanced query string in data" do + Excon.stub({}, { body: "", status: 200 }) + + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + connection = Excon.new("http://example.com/path") + response = connection.get(mock: true, query: build_nested_query({ foo: "bar", baz: [1, 2], qux: { a: 1, b: 2 } })) + + expect(response.status).to eq(200) + expect(transaction.span_recorder.spans.count).to eq(2) + + request_span = transaction.span_recorder.spans.last + expect(request_span.op).to eq("http.client") + expect(request_span.origin).to eq("auto.http.excon") + expect(request_span.start_timestamp).not_to be_nil + expect(request_span.timestamp).not_to be_nil + expect(request_span.start_timestamp).not_to eq(request_span.timestamp) + expect(request_span.description).to eq("GET http://example.com/path") + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "http://example.com/path", + "http.request.method" => "GET", + "http.query" => "foo=bar&baz%5B%5D=1&baz%5B%5D=2&qux%5Ba%5D=1&qux%5Bb%5D=2" + }) + end + + it "records breadcrumbs" do + Excon.stub({}, { body: "", status: 200 }) + + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + _response = Excon.get("http://example.com/path?foo=bar", mock: true) + + transaction.span_recorder.spans.last + + crumb = Sentry.get_current_scope.breadcrumbs.peek + + expect(crumb.category).to eq("http") + expect(crumb.data[:status]).to eq(200) + expect(crumb.data[:method]).to eq("GET") + expect(crumb.data[:url]).to eq("http://example.com/path") + expect(crumb.data[:query]).to eq("foo=bar") + expect(crumb.data[:body]).to be(nil) + end + end + + context "with config.send_default_pii = false" do + before do + Sentry.configuration.send_default_pii = false + end + + it "records the request's span without query string" do + Excon.stub({}, { body: "", status: 200 }) + + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + response = Excon.get("http://example.com/path?foo=bar", mock: true) + + expect(response.status).to eq(200) + expect(transaction.span_recorder.spans.count).to eq(2) + + request_span = transaction.span_recorder.spans.last + expect(request_span.op).to eq("http.client") + expect(request_span.origin).to eq("auto.http.excon") + expect(request_span.start_timestamp).not_to be_nil + expect(request_span.timestamp).not_to be_nil + expect(request_span.start_timestamp).not_to eq(request_span.timestamp) + expect(request_span.description).to eq("GET http://example.com/path") + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "http://example.com/path", + "http.request.method" => "GET" + }) + end + end + + context "when there're multiple requests" do + let(:transaction) { Sentry.start_transaction } + + before do + Sentry.get_current_scope.set_span(transaction) + end + + def verify_spans(transaction) + expect(transaction.span_recorder.spans.count).to eq(3) + expect(transaction.span_recorder.spans[0]).to eq(transaction) + + request_span = transaction.span_recorder.spans[1] + expect(request_span.op).to eq("http.client") + expect(request_span.origin).to eq("auto.http.excon") + expect(request_span.start_timestamp).not_to be_nil + expect(request_span.timestamp).not_to be_nil + expect(request_span.start_timestamp).not_to eq(request_span.timestamp) + expect(request_span.description).to eq("GET http://example.com/path") + expect(request_span.data).to eq({ + "http.response.status_code" => 200, + "url" => "http://example.com/path", + "http.request.method" => "GET" + }) + + request_span = transaction.span_recorder.spans[2] + expect(request_span.op).to eq("http.client") + expect(request_span.origin).to eq("auto.http.excon") + expect(request_span.start_timestamp).not_to be_nil + expect(request_span.timestamp).not_to be_nil + expect(request_span.start_timestamp).not_to eq(request_span.timestamp) + expect(request_span.description).to eq("GET http://example.com/path") + expect(request_span.data).to eq({ + "http.response.status_code" => 404, + "url" => "http://example.com/path", + "http.request.method" => "GET" + }) + end + + it "doesn't mess different requests' data together" do + Excon.stub({}, { body: "", status: 200 }) + response = Excon.get("http://example.com/path?foo=bar", mock: true) + expect(response.status).to eq(200) + + Excon.stub({}, { body: "", status: 404 }) + response = Excon.get("http://example.com/path?foo=bar", mock: true) + expect(response.status).to eq(404) + + verify_spans(transaction) + end + + context "with nested span" do + let(:span) { transaction.start_child(op: "child span") } + + before do + Sentry.get_current_scope.set_span(span) + end + + it "attaches http spans to the span instead of top-level transaction" do + Excon.stub({}, { body: "", status: 200 }) + response = Excon.get("http://example.com/path?foo=bar", mock: true) + expect(response.status).to eq(200) + + expect(transaction.span_recorder.spans.count).to eq(3) + expect(span.parent_span_id).to eq(transaction.span_id) + http_span = transaction.span_recorder.spans.last + expect(http_span.parent_span_id).to eq(span.span_id) + end + end + end + end + + context "without SDK" do + it "doesn't affect the HTTP lib anything" do + Excon.stub({}, { body: "", status: 200 }) + + response = Excon.get("http://example.com/path") + expect(response.status).to eq(200) + end + end +end diff --git a/sentry-ruby/spec/sentry_spec.rb b/sentry-ruby/spec/sentry_spec.rb index dabdcd07e..9a188e9f3 100644 --- a/sentry-ruby/spec/sentry_spec.rb +++ b/sentry-ruby/spec/sentry_spec.rb @@ -1235,5 +1235,15 @@ def foo; end expect(target_class.instance_methods).to include(:foo) end end + + context "with patch and block" do + it "raises error" do + expect do + described_class.register_patch(:bad_patch, module_patch, target_class) do + target_class.send(:prepend, module_patch) + end + end.to raise_error(ArgumentError, "Please provide either a patch and its target OR a block, but not both") + end + end end end From f2251388ed3af0a564c0fbac9abe4934ef4dbf72 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Thu, 28 Nov 2024 12:00:31 +0100 Subject: [PATCH 73/96] Add mutex sync to SessionFlusher aggregates (#2469) --- CHANGELOG.md | 2 ++ sentry-ruby/lib/sentry/session_flusher.rb | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d11bda1..6a88e9d8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ - Fix `send_default_pii` handling in rails controller spans [#2443](https://github.com/getsentry/sentry-ruby/pull/2443) - Fixes [#2438](https://github.com/getsentry/sentry-ruby/issues/2438) - Fix `RescuedExceptionInterceptor` to handle an empty configuration [#2428](https://github.com/getsentry/sentry-ruby/pull/2428) +- Add mutex sync to `SessionFlusher` aggregates [#2469](https://github.com/getsentry/sentry-ruby/pull/2469) + - Fixes [#2468](https://github.com/getsentry/sentry-ruby/issues/2468) ## 5.21.0 diff --git a/sentry-ruby/lib/sentry/session_flusher.rb b/sentry-ruby/lib/sentry/session_flusher.rb index f992a3b20..8f0510832 100644 --- a/sentry-ruby/lib/sentry/session_flusher.rb +++ b/sentry-ruby/lib/sentry/session_flusher.rb @@ -10,6 +10,7 @@ def initialize(configuration, client) @pending_aggregates = {} @release = configuration.release @environment = configuration.environment + @mutex = Mutex.new log_debug("[Sessions] Sessions won't be captured without a valid release") unless @release end @@ -18,7 +19,6 @@ def flush return if @pending_aggregates.empty? @client.capture_envelope(pending_envelope) - @pending_aggregates = {} end alias_method :run, :flush @@ -42,11 +42,15 @@ def init_aggregates(aggregation_key) end def pending_envelope - envelope = Envelope.new + aggregates = @mutex.synchronize do + aggregates = @pending_aggregates.values + @pending_aggregates = {} + aggregates + end + envelope = Envelope.new header = { type: "sessions" } - payload = { attrs: attrs, aggregates: @pending_aggregates.values } - + payload = { attrs: attrs, aggregates: aggregates } envelope.add_item(header, payload) envelope end From 0f0666cb3f085a41c24c46d641c1a097c60d0efc Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Mon, 2 Dec 2024 20:33:42 +0800 Subject: [PATCH 74/96] Fix sentry-rails' backtrace cleaner issues (#2475) * Clear Rails' default backtrace filters from Sentry's backtrace cleaner In Rails 7.2, Rails's backtrace cleaner, which sentry-rails' backtrace cleaner inherits from, starts shortening gem's paths in backtraces. This will prevent sentry-ruby's `Sentry::Backtrace` from handling them correctly, which will result in issues like #2472. This commit avoids the issue by clearing the default filters that Sentry's backtrace cleaner inherits. * Remove premature path-removal filter This filter removes the project root part from the stacktrace, which prevents sentry-ruby from retaining the correct absolute path of it. --- CHANGELOG.md | 2 ++ sentry-rails/lib/sentry/rails/backtrace_cleaner.rb | 8 +++----- sentry-rails/spec/sentry/rails/event_spec.rb | 10 +++++++--- sentry-rails/spec/sentry/rails_spec.rb | 10 ++++++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a88e9d8c..945926b6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ - Fix `RescuedExceptionInterceptor` to handle an empty configuration [#2428](https://github.com/getsentry/sentry-ruby/pull/2428) - Add mutex sync to `SessionFlusher` aggregates [#2469](https://github.com/getsentry/sentry-ruby/pull/2469) - Fixes [#2468](https://github.com/getsentry/sentry-ruby/issues/2468) +- Fix sentry-rails' backtrace cleaner issues ([#2475](https://github.com/getsentry/sentry-ruby/pull/2475)) + - Fixes [#2472](https://github.com/getsentry/sentry-ruby/issues/2472) ## 5.21.0 diff --git a/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb b/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb index 57030f733..3400df7e0 100644 --- a/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb +++ b/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb @@ -11,13 +11,11 @@ class BacktraceCleaner < ActiveSupport::BacktraceCleaner def initialize super - # we don't want any default silencers because they're too aggressive + # We don't want any default silencers because they're too aggressive remove_silencers! + # We don't want any default filters because Rails 7.2 starts shortening the paths. See #2472 + remove_filters! - @root = "#{Sentry.configuration.project_root}/" - add_filter do |line| - line.start_with?(@root) ? line.from(@root.size) : line - end add_filter do |line| if line =~ RENDER_TEMPLATE_PATTERN line.sub(RENDER_TEMPLATE_PATTERN, "") diff --git a/sentry-rails/spec/sentry/rails/event_spec.rb b/sentry-rails/spec/sentry/rails/event_spec.rb index 6c3f7b661..8dc969d08 100644 --- a/sentry-rails/spec/sentry/rails/event_spec.rb +++ b/sentry-rails/spec/sentry/rails/event_spec.rb @@ -32,6 +32,7 @@ it 'marks in_app correctly' do frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[0][:filename]).to eq("test/some/other/path") + expect(frames[0][:abs_path]).to eq("test/some/other/path") expect(frames[0][:in_app]).to eq(true) expect(frames[1][:filename]).to eq("/app/some/other/path") expect(frames[1][:in_app]).to eq(false) @@ -41,7 +42,7 @@ expect(frames[3][:in_app]).to eq(true) expect(frames[4][:filename]).to eq("vendor/bundle/some_gem.rb") expect(frames[4][:in_app]).to eq(false) - expect(frames[5][:filename]).to eq("vendor/bundle/cache/other_gem.rb") + expect(frames[5][:filename]).to eq("dummy/test_rails_app/vendor/bundle/cache/other_gem.rb") expect(frames[5][:in_app]).to eq(false) end @@ -50,6 +51,7 @@ $LOAD_PATH << "#{Rails.root}/app/models" frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[3][:filename]).to eq("app/models/user.rb") + expect(frames[3][:abs_path]).to eq("#{Rails.root}/app/models/user.rb") $LOAD_PATH.delete("#{Rails.root}/app/models") end end @@ -58,7 +60,8 @@ it 'normalizes the filename using the load path' do $LOAD_PATH.push "vendor/bundle" frames = hash[:exception][:values][0][:stacktrace][:frames] - expect(frames[5][:filename]).to eq("cache/other_gem.rb") + expect(frames[5][:filename]).to eq("dummy/test_rails_app/vendor/bundle/cache/other_gem.rb") + expect(frames[5][:abs_path]).to eq("#{Rails.root}/vendor/bundle/cache/other_gem.rb") $LOAD_PATH.pop end end @@ -66,7 +69,8 @@ context "when a non-in_app path under project_root isn't on the load path" do it 'normalizes the filename using project_root' do frames = hash[:exception][:values][0][:stacktrace][:frames] - expect(frames[5][:filename]).to eq("vendor/bundle/cache/other_gem.rb") + expect(frames[5][:filename]).to eq("dummy/test_rails_app/vendor/bundle/cache/other_gem.rb") + expect(frames[5][:abs_path]).to eq("#{Rails.root}/vendor/bundle/cache/other_gem.rb") end end end diff --git a/sentry-rails/spec/sentry/rails_spec.rb b/sentry-rails/spec/sentry/rails_spec.rb index 7a2f3ec15..8d4e5367f 100644 --- a/sentry-rails/spec/sentry/rails_spec.rb +++ b/sentry-rails/spec/sentry/rails_spec.rb @@ -242,6 +242,16 @@ def capture_in_separate_process(exit_code:) expect(traces.dig(-1, "function")).to be_nil end + it "makes sure BacktraceCleaner gem cleanup doesn't affect context lines population" do + get "/view_exception" + + traces = event.dig("exception", "values", 0, "stacktrace", "frames") + gem_frame = traces.find { |t| t["abs_path"].match(/actionview/) } + expect(gem_frame["pre_context"]).not_to be_empty + expect(gem_frame["post_context"]).not_to be_empty + expect(gem_frame["context_line"]).not_to be_empty + end + it "doesn't filters exception backtrace if backtrace_cleanup_callback is overridden" do make_basic_app do |config| config.backtrace_cleanup_callback = lambda { |backtrace| backtrace } From e8566fbc1eb2db2de03adf386c12d41dcca83d54 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 3 Dec 2024 00:13:30 +0100 Subject: [PATCH 75/96] Fix missing OpenStruct in raven CI (#2480) --- sentry-raven/spec/raven/json_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/sentry-raven/spec/raven/json_spec.rb b/sentry-raven/spec/raven/json_spec.rb index 482b79fb3..9c511c48b 100644 --- a/sentry-raven/spec/raven/json_spec.rb +++ b/sentry-raven/spec/raven/json_spec.rb @@ -2,6 +2,7 @@ # JSON impl we use handles it in the way that we expect. require 'spec_helper' +require 'ostruct' RSpec.describe JSON do data = [ From 0f89aa8b870820c7b43e8fac297d1467abcbef6a Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Tue, 3 Dec 2024 23:02:43 +0800 Subject: [PATCH 76/96] Test against official Rails 8.0 release (#2479) --- .github/workflows/sentry_rails_test.yml | 4 ++-- sentry-rails/Gemfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index 06a5867c0..b52abde8a 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -51,8 +51,8 @@ jobs: - { ruby_version: "3.1", rails_version: 7.2.0 } - { ruby_version: "3.2", rails_version: 7.2.0 } - { ruby_version: "3.3", rails_version: 7.2.0 } - - { ruby_version: "3.2", rails_version: "8.0.0.rc1" } - - { ruby_version: "3.3", rails_version: "8.0.0.rc1" } + - { ruby_version: "3.2", rails_version: "8.0.0" } + - { ruby_version: "3.3", rails_version: "8.0.0" } - { ruby_version: "jruby", rails_version: 6.1.0 } - { ruby_version: "3.2", diff --git a/sentry-rails/Gemfile b/sentry-rails/Gemfile index 53f632539..5000bb3b2 100644 --- a/sentry-rails/Gemfile +++ b/sentry-rails/Gemfile @@ -15,12 +15,12 @@ end ruby_version = Gem::Version.new(RUBY_VERSION) rails_version = ENV["RAILS_VERSION"] -rails_version = "7.2.0" if rails_version.nil? +rails_version = "8.0.0" if rails_version.nil? rails_version = Gem::Version.new(rails_version) gem "rails", "~> #{rails_version}" -if rails_version >= Gem::Version.new("8.0.0.alpha") +if rails_version >= Gem::Version.new("8.0.0") gem "rspec-rails" gem "sqlite3", platform: :ruby elsif rails_version >= Gem::Version.new("7.1.0") From 4eb1dffd1b58ed9256f25a01f367042f9eead733 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 3 Dec 2024 17:35:21 +0100 Subject: [PATCH 77/96] Pin jar-dependencies for jruby CI (#2482) --- Gemfile | 2 ++ sentry-delayed_job/Gemfile | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 9847a55e8..2dbaf0283 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,8 @@ gem "rake", "~> 12.0" ruby_version = Gem::Version.new(RUBY_VERSION) +gem "jar-dependencies", "0.4.1" if RUBY_PLATFORM == "java" + # Development tools if ruby_version >= Gem::Version.new("2.7.0") gem "debug", github: "ruby/debug", platform: :ruby diff --git a/sentry-delayed_job/Gemfile b/sentry-delayed_job/Gemfile index d32b3f24e..ddf765ba0 100644 --- a/sentry-delayed_job/Gemfile +++ b/sentry-delayed_job/Gemfile @@ -8,9 +8,6 @@ gemspec gem "sentry-ruby", path: "../sentry-ruby" gem "sentry-rails", path: "../sentry-rails" -# For https://github.com/ruby/psych/issues/655 -gem "psych", "5.1.0" - gem "delayed_job" gem "delayed_job_active_record" From 95a1b72d2c0cf140cf71a0eca94f691037f0cdcf Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Wed, 4 Dec 2024 15:10:32 +0100 Subject: [PATCH 78/96] changelog for 5.22.0 (#2483) --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 945926b6c..42731ca5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## 5.22.0 ### Features @@ -6,7 +6,7 @@ - Add support for Sentry Cache instrumentation, when using Rails.cache [#2380](https://github.com/getsentry/sentry-ruby/pull/2380) - Add support for Queue Instrumentation for Sidekiq. [#2403](https://github.com/getsentry/sentry-ruby/pull/2403) - Add support for string errors in error reporter ([#2464](https://github.com/getsentry/sentry-ruby/pull/2464)) -- Reset trace_id and add root transaction for sidekiq-cron [#2446](https://github.com/getsentry/sentry-ruby/pull/2446) +- Reset `trace_id` and add root transaction for sidekiq-cron [#2446](https://github.com/getsentry/sentry-ruby/pull/2446) - Add support for Excon HTTP client instrumentation ([#2383](https://github.com/getsentry/sentry-ruby/pull/2383)) Note: MemoryStore and FileStore require Rails 8.0+ From 2932e835fb8b55b2f59227f43daad829ba13f376 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Wed, 4 Dec 2024 14:31:14 +0000 Subject: [PATCH 79/96] release: 5.22.0 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index e9d6999c6..c927eab71 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -2,6 +2,6 @@ module Sentry module DelayedJob - VERSION = "5.21.0" + VERSION = "5.22.0" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index fc6a50341..e669ef864 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.21.0" + spec.add_dependency "sentry-ruby", "~> 5.22.0" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index d9e8b1083..e45412dce 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.21.0" + VERSION = "5.22.0" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 516908891..70ccfe255 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.21.0" + spec.add_dependency "sentry-ruby", "~> 5.22.0" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index f234ea7ea..d17f1a73c 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -2,6 +2,6 @@ module Sentry module Rails - VERSION = "5.21.0" + VERSION = "5.22.0" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index ebb19c1b0..597146887 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -31,5 +31,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.21.0" + spec.add_dependency "sentry-ruby", "~> 5.22.0" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index e8e9d7466..31143929e 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -2,6 +2,6 @@ module Sentry module Resque - VERSION = "5.21.0" + VERSION = "5.22.0" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index 1f5dd7085..f7d2076f6 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.21.0" + spec.add_dependency "sentry-ruby", "~> 5.22.0" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index cb7b82b61..35f768ea7 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.21.0" + VERSION = "5.22.0" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index 5028b6c59..c490a94c0 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -2,6 +2,6 @@ module Sentry module Sidekiq - VERSION = "5.21.0" + VERSION = "5.22.0" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index 375ec153c..b191f9886 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.21.0" + spec.add_dependency "sentry-ruby", "~> 5.22.0" spec.add_dependency "sidekiq", ">= 3.0" end From 3d2e5e6cbe4e6fd2554e984e8787f7db71e88dfd Mon Sep 17 00:00:00 2001 From: Alexey Zapparov Date: Thu, 5 Dec 2024 09:00:46 +0100 Subject: [PATCH 80/96] fix: Safe-navigate to session flusher (#2396) --- sentry-ruby/lib/sentry/hub.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sentry-ruby/lib/sentry/hub.rb b/sentry-ruby/lib/sentry/hub.rb index b9b58638d..d6e3ad2d0 100644 --- a/sentry-ruby/lib/sentry/hub.rb +++ b/sentry-ruby/lib/sentry/hub.rb @@ -255,7 +255,11 @@ def end_session return unless session session.close - Sentry.session_flusher.add_session(session) + + # NOTE: Under some circumstances, session_flusher nilified out of sync + # See: https://github.com/getsentry/sentry-ruby/issues/2378 + # See: https://github.com/getsentry/sentry-ruby/pull/2396 + Sentry.session_flusher&.add_session(session) end def with_session_tracking(&block) From 1eb011b2ae31459bd3e2060dae7925e3b2629572 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 5 Dec 2024 15:06:58 +0100 Subject: [PATCH 81/96] Update CHANGELOG.md (#2484) --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42731ca5f..8cef69a86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Bug Fixes + +- Safe-navigate to session flusher [#2396](https://github.com/getsentry/sentry-ruby/pull/2396) + ## 5.22.0 ### Features From 9d37d283319426ba14d79274d986fdb130a560e4 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 10 Dec 2024 14:11:13 +0100 Subject: [PATCH 82/96] Fix latency related nil error for Sidekiq Queues module span data (#2486) --- CHANGELOG.md | 2 + sentry-ruby/lib/sentry/span.rb | 5 +++ .../sidekiq/sentry_context_middleware.rb | 21 ++++++---- .../sidekiq/sentry_context_middleware_spec.rb | 41 +++++++++++++++---- 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cef69a86..d81b81577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ### Bug Fixes - Safe-navigate to session flusher [#2396](https://github.com/getsentry/sentry-ruby/pull/2396) +- Fix latency related nil error for Sidekiq Queues Module span data [#2486](https://github.com/getsentry/sentry-ruby/pull/2486) + - Fixes [#2485](https://github.com/getsentry/sentry-ruby/issues/2485) ## 5.22.0 diff --git a/sentry-ruby/lib/sentry/span.rb b/sentry-ruby/lib/sentry/span.rb index 3dd2158ea..256d8bd2f 100644 --- a/sentry-ruby/lib/sentry/span.rb +++ b/sentry-ruby/lib/sentry/span.rb @@ -44,6 +44,11 @@ module DataConventions LINENO = "code.lineno" FUNCTION = "code.function" NAMESPACE = "code.namespace" + + MESSAGING_MESSAGE_ID = "messaging.message.id" + MESSAGING_DESTINATION_NAME = "messaging.destination.name" + MESSAGING_MESSAGE_RECEIVE_LATENCY = "messaging.message.receive.latency" + MESSAGING_MESSAGE_RETRY_COUNT = "messaging.message.retry.count" end STATUS_MAP = { diff --git a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb index 690f26ade..85c115e93 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb @@ -6,12 +6,12 @@ module Sentry module Sidekiq module Helpers def set_span_data(span, id:, queue:, latency: nil, retry_count: nil) - if span - span.set_data("messaging.message.id", id) - span.set_data("messaging.destination.name", queue) - span.set_data("messaging.message.receive.latency", latency) if latency - span.set_data("messaging.message.retry.count", retry_count) if retry_count - end + return unless span + + span.set_data(Span::DataConventions::MESSAGING_MESSAGE_ID, id) + span.set_data(Span::DataConventions::MESSAGING_DESTINATION_NAME, queue) + span.set_data(Span::DataConventions::MESSAGING_MESSAGE_RECEIVE_LATENCY, latency) if latency + span.set_data(Span::DataConventions::MESSAGING_MESSAGE_RETRY_COUNT, retry_count) if retry_count end end @@ -40,7 +40,14 @@ def call(worker, job, queue) if transaction scope.set_span(transaction) - set_span_data(transaction, id: job["jid"], queue: queue, latency: ((Time.now.to_f - job["enqueued_at"]) * 1000).to_i, retry_count: job["retry_count"] || 0) + latency = ((Time.now.to_f - job["enqueued_at"]) * 1000).to_i if job["enqueued_at"] + set_span_data( + transaction, + id: job["jid"], + queue: queue, + latency: latency, + retry_count: job["retry_count"] || 0 + ) end begin diff --git a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb index ea930ee4e..45907adb4 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb @@ -2,6 +2,7 @@ require "spec_helper" require "timecop" +require 'sidekiq/api' RSpec.shared_context "sidekiq", shared_context: :metadata do let(:user) { { "id" => rand(10_000) } } @@ -66,27 +67,53 @@ expect(transaction.contexts.dig(:trace, :origin)).to eq('auto.queue.sidekiq') end - it "adds a queue.process spans" do - Timecop.freeze do - execute_worker(processor, HappyWorker) - execute_worker(processor, HappyWorker, jid: '123456', timecop_delay: Time.now + 86400) + context "span data for Queues module" do + it "adds a queue.process transaction with correct data" do + Timecop.freeze do + execute_worker(processor, HappyWorker) + end - expect(transport.events.count).to eq(2) + expect(transport.events.count).to eq(1) transaction = transport.events[0] expect(transaction).not_to be_nil expect(transaction.spans.count).to eq(0) expect(transaction.contexts[:trace][:data]['messaging.message.id']).to eq('123123') # Default defined in #execute_worker expect(transaction.contexts[:trace][:data]['messaging.destination.name']).to eq('default') - expect(transaction.contexts[:trace][:data]['messaging.message.retry.count']).to eq(0) expect(transaction.contexts[:trace][:data]['messaging.message.receive.latency']).to eq(0) + expect(transaction.contexts[:trace][:data]['messaging.message.retry.count']).to eq(0) + end + + it "adds a queue.process transaction with correct latency data" do + Timecop.freeze do + execute_worker(processor, HappyWorker, jid: '123456', timecop_delay: Time.now + 86400) + end + + expect(transport.events.count).to eq(1) - transaction = transport.events[1] + transaction = transport.events[0] expect(transaction).not_to be_nil expect(transaction.spans.count).to eq(0) expect(transaction.contexts[:trace][:data]['messaging.message.id']).to eq('123456') # Explicitly set above. expect(transaction.contexts[:trace][:data]['messaging.destination.name']).to eq('default') expect(transaction.contexts[:trace][:data]['messaging.message.receive.latency']).to eq(86400000) + expect(transaction.contexts[:trace][:data]['messaging.message.retry.count']).to eq(0) + end + + if MIN_SIDEKIQ_6 + it "does not fail for latency when performed inline" do + HappyWorker.perform_inline + + expect(transport.events.count).to eq(1) + + transaction = transport.events[0] + expect(transaction).not_to be_nil + expect(transaction.spans.count).to eq(0) + expect(transaction.contexts[:trace][:data]['messaging.message.id']).to be_a(String) + expect(transaction.contexts[:trace][:data]['messaging.destination.name']).to eq('default') + expect(transaction.contexts[:trace][:data]['messaging.message.receive.latency']).to be_nil + expect(transaction.contexts[:trace][:data]['messaging.message.retry.count']).to eq(0) + end end end From d8c10667ded5d4047eda61e20c7be78093192efc Mon Sep 17 00:00:00 2001 From: Stephanie Anderson Date: Tue, 10 Dec 2024 16:41:58 +0100 Subject: [PATCH 83/96] chore(meta): update issue templates to use issue types (#2488) --- .../{feature_request.md => 01-feature.md} | 9 ++-- .github/ISSUE_TEMPLATE/02-improvement.md | 11 +++++ .github/ISSUE_TEMPLATE/03-bug.yml | 45 ++++++++++++++++++ .github/ISSUE_TEMPLATE/bug_report.yml | 46 ------------------- .github/ISSUE_TEMPLATE/question.md | 9 ---- 5 files changed, 59 insertions(+), 61 deletions(-) rename .github/ISSUE_TEMPLATE/{feature_request.md => 01-feature.md} (51%) create mode 100644 .github/ISSUE_TEMPLATE/02-improvement.md create mode 100644 .github/ISSUE_TEMPLATE/03-bug.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml delete mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/01-feature.md similarity index 51% rename from .github/ISSUE_TEMPLATE/feature_request.md rename to .github/ISSUE_TEMPLATE/01-feature.md index 8937d5bc0..64a5a5424 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/01-feature.md @@ -1,10 +1,7 @@ --- -name: Feature Request -about: Propose a new feature of the Ruby SDK -title: '' -labels: enhancement -assignees: - +name: 💡 Feature Request +about: Propose new functionality for the SDK +type: Feature --- **Describe the idea** diff --git a/.github/ISSUE_TEMPLATE/02-improvement.md b/.github/ISSUE_TEMPLATE/02-improvement.md new file mode 100644 index 000000000..121c7277c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02-improvement.md @@ -0,0 +1,11 @@ +--- +name: 💡 Improvement +about: Propose an improvement for existing functionality of the SDK +type: Improvement +--- + +**Describe the idea** + +**Why do you think it's beneficial to most of the users** + +**Possible implementation** diff --git a/.github/ISSUE_TEMPLATE/03-bug.yml b/.github/ISSUE_TEMPLATE/03-bug.yml new file mode 100644 index 000000000..81a5e224c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/03-bug.yml @@ -0,0 +1,45 @@ +name: 🐞 Bug Report +description: "Report an unexpected problem or behavior of this SDK" +type: Bug +body: + - type: textarea + attributes: + label: Issue Description + validations: + required: true + - type: textarea + attributes: + label: Reproduction Steps + validations: + required: true + - type: textarea + attributes: + label: Expected Behavior + validations: + required: true + - type: textarea + attributes: + label: Actual Behavior + validations: + required: true + - type: input + attributes: + label: Ruby Version + validations: + required: true + - type: input + attributes: + label: SDK Version + validations: + required: true + - type: input + attributes: + label: Integration and Its Version + description: e.g. Rails/Sidekiq/Rake/DelayedJob...etc. + validations: + required: false + - type: textarea + attributes: + label: Sentry Config + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml deleted file mode 100644 index 216f73087..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Bug report -description: "Report an SDK issue" -labels: bug -assignees: sl0thentr0py -body: -- type: textarea - attributes: - label: Issue Description - validations: - required: true -- type: textarea - attributes: - label: Reproduction Steps - validations: - required: true -- type: textarea - attributes: - label: Expected Behavior - validations: - required: true -- type: textarea - attributes: - label: Actual Behavior - validations: - required: true -- type: input - attributes: - label: Ruby Version - validations: - required: true -- type: input - attributes: - label: SDK Version - validations: - required: true -- type: input - attributes: - label: Integration and Its Version - description: e.g. Rails/Sidekiq/Rake/DelayedJob...etc. - validations: - required: false -- type: textarea - attributes: - label: Sentry Config - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index 79c87a961..000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: Question -about: Ask questions about the Ruby SDK -title: '' -labels: question -assignees: sl0thentr0py - ---- - From a75819a894d7891a7728c16ca739ce27041685d0 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 13 Dec 2024 16:20:28 +0100 Subject: [PATCH 84/96] [ci] remove jruby-head until we can address #2490 (#2494) --- .github/workflows/sentry_delayed_job_test.yml | 1 + .github/workflows/sentry_opentelemetry_test.yml | 2 ++ .github/workflows/sentry_resque_test.yml | 2 ++ .github/workflows/sentry_ruby_test.yml | 2 ++ 4 files changed, 7 insertions(+) diff --git a/.github/workflows/sentry_delayed_job_test.yml b/.github/workflows/sentry_delayed_job_test.yml index d40cdfaa1..cc8d52f4e 100644 --- a/.github/workflows/sentry_delayed_job_test.yml +++ b/.github/workflows/sentry_delayed_job_test.yml @@ -47,6 +47,7 @@ jobs: # LoadError: # cannot load such file -- mutex_m - { ruby_version: "head" } + - { ruby_version: 'jruby-head' } steps: - uses: actions/checkout@v1 - name: Install sqlite diff --git a/.github/workflows/sentry_opentelemetry_test.yml b/.github/workflows/sentry_opentelemetry_test.yml index 2f377894f..913afadc0 100644 --- a/.github/workflows/sentry_opentelemetry_test.yml +++ b/.github/workflows/sentry_opentelemetry_test.yml @@ -43,6 +43,8 @@ jobs: rubyopt: "--enable-frozen-string-literal --debug=frozen-string-literal", }, } + exclude: + - { ruby_version: 'jruby-head' } steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/sentry_resque_test.yml b/.github/workflows/sentry_resque_test.yml index 015a1bcce..d03411138 100644 --- a/.github/workflows/sentry_resque_test.yml +++ b/.github/workflows/sentry_resque_test.yml @@ -41,6 +41,8 @@ jobs: rubyopt: "--enable-frozen-string-literal --debug=frozen-string-literal", }, } + exclude: + - { ruby_version: 'jruby-head' } steps: - uses: actions/checkout@v1 - name: Set up Ruby ${{ matrix.ruby_version }} diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index 60fa831f5..2a1c9614e 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -59,6 +59,8 @@ jobs: rack_version: 3.1, redis_rb_version: 5.3 } + exclude: + - { ruby_version: 'jruby-head' } steps: - uses: actions/checkout@v1 From 6a46d9fba33c45d03fbb93ee1f26e313f0ed24b5 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 13 Dec 2024 21:39:44 +0100 Subject: [PATCH 85/96] Update CHANGELOG for 5.22.1 (#2496) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d81b81577..9377ad976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## 5.22.1 ### Bug Fixes From 3cf4616cd91f10dca5462cd16c5574051c7418be Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Mon, 16 Dec 2024 10:49:50 +0000 Subject: [PATCH 86/96] release: 5.22.1 --- sentry-delayed_job/lib/sentry/delayed_job/version.rb | 2 +- sentry-delayed_job/sentry-delayed_job.gemspec | 2 +- sentry-opentelemetry/lib/sentry/opentelemetry/version.rb | 2 +- sentry-opentelemetry/sentry-opentelemetry.gemspec | 2 +- sentry-rails/lib/sentry/rails/version.rb | 2 +- sentry-rails/sentry-rails.gemspec | 2 +- sentry-resque/lib/sentry/resque/version.rb | 2 +- sentry-resque/sentry-resque.gemspec | 2 +- sentry-ruby/lib/sentry/version.rb | 2 +- sentry-sidekiq/lib/sentry/sidekiq/version.rb | 2 +- sentry-sidekiq/sentry-sidekiq.gemspec | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sentry-delayed_job/lib/sentry/delayed_job/version.rb b/sentry-delayed_job/lib/sentry/delayed_job/version.rb index c927eab71..64ea7616b 100644 --- a/sentry-delayed_job/lib/sentry/delayed_job/version.rb +++ b/sentry-delayed_job/lib/sentry/delayed_job/version.rb @@ -2,6 +2,6 @@ module Sentry module DelayedJob - VERSION = "5.22.0" + VERSION = "5.22.1" end end diff --git a/sentry-delayed_job/sentry-delayed_job.gemspec b/sentry-delayed_job/sentry-delayed_job.gemspec index e669ef864..3f07ba88b 100644 --- a/sentry-delayed_job/sentry-delayed_job.gemspec +++ b/sentry-delayed_job/sentry-delayed_job.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.22.0" + spec.add_dependency "sentry-ruby", "~> 5.22.1" spec.add_dependency "delayed_job", ">= 4.0" end diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb index e45412dce..994c42977 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/version.rb @@ -2,6 +2,6 @@ module Sentry module OpenTelemetry - VERSION = "5.22.0" + VERSION = "5.22.1" end end diff --git a/sentry-opentelemetry/sentry-opentelemetry.gemspec b/sentry-opentelemetry/sentry-opentelemetry.gemspec index 70ccfe255..2b1385e54 100644 --- a/sentry-opentelemetry/sentry-opentelemetry.gemspec +++ b/sentry-opentelemetry/sentry-opentelemetry.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.22.0" + spec.add_dependency "sentry-ruby", "~> 5.22.1" spec.add_dependency "opentelemetry-sdk", "~> 1.0" end diff --git a/sentry-rails/lib/sentry/rails/version.rb b/sentry-rails/lib/sentry/rails/version.rb index d17f1a73c..99cb90c13 100644 --- a/sentry-rails/lib/sentry/rails/version.rb +++ b/sentry-rails/lib/sentry/rails/version.rb @@ -2,6 +2,6 @@ module Sentry module Rails - VERSION = "5.22.0" + VERSION = "5.22.1" end end diff --git a/sentry-rails/sentry-rails.gemspec b/sentry-rails/sentry-rails.gemspec index 597146887..69e8e45f3 100644 --- a/sentry-rails/sentry-rails.gemspec +++ b/sentry-rails/sentry-rails.gemspec @@ -31,5 +31,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "railties", ">= 5.0" - spec.add_dependency "sentry-ruby", "~> 5.22.0" + spec.add_dependency "sentry-ruby", "~> 5.22.1" end diff --git a/sentry-resque/lib/sentry/resque/version.rb b/sentry-resque/lib/sentry/resque/version.rb index 31143929e..b89656b63 100644 --- a/sentry-resque/lib/sentry/resque/version.rb +++ b/sentry-resque/lib/sentry/resque/version.rb @@ -2,6 +2,6 @@ module Sentry module Resque - VERSION = "5.22.0" + VERSION = "5.22.1" end end diff --git a/sentry-resque/sentry-resque.gemspec b/sentry-resque/sentry-resque.gemspec index f7d2076f6..9683fe3a5 100644 --- a/sentry-resque/sentry-resque.gemspec +++ b/sentry-resque/sentry-resque.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.22.0" + spec.add_dependency "sentry-ruby", "~> 5.22.1" spec.add_dependency "resque", ">= 1.24" end diff --git a/sentry-ruby/lib/sentry/version.rb b/sentry-ruby/lib/sentry/version.rb index 35f768ea7..f7bb5503c 100644 --- a/sentry-ruby/lib/sentry/version.rb +++ b/sentry-ruby/lib/sentry/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Sentry - VERSION = "5.22.0" + VERSION = "5.22.1" end diff --git a/sentry-sidekiq/lib/sentry/sidekiq/version.rb b/sentry-sidekiq/lib/sentry/sidekiq/version.rb index c490a94c0..e58872566 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/version.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/version.rb @@ -2,6 +2,6 @@ module Sentry module Sidekiq - VERSION = "5.22.0" + VERSION = "5.22.1" end end diff --git a/sentry-sidekiq/sentry-sidekiq.gemspec b/sentry-sidekiq/sentry-sidekiq.gemspec index b191f9886..924954e58 100644 --- a/sentry-sidekiq/sentry-sidekiq.gemspec +++ b/sentry-sidekiq/sentry-sidekiq.gemspec @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "sentry-ruby", "~> 5.22.0" + spec.add_dependency "sentry-ruby", "~> 5.22.1" spec.add_dependency "sidekiq", ">= 3.0" end From d21c5000d5d9e9fa5a8ba93403c2ed65a8173808 Mon Sep 17 00:00:00 2001 From: Jeffrey Hung <17494876+Jeffreyhung@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:39:21 -0800 Subject: [PATCH 87/96] Replace release bot with GH app (#2491) --- .github/workflows/prepare_batch_release.yml | 10 ++++++++-- .github/workflows/prepare_raven_release.yml | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/prepare_batch_release.yml b/.github/workflows/prepare_batch_release.yml index 38a785f29..987f2132e 100644 --- a/.github/workflows/prepare_batch_release.yml +++ b/.github/workflows/prepare_batch_release.yml @@ -13,14 +13,20 @@ jobs: runs-on: ubuntu-latest name: "Release a new version" steps: + - name: Get auth token + id: token + uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0 + with: + app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} + private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} - uses: actions/checkout@v2 with: - token: ${{ secrets.GH_RELEASE_PAT }} + token: ${{ steps.token.outputs.token }} fetch-depth: 0 - name: Prepare release uses: getsentry/action-prepare-release@v1 env: - GITHUB_TOKEN: ${{ secrets.GH_RELEASE_PAT }} + GITHUB_TOKEN: ${{ steps.token.outputs.token }} with: version: ${{ github.event.inputs.version }} force: ${{ github.event.inputs.force }} diff --git a/.github/workflows/prepare_raven_release.yml b/.github/workflows/prepare_raven_release.yml index 7c8504610..39dd4301a 100644 --- a/.github/workflows/prepare_raven_release.yml +++ b/.github/workflows/prepare_raven_release.yml @@ -13,14 +13,20 @@ jobs: runs-on: ubuntu-latest name: "Release a new version" steps: + - name: Get auth token + id: token + uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0 + with: + app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} + private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} - uses: actions/checkout@v2 with: - token: ${{ secrets.GH_RELEASE_PAT }} + token: ${{ steps.token.outputs.token }} fetch-depth: 0 - name: Prepare release uses: getsentry/action-prepare-release@v1 env: - GITHUB_TOKEN: ${{ secrets.GH_RELEASE_PAT }} + GITHUB_TOKEN: ${{ steps.token.outputs.token }} with: path: sentry-raven version: ${{ github.event.inputs.version }} From bb9ce728fe95c5c215ba891593983e1f226e1bb9 Mon Sep 17 00:00:00 2001 From: Krzysztof Jablonski Date: Thu, 19 Dec 2024 08:23:38 +0100 Subject: [PATCH 88/96] Improve the accuracy of duration calculations in cron jobs monitoring (#2471) * Update monitor_check_ins.rb * Update CHANGELOG.md --------- Co-authored-by: Peter Solnica --- CHANGELOG.md | 1 + sentry-ruby/lib/sentry/cron/monitor_check_ins.rb | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9377ad976..d7eed0898 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Add support for string errors in error reporter ([#2464](https://github.com/getsentry/sentry-ruby/pull/2464)) - Reset `trace_id` and add root transaction for sidekiq-cron [#2446](https://github.com/getsentry/sentry-ruby/pull/2446) - Add support for Excon HTTP client instrumentation ([#2383](https://github.com/getsentry/sentry-ruby/pull/2383)) +- Improve the accuracy of duration calculations in cron jobs monitoring ([#2471](https://github.com/getsentry/sentry-ruby/pull/2471)) Note: MemoryStore and FileStore require Rails 8.0+ diff --git a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb index 835ae84ad..314733cfb 100644 --- a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb +++ b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb @@ -14,12 +14,12 @@ def perform(*args, **opts) :in_progress, monitor_config: monitor_config) - start = Sentry.utc_now.to_i + start = Process.clock_gettime(Process::CLOCK_MONOTONIC) begin # need to do this on ruby <= 2.6 sadly ret = method(:perform).super_method.arity == 0 ? super() : super - duration = Sentry.utc_now.to_i - start + duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start Sentry.capture_check_in(slug, :ok, @@ -29,7 +29,7 @@ def perform(*args, **opts) ret rescue Exception - duration = Sentry.utc_now.to_i - start + duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start Sentry.capture_check_in(slug, :error, From 98b30d25f7cfe9e64429f3a7337436464a436899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Peignier?= Date: Wed, 18 Dec 2024 23:54:06 -0800 Subject: [PATCH 89/96] Default to internal_error rather than unknown_error (#2473) * Default to internal_error rather than unknown_error * Add tests for SpanProcessor#update_span_status * Update CHANGELOG * Update CHANGELOG.md --------- Co-authored-by: Peter Solnica --- CHANGELOG.md | 6 ++ .../sentry/opentelemetry/span_processor.rb | 2 +- .../opentelemetry/span_processor_spec.rb | 55 ++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7eed0898..ffb8a9c51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Bug fixes + +- Default to `internal_error` error type for OpenTelemetry spans [#2473](https://github.com/getsentry/sentry-ruby/pull/2473) + ## 5.22.1 ### Bug Fixes diff --git a/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb b/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb index fceef7e64..e898c6b33 100644 --- a/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb +++ b/sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb @@ -151,7 +151,7 @@ def update_span_status(sentry_span, otel_span) if (http_status_code = otel_span.attributes[SEMANTIC_CONVENTIONS::HTTP_STATUS_CODE]) sentry_span.set_http_status(http_status_code) elsif (status_code = otel_span.status.code) - status = [0, 1].include?(status_code) ? "ok" : "unknown_error" + status = [0, 1].include?(status_code) ? "ok" : "internal_error" sentry_span.set_status(status) end end diff --git a/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb b/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb index 0d5626730..a769e6783 100644 --- a/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb +++ b/sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb @@ -8,6 +8,27 @@ let(:tracer) { ::OpenTelemetry.tracer_provider.tracer('sentry', '1.0') } let(:empty_context) { ::OpenTelemetry::Context.empty } let(:invalid_span) { ::OpenTelemetry::SDK::Trace::Span::INVALID } + let(:error_span) do + attributes = { + 'http.method' => 'GET', + 'http.host' => 'sentry.io', + 'http.scheme' => 'https' + } + + tracer.start_root_span('HTTP GET', attributes: attributes, kind: :server).tap do |span| + span.status = OpenTelemetry::Trace::Status.error("not a success") + end + end + let(:http_error_span) do + attributes = { + 'http.method' => 'GET', + 'http.host' => 'sentry.io', + 'http.scheme' => 'https', + 'http.status_code' => '409' + } + + tracer.start_root_span('HTTP GET', attributes: attributes, kind: :server) + end let(:root_span) do attributes = { @@ -197,12 +218,16 @@ subject.on_start(root_span, empty_context) subject.on_start(child_db_span, root_parent_context) subject.on_start(child_http_span, root_parent_context) + subject.on_start(error_span, empty_context) + subject.on_start(http_error_span, empty_context) end let(:finished_db_span) { child_db_span.finish } let(:finished_http_span) { child_http_span.finish } let(:finished_root_span) { root_span.finish } let(:finished_invalid_span) { invalid_span.finish } + let(:finished_error_span) { error_span.finish } + let(:finished_http_error_span) { http_error_span.finish } it 'noops when not initialized' do expect(Sentry).to receive(:initialized?).and_return(false) @@ -224,6 +249,30 @@ subject.on_finish(finished_invalid_span) end + it 'updates span status on error' do + expect(subject.span_map).to receive(:delete).and_call_original + + span_id = finished_error_span.context.hex_span_id + sentry_span = subject.span_map[span_id] + + expect(sentry_span).to receive(:finish).and_call_original + subject.on_finish(finished_error_span) + + expect(sentry_span.status).to eq('internal_error') + end + + it 'updates span status on HTTP error' do + expect(subject.span_map).to receive(:delete).and_call_original + + span_id = finished_http_error_span.context.hex_span_id + sentry_span = subject.span_map[span_id] + + expect(sentry_span).to receive(:finish).and_call_original + subject.on_finish(finished_http_error_span) + + expect(sentry_span.status).to eq('already_exists') + end + it 'finishes sentry child span on otel child db span finish' do expect(subject.span_map).to receive(:delete).and_call_original @@ -241,7 +290,7 @@ expect(sentry_span.data).to include({ 'otel.kind' => finished_db_span.kind }) expect(sentry_span.timestamp).to eq(finished_db_span.end_timestamp / 1e9) - expect(subject.span_map.size).to eq(2) + expect(subject.span_map.size).to eq(4) expect(subject.span_map.keys).not_to include(span_id) end @@ -263,13 +312,15 @@ expect(sentry_span.timestamp).to eq(finished_http_span.end_timestamp / 1e9) expect(sentry_span.status).to eq('ok') - expect(subject.span_map.size).to eq(2) + expect(subject.span_map.size).to eq(4) expect(subject.span_map.keys).not_to include(span_id) end it 'finishes sentry transaction on otel root span finish' do subject.on_finish(finished_db_span) subject.on_finish(finished_http_span) + subject.on_finish(finished_error_span) + subject.on_finish(finished_http_error_span) expect(subject.span_map).to receive(:delete).and_call_original From e2322555d569d146a25613c6a395dbd43a17ac5a Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 19 Dec 2024 09:11:40 +0100 Subject: [PATCH 90/96] Update CHANGELOG.md (#2502) --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffb8a9c51..cd18e7413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased +### Features + +- Improve the accuracy of duration calculations in cron jobs monitoring ([#2471](https://github.com/getsentry/sentry-ruby/pull/2471)) + ### Bug fixes - Default to `internal_error` error type for OpenTelemetry spans [#2473](https://github.com/getsentry/sentry-ruby/pull/2473) @@ -18,13 +22,11 @@ - Add `include_sentry_event` matcher for RSpec [#2424](https://github.com/getsentry/sentry-ruby/pull/2424) - Add support for Sentry Cache instrumentation, when using Rails.cache [#2380](https://github.com/getsentry/sentry-ruby/pull/2380) + Note: MemoryStore and FileStore require Rails 8.0+ - Add support for Queue Instrumentation for Sidekiq. [#2403](https://github.com/getsentry/sentry-ruby/pull/2403) - Add support for string errors in error reporter ([#2464](https://github.com/getsentry/sentry-ruby/pull/2464)) - Reset `trace_id` and add root transaction for sidekiq-cron [#2446](https://github.com/getsentry/sentry-ruby/pull/2446) - Add support for Excon HTTP client instrumentation ([#2383](https://github.com/getsentry/sentry-ruby/pull/2383)) -- Improve the accuracy of duration calculations in cron jobs monitoring ([#2471](https://github.com/getsentry/sentry-ruby/pull/2471)) - - Note: MemoryStore and FileStore require Rails 8.0+ ### Bug Fixes From ad535cc67b6084329cbf5992c3a184a4b1f80a6b Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 19 Dec 2024 09:11:53 +0100 Subject: [PATCH 91/96] Add Metrics.duration_(start,end) (#2501) --- sentry-ruby/lib/sentry/cron/monitor_check_ins.rb | 6 +++--- sentry-ruby/lib/sentry/metrics/timing.rb | 8 ++++++++ sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb index 314733cfb..df7445286 100644 --- a/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb +++ b/sentry-ruby/lib/sentry/cron/monitor_check_ins.rb @@ -14,12 +14,12 @@ def perform(*args, **opts) :in_progress, monitor_config: monitor_config) - start = Process.clock_gettime(Process::CLOCK_MONOTONIC) + start = Metrics::Timing.duration_start begin # need to do this on ruby <= 2.6 sadly ret = method(:perform).super_method.arity == 0 ? super() : super - duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start + duration = Metrics::Timing.duration_end(start) Sentry.capture_check_in(slug, :ok, @@ -29,7 +29,7 @@ def perform(*args, **opts) ret rescue Exception - duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start + duration = Metrics::Timing.duration_end(start) Sentry.capture_check_in(slug, :error, diff --git a/sentry-ruby/lib/sentry/metrics/timing.rb b/sentry-ruby/lib/sentry/metrics/timing.rb index 510434583..6d4d9b66d 100644 --- a/sentry-ruby/lib/sentry/metrics/timing.rb +++ b/sentry-ruby/lib/sentry/metrics/timing.rb @@ -37,6 +37,14 @@ def day def week Sentry.utc_now.to_i / (3600.0 * 24.0 * 7.0) end + + def duration_start + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + + def duration_end(start) + Process.clock_gettime(Process::CLOCK_MONOTONIC) - start + end end end end diff --git a/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb b/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb index 48cd3e044..f34600699 100644 --- a/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb +++ b/sentry-ruby/spec/sentry/cron/monitor_check_ins_spec.rb @@ -123,6 +123,7 @@ def perform(a, b = 42, c: 99) expect(ok_event.monitor_slug).to eq('job') expect(ok_event.status).to eq(:ok) expect(ok_event.monitor_config).to be_nil + expect(ok_event.duration).to be > 0 end end @@ -162,6 +163,7 @@ def perform; work end expect(ok_event.monitor_slug).to eq('job') expect(ok_event.status).to eq(:ok) expect(ok_event.monitor_config).to be_nil + expect(ok_event.duration).to be > 0 end end From bf8d8c5ce3a12df04155fa85eb95a37ad779cf44 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Thu, 2 Jan 2025 08:29:29 +0800 Subject: [PATCH 92/96] Add multi-root workspace configuration file (#2505) Currently, to make LSP servers like Ruby LSP properly work for gem, like `sentry-ruby`, we need to open `/sentry-ruby` separately. When working on tasks across multiple gems, like `sentry-ruby` and `sentry-rails`, it requires 2 separate VS Code windows while each can not interact with each other. For example, when using `Debug` code lens provided by Ruby LSP in `sentry-rails`'s tests, we can put breakpoints inside `sentry-rails`'s codebase, but not in `sentry-ruby`. But if we open the project through this new workspace configuration file, the multi-root workspace feature in VS Code will allow us to - Access code across multiple gems - Debug code with VS Code across multiple gems - Run language servers independently for each gem --- CONTRIBUTING.md | 5 +++++ sentry-ruby.code-workspace | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 sentry-ruby.code-workspace diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3619eb371..8d2a93368 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,11 @@ You can contribute to this project in the following ways: And if you have any questions, please feel free to reach out on [Discord]. +## Develop This Project With Multi-root Workspaces + +If you use editors that support [VS Code-style multi-root workspaces](https://code.visualstudio.com/docs/editor/multi-root-workspaces), +such as VS Code, Cursor...etc., opening the editor with `sentry-ruby.code-workspace` file will provide a better development experience. + ## Contribute To Individual Gems - Install the dependencies of a specific gem by running `bundle` in it's subdirectory. I.e: diff --git a/sentry-ruby.code-workspace b/sentry-ruby.code-workspace new file mode 100644 index 000000000..5c90507e0 --- /dev/null +++ b/sentry-ruby.code-workspace @@ -0,0 +1,30 @@ +{ + "folders": [ + { + "path": "sentry-ruby" + }, + { + "path": "sentry-rails" + }, + { + "path": "sentry-sidekiq" + }, + { + "path": "sentry-delayed_job" + }, + { + "path": "sentry-resque" + }, + { + "path": "sentry-opentelemetry" + }, + { + "path": ".github" + } + ], + "extensions": { + "recommendations": [ + "Shopify.ruby-lsp" + ] + } +} From 7fe7f88419a5833fd471f26cab9ad4fea7d09113 Mon Sep 17 00:00:00 2001 From: Frederik Spang Date: Thu, 2 Jan 2025 11:42:37 +0100 Subject: [PATCH 93/96] Test Ruby 3.4; Upgrade actions workflows versions (#2506) * Update tons of actions, with ruby 3.4 * Add code.namespace support, which is possible in 3.4 * Fixes backtracecleaner with inline templates * Add CHANGELOG entry [ci skip] --- .github/workflows/build_batch_release.yml | 4 ++-- .github/workflows/build_release.yml | 6 +++--- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/lint.yml | 4 ++-- .github/workflows/prepare_batch_release.yml | 2 +- .github/workflows/prepare_raven_release.yml | 2 +- .github/workflows/sentry_delayed_job_test.yml | 4 ++-- .github/workflows/sentry_opentelemetry_test.yml | 4 ++-- .github/workflows/sentry_rails_test.yml | 6 ++++-- .github/workflows/sentry_raven_test.yml | 2 +- .github/workflows/sentry_resque_test.yml | 4 ++-- .github/workflows/sentry_ruby_test.yml | 9 +++++++-- .github/workflows/sentry_sidekiq_test.yml | 13 ++++++------- CHANGELOG.md | 7 +++++++ sentry-rails/lib/sentry/rails/backtrace_cleaner.rb | 2 +- .../rails/tracing/active_record_subscriber.rb | 1 + .../rails/tracing/active_record_subscriber_spec.rb | 2 ++ sentry-ruby/lib/sentry/backtrace.rb | 7 ++++--- 18 files changed, 49 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build_batch_release.yml b/.github/workflows/build_batch_release.yml index ff584e14d..9e8ed0776 100644 --- a/.github/workflows/build_batch_release.yml +++ b/.github/workflows/build_batch_release.yml @@ -9,11 +9,11 @@ jobs: name: Build gems runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.3 + ruby-version: 3.4 - name: Build gem source run: ruby .scripts/batch_build.rb - name: Archive Artifacts diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml index 3dfe24f81..ac02f9a3e 100644 --- a/.github/workflows/build_release.yml +++ b/.github/workflows/build_release.yml @@ -9,12 +9,12 @@ jobs: name: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: 3.4 - name: Capture sdk name uses: actions-ecosystem/action-regex-match@v2 id: regex-match diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index bd6958c10..a3cd6b1ab 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -42,7 +42,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 43180011d..5a0a66f0b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,11 +6,11 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: "3.3" + ruby-version: "3.4" bundler-cache: true - name: Run rubocop run: bundle exec rubocop diff --git a/.github/workflows/prepare_batch_release.yml b/.github/workflows/prepare_batch_release.yml index 987f2132e..4fbdce88a 100644 --- a/.github/workflows/prepare_batch_release.yml +++ b/.github/workflows/prepare_batch_release.yml @@ -19,7 +19,7 @@ jobs: with: app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: token: ${{ steps.token.outputs.token }} fetch-depth: 0 diff --git a/.github/workflows/prepare_raven_release.yml b/.github/workflows/prepare_raven_release.yml index 39dd4301a..871401fcf 100644 --- a/.github/workflows/prepare_raven_release.yml +++ b/.github/workflows/prepare_raven_release.yml @@ -19,7 +19,7 @@ jobs: with: app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: token: ${{ steps.token.outputs.token }} fetch-depth: 0 diff --git a/.github/workflows/sentry_delayed_job_test.yml b/.github/workflows/sentry_delayed_job_test.yml index cc8d52f4e..d162c5cd4 100644 --- a/.github/workflows/sentry_delayed_job_test.yml +++ b/.github/workflows/sentry_delayed_job_test.yml @@ -49,7 +49,7 @@ jobs: - { ruby_version: "head" } - { ruby_version: 'jruby-head' } steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Install sqlite run: | # See https://github.community/t5/GitHub-Actions/ubuntu-latest-Apt-repository-list-issues/td-p/41122/page/2 @@ -68,6 +68,6 @@ jobs: - name: Upload Coverage if: ${{ matrix.options.codecov }} - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_opentelemetry_test.yml b/.github/workflows/sentry_opentelemetry_test.yml index 913afadc0..fbe31e222 100644 --- a/.github/workflows/sentry_opentelemetry_test.yml +++ b/.github/workflows/sentry_opentelemetry_test.yml @@ -46,7 +46,7 @@ jobs: exclude: - { ruby_version: 'jruby-head' } steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Set up Ruby ${{ matrix.ruby_version }} uses: ruby/setup-ruby@v1 @@ -58,6 +58,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_rails_test.yml b/.github/workflows/sentry_rails_test.yml index b52abde8a..4573aae36 100644 --- a/.github/workflows/sentry_rails_test.yml +++ b/.github/workflows/sentry_rails_test.yml @@ -51,8 +51,10 @@ jobs: - { ruby_version: "3.1", rails_version: 7.2.0 } - { ruby_version: "3.2", rails_version: 7.2.0 } - { ruby_version: "3.3", rails_version: 7.2.0 } + - { ruby_version: "3.4", rails_version: 7.2.0 } - { ruby_version: "3.2", rails_version: "8.0.0" } - { ruby_version: "3.3", rails_version: "8.0.0" } + - { ruby_version: "3.4", rails_version: "8.0.0" } - { ruby_version: "jruby", rails_version: 6.1.0 } - { ruby_version: "3.2", @@ -67,7 +69,7 @@ jobs: rails_version: 7.1.0 } steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Install sqlite and ImageMagick run: | # See https://github.community/t5/GitHub-Actions/ubuntu-latest-Apt-repository-list-issues/td-p/41122/page/2 @@ -84,6 +86,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_raven_test.yml b/.github/workflows/sentry_raven_test.yml index c1732dd85..4e120cb24 100644 --- a/.github/workflows/sentry_raven_test.yml +++ b/.github/workflows/sentry_raven_test.yml @@ -48,7 +48,7 @@ jobs: rails_version: 6.0.0 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Set up Ruby ${{ matrix.ruby_version }} uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/sentry_resque_test.yml b/.github/workflows/sentry_resque_test.yml index d03411138..861187baa 100644 --- a/.github/workflows/sentry_resque_test.yml +++ b/.github/workflows/sentry_resque_test.yml @@ -44,7 +44,7 @@ jobs: exclude: - { ruby_version: 'jruby-head' } steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Set up Ruby ${{ matrix.ruby_version }} uses: ruby/setup-ruby@v1 with: @@ -67,6 +67,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_ruby_test.yml b/.github/workflows/sentry_ruby_test.yml index 2a1c9614e..b2b90e2a6 100644 --- a/.github/workflows/sentry_ruby_test.yml +++ b/.github/workflows/sentry_ruby_test.yml @@ -59,10 +59,15 @@ jobs: rack_version: 3.1, redis_rb_version: 5.3 } + - { + ruby_version: 3.4, + rack_version: 3.1, + redis_rb_version: 5.3 + } exclude: - { ruby_version: 'jruby-head' } steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Set up Ruby ${{ matrix.ruby_version }} uses: ruby/setup-ruby@v1 @@ -79,6 +84,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/sentry_sidekiq_test.yml b/.github/workflows/sentry_sidekiq_test.yml index 7b7768069..9ef84ff1a 100644 --- a/.github/workflows/sentry_sidekiq_test.yml +++ b/.github/workflows/sentry_sidekiq_test.yml @@ -28,7 +28,7 @@ jobs: fail-fast: false matrix: sidekiq_version: ["5.0", "6.5", "7.0"] - ruby_version: ["2.7", "3.0", "3.1", "3.2", "3.3", jruby] + ruby_version: ["2.7", "3.0", "3.1", "3.2", "3.3", "3.4", jruby] include: - { ruby_version: 2.4, sidekiq_version: 5.0 } - { ruby_version: 2.5, sidekiq_version: 5.0 } @@ -46,12 +46,11 @@ jobs: rubyopt: "--enable-frozen-string-literal --debug=frozen-string-literal", }, } - - { - ruby_version: "3.2", - sidekiq_version: 7.0 - } + - { ruby_version: "3.2", sidekiq_version: 7.0 } + - { ruby_version: "3.3", sidekiq_version: 7.0 } + - { ruby_version: "3.4", sidekiq_version: 7.0 } steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Set up Ruby ${{ matrix.ruby_version }} uses: ruby/setup-ruby@v1 @@ -70,6 +69,6 @@ jobs: run: bundle exec rake - name: Upload Coverage - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index cd18e7413..6b5df7420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,18 @@ ### Features - Improve the accuracy of duration calculations in cron jobs monitoring ([#2471](https://github.com/getsentry/sentry-ruby/pull/2471)) +- Support `code.namespace` for Ruby 3.4+ stacktraces ([#2506](https://github.com/getsentry/sentry-ruby/pull/2506)) + ### Bug fixes - Default to `internal_error` error type for OpenTelemetry spans [#2473](https://github.com/getsentry/sentry-ruby/pull/2473) +### Internal + +- Test Ruby 3.4 in CI ([#2506](https://github.com/getsentry/sentry-ruby/pull/2506)) +- Upgrade actions workflows versions ([#2506](https://github.com/getsentry/sentry-ruby/pull/2506)) + ## 5.22.1 ### Bug Fixes diff --git a/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb b/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb index 3400df7e0..ce32173a0 100644 --- a/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb +++ b/sentry-rails/lib/sentry/rails/backtrace_cleaner.rb @@ -7,7 +7,7 @@ module Sentry module Rails class BacktraceCleaner < ActiveSupport::BacktraceCleaner APP_DIRS_PATTERN = /\A(?:\.\/)?(?:app|config|lib|test|\(\w*\))/ - RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/ + RENDER_TEMPLATE_PATTERN = /:in (?:`|').*_\w+_{2,3}\d+_\d+'/ def initialize super diff --git a/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb b/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb index 480e7011a..09468b6cc 100644 --- a/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb +++ b/sentry-rails/lib/sentry/rails/tracing/active_record_subscriber.rb @@ -71,6 +71,7 @@ def subscribe! if source_location backtrace_line = Sentry::Backtrace::Line.parse(source_location) + span.set_data(Span::DataConventions::FILEPATH, backtrace_line.file) if backtrace_line.file span.set_data(Span::DataConventions::LINENO, backtrace_line.number) if backtrace_line.number span.set_data(Span::DataConventions::FUNCTION, backtrace_line.method) if backtrace_line.method diff --git a/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb b/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb index 2441a63d3..be674869f 100644 --- a/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb +++ b/sentry-rails/spec/sentry/rails/tracing/active_record_subscriber_spec.rb @@ -51,6 +51,7 @@ def foo Post.all.to_a end query_line = __LINE__ - 2 + rspec_class = self.name # RSpec::ExampleGroups::[....] before do transaction = Sentry::Transaction.new(sampled: true, hub: Sentry.get_current_hub) @@ -94,6 +95,7 @@ def foo data = span[:data] expect(data["code.filepath"]).to eq(__FILE__) expect(data["code.lineno"]).to eq(query_line) + expect(data["code.namespace"]).to eq(rspec_class) if RUBY_VERSION.to_f >= 3.4 expect(data["code.function"]).to eq("foo") end end diff --git a/sentry-ruby/lib/sentry/backtrace.rb b/sentry-ruby/lib/sentry/backtrace.rb index 5fd2aadff..7c17adfec 100644 --- a/sentry-ruby/lib/sentry/backtrace.rb +++ b/sentry-ruby/lib/sentry/backtrace.rb @@ -12,7 +12,7 @@ class Line RUBY_INPUT_FORMAT = / ^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>): (\d+) - (?: :in\s('|`)([^']+)')?$ + (?: :in\s('|`)(?:([\w:]+)\#)?([^']+)')?$ /x # org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170) @@ -37,10 +37,11 @@ class Line # @return [Line] The parsed backtrace line def self.parse(unparsed_line, in_app_pattern = nil) ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT) + if ruby_match - _, file, number, _, method = ruby_match.to_a + _, file, number, _, module_name, method = ruby_match.to_a file.sub!(/\.class$/, RB_EXTENSION) - module_name = nil + module_name = module_name else java_match = unparsed_line.match(JAVA_INPUT_FORMAT) _, module_name, method, file, number = java_match.to_a From 4a0f70e9980dd8934b8ec3246dc0cea4c91d3996 Mon Sep 17 00:00:00 2001 From: Ben Hutton Date: Thu, 2 Jan 2025 07:44:05 -0500 Subject: [PATCH 94/96] Use attempt_threshold to skip reporting on first N attempts (#2503) Co-authored-by: Peter Solnica Closes #1632 --- CHANGELOG.md | 2 +- .../lib/sentry/sidekiq/error_handler.rb | 13 ++++++ sentry-sidekiq/spec/sentry/sidekiq_spec.rb | 41 +++++++++++++++---- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b5df7420..920b85fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,9 @@ ### Features - Improve the accuracy of duration calculations in cron jobs monitoring ([#2471](https://github.com/getsentry/sentry-ruby/pull/2471)) +- Use attempt_threshold to skip reporting on first N attempts ([#2503](https://github.com/getsentry/sentry-ruby/pull/2503)) - Support `code.namespace` for Ruby 3.4+ stacktraces ([#2506](https://github.com/getsentry/sentry-ruby/pull/2506)) - ### Bug fixes - Default to `internal_error` error type for OpenTelemetry spans [#2473](https://github.com/getsentry/sentry-ruby/pull/2473) diff --git a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb index 50c720929..64659df1e 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/error_handler.rb @@ -31,6 +31,19 @@ def call(ex, context, sidekiq_config = nil) end end + # Check if the retry count is below the attempt_threshold + attempt_threshold = context.dig(:job, "attempt_threshold") + if attempt_threshold && retryable?(context) + attempt_threshold = attempt_threshold.to_i + retry_count = context.dig(:job, "retry_count") + # attempt 1 - retry_count is nil + # attempt 2 - this is your first retry so retry_count is 0 + # attempt 3 - you have retried once, retry_count is 1 + attempt = retry_count.nil? ? 1 : retry_count.to_i + 2 + + return if attempt < attempt_threshold + end + Sentry::Sidekiq.capture_exception( ex, contexts: { sidekiq: context_filter.filtered }, diff --git a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb index 4c788c9ce..110ea850a 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq_spec.rb @@ -109,18 +109,45 @@ expect(retry_set.count).to eq(1) end + def retry_last_failed_job + retry_set.first.add_to_queue + job = queue.first + work = Sidekiq::BasicFetch::UnitOfWork.new('queue:default', job.value) + process_work(processor, work) + end + + context "with attempt_threshold" do + it "doesn't report the error until attempts equal the threshold" do + worker = Class.new(SadWorker) + worker.sidekiq_options attempt_threshold: 3 + + execute_worker(processor, worker) + expect(transport.events.count).to eq(0) + + retry_last_failed_job + expect(transport.events.count).to eq(0) + + retry_last_failed_job + expect(transport.events.count).to eq(1) + end + + it "doesn't report the error when threshold is not reached" do + worker = Class.new(SadWorker) + worker.sidekiq_options attempt_threshold: 3 + + execute_worker(processor, worker) + expect(transport.events.count).to eq(0) + + retry_last_failed_job + expect(transport.events.count).to eq(0) + end + end + context "with config.report_after_job_retries = true" do before do Sentry.configuration.sidekiq.report_after_job_retries = true end - def retry_last_failed_job - retry_set.first.add_to_queue - job = queue.first - work = Sidekiq::BasicFetch::UnitOfWork.new('queue:default', job.value) - process_work(processor, work) - end - context "when retry: is specified" do it "doesn't report the error until retries are exhuasted" do worker = Class.new(SadWorker) From 7ad595a41ecb3a7aee8c22f8a8f39ec467b6be1f Mon Sep 17 00:00:00 2001 From: Karl Entwistle Date: Thu, 2 Jan 2025 13:49:45 +0000 Subject: [PATCH 95/96] Ignore Sidekiq::JobRetry::Handled exception (#2337) * Ignore Sidekiq::JobRetry::Handled exception * Style/TrailingCommaInArrayLiteral * Update CHANGELOG --------- Co-authored-by: Karl Entwistle --- CHANGELOG.md | 1 + sentry-sidekiq/lib/sentry/sidekiq/configuration.rb | 5 ++++- sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 920b85fb2..954b4ac33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ ### Bug Fixes +- Ignore internal Sidekiq::JobRetry::Handled exception [#2337](https://github.com/getsentry/sentry-ruby/pull/2337) - Fix Vernier profiler not stopping when already stopped [#2429](https://github.com/getsentry/sentry-ruby/pull/2429) - Fix `send_default_pii` handling in rails controller spans [#2443](https://github.com/getsentry/sentry-ruby/pull/2443) - Fixes [#2438](https://github.com/getsentry/sentry-ruby/issues/2438) diff --git a/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb b/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb index b6ef3856c..eea6f4c35 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/configuration.rb @@ -11,7 +11,10 @@ class Configuration end module Sidekiq - IGNORE_DEFAULT = ["Sidekiq::JobRetry::Skip"] + IGNORE_DEFAULT = [ + "Sidekiq::JobRetry::Skip", + "Sidekiq::JobRetry::Handled" + ] class Configuration # Set this option to true if you want Sentry to only capture the last job diff --git a/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb index 7e9066ffe..2bcab6c58 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/configuration_spec.rb @@ -15,6 +15,12 @@ expect(config.excluded_exceptions).to include("Sidekiq::JobRetry::Skip") end + it "adds Sidekiq::JobRetry::Handled to the ignore list" do + config = Sentry::Configuration.new + + expect(config.excluded_exceptions).to include("Sidekiq::JobRetry::Handled") + end + describe "#report_after_job_retries" do it "has correct default value" do expect(subject.report_after_job_retries).to eq(false) From a9301f39bf716d890a702e0c8b17c8ff9059f1f3 Mon Sep 17 00:00:00 2001 From: Olivier Bellone Date: Thu, 2 Jan 2025 13:02:40 -0800 Subject: [PATCH 96/96] Fix ActiveJob tests for Rails 7.2 and 8.0 (#2487) --- sentry-rails/Gemfile | 2 +- sentry-rails/spec/sentry/rails/activejob_spec.rb | 4 ++-- sentry-rails/spec/spec_helper.rb | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sentry-rails/Gemfile b/sentry-rails/Gemfile index 5000bb3b2..53cfb92d7 100644 --- a/sentry-rails/Gemfile +++ b/sentry-rails/Gemfile @@ -22,7 +22,7 @@ gem "rails", "~> #{rails_version}" if rails_version >= Gem::Version.new("8.0.0") gem "rspec-rails" - gem "sqlite3", platform: :ruby + gem "sqlite3", "~> 2.1.1", platform: :ruby elsif rails_version >= Gem::Version.new("7.1.0") gem "rspec-rails" gem "sqlite3", "~> 1.7.3", platform: :ruby diff --git a/sentry-rails/spec/sentry/rails/activejob_spec.rb b/sentry-rails/spec/sentry/rails/activejob_spec.rb index cf986d937..ffcb4d44c 100644 --- a/sentry-rails/spec/sentry/rails/activejob_spec.rb +++ b/sentry-rails/spec/sentry/rails/activejob_spec.rb @@ -68,7 +68,7 @@ class FailedJobWithCron < FailedJob end -RSpec.describe "without Sentry initialized" do +RSpec.describe "without Sentry initialized", type: :job do it "runs job" do expect { FailedJob.perform_now }.to raise_error(FailedJob::TestError) end @@ -78,7 +78,7 @@ class FailedJobWithCron < FailedJob end end -RSpec.describe "ActiveJob integration" do +RSpec.describe "ActiveJob integration", type: :job do before do make_basic_app end diff --git a/sentry-rails/spec/spec_helper.rb b/sentry-rails/spec/spec_helper.rb index 68b7d5a04..5928e7134 100644 --- a/sentry-rails/spec/spec_helper.rb +++ b/sentry-rails/spec/spec_helper.rb @@ -56,6 +56,8 @@ ENV.delete('RAILS_ENV') ENV.delete('RACK_ENV') end + + config.include ActiveJob::TestHelper, type: :job end def reload_send_event_job