Skip to content

Bump sentry-ruby from 6.5.0 to 6.6.1#1001

Closed
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/bundler/sentry-ruby-6.6.1
Closed

Bump sentry-ruby from 6.5.0 to 6.6.1#1001
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/bundler/sentry-ruby-6.6.1

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jun 9, 2026

Copy link
Copy Markdown
Contributor

Bumps sentry-ruby from 6.5.0 to 6.6.1.

Changelog

Sourced from sentry-ruby's changelog.

6.6.1

Bug Fixes 🐛

6.6.0

New Features ✨

  • (yabeda) Add sentry-yabeda adapter gem by @​dingsdax in #2925

    There's a new sentry-yabeda gem that integrates Sentry Metrics with Yabeda. Add the new gem to your Gemfile:

    gem "sentry-yabeda"

    Initialize Sentry with metrics enabled. The Yabeda adapter registers itself automatically when sentry-yabeda is required — there's no extra setup:

    Sentry.init do |config|
      config.dsn = ENV["SENTRY_DSN"]
      config.enable_metrics = true
    end
  • Add release detection from Kamal deployment by @​t27duck in #2895

Bug Fixes 🐛

Internal Changes 🔧

We made some memory performance and caching improvements with the help of pi-autoresearch. Enjoy the lower overhead!

Commits
  • 3a55ed2 release: 6.6.1
  • 129ada3 fix: guard TelemetryEventBuffer against re-entrant mutex acquisition (#2964)
  • 1754a7f release: 6.6.0
  • af610cd fix(stacktrace): stop leaking internal frame state into event payload (#2962)
  • 427612b fix(tests): proper dummy transport clean up for hub cloning (#2957)
  • 3b64cc2 feat(yabeda): Add sentry-yabeda adapter gem (#2925)
  • f6e0ad1 perf: Use FilenameCache in profilers (#2919)
  • e2a073a perf: Add FilenameCache to cache compute_filename results (#2904)
  • 0dd3f05 test: Fix flaky concurrent test in telemetry buffer (#2920)
  • 688bd62 Add release detection from Kamal deployment (#2895)
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [sentry-ruby](https://github.com/getsentry/sentry-ruby) from 6.5.0 to 6.6.1.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](getsentry/sentry-ruby@6.5.0...6.6.1)

---
updated-dependencies:
- dependency-name: sentry-ruby
  dependency-version: 6.6.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies ruby Pull requests that update Ruby code labels Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

4 similar comments
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT homepage:
    6.5.0: https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby
    6.6.1: https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby
  DIFFERENT metadata:
    6.5.0: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.5.0/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.5.0"}
    6.6.1: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.6.1/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.6.1"}
  DIFFERENT version:
    6.5.0: 6.5.0
    6.6.1: 6.6.1
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
            lib/sentry/utils/filename_cache.rb +47/-0
      * Changed:
            README.md +3/-0
            lib/sentry-ruby.rb +1/-0
            lib/sentry/backtrace.rb +6/-4
            lib/sentry/backtrace/line.rb +16/-9
            lib/sentry/configuration.rb +7/-1
            lib/sentry/hub.rb +6/-0
            lib/sentry/interfaces/request.rb +13/-4
            lib/sentry/interfaces/stacktrace.rb +2/-29
            lib/sentry/interfaces/stacktrace_builder.rb +22/-6
            lib/sentry/linecache.rb +18/-21
            lib/sentry/profiler.rb +1/-0
            lib/sentry/profiler/helpers.rb +1/-21
            lib/sentry/release_detector.rb +5/-0
            lib/sentry/telemetry_event_buffer.rb +3/-0
            lib/sentry/test_helper.rb +41/-8
            lib/sentry/transport/dummy_transport.rb +7/-0
            lib/sentry/utils/http_tracing.rb +7/-1
            lib/sentry/vernier/output.rb +2/-1
            lib/sentry/vernier/profiler.rb +3/-1
            lib/sentry/version.rb +1/-1
  DIFFERENT extra_rdoc_files:
    6.5.0->6.6.1:
      * Changed:
            README.md +3/-0

4 similar comments
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT homepage:
    6.5.0: https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby
    6.6.1: https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby
  DIFFERENT metadata:
    6.5.0: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.5.0/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.5.0"}
    6.6.1: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.6.1/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.6.1"}
  DIFFERENT version:
    6.5.0: 6.5.0
    6.6.1: 6.6.1
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
            lib/sentry/utils/filename_cache.rb +47/-0
      * Changed:
            README.md +3/-0
            lib/sentry-ruby.rb +1/-0
            lib/sentry/backtrace.rb +6/-4
            lib/sentry/backtrace/line.rb +16/-9
            lib/sentry/configuration.rb +7/-1
            lib/sentry/hub.rb +6/-0
            lib/sentry/interfaces/request.rb +13/-4
            lib/sentry/interfaces/stacktrace.rb +2/-29
            lib/sentry/interfaces/stacktrace_builder.rb +22/-6
            lib/sentry/linecache.rb +18/-21
            lib/sentry/profiler.rb +1/-0
            lib/sentry/profiler/helpers.rb +1/-21
            lib/sentry/release_detector.rb +5/-0
            lib/sentry/telemetry_event_buffer.rb +3/-0
            lib/sentry/test_helper.rb +41/-8
            lib/sentry/transport/dummy_transport.rb +7/-0
            lib/sentry/utils/http_tracing.rb +7/-1
            lib/sentry/vernier/output.rb +2/-1
            lib/sentry/vernier/profiler.rb +3/-1
            lib/sentry/version.rb +1/-1
  DIFFERENT extra_rdoc_files:
    6.5.0->6.6.1:
      * Changed:
            README.md +3/-0

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT homepage:
    6.5.0: https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby
    6.6.1: https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby
  DIFFERENT metadata:
    6.5.0: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.5.0/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.5.0"}
    6.6.1: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.6.1/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.6.1"}
  DIFFERENT version:
    6.5.0: 6.5.0
    6.6.1: 6.6.1
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
            lib/sentry/utils/filename_cache.rb +47/-0
      * Changed:
            README.md +3/-0
            lib/sentry-ruby.rb +1/-0
            lib/sentry/backtrace.rb +6/-4
            lib/sentry/backtrace/line.rb +16/-9
            lib/sentry/configuration.rb +7/-1
            lib/sentry/hub.rb +6/-0
            lib/sentry/interfaces/request.rb +13/-4
            lib/sentry/interfaces/stacktrace.rb +2/-29
            lib/sentry/interfaces/stacktrace_builder.rb +22/-6
            lib/sentry/linecache.rb +18/-21
            lib/sentry/profiler.rb +1/-0
            lib/sentry/profiler/helpers.rb +1/-21
            lib/sentry/release_detector.rb +5/-0
            lib/sentry/telemetry_event_buffer.rb +3/-0
            lib/sentry/test_helper.rb +41/-8
            lib/sentry/transport/dummy_transport.rb +7/-0
            lib/sentry/utils/http_tracing.rb +7/-1
            lib/sentry/vernier/output.rb +2/-1
            lib/sentry/vernier/profiler.rb +3/-1
            lib/sentry/version.rb +1/-1
  DIFFERENT extra_rdoc_files:
    6.5.0->6.6.1:
      * Changed:
            README.md +3/-0

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT homepage:
    6.5.0: https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby
    6.6.1: https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby
  DIFFERENT metadata:
    6.5.0: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.5.0/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.5.0"}
    6.6.1: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.6.1/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.6.1"}
  DIFFERENT version:
    6.5.0: 6.5.0
    6.6.1: 6.6.1
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
            lib/sentry/utils/filename_cache.rb +47/-0
      * Changed:
            README.md +3/-0
            lib/sentry-ruby.rb +1/-0
            lib/sentry/backtrace.rb +6/-4
            lib/sentry/backtrace/line.rb +16/-9
            lib/sentry/configuration.rb +7/-1
            lib/sentry/hub.rb +6/-0
            lib/sentry/interfaces/request.rb +13/-4
            lib/sentry/interfaces/stacktrace.rb +2/-29
            lib/sentry/interfaces/stacktrace_builder.rb +22/-6
            lib/sentry/linecache.rb +18/-21
            lib/sentry/profiler.rb +1/-0
            lib/sentry/profiler/helpers.rb +1/-21
            lib/sentry/release_detector.rb +5/-0
            lib/sentry/telemetry_event_buffer.rb +3/-0
            lib/sentry/test_helper.rb +41/-8
            lib/sentry/transport/dummy_transport.rb +7/-0
            lib/sentry/utils/http_tracing.rb +7/-1
            lib/sentry/vernier/output.rb +2/-1
            lib/sentry/vernier/profiler.rb +3/-1
            lib/sentry/version.rb +1/-1
  DIFFERENT extra_rdoc_files:
    6.5.0->6.6.1:
      * Changed:
            README.md +3/-0

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT homepage:
    6.5.0: https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby
    6.6.1: https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby
  DIFFERENT metadata:
    6.5.0: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.5.0/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.5.0/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.5.0"}
    6.6.1: {"homepage_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "source_code_uri" => "https://github.com/getsentry/sentry-ruby/tree/6.6.1/sentry-ruby", "changelog_uri" => "https://github.com/getsentry/sentry-ruby/blob/6.6.1/CHANGELOG.md", "bug_tracker_uri" => "https://github.com/getsentry/sentry-ruby/issues", "documentation_uri" => "http://www.rubydoc.info/gems/sentry-ruby/6.6.1"}
  DIFFERENT version:
    6.5.0: 6.5.0
    6.6.1: 6.6.1
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
            lib/sentry/utils/filename_cache.rb +47/-0
      * Changed:
            README.md +3/-0
            lib/sentry-ruby.rb +1/-0
            lib/sentry/backtrace.rb +6/-4
            lib/sentry/backtrace/line.rb +16/-9
            lib/sentry/configuration.rb +7/-1
            lib/sentry/hub.rb +6/-0
            lib/sentry/interfaces/request.rb +13/-4
            lib/sentry/interfaces/stacktrace.rb +2/-29
            lib/sentry/interfaces/stacktrace_builder.rb +22/-6
            lib/sentry/linecache.rb +18/-21
            lib/sentry/profiler.rb +1/-0
            lib/sentry/profiler/helpers.rb +1/-21
            lib/sentry/release_detector.rb +5/-0
            lib/sentry/telemetry_event_buffer.rb +3/-0
            lib/sentry/test_helper.rb +41/-8
            lib/sentry/transport/dummy_transport.rb +7/-0
            lib/sentry/utils/http_tracing.rb +7/-1
            lib/sentry/vernier/output.rb +2/-1
            lib/sentry/vernier/profiler.rb +3/-1
            lib/sentry/version.rb +1/-1
  DIFFERENT extra_rdoc_files:
    6.5.0->6.6.1:
      * Changed:
            README.md +3/-0

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare --diff sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
        lib/sentry/utils/filename_cache.rb
                --- /tmp/20260609-724-ucgs8f	2026-06-09 02:33:31.328936460 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/utils/filename_cache.rb	2026-06-09 02:33:31.326936433 +0000
                @@ -0,0 +1,47 @@
                +# frozen_string_literal: true
                +
                +module Sentry
                +  class FilenameCache
                +    attr_reader :cache
                +
                +    def initialize(project_root)
                +      @project_root = project_root
                +      @load_paths = $LOAD_PATH.map(&:to_s).sort_by(&:size).reverse.freeze
                +      @cache = {}
                +    end
                +
                +    def compute_filename(abs_path, in_app, strip_backtrace_load_path)
                +      return unless abs_path
                +      return abs_path unless strip_backtrace_load_path
                +
                +      @cache.fetch(abs_path) do
                +        under_root = @project_root && abs_path.start_with?(@project_root)
                +        prefix =
                +          if under_root && in_app
                +            @project_root
                +          elsif under_root
                +            longest_load_path(abs_path) || @project_root
                +          else
                +            longest_load_path(abs_path)
                +          end
                +
                +        @cache[abs_path] = if prefix
                +          offset = if prefix.end_with?(File::SEPARATOR)
                +            prefix.bytesize
                +          else
                +            prefix.bytesize + 1
                +          end
                +          abs_path.byteslice(offset, abs_path.bytesize - offset)
                +        else
                +          abs_path
                +        end
                +      end
                +    end
                +
                +    private
                +
                +    def longest_load_path(abs_path)
                +      @load_paths.find { |path| abs_path.start_with?(path) }
                +    end
                +  end
                +end
      * Changed:
        README.md
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/README.md	2026-06-09 02:33:31.309936198 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/README.md	2026-06-09 02:33:31.319936336 +0000
                @@ -23,0 +24 @@
                +| [![Gem Version](https://img.shields.io/gem/v/sentry-yabeda?label=sentry-yabeda)](https://rubygems.org/gems/sentry-yabeda) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [![codecov](https://codecov.io/gh/getsentry/sentry-ruby/graph/badge.svg?token=ZePzrpZFP6&component=sentry-yabeda)](https://codecov.io/gh/getsentry/sentry-ruby) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-yabeda) |
                @@ -55,0 +57 @@
                +gem "sentry-yabeda"
                @@ -95,0 +98 @@
                +- [Yabeda](https://docs.sentry.io/platforms/ruby/guides/yabeda/)
        lib/sentry-ruby.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry-ruby.rb	2026-06-09 02:33:31.309936198 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry-ruby.rb	2026-06-09 02:33:31.319936336 +0000
                @@ -270,0 +271 @@
                +        client.configuration.run_after_close_callbacks
        lib/sentry/backtrace.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/backtrace.rb	2026-06-09 02:33:31.310936212 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/backtrace.rb	2026-06-09 02:33:31.319936336 +0000
                @@ -13 +13,3 @@
                -    def self.parse(backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback)
                +    # @deprecated project_root, in_app_pattern passed from outside
                +    # @deprecated app_dirs_pattern, in_app_pattern passed from outside
                +    def self.parse(backtrace, project_root, app_dirs_pattern, in_app_pattern: nil, &backtrace_cleanup_callback)
                @@ -18,3 +20,3 @@
                -      in_app_pattern ||= begin
                -        Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
                -      end
                +      # in_app_pattern is now passed in from StacktraceBuilder, so this regex won't be triggered
                +      # only here for backwards compat and will be deleted
                +      in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
        lib/sentry/backtrace/line.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/backtrace/line.rb	2026-06-09 02:33:31.310936212 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/backtrace/line.rb	2026-06-09 02:33:31.320936350 +0000
                @@ -8,0 +9 @@
                +      CLASS_EXTENSION = ".class"
                @@ -40,3 +41,7 @@
                -          _, file, number, _, module_name, method = ruby_match.to_a
                -          file.sub!(/\.class$/, RB_EXTENSION)
                -          module_name = module_name
                +          file = ruby_match[1]
                +          number = ruby_match[2]
                +          module_name = ruby_match[4]
                +          method = ruby_match[5]
                +          if file.end_with?(CLASS_EXTENSION)
                +            file.sub!(/\.class$/, RB_EXTENSION)
                +          end
                @@ -45 +50,6 @@
                -          _, module_name, method, file, number = java_match.to_a
                +          if java_match
                +            module_name = java_match[1]
                +            method = java_match[2]
                +            file = java_match[3]
                +            number = java_match[4]
                +          end
                @@ -76,0 +87 @@
                +        return false unless file
                @@ -78,5 +89 @@
                -        if file =~ in_app_pattern
                -          true
                -        else
                -          false
                -        end
                +        file.match?(in_app_pattern)
        lib/sentry/configuration.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/configuration.rb	2026-06-09 02:33:31.311936226 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/configuration.rb	2026-06-09 02:33:31.320936350 +0000
                @@ -464 +464,2 @@
                -          configured: { before: [], after: [] }
                +          configured: { before: [], after: [] },
                +          closed: { before: [], after: [] }
                @@ -798,0 +800,5 @@
                +    end
                +
                +    # @api private
                +    def run_after_close_callbacks
                +      run_callbacks(:after, :closed)
        lib/sentry/hub.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/hub.rb	2026-06-09 02:33:31.313936253 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/hub.rb	2026-06-09 02:33:31.322936377 +0000
                @@ -56,0 +57,6 @@
                +    # All clients bound across the hub's scope stack, base layer first.
                +    # @return [Array<Client>]
                +    def clients
                +      @stack.map(&:client).compact
                +    end
                +
        lib/sentry/interfaces/request.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/interfaces/request.rb	2026-06-09 02:33:31.313936253 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/interfaces/request.rb	2026-06-09 02:33:31.322936377 +0000
                @@ -13,0 +14,3 @@
                +    # Regex to detect lowercase chars — match? is allocation-free (no MatchData/String)
                +    LOWERCASE_PATTERN = /[a-z]/.freeze
                +
                @@ -96 +99 @@
                -          key = key.sub(/^HTTP_/, "")
                +          key = key.delete_prefix("HTTP_")
                @@ -111 +114 @@
                -      key.upcase != key || # lower-case envs aren't real http headers
                +      key.match?(LOWERCASE_PATTERN) || # lower-case envs aren't real http headers
                @@ -122,2 +125 @@
                -      rack_version = Gem::Version.new(::Rack.release)
                -      return false if rack_version >= Gem::Version.new("3.0")
                +      return false if self.class.rack_3_or_above?
                @@ -125,0 +128,7 @@
                +    end
                +
                +    def self.rack_3_or_above?
                +      return @rack_3_or_above if defined?(@rack_3_or_above)
                +
                +      @rack_3_or_above = defined?(::Rack) &&
                +        Gem::Version.new(::Rack.release) >= Gem::Version.new("3.0")
        lib/sentry/interfaces/stacktrace.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:31.313936253 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:31.322936377 +0000
                @@ -30,4 +30 @@
                -      def initialize(project_root, line, strip_backtrace_load_path = true)
                -        @project_root = project_root
                -        @strip_backtrace_load_path = strip_backtrace_load_path
                -
                +      def initialize(project_root, line, strip_backtrace_load_path = true, filename_cache: nil)
                @@ -39 +36 @@
                -        @filename = compute_filename
                +        @filename = filename_cache&.compute_filename(@abs_path, @in_app, strip_backtrace_load_path)
                @@ -46,16 +42,0 @@
                -      def compute_filename
                -        return if abs_path.nil?
                -        return abs_path unless @strip_backtrace_load_path
                -
                -        prefix =
                -          if under_project_root? && in_app
                -            @project_root
                -          elsif under_project_root?
                -            longest_load_path || @project_root
                -          else
                -            longest_load_path
                -          end
                -
                -        prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
                -      end
                -
                @@ -79,8 +59,0 @@
                -
                -      def under_project_root?
                -        @project_root && abs_path.start_with?(@project_root)
                -      end
                -
                -      def longest_load_path
                -        $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
                -      end
        lib/sentry/interfaces/stacktrace_builder.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:31.313936253 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:31.323936391 +0000
                @@ -2,0 +3,2 @@
                +require "sentry/utils/filename_cache"
                +
                @@ -22,0 +25,3 @@
                +    # @return [FilenameCache]
                +    attr_reader :filename_cache
                +
                @@ -48,0 +54,2 @@
                +      @in_app_pattern = Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}") if app_dirs_pattern
                +      @filename_cache = FilenameCache.new(project_root)
                @@ -67 +74,10 @@
                -      parsed_lines = parse_backtrace_lines(backtrace).select(&:file)
                +      parsed_lines = parse_backtrace_lines(backtrace)
                +
                +      # Build frames in reverse order, skipping lines without files
                +      # Single pass instead of select + reverse + map + compact
                +      frames = []
                +      i = parsed_lines.size - 1
                +      while i >= 0
                +        line = parsed_lines[i]
                +        i -= 1
                +        next unless line.file
                @@ -69 +84,0 @@
                -      frames = parsed_lines.reverse.map do |line|
                @@ -72,2 +87,2 @@
                -        frame
                -      end.compact
                +        frames << frame if frame
                +      end
                @@ -81 +96 @@
                -      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path)
                +      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path, filename_cache: @filename_cache)
                @@ -88 +103,2 @@
                -        backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback
                +        backtrace, project_root, app_dirs_pattern,
                +        in_app_pattern: @in_app_pattern, &backtrace_cleanup_callback
        lib/sentry/linecache.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/linecache.rb	2026-06-09 02:33:31.314936267 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/linecache.rb	2026-06-09 02:33:31.323936391 +0000
                @@ -15 +15,2 @@
                -      return nil, nil, nil unless valid_path?(filename)
                +      lines = getlines(filename)
                +      return nil, nil, nil unless lines
                @@ -17,4 +18,6 @@
                -      lines = Array.new(2 * context + 1) do |i|
                -        getline(filename, lineno - context + i)
                -      end
                -      [lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]]
                +      first_line = lineno - context
                +      pre = Array.new(context) { |i| line_at(lines, first_line + i) }
                +      context_line = line_at(lines, lineno)
                +      post = Array.new(context) { |i| line_at(lines, lineno + 1 + i) }
                +
                +      [pre, context_line, post]
                @@ -25,3 +28,4 @@
                -    def valid_path?(path)
                -      lines = getlines(path)
                -      !lines.nil?
                +    def line_at(lines, n)
                +      return nil if n < 1
                +
                +      lines[n - 1]
                @@ -31,4 +35,6 @@
                -      @cache[path] ||= begin
                -        File.open(path, "r", &:readlines)
                -      rescue
                -        nil
                +      @cache.fetch(path) do
                +        @cache[path] = begin
                +          File.open(path, "r", &:readlines)
                +        rescue
                +          nil
                +        end
                @@ -36,9 +41,0 @@
                -    end
                -
                -    def getline(path, n)
                -      return nil if n < 1
                -
                -      lines = getlines(path)
                -      return nil if lines.nil?
                -
                -      lines[n - 1]
        lib/sentry/profiler.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/profiler.rb	2026-06-09 02:33:31.314936267 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/profiler.rb	2026-06-09 02:33:31.323936391 +0000
                @@ -28,0 +29 @@
                +      @filename_cache = configuration.stacktrace_builder.filename_cache
        lib/sentry/profiler/helpers.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:31.314936267 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:31.323936391 +0000
                @@ -12,3 +11,0 @@
                -      # 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
                @@ -16,18 +13 @@
                -        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
                +        @filename_cache.compute_filename(abs_path, in_app, true)
        lib/sentry/release_detector.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/release_detector.rb	2026-06-09 02:33:31.315936281 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/release_detector.rb	2026-06-09 02:33:31.324936405 +0000
                @@ -8,0 +9 @@
                +        detect_release_from_kamal ||
                @@ -31,0 +33,4 @@
                +      end
                +
                +      def detect_release_from_kamal
                +        ENV["KAMAL_VERSION"]
        lib/sentry/telemetry_event_buffer.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:31.316936295 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:31.325936419 +0000
                @@ -52,0 +53,3 @@
                +      # Prevent ThreadError from re-entrant locking (e.g. transport instrumentation calling Sentry.metrics.*)
                +      return self if @mutex.owned?
                +
        lib/sentry/test_helper.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/test_helper.rb	2026-06-09 02:33:31.316936295 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/test_helper.rb	2026-06-09 02:33:31.325936419 +0000
                @@ -39,0 +40,7 @@
                +      # Install the testing clients on the *main* hub rather than the current
                +      # thread's hub. `Sentry.clone_hub_to_current_thread` (used by
                +      # Sentry::Rack::CaptureExceptions) always clones the main hub, so if we
                +      # only mutated the thread-local hub a request-time clone would observe a
                +      # stale transport.
                +      main_hub = Sentry.get_main_hub
                +
                @@ -42 +49 @@
                -      Sentry.get_current_hub.bind_client(base_client)
                +      main_hub.bind_client(base_client)
                @@ -44 +51 @@
                -      Sentry.get_current_hub.push_scope
                +      main_hub.push_scope
                @@ -46 +53,6 @@
                -      Sentry.get_current_hub.bind_client(test_client)
                +      main_hub.bind_client(test_client)
                +
                +      # Realign the current thread's hub with the main hub so direct
                +      # `sentry_events` reads and any hub the Rack middleware clones from the
                +      # main hub all observe the same DummyTransport.
                +      Thread.current.thread_variable_set(Sentry::THREAD_LOCAL, main_hub)
                @@ -57,2 +69,5 @@
                -      # pop testing layer created by `setup_sentry_test`
                -      # but keep the base layer to avoid nil-pointer errors
                +      # pop the testing layer created by `setup_sentry_test` off the *main*
                +      # hub (that is where `setup_sentry_test` pushed it), keeping the base
                +      # layer to avoid nil-pointer errors. Popping the current thread's hub
                +      # would leave the test layer dangling on the main hub, which the next
                +      # request-time clone would inherit.
                @@ -60,2 +75,3 @@
                -      if Sentry.get_current_hub.instance_variable_get(:@stack).size > 1
                -        Sentry.get_current_hub.pop_scope
                +      main_hub = Sentry.get_main_hub
                +      if main_hub.instance_variable_get(:@stack).size > 1
                +        main_hub.pop_scope
                @@ -69 +85,7 @@
                -      sentry_transport.clear if sentry_transport.respond_to?(:clear)
                +      # Clear every transport reachable from the current thread's hub and the
                +      # main hub (including its base layer). A request-time clone shares the
                +      # main hub's base-layer transport, so clearing only the current
                +      # transport would let stale events survive into the next test.
                +      sentry_test_transports.each do |transport|
                +        transport.clear if transport.respond_to?(:clear)
                +      end
                @@ -83,0 +106,11 @@
                +    end
                +
                +    # Every transport reachable from the current thread's hub and the main
                +    # hub, across all stack layers. Used by `clear_sentry_events` so a stale
                +    # DummyTransport (e.g. the main hub's base layer that a request-time clone
                +    # shares) cannot carry leftover events into the next test.
                +    # @return [Array<Transport>]
                +    def sentry_test_transports
                +      [Sentry.get_current_hub, Sentry.get_main_hub].compact.uniq.flat_map do |hub|
                +        hub.clients.map(&:transport)
                +      end.compact.uniq
        lib/sentry/transport/dummy_transport.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:31.316936295 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:31.326936433 +0000
                @@ -20,0 +21,7 @@
                +
                +    # Empties the captured events and envelopes so `TestHelper.clear_sentry_events`
                +    # also clears the dummy transport instance
                +    def clear
                +      @events.clear
                +      @envelopes.clear
                +    end
        lib/sentry/utils/http_tracing.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:31.317936308 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:31.326936433 +0000
                @@ -15 +15,7 @@
                -        Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v }
                +        Sentry.get_trace_propagation_headers&.each do |k, v|
                +          if k == BAGGAGE_HEADER_NAME && req[k]
                +            req[k] = "#{v},#{req[k]}"
                +          else
                +            req[k] = v
                +          end
                +        end
        lib/sentry/vernier/output.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/vernier/output.rb	2026-06-09 02:33:31.317936308 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/vernier/output.rb	2026-06-09 02:33:31.327936446 +0000
                @@ -13 +13 @@
                -      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:)
                +      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:, filename_cache:)
                @@ -17,0 +18 @@
                +        @filename_cache = filename_cache
        lib/sentry/vernier/profiler.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:31.318936322 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:31.327936446 +0000
                @@ -26,0 +27 @@
                +        @filename_cache = configuration.stacktrace_builder.filename_cache
                @@ -128 +129,2 @@
                -          in_app_pattern: @in_app_pattern
                +          in_app_pattern: @in_app_pattern,
                +          filename_cache: @filename_cache
        lib/sentry/version.rb
                --- /tmp/d20260609-724-6d50fe/sentry-ruby-6.5.0/lib/sentry/version.rb	2026-06-09 02:33:31.318936322 +0000
                +++ /tmp/d20260609-724-6d50fe/sentry-ruby-6.6.1/lib/sentry/version.rb	2026-06-09 02:33:31.327936446 +0000
                @@ -4 +4 @@
                -  VERSION = "6.5.0"
                +  VERSION = "6.6.1"

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare --diff sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
        lib/sentry/utils/filename_cache.rb
                --- /tmp/20260609-724-6qys92	2026-06-09 02:33:33.082492296 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/utils/filename_cache.rb	2026-06-09 02:33:33.081492292 +0000
                @@ -0,0 +1,47 @@
                +# frozen_string_literal: true
                +
                +module Sentry
                +  class FilenameCache
                +    attr_reader :cache
                +
                +    def initialize(project_root)
                +      @project_root = project_root
                +      @load_paths = $LOAD_PATH.map(&:to_s).sort_by(&:size).reverse.freeze
                +      @cache = {}
                +    end
                +
                +    def compute_filename(abs_path, in_app, strip_backtrace_load_path)
                +      return unless abs_path
                +      return abs_path unless strip_backtrace_load_path
                +
                +      @cache.fetch(abs_path) do
                +        under_root = @project_root && abs_path.start_with?(@project_root)
                +        prefix =
                +          if under_root && in_app
                +            @project_root
                +          elsif under_root
                +            longest_load_path(abs_path) || @project_root
                +          else
                +            longest_load_path(abs_path)
                +          end
                +
                +        @cache[abs_path] = if prefix
                +          offset = if prefix.end_with?(File::SEPARATOR)
                +            prefix.bytesize
                +          else
                +            prefix.bytesize + 1
                +          end
                +          abs_path.byteslice(offset, abs_path.bytesize - offset)
                +        else
                +          abs_path
                +        end
                +      end
                +    end
                +
                +    private
                +
                +    def longest_load_path(abs_path)
                +      @load_paths.find { |path| abs_path.start_with?(path) }
                +    end
                +  end
                +end
      * Changed:
        README.md
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/README.md	2026-06-09 02:33:33.051492170 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/README.md	2026-06-09 02:33:33.065492227 +0000
                @@ -23,0 +24 @@
                +| [![Gem Version](https://img.shields.io/gem/v/sentry-yabeda?label=sentry-yabeda)](https://rubygems.org/gems/sentry-yabeda) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [![codecov](https://codecov.io/gh/getsentry/sentry-ruby/graph/badge.svg?token=ZePzrpZFP6&component=sentry-yabeda)](https://codecov.io/gh/getsentry/sentry-ruby) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-yabeda) |
                @@ -55,0 +57 @@
                +gem "sentry-yabeda"
                @@ -95,0 +98 @@
                +- [Yabeda](https://docs.sentry.io/platforms/ruby/guides/yabeda/)
        lib/sentry-ruby.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry-ruby.rb	2026-06-09 02:33:33.052492175 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry-ruby.rb	2026-06-09 02:33:33.066492231 +0000
                @@ -270,0 +271 @@
                +        client.configuration.run_after_close_callbacks
        lib/sentry/backtrace.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/backtrace.rb	2026-06-09 02:33:33.052492175 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/backtrace.rb	2026-06-09 02:33:33.067492235 +0000
                @@ -13 +13,3 @@
                -    def self.parse(backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback)
                +    # @deprecated project_root, in_app_pattern passed from outside
                +    # @deprecated app_dirs_pattern, in_app_pattern passed from outside
                +    def self.parse(backtrace, project_root, app_dirs_pattern, in_app_pattern: nil, &backtrace_cleanup_callback)
                @@ -18,3 +20,3 @@
                -      in_app_pattern ||= begin
                -        Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
                -      end
                +      # in_app_pattern is now passed in from StacktraceBuilder, so this regex won't be triggered
                +      # only here for backwards compat and will be deleted
                +      in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
        lib/sentry/backtrace/line.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/backtrace/line.rb	2026-06-09 02:33:33.052492175 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/backtrace/line.rb	2026-06-09 02:33:33.067492235 +0000
                @@ -8,0 +9 @@
                +      CLASS_EXTENSION = ".class"
                @@ -40,3 +41,7 @@
                -          _, file, number, _, module_name, method = ruby_match.to_a
                -          file.sub!(/\.class$/, RB_EXTENSION)
                -          module_name = module_name
                +          file = ruby_match[1]
                +          number = ruby_match[2]
                +          module_name = ruby_match[4]
                +          method = ruby_match[5]
                +          if file.end_with?(CLASS_EXTENSION)
                +            file.sub!(/\.class$/, RB_EXTENSION)
                +          end
                @@ -45 +50,6 @@
                -          _, module_name, method, file, number = java_match.to_a
                +          if java_match
                +            module_name = java_match[1]
                +            method = java_match[2]
                +            file = java_match[3]
                +            number = java_match[4]
                +          end
                @@ -76,0 +87 @@
                +        return false unless file
                @@ -78,5 +89 @@
                -        if file =~ in_app_pattern
                -          true
                -        else
                -          false
                -        end
                +        file.match?(in_app_pattern)
        lib/sentry/configuration.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/configuration.rb	2026-06-09 02:33:33.053492178 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/configuration.rb	2026-06-09 02:33:33.069492244 +0000
                @@ -464 +464,2 @@
                -          configured: { before: [], after: [] }
                +          configured: { before: [], after: [] },
                +          closed: { before: [], after: [] }
                @@ -798,0 +800,5 @@
                +    end
                +
                +    # @api private
                +    def run_after_close_callbacks
                +      run_callbacks(:after, :closed)
        lib/sentry/hub.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/hub.rb	2026-06-09 02:33:33.055492187 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/hub.rb	2026-06-09 02:33:33.073492260 +0000
                @@ -56,0 +57,6 @@
                +    # All clients bound across the hub's scope stack, base layer first.
                +    # @return [Array<Client>]
                +    def clients
                +      @stack.map(&:client).compact
                +    end
                +
        lib/sentry/interfaces/request.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/interfaces/request.rb	2026-06-09 02:33:33.056492191 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/interfaces/request.rb	2026-06-09 02:33:33.074492264 +0000
                @@ -13,0 +14,3 @@
                +    # Regex to detect lowercase chars — match? is allocation-free (no MatchData/String)
                +    LOWERCASE_PATTERN = /[a-z]/.freeze
                +
                @@ -96 +99 @@
                -          key = key.sub(/^HTTP_/, "")
                +          key = key.delete_prefix("HTTP_")
                @@ -111 +114 @@
                -      key.upcase != key || # lower-case envs aren't real http headers
                +      key.match?(LOWERCASE_PATTERN) || # lower-case envs aren't real http headers
                @@ -122,2 +125 @@
                -      rack_version = Gem::Version.new(::Rack.release)
                -      return false if rack_version >= Gem::Version.new("3.0")
                +      return false if self.class.rack_3_or_above?
                @@ -125,0 +128,7 @@
                +    end
                +
                +    def self.rack_3_or_above?
                +      return @rack_3_or_above if defined?(@rack_3_or_above)
                +
                +      @rack_3_or_above = defined?(::Rack) &&
                +        Gem::Version.new(::Rack.release) >= Gem::Version.new("3.0")
        lib/sentry/interfaces/stacktrace.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:33.056492191 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:33.074492264 +0000
                @@ -30,4 +30 @@
                -      def initialize(project_root, line, strip_backtrace_load_path = true)
                -        @project_root = project_root
                -        @strip_backtrace_load_path = strip_backtrace_load_path
                -
                +      def initialize(project_root, line, strip_backtrace_load_path = true, filename_cache: nil)
                @@ -39 +36 @@
                -        @filename = compute_filename
                +        @filename = filename_cache&.compute_filename(@abs_path, @in_app, strip_backtrace_load_path)
                @@ -46,16 +42,0 @@
                -      def compute_filename
                -        return if abs_path.nil?
                -        return abs_path unless @strip_backtrace_load_path
                -
                -        prefix =
                -          if under_project_root? && in_app
                -            @project_root
                -          elsif under_project_root?
                -            longest_load_path || @project_root
                -          else
                -            longest_load_path
                -          end
                -
                -        prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
                -      end
                -
                @@ -79,8 +59,0 @@
                -
                -      def under_project_root?
                -        @project_root && abs_path.start_with?(@project_root)
                -      end
                -
                -      def longest_load_path
                -        $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
                -      end
        lib/sentry/interfaces/stacktrace_builder.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:33.056492191 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:33.074492264 +0000
                @@ -2,0 +3,2 @@
                +require "sentry/utils/filename_cache"
                +
                @@ -22,0 +25,3 @@
                +    # @return [FilenameCache]
                +    attr_reader :filename_cache
                +
                @@ -48,0 +54,2 @@
                +      @in_app_pattern = Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}") if app_dirs_pattern
                +      @filename_cache = FilenameCache.new(project_root)
                @@ -67 +74,10 @@
                -      parsed_lines = parse_backtrace_lines(backtrace).select(&:file)
                +      parsed_lines = parse_backtrace_lines(backtrace)
                +
                +      # Build frames in reverse order, skipping lines without files
                +      # Single pass instead of select + reverse + map + compact
                +      frames = []
                +      i = parsed_lines.size - 1
                +      while i >= 0
                +        line = parsed_lines[i]
                +        i -= 1
                +        next unless line.file
                @@ -69 +84,0 @@
                -      frames = parsed_lines.reverse.map do |line|
                @@ -72,2 +87,2 @@
                -        frame
                -      end.compact
                +        frames << frame if frame
                +      end
                @@ -81 +96 @@
                -      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path)
                +      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path, filename_cache: @filename_cache)
                @@ -88 +103,2 @@
                -        backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback
                +        backtrace, project_root, app_dirs_pattern,
                +        in_app_pattern: @in_app_pattern, &backtrace_cleanup_callback
        lib/sentry/linecache.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/linecache.rb	2026-06-09 02:33:33.056492191 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/linecache.rb	2026-06-09 02:33:33.075492268 +0000
                @@ -15 +15,2 @@
                -      return nil, nil, nil unless valid_path?(filename)
                +      lines = getlines(filename)
                +      return nil, nil, nil unless lines
                @@ -17,4 +18,6 @@
                -      lines = Array.new(2 * context + 1) do |i|
                -        getline(filename, lineno - context + i)
                -      end
                -      [lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]]
                +      first_line = lineno - context
                +      pre = Array.new(context) { |i| line_at(lines, first_line + i) }
                +      context_line = line_at(lines, lineno)
                +      post = Array.new(context) { |i| line_at(lines, lineno + 1 + i) }
                +
                +      [pre, context_line, post]
                @@ -25,3 +28,4 @@
                -    def valid_path?(path)
                -      lines = getlines(path)
                -      !lines.nil?
                +    def line_at(lines, n)
                +      return nil if n < 1
                +
                +      lines[n - 1]
                @@ -31,4 +35,6 @@
                -      @cache[path] ||= begin
                -        File.open(path, "r", &:readlines)
                -      rescue
                -        nil
                +      @cache.fetch(path) do
                +        @cache[path] = begin
                +          File.open(path, "r", &:readlines)
                +        rescue
                +          nil
                +        end
                @@ -36,9 +41,0 @@
                -    end
                -
                -    def getline(path, n)
                -      return nil if n < 1
                -
                -      lines = getlines(path)
                -      return nil if lines.nil?
                -
                -      lines[n - 1]
        lib/sentry/profiler.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/profiler.rb	2026-06-09 02:33:33.057492195 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/profiler.rb	2026-06-09 02:33:33.076492272 +0000
                @@ -28,0 +29 @@
                +      @filename_cache = configuration.stacktrace_builder.filename_cache
        lib/sentry/profiler/helpers.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:33.057492195 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:33.077492276 +0000
                @@ -12,3 +11,0 @@
                -      # 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
                @@ -16,18 +13 @@
                -        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
                +        @filename_cache.compute_filename(abs_path, in_app, true)
        lib/sentry/release_detector.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/release_detector.rb	2026-06-09 02:33:33.058492199 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/release_detector.rb	2026-06-09 02:33:33.078492280 +0000
                @@ -8,0 +9 @@
                +        detect_release_from_kamal ||
                @@ -31,0 +33,4 @@
                +      end
                +
                +      def detect_release_from_kamal
                +        ENV["KAMAL_VERSION"]
        lib/sentry/telemetry_event_buffer.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:33.059492203 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:33.079492284 +0000
                @@ -52,0 +53,3 @@
                +      # Prevent ThreadError from re-entrant locking (e.g. transport instrumentation calling Sentry.metrics.*)
                +      return self if @mutex.owned?
                +
        lib/sentry/test_helper.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/test_helper.rb	2026-06-09 02:33:33.059492203 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/test_helper.rb	2026-06-09 02:33:33.079492284 +0000
                @@ -39,0 +40,7 @@
                +      # Install the testing clients on the *main* hub rather than the current
                +      # thread's hub. `Sentry.clone_hub_to_current_thread` (used by
                +      # Sentry::Rack::CaptureExceptions) always clones the main hub, so if we
                +      # only mutated the thread-local hub a request-time clone would observe a
                +      # stale transport.
                +      main_hub = Sentry.get_main_hub
                +
                @@ -42 +49 @@
                -      Sentry.get_current_hub.bind_client(base_client)
                +      main_hub.bind_client(base_client)
                @@ -44 +51 @@
                -      Sentry.get_current_hub.push_scope
                +      main_hub.push_scope
                @@ -46 +53,6 @@
                -      Sentry.get_current_hub.bind_client(test_client)
                +      main_hub.bind_client(test_client)
                +
                +      # Realign the current thread's hub with the main hub so direct
                +      # `sentry_events` reads and any hub the Rack middleware clones from the
                +      # main hub all observe the same DummyTransport.
                +      Thread.current.thread_variable_set(Sentry::THREAD_LOCAL, main_hub)
                @@ -57,2 +69,5 @@
                -      # pop testing layer created by `setup_sentry_test`
                -      # but keep the base layer to avoid nil-pointer errors
                +      # pop the testing layer created by `setup_sentry_test` off the *main*
                +      # hub (that is where `setup_sentry_test` pushed it), keeping the base
                +      # layer to avoid nil-pointer errors. Popping the current thread's hub
                +      # would leave the test layer dangling on the main hub, which the next
                +      # request-time clone would inherit.
                @@ -60,2 +75,3 @@
                -      if Sentry.get_current_hub.instance_variable_get(:@stack).size > 1
                -        Sentry.get_current_hub.pop_scope
                +      main_hub = Sentry.get_main_hub
                +      if main_hub.instance_variable_get(:@stack).size > 1
                +        main_hub.pop_scope
                @@ -69 +85,7 @@
                -      sentry_transport.clear if sentry_transport.respond_to?(:clear)
                +      # Clear every transport reachable from the current thread's hub and the
                +      # main hub (including its base layer). A request-time clone shares the
                +      # main hub's base-layer transport, so clearing only the current
                +      # transport would let stale events survive into the next test.
                +      sentry_test_transports.each do |transport|
                +        transport.clear if transport.respond_to?(:clear)
                +      end
                @@ -83,0 +106,11 @@
                +    end
                +
                +    # Every transport reachable from the current thread's hub and the main
                +    # hub, across all stack layers. Used by `clear_sentry_events` so a stale
                +    # DummyTransport (e.g. the main hub's base layer that a request-time clone
                +    # shares) cannot carry leftover events into the next test.
                +    # @return [Array<Transport>]
                +    def sentry_test_transports
                +      [Sentry.get_current_hub, Sentry.get_main_hub].compact.uniq.flat_map do |hub|
                +        hub.clients.map(&:transport)
                +      end.compact.uniq
        lib/sentry/transport/dummy_transport.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:33.060492207 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:33.080492288 +0000
                @@ -20,0 +21,7 @@
                +
                +    # Empties the captured events and envelopes so `TestHelper.clear_sentry_events`
                +    # also clears the dummy transport instance
                +    def clear
                +      @events.clear
                +      @envelopes.clear
                +    end
        lib/sentry/utils/http_tracing.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:33.060492207 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:33.081492292 +0000
                @@ -15 +15,7 @@
                -        Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v }
                +        Sentry.get_trace_propagation_headers&.each do |k, v|
                +          if k == BAGGAGE_HEADER_NAME && req[k]
                +            req[k] = "#{v},#{req[k]}"
                +          else
                +            req[k] = v
                +          end
                +        end
        lib/sentry/vernier/output.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/vernier/output.rb	2026-06-09 02:33:33.061492211 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/vernier/output.rb	2026-06-09 02:33:33.082492296 +0000
                @@ -13 +13 @@
                -      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:)
                +      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:, filename_cache:)
                @@ -17,0 +18 @@
                +        @filename_cache = filename_cache
        lib/sentry/vernier/profiler.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:33.061492211 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:33.082492296 +0000
                @@ -26,0 +27 @@
                +        @filename_cache = configuration.stacktrace_builder.filename_cache
                @@ -128 +129,2 @@
                -          in_app_pattern: @in_app_pattern
                +          in_app_pattern: @in_app_pattern,
                +          filename_cache: @filename_cache
        lib/sentry/version.rb
                --- /tmp/d20260609-724-dy5fuh/sentry-ruby-6.5.0/lib/sentry/version.rb	2026-06-09 02:33:33.061492211 +0000
                +++ /tmp/d20260609-724-dy5fuh/sentry-ruby-6.6.1/lib/sentry/version.rb	2026-06-09 02:33:33.082492296 +0000
                @@ -4 +4 @@
                -  VERSION = "6.5.0"
                +  VERSION = "6.6.1"

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare --diff sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
        lib/sentry/utils/filename_cache.rb
                --- /tmp/20260609-735-srvjz7	2026-06-09 02:33:41.421463257 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/utils/filename_cache.rb	2026-06-09 02:33:41.420463230 +0000
                @@ -0,0 +1,47 @@
                +# frozen_string_literal: true
                +
                +module Sentry
                +  class FilenameCache
                +    attr_reader :cache
                +
                +    def initialize(project_root)
                +      @project_root = project_root
                +      @load_paths = $LOAD_PATH.map(&:to_s).sort_by(&:size).reverse.freeze
                +      @cache = {}
                +    end
                +
                +    def compute_filename(abs_path, in_app, strip_backtrace_load_path)
                +      return unless abs_path
                +      return abs_path unless strip_backtrace_load_path
                +
                +      @cache.fetch(abs_path) do
                +        under_root = @project_root && abs_path.start_with?(@project_root)
                +        prefix =
                +          if under_root && in_app
                +            @project_root
                +          elsif under_root
                +            longest_load_path(abs_path) || @project_root
                +          else
                +            longest_load_path(abs_path)
                +          end
                +
                +        @cache[abs_path] = if prefix
                +          offset = if prefix.end_with?(File::SEPARATOR)
                +            prefix.bytesize
                +          else
                +            prefix.bytesize + 1
                +          end
                +          abs_path.byteslice(offset, abs_path.bytesize - offset)
                +        else
                +          abs_path
                +        end
                +      end
                +    end
                +
                +    private
                +
                +    def longest_load_path(abs_path)
                +      @load_paths.find { |path| abs_path.start_with?(path) }
                +    end
                +  end
                +end
      * Changed:
        README.md
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/README.md	2026-06-09 02:33:41.402462742 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/README.md	2026-06-09 02:33:41.412463013 +0000
                @@ -23,0 +24 @@
                +| [![Gem Version](https://img.shields.io/gem/v/sentry-yabeda?label=sentry-yabeda)](https://rubygems.org/gems/sentry-yabeda) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [![codecov](https://codecov.io/gh/getsentry/sentry-ruby/graph/badge.svg?token=ZePzrpZFP6&component=sentry-yabeda)](https://codecov.io/gh/getsentry/sentry-ruby) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-yabeda) |
                @@ -55,0 +57 @@
                +gem "sentry-yabeda"
                @@ -95,0 +98 @@
                +- [Yabeda](https://docs.sentry.io/platforms/ruby/guides/yabeda/)
        lib/sentry-ruby.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry-ruby.rb	2026-06-09 02:33:41.402462742 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry-ruby.rb	2026-06-09 02:33:41.413463040 +0000
                @@ -270,0 +271 @@
                +        client.configuration.run_after_close_callbacks
        lib/sentry/backtrace.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/backtrace.rb	2026-06-09 02:33:41.403462769 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/backtrace.rb	2026-06-09 02:33:41.413463040 +0000
                @@ -13 +13,3 @@
                -    def self.parse(backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback)
                +    # @deprecated project_root, in_app_pattern passed from outside
                +    # @deprecated app_dirs_pattern, in_app_pattern passed from outside
                +    def self.parse(backtrace, project_root, app_dirs_pattern, in_app_pattern: nil, &backtrace_cleanup_callback)
                @@ -18,3 +20,3 @@
                -      in_app_pattern ||= begin
                -        Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
                -      end
                +      # in_app_pattern is now passed in from StacktraceBuilder, so this regex won't be triggered
                +      # only here for backwards compat and will be deleted
                +      in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
        lib/sentry/backtrace/line.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/backtrace/line.rb	2026-06-09 02:33:41.403462769 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/backtrace/line.rb	2026-06-09 02:33:41.413463040 +0000
                @@ -8,0 +9 @@
                +      CLASS_EXTENSION = ".class"
                @@ -40,3 +41,7 @@
                -          _, file, number, _, module_name, method = ruby_match.to_a
                -          file.sub!(/\.class$/, RB_EXTENSION)
                -          module_name = module_name
                +          file = ruby_match[1]
                +          number = ruby_match[2]
                +          module_name = ruby_match[4]
                +          method = ruby_match[5]
                +          if file.end_with?(CLASS_EXTENSION)
                +            file.sub!(/\.class$/, RB_EXTENSION)
                +          end
                @@ -45 +50,6 @@
                -          _, module_name, method, file, number = java_match.to_a
                +          if java_match
                +            module_name = java_match[1]
                +            method = java_match[2]
                +            file = java_match[3]
                +            number = java_match[4]
                +          end
                @@ -76,0 +87 @@
                +        return false unless file
                @@ -78,5 +89 @@
                -        if file =~ in_app_pattern
                -          true
                -        else
                -          false
                -        end
                +        file.match?(in_app_pattern)
        lib/sentry/configuration.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/configuration.rb	2026-06-09 02:33:41.405462823 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/configuration.rb	2026-06-09 02:33:41.414463067 +0000
                @@ -464 +464,2 @@
                -          configured: { before: [], after: [] }
                +          configured: { before: [], after: [] },
                +          closed: { before: [], after: [] }
                @@ -798,0 +800,5 @@
                +    end
                +
                +    # @api private
                +    def run_after_close_callbacks
                +      run_callbacks(:after, :closed)
        lib/sentry/hub.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/hub.rb	2026-06-09 02:33:41.406462850 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/hub.rb	2026-06-09 02:33:41.416463121 +0000
                @@ -56,0 +57,6 @@
                +    # All clients bound across the hub's scope stack, base layer first.
                +    # @return [Array<Client>]
                +    def clients
                +      @stack.map(&:client).compact
                +    end
                +
        lib/sentry/interfaces/request.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/interfaces/request.rb	2026-06-09 02:33:41.407462877 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/interfaces/request.rb	2026-06-09 02:33:41.416463121 +0000
                @@ -13,0 +14,3 @@
                +    # Regex to detect lowercase chars — match? is allocation-free (no MatchData/String)
                +    LOWERCASE_PATTERN = /[a-z]/.freeze
                +
                @@ -96 +99 @@
                -          key = key.sub(/^HTTP_/, "")
                +          key = key.delete_prefix("HTTP_")
                @@ -111 +114 @@
                -      key.upcase != key || # lower-case envs aren't real http headers
                +      key.match?(LOWERCASE_PATTERN) || # lower-case envs aren't real http headers
                @@ -122,2 +125 @@
                -      rack_version = Gem::Version.new(::Rack.release)
                -      return false if rack_version >= Gem::Version.new("3.0")
                +      return false if self.class.rack_3_or_above?
                @@ -125,0 +128,7 @@
                +    end
                +
                +    def self.rack_3_or_above?
                +      return @rack_3_or_above if defined?(@rack_3_or_above)
                +
                +      @rack_3_or_above = defined?(::Rack) &&
                +        Gem::Version.new(::Rack.release) >= Gem::Version.new("3.0")
        lib/sentry/interfaces/stacktrace.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:41.407462877 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:41.416463121 +0000
                @@ -30,4 +30 @@
                -      def initialize(project_root, line, strip_backtrace_load_path = true)
                -        @project_root = project_root
                -        @strip_backtrace_load_path = strip_backtrace_load_path
                -
                +      def initialize(project_root, line, strip_backtrace_load_path = true, filename_cache: nil)
                @@ -39 +36 @@
                -        @filename = compute_filename
                +        @filename = filename_cache&.compute_filename(@abs_path, @in_app, strip_backtrace_load_path)
                @@ -46,16 +42,0 @@
                -      def compute_filename
                -        return if abs_path.nil?
                -        return abs_path unless @strip_backtrace_load_path
                -
                -        prefix =
                -          if under_project_root? && in_app
                -            @project_root
                -          elsif under_project_root?
                -            longest_load_path || @project_root
                -          else
                -            longest_load_path
                -          end
                -
                -        prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
                -      end
                -
                @@ -79,8 +59,0 @@
                -
                -      def under_project_root?
                -        @project_root && abs_path.start_with?(@project_root)
                -      end
                -
                -      def longest_load_path
                -        $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
                -      end
        lib/sentry/interfaces/stacktrace_builder.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:41.407462877 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:41.416463121 +0000
                @@ -2,0 +3,2 @@
                +require "sentry/utils/filename_cache"
                +
                @@ -22,0 +25,3 @@
                +    # @return [FilenameCache]
                +    attr_reader :filename_cache
                +
                @@ -48,0 +54,2 @@
                +      @in_app_pattern = Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}") if app_dirs_pattern
                +      @filename_cache = FilenameCache.new(project_root)
                @@ -67 +74,10 @@
                -      parsed_lines = parse_backtrace_lines(backtrace).select(&:file)
                +      parsed_lines = parse_backtrace_lines(backtrace)
                +
                +      # Build frames in reverse order, skipping lines without files
                +      # Single pass instead of select + reverse + map + compact
                +      frames = []
                +      i = parsed_lines.size - 1
                +      while i >= 0
                +        line = parsed_lines[i]
                +        i -= 1
                +        next unless line.file
                @@ -69 +84,0 @@
                -      frames = parsed_lines.reverse.map do |line|
                @@ -72,2 +87,2 @@
                -        frame
                -      end.compact
                +        frames << frame if frame
                +      end
                @@ -81 +96 @@
                -      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path)
                +      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path, filename_cache: @filename_cache)
                @@ -88 +103,2 @@
                -        backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback
                +        backtrace, project_root, app_dirs_pattern,
                +        in_app_pattern: @in_app_pattern, &backtrace_cleanup_callback
        lib/sentry/linecache.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/linecache.rb	2026-06-09 02:33:41.407462877 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/linecache.rb	2026-06-09 02:33:41.416463121 +0000
                @@ -15 +15,2 @@
                -      return nil, nil, nil unless valid_path?(filename)
                +      lines = getlines(filename)
                +      return nil, nil, nil unless lines
                @@ -17,4 +18,6 @@
                -      lines = Array.new(2 * context + 1) do |i|
                -        getline(filename, lineno - context + i)
                -      end
                -      [lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]]
                +      first_line = lineno - context
                +      pre = Array.new(context) { |i| line_at(lines, first_line + i) }
                +      context_line = line_at(lines, lineno)
                +      post = Array.new(context) { |i| line_at(lines, lineno + 1 + i) }
                +
                +      [pre, context_line, post]
                @@ -25,3 +28,4 @@
                -    def valid_path?(path)
                -      lines = getlines(path)
                -      !lines.nil?
                +    def line_at(lines, n)
                +      return nil if n < 1
                +
                +      lines[n - 1]
                @@ -31,4 +35,6 @@
                -      @cache[path] ||= begin
                -        File.open(path, "r", &:readlines)
                -      rescue
                -        nil
                +      @cache.fetch(path) do
                +        @cache[path] = begin
                +          File.open(path, "r", &:readlines)
                +        rescue
                +          nil
                +        end
                @@ -36,9 +41,0 @@
                -    end
                -
                -    def getline(path, n)
                -      return nil if n < 1
                -
                -      lines = getlines(path)
                -      return nil if lines.nil?
                -
                -      lines[n - 1]
        lib/sentry/profiler.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/profiler.rb	2026-06-09 02:33:41.408462904 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/profiler.rb	2026-06-09 02:33:41.417463149 +0000
                @@ -28,0 +29 @@
                +      @filename_cache = configuration.stacktrace_builder.filename_cache
        lib/sentry/profiler/helpers.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:41.408462904 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:41.417463149 +0000
                @@ -12,3 +11,0 @@
                -      # 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
                @@ -16,18 +13 @@
                -        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
                +        @filename_cache.compute_filename(abs_path, in_app, true)
        lib/sentry/release_detector.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/release_detector.rb	2026-06-09 02:33:41.408462904 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/release_detector.rb	2026-06-09 02:33:41.418463176 +0000
                @@ -8,0 +9 @@
                +        detect_release_from_kamal ||
                @@ -31,0 +33,4 @@
                +      end
                +
                +      def detect_release_from_kamal
                +        ENV["KAMAL_VERSION"]
        lib/sentry/telemetry_event_buffer.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:41.409462931 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:41.419463203 +0000
                @@ -52,0 +53,3 @@
                +      # Prevent ThreadError from re-entrant locking (e.g. transport instrumentation calling Sentry.metrics.*)
                +      return self if @mutex.owned?
                +
        lib/sentry/test_helper.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/test_helper.rb	2026-06-09 02:33:41.409462931 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/test_helper.rb	2026-06-09 02:33:41.419463203 +0000
                @@ -39,0 +40,7 @@
                +      # Install the testing clients on the *main* hub rather than the current
                +      # thread's hub. `Sentry.clone_hub_to_current_thread` (used by
                +      # Sentry::Rack::CaptureExceptions) always clones the main hub, so if we
                +      # only mutated the thread-local hub a request-time clone would observe a
                +      # stale transport.
                +      main_hub = Sentry.get_main_hub
                +
                @@ -42 +49 @@
                -      Sentry.get_current_hub.bind_client(base_client)
                +      main_hub.bind_client(base_client)
                @@ -44 +51 @@
                -      Sentry.get_current_hub.push_scope
                +      main_hub.push_scope
                @@ -46 +53,6 @@
                -      Sentry.get_current_hub.bind_client(test_client)
                +      main_hub.bind_client(test_client)
                +
                +      # Realign the current thread's hub with the main hub so direct
                +      # `sentry_events` reads and any hub the Rack middleware clones from the
                +      # main hub all observe the same DummyTransport.
                +      Thread.current.thread_variable_set(Sentry::THREAD_LOCAL, main_hub)
                @@ -57,2 +69,5 @@
                -      # pop testing layer created by `setup_sentry_test`
                -      # but keep the base layer to avoid nil-pointer errors
                +      # pop the testing layer created by `setup_sentry_test` off the *main*
                +      # hub (that is where `setup_sentry_test` pushed it), keeping the base
                +      # layer to avoid nil-pointer errors. Popping the current thread's hub
                +      # would leave the test layer dangling on the main hub, which the next
                +      # request-time clone would inherit.
                @@ -60,2 +75,3 @@
                -      if Sentry.get_current_hub.instance_variable_get(:@stack).size > 1
                -        Sentry.get_current_hub.pop_scope
                +      main_hub = Sentry.get_main_hub
                +      if main_hub.instance_variable_get(:@stack).size > 1
                +        main_hub.pop_scope
                @@ -69 +85,7 @@
                -      sentry_transport.clear if sentry_transport.respond_to?(:clear)
                +      # Clear every transport reachable from the current thread's hub and the
                +      # main hub (including its base layer). A request-time clone shares the
                +      # main hub's base-layer transport, so clearing only the current
                +      # transport would let stale events survive into the next test.
                +      sentry_test_transports.each do |transport|
                +        transport.clear if transport.respond_to?(:clear)
                +      end
                @@ -83,0 +106,11 @@
                +    end
                +
                +    # Every transport reachable from the current thread's hub and the main
                +    # hub, across all stack layers. Used by `clear_sentry_events` so a stale
                +    # DummyTransport (e.g. the main hub's base layer that a request-time clone
                +    # shares) cannot carry leftover events into the next test.
                +    # @return [Array<Transport>]
                +    def sentry_test_transports
                +      [Sentry.get_current_hub, Sentry.get_main_hub].compact.uniq.flat_map do |hub|
                +        hub.clients.map(&:transport)
                +      end.compact.uniq
        lib/sentry/transport/dummy_transport.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:41.410462959 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:41.419463203 +0000
                @@ -20,0 +21,7 @@
                +
                +    # Empties the captured events and envelopes so `TestHelper.clear_sentry_events`
                +    # also clears the dummy transport instance
                +    def clear
                +      @events.clear
                +      @envelopes.clear
                +    end
        lib/sentry/utils/http_tracing.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:41.410462959 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:41.420463230 +0000
                @@ -15 +15,7 @@
                -        Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v }
                +        Sentry.get_trace_propagation_headers&.each do |k, v|
                +          if k == BAGGAGE_HEADER_NAME && req[k]
                +            req[k] = "#{v},#{req[k]}"
                +          else
                +            req[k] = v
                +          end
                +        end
        lib/sentry/vernier/output.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/vernier/output.rb	2026-06-09 02:33:41.411462986 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/vernier/output.rb	2026-06-09 02:33:41.420463230 +0000
                @@ -13 +13 @@
                -      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:)
                +      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:, filename_cache:)
                @@ -17,0 +18 @@
                +        @filename_cache = filename_cache
        lib/sentry/vernier/profiler.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:41.411462986 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:41.421463257 +0000
                @@ -26,0 +27 @@
                +        @filename_cache = configuration.stacktrace_builder.filename_cache
                @@ -128 +129,2 @@
                -          in_app_pattern: @in_app_pattern
                +          in_app_pattern: @in_app_pattern,
                +          filename_cache: @filename_cache
        lib/sentry/version.rb
                --- /tmp/d20260609-735-n6zpy0/sentry-ruby-6.5.0/lib/sentry/version.rb	2026-06-09 02:33:41.411462986 +0000
                +++ /tmp/d20260609-735-n6zpy0/sentry-ruby-6.6.1/lib/sentry/version.rb	2026-06-09 02:33:41.421463257 +0000
                @@ -4 +4 @@
                -  VERSION = "6.5.0"
                +  VERSION = "6.6.1"

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare --diff sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
        lib/sentry/utils/filename_cache.rb
                --- /tmp/20260609-764-vr8897	2026-06-09 02:33:49.062309491 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/utils/filename_cache.rb	2026-06-09 02:33:49.061309493 +0000
                @@ -0,0 +1,47 @@
                +# frozen_string_literal: true
                +
                +module Sentry
                +  class FilenameCache
                +    attr_reader :cache
                +
                +    def initialize(project_root)
                +      @project_root = project_root
                +      @load_paths = $LOAD_PATH.map(&:to_s).sort_by(&:size).reverse.freeze
                +      @cache = {}
                +    end
                +
                +    def compute_filename(abs_path, in_app, strip_backtrace_load_path)
                +      return unless abs_path
                +      return abs_path unless strip_backtrace_load_path
                +
                +      @cache.fetch(abs_path) do
                +        under_root = @project_root && abs_path.start_with?(@project_root)
                +        prefix =
                +          if under_root && in_app
                +            @project_root
                +          elsif under_root
                +            longest_load_path(abs_path) || @project_root
                +          else
                +            longest_load_path(abs_path)
                +          end
                +
                +        @cache[abs_path] = if prefix
                +          offset = if prefix.end_with?(File::SEPARATOR)
                +            prefix.bytesize
                +          else
                +            prefix.bytesize + 1
                +          end
                +          abs_path.byteslice(offset, abs_path.bytesize - offset)
                +        else
                +          abs_path
                +        end
                +      end
                +    end
                +
                +    private
                +
                +    def longest_load_path(abs_path)
                +      @load_paths.find { |path| abs_path.start_with?(path) }
                +    end
                +  end
                +end
      * Changed:
        README.md
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/README.md	2026-06-09 02:33:49.039309523 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/README.md	2026-06-09 02:33:49.051309506 +0000
                @@ -23,0 +24 @@
                +| [![Gem Version](https://img.shields.io/gem/v/sentry-yabeda?label=sentry-yabeda)](https://rubygems.org/gems/sentry-yabeda) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [![codecov](https://codecov.io/gh/getsentry/sentry-ruby/graph/badge.svg?token=ZePzrpZFP6&component=sentry-yabeda)](https://codecov.io/gh/getsentry/sentry-ruby) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-yabeda) |
                @@ -55,0 +57 @@
                +gem "sentry-yabeda"
                @@ -95,0 +98 @@
                +- [Yabeda](https://docs.sentry.io/platforms/ruby/guides/yabeda/)
        lib/sentry-ruby.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry-ruby.rb	2026-06-09 02:33:49.040309522 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry-ruby.rb	2026-06-09 02:33:49.051309506 +0000
                @@ -270,0 +271 @@
                +        client.configuration.run_after_close_callbacks
        lib/sentry/backtrace.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/backtrace.rb	2026-06-09 02:33:49.040309522 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/backtrace.rb	2026-06-09 02:33:49.052309505 +0000
                @@ -13 +13,3 @@
                -    def self.parse(backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback)
                +    # @deprecated project_root, in_app_pattern passed from outside
                +    # @deprecated app_dirs_pattern, in_app_pattern passed from outside
                +    def self.parse(backtrace, project_root, app_dirs_pattern, in_app_pattern: nil, &backtrace_cleanup_callback)
                @@ -18,3 +20,3 @@
                -      in_app_pattern ||= begin
                -        Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
                -      end
                +      # in_app_pattern is now passed in from StacktraceBuilder, so this regex won't be triggered
                +      # only here for backwards compat and will be deleted
                +      in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
        lib/sentry/backtrace/line.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/backtrace/line.rb	2026-06-09 02:33:49.040309522 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/backtrace/line.rb	2026-06-09 02:33:49.052309505 +0000
                @@ -8,0 +9 @@
                +      CLASS_EXTENSION = ".class"
                @@ -40,3 +41,7 @@
                -          _, file, number, _, module_name, method = ruby_match.to_a
                -          file.sub!(/\.class$/, RB_EXTENSION)
                -          module_name = module_name
                +          file = ruby_match[1]
                +          number = ruby_match[2]
                +          module_name = ruby_match[4]
                +          method = ruby_match[5]
                +          if file.end_with?(CLASS_EXTENSION)
                +            file.sub!(/\.class$/, RB_EXTENSION)
                +          end
                @@ -45 +50,6 @@
                -          _, module_name, method, file, number = java_match.to_a
                +          if java_match
                +            module_name = java_match[1]
                +            method = java_match[2]
                +            file = java_match[3]
                +            number = java_match[4]
                +          end
                @@ -76,0 +87 @@
                +        return false unless file
                @@ -78,5 +89 @@
                -        if file =~ in_app_pattern
                -          true
                -        else
                -          false
                -        end
                +        file.match?(in_app_pattern)
        lib/sentry/configuration.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/configuration.rb	2026-06-09 02:33:49.041309520 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/configuration.rb	2026-06-09 02:33:49.053309504 +0000
                @@ -464 +464,2 @@
                -          configured: { before: [], after: [] }
                +          configured: { before: [], after: [] },
                +          closed: { before: [], after: [] }
                @@ -798,0 +800,5 @@
                +    end
                +
                +    # @api private
                +    def run_after_close_callbacks
                +      run_callbacks(:after, :closed)
        lib/sentry/hub.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/hub.rb	2026-06-09 02:33:49.044309516 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/hub.rb	2026-06-09 02:33:49.056309500 +0000
                @@ -56,0 +57,6 @@
                +    # All clients bound across the hub's scope stack, base layer first.
                +    # @return [Array<Client>]
                +    def clients
                +      @stack.map(&:client).compact
                +    end
                +
        lib/sentry/interfaces/request.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/interfaces/request.rb	2026-06-09 02:33:49.044309516 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/interfaces/request.rb	2026-06-09 02:33:49.056309500 +0000
                @@ -13,0 +14,3 @@
                +    # Regex to detect lowercase chars — match? is allocation-free (no MatchData/String)
                +    LOWERCASE_PATTERN = /[a-z]/.freeze
                +
                @@ -96 +99 @@
                -          key = key.sub(/^HTTP_/, "")
                +          key = key.delete_prefix("HTTP_")
                @@ -111 +114 @@
                -      key.upcase != key || # lower-case envs aren't real http headers
                +      key.match?(LOWERCASE_PATTERN) || # lower-case envs aren't real http headers
                @@ -122,2 +125 @@
                -      rack_version = Gem::Version.new(::Rack.release)
                -      return false if rack_version >= Gem::Version.new("3.0")
                +      return false if self.class.rack_3_or_above?
                @@ -125,0 +128,7 @@
                +    end
                +
                +    def self.rack_3_or_above?
                +      return @rack_3_or_above if defined?(@rack_3_or_above)
                +
                +      @rack_3_or_above = defined?(::Rack) &&
                +        Gem::Version.new(::Rack.release) >= Gem::Version.new("3.0")
        lib/sentry/interfaces/stacktrace.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:49.044309516 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:49.056309500 +0000
                @@ -30,4 +30 @@
                -      def initialize(project_root, line, strip_backtrace_load_path = true)
                -        @project_root = project_root
                -        @strip_backtrace_load_path = strip_backtrace_load_path
                -
                +      def initialize(project_root, line, strip_backtrace_load_path = true, filename_cache: nil)
                @@ -39 +36 @@
                -        @filename = compute_filename
                +        @filename = filename_cache&.compute_filename(@abs_path, @in_app, strip_backtrace_load_path)
                @@ -46,16 +42,0 @@
                -      def compute_filename
                -        return if abs_path.nil?
                -        return abs_path unless @strip_backtrace_load_path
                -
                -        prefix =
                -          if under_project_root? && in_app
                -            @project_root
                -          elsif under_project_root?
                -            longest_load_path || @project_root
                -          else
                -            longest_load_path
                -          end
                -
                -        prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
                -      end
                -
                @@ -79,8 +59,0 @@
                -
                -      def under_project_root?
                -        @project_root && abs_path.start_with?(@project_root)
                -      end
                -
                -      def longest_load_path
                -        $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
                -      end
        lib/sentry/interfaces/stacktrace_builder.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:49.044309516 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:49.056309500 +0000
                @@ -2,0 +3,2 @@
                +require "sentry/utils/filename_cache"
                +
                @@ -22,0 +25,3 @@
                +    # @return [FilenameCache]
                +    attr_reader :filename_cache
                +
                @@ -48,0 +54,2 @@
                +      @in_app_pattern = Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}") if app_dirs_pattern
                +      @filename_cache = FilenameCache.new(project_root)
                @@ -67 +74,10 @@
                -      parsed_lines = parse_backtrace_lines(backtrace).select(&:file)
                +      parsed_lines = parse_backtrace_lines(backtrace)
                +
                +      # Build frames in reverse order, skipping lines without files
                +      # Single pass instead of select + reverse + map + compact
                +      frames = []
                +      i = parsed_lines.size - 1
                +      while i >= 0
                +        line = parsed_lines[i]
                +        i -= 1
                +        next unless line.file
                @@ -69 +84,0 @@
                -      frames = parsed_lines.reverse.map do |line|
                @@ -72,2 +87,2 @@
                -        frame
                -      end.compact
                +        frames << frame if frame
                +      end
                @@ -81 +96 @@
                -      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path)
                +      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path, filename_cache: @filename_cache)
                @@ -88 +103,2 @@
                -        backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback
                +        backtrace, project_root, app_dirs_pattern,
                +        in_app_pattern: @in_app_pattern, &backtrace_cleanup_callback
        lib/sentry/linecache.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/linecache.rb	2026-06-09 02:33:49.045309515 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/linecache.rb	2026-06-09 02:33:49.056309500 +0000
                @@ -15 +15,2 @@
                -      return nil, nil, nil unless valid_path?(filename)
                +      lines = getlines(filename)
                +      return nil, nil, nil unless lines
                @@ -17,4 +18,6 @@
                -      lines = Array.new(2 * context + 1) do |i|
                -        getline(filename, lineno - context + i)
                -      end
                -      [lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]]
                +      first_line = lineno - context
                +      pre = Array.new(context) { |i| line_at(lines, first_line + i) }
                +      context_line = line_at(lines, lineno)
                +      post = Array.new(context) { |i| line_at(lines, lineno + 1 + i) }
                +
                +      [pre, context_line, post]
                @@ -25,3 +28,4 @@
                -    def valid_path?(path)
                -      lines = getlines(path)
                -      !lines.nil?
                +    def line_at(lines, n)
                +      return nil if n < 1
                +
                +      lines[n - 1]
                @@ -31,4 +35,6 @@
                -      @cache[path] ||= begin
                -        File.open(path, "r", &:readlines)
                -      rescue
                -        nil
                +      @cache.fetch(path) do
                +        @cache[path] = begin
                +          File.open(path, "r", &:readlines)
                +        rescue
                +          nil
                +        end
                @@ -36,9 +41,0 @@
                -    end
                -
                -    def getline(path, n)
                -      return nil if n < 1
                -
                -      lines = getlines(path)
                -      return nil if lines.nil?
                -
                -      lines[n - 1]
        lib/sentry/profiler.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/profiler.rb	2026-06-09 02:33:49.045309515 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/profiler.rb	2026-06-09 02:33:49.057309498 +0000
                @@ -28,0 +29 @@
                +      @filename_cache = configuration.stacktrace_builder.filename_cache
        lib/sentry/profiler/helpers.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:49.045309515 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:49.057309498 +0000
                @@ -12,3 +11,0 @@
                -      # 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
                @@ -16,18 +13 @@
                -        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
                +        @filename_cache.compute_filename(abs_path, in_app, true)
        lib/sentry/release_detector.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/release_detector.rb	2026-06-09 02:33:49.046309514 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/release_detector.rb	2026-06-09 02:33:49.058309497 +0000
                @@ -8,0 +9 @@
                +        detect_release_from_kamal ||
                @@ -31,0 +33,4 @@
                +      end
                +
                +      def detect_release_from_kamal
                +        ENV["KAMAL_VERSION"]
        lib/sentry/telemetry_event_buffer.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:49.047309512 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:49.059309495 +0000
                @@ -52,0 +53,3 @@
                +      # Prevent ThreadError from re-entrant locking (e.g. transport instrumentation calling Sentry.metrics.*)
                +      return self if @mutex.owned?
                +
        lib/sentry/test_helper.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/test_helper.rb	2026-06-09 02:33:49.047309512 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/test_helper.rb	2026-06-09 02:33:49.059309495 +0000
                @@ -39,0 +40,7 @@
                +      # Install the testing clients on the *main* hub rather than the current
                +      # thread's hub. `Sentry.clone_hub_to_current_thread` (used by
                +      # Sentry::Rack::CaptureExceptions) always clones the main hub, so if we
                +      # only mutated the thread-local hub a request-time clone would observe a
                +      # stale transport.
                +      main_hub = Sentry.get_main_hub
                +
                @@ -42 +49 @@
                -      Sentry.get_current_hub.bind_client(base_client)
                +      main_hub.bind_client(base_client)
                @@ -44 +51 @@
                -      Sentry.get_current_hub.push_scope
                +      main_hub.push_scope
                @@ -46 +53,6 @@
                -      Sentry.get_current_hub.bind_client(test_client)
                +      main_hub.bind_client(test_client)
                +
                +      # Realign the current thread's hub with the main hub so direct
                +      # `sentry_events` reads and any hub the Rack middleware clones from the
                +      # main hub all observe the same DummyTransport.
                +      Thread.current.thread_variable_set(Sentry::THREAD_LOCAL, main_hub)
                @@ -57,2 +69,5 @@
                -      # pop testing layer created by `setup_sentry_test`
                -      # but keep the base layer to avoid nil-pointer errors
                +      # pop the testing layer created by `setup_sentry_test` off the *main*
                +      # hub (that is where `setup_sentry_test` pushed it), keeping the base
                +      # layer to avoid nil-pointer errors. Popping the current thread's hub
                +      # would leave the test layer dangling on the main hub, which the next
                +      # request-time clone would inherit.
                @@ -60,2 +75,3 @@
                -      if Sentry.get_current_hub.instance_variable_get(:@stack).size > 1
                -        Sentry.get_current_hub.pop_scope
                +      main_hub = Sentry.get_main_hub
                +      if main_hub.instance_variable_get(:@stack).size > 1
                +        main_hub.pop_scope
                @@ -69 +85,7 @@
                -      sentry_transport.clear if sentry_transport.respond_to?(:clear)
                +      # Clear every transport reachable from the current thread's hub and the
                +      # main hub (including its base layer). A request-time clone shares the
                +      # main hub's base-layer transport, so clearing only the current
                +      # transport would let stale events survive into the next test.
                +      sentry_test_transports.each do |transport|
                +        transport.clear if transport.respond_to?(:clear)
                +      end
                @@ -83,0 +106,11 @@
                +    end
                +
                +    # Every transport reachable from the current thread's hub and the main
                +    # hub, across all stack layers. Used by `clear_sentry_events` so a stale
                +    # DummyTransport (e.g. the main hub's base layer that a request-time clone
                +    # shares) cannot carry leftover events into the next test.
                +    # @return [Array<Transport>]
                +    def sentry_test_transports
                +      [Sentry.get_current_hub, Sentry.get_main_hub].compact.uniq.flat_map do |hub|
                +        hub.clients.map(&:transport)
                +      end.compact.uniq
        lib/sentry/transport/dummy_transport.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:49.048309511 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:49.060309494 +0000
                @@ -20,0 +21,7 @@
                +
                +    # Empties the captured events and envelopes so `TestHelper.clear_sentry_events`
                +    # also clears the dummy transport instance
                +    def clear
                +      @events.clear
                +      @envelopes.clear
                +    end
        lib/sentry/utils/http_tracing.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:49.049309509 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:49.061309493 +0000
                @@ -15 +15,7 @@
                -        Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v }
                +        Sentry.get_trace_propagation_headers&.each do |k, v|
                +          if k == BAGGAGE_HEADER_NAME && req[k]
                +            req[k] = "#{v},#{req[k]}"
                +          else
                +            req[k] = v
                +          end
                +        end
        lib/sentry/vernier/output.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/vernier/output.rb	2026-06-09 02:33:49.049309509 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/vernier/output.rb	2026-06-09 02:33:49.062309491 +0000
                @@ -13 +13 @@
                -      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:)
                +      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:, filename_cache:)
                @@ -17,0 +18 @@
                +        @filename_cache = filename_cache
        lib/sentry/vernier/profiler.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:49.049309509 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:49.062309491 +0000
                @@ -26,0 +27 @@
                +        @filename_cache = configuration.stacktrace_builder.filename_cache
                @@ -128 +129,2 @@
                -          in_app_pattern: @in_app_pattern
                +          in_app_pattern: @in_app_pattern,
                +          filename_cache: @filename_cache
        lib/sentry/version.rb
                --- /tmp/d20260609-764-9gif10/sentry-ruby-6.5.0/lib/sentry/version.rb	2026-06-09 02:33:49.049309509 +0000
                +++ /tmp/d20260609-764-9gif10/sentry-ruby-6.6.1/lib/sentry/version.rb	2026-06-09 02:33:49.062309491 +0000
                @@ -4 +4 @@
                -  VERSION = "6.5.0"
                +  VERSION = "6.6.1"

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

gem compare --diff sentry-ruby 6.5.0 6.6.1

Compared versions: ["6.5.0", "6.6.1"]
  DIFFERENT files:
    6.5.0->6.6.1:
      * Added:
        lib/sentry/utils/filename_cache.rb
                --- /tmp/20260609-745-rcar8s	2026-06-09 02:33:49.416182318 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/utils/filename_cache.rb	2026-06-09 02:33:49.414182305 +0000
                @@ -0,0 +1,47 @@
                +# frozen_string_literal: true
                +
                +module Sentry
                +  class FilenameCache
                +    attr_reader :cache
                +
                +    def initialize(project_root)
                +      @project_root = project_root
                +      @load_paths = $LOAD_PATH.map(&:to_s).sort_by(&:size).reverse.freeze
                +      @cache = {}
                +    end
                +
                +    def compute_filename(abs_path, in_app, strip_backtrace_load_path)
                +      return unless abs_path
                +      return abs_path unless strip_backtrace_load_path
                +
                +      @cache.fetch(abs_path) do
                +        under_root = @project_root && abs_path.start_with?(@project_root)
                +        prefix =
                +          if under_root && in_app
                +            @project_root
                +          elsif under_root
                +            longest_load_path(abs_path) || @project_root
                +          else
                +            longest_load_path(abs_path)
                +          end
                +
                +        @cache[abs_path] = if prefix
                +          offset = if prefix.end_with?(File::SEPARATOR)
                +            prefix.bytesize
                +          else
                +            prefix.bytesize + 1
                +          end
                +          abs_path.byteslice(offset, abs_path.bytesize - offset)
                +        else
                +          abs_path
                +        end
                +      end
                +    end
                +
                +    private
                +
                +    def longest_load_path(abs_path)
                +      @load_paths.find { |path| abs_path.start_with?(path) }
                +    end
                +  end
                +end
      * Changed:
        README.md
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/README.md	2026-06-09 02:33:49.393182170 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/README.md	2026-06-09 02:33:49.405182247 +0000
                @@ -23,0 +24 @@
                +| [![Gem Version](https://img.shields.io/gem/v/sentry-yabeda?label=sentry-yabeda)](https://rubygems.org/gems/sentry-yabeda) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/tests.yml) | [![codecov](https://codecov.io/gh/getsentry/sentry-ruby/graph/badge.svg?token=ZePzrpZFP6&component=sentry-yabeda)](https://codecov.io/gh/getsentry/sentry-ruby) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-yabeda) |
                @@ -55,0 +57 @@
                +gem "sentry-yabeda"
                @@ -95,0 +98 @@
                +- [Yabeda](https://docs.sentry.io/platforms/ruby/guides/yabeda/)
        lib/sentry-ruby.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry-ruby.rb	2026-06-09 02:33:49.393182170 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry-ruby.rb	2026-06-09 02:33:49.406182253 +0000
                @@ -270,0 +271 @@
                +        client.configuration.run_after_close_callbacks
        lib/sentry/backtrace.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/backtrace.rb	2026-06-09 02:33:49.394182176 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/backtrace.rb	2026-06-09 02:33:49.406182253 +0000
                @@ -13 +13,3 @@
                -    def self.parse(backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback)
                +    # @deprecated project_root, in_app_pattern passed from outside
                +    # @deprecated app_dirs_pattern, in_app_pattern passed from outside
                +    def self.parse(backtrace, project_root, app_dirs_pattern, in_app_pattern: nil, &backtrace_cleanup_callback)
                @@ -18,3 +20,3 @@
                -      in_app_pattern ||= begin
                -        Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
                -      end
                +      # in_app_pattern is now passed in from StacktraceBuilder, so this regex won't be triggered
                +      # only here for backwards compat and will be deleted
                +      in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
        lib/sentry/backtrace/line.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/backtrace/line.rb	2026-06-09 02:33:49.394182176 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/backtrace/line.rb	2026-06-09 02:33:49.406182253 +0000
                @@ -8,0 +9 @@
                +      CLASS_EXTENSION = ".class"
                @@ -40,3 +41,7 @@
                -          _, file, number, _, module_name, method = ruby_match.to_a
                -          file.sub!(/\.class$/, RB_EXTENSION)
                -          module_name = module_name
                +          file = ruby_match[1]
                +          number = ruby_match[2]
                +          module_name = ruby_match[4]
                +          method = ruby_match[5]
                +          if file.end_with?(CLASS_EXTENSION)
                +            file.sub!(/\.class$/, RB_EXTENSION)
                +          end
                @@ -45 +50,6 @@
                -          _, module_name, method, file, number = java_match.to_a
                +          if java_match
                +            module_name = java_match[1]
                +            method = java_match[2]
                +            file = java_match[3]
                +            number = java_match[4]
                +          end
                @@ -76,0 +87 @@
                +        return false unless file
                @@ -78,5 +89 @@
                -        if file =~ in_app_pattern
                -          true
                -        else
                -          false
                -        end
                +        file.match?(in_app_pattern)
        lib/sentry/configuration.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/configuration.rb	2026-06-09 02:33:49.395182183 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/configuration.rb	2026-06-09 02:33:49.407182260 +0000
                @@ -464 +464,2 @@
                -          configured: { before: [], after: [] }
                +          configured: { before: [], after: [] },
                +          closed: { before: [], after: [] }
                @@ -798,0 +800,5 @@
                +    end
                +
                +    # @api private
                +    def run_after_close_callbacks
                +      run_callbacks(:after, :closed)
        lib/sentry/hub.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/hub.rb	2026-06-09 02:33:49.397182196 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/hub.rb	2026-06-09 02:33:49.409182273 +0000
                @@ -56,0 +57,6 @@
                +    # All clients bound across the hub's scope stack, base layer first.
                +    # @return [Array<Client>]
                +    def clients
                +      @stack.map(&:client).compact
                +    end
                +
        lib/sentry/interfaces/request.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/interfaces/request.rb	2026-06-09 02:33:49.398182202 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/interfaces/request.rb	2026-06-09 02:33:49.409182273 +0000
                @@ -13,0 +14,3 @@
                +    # Regex to detect lowercase chars — match? is allocation-free (no MatchData/String)
                +    LOWERCASE_PATTERN = /[a-z]/.freeze
                +
                @@ -96 +99 @@
                -          key = key.sub(/^HTTP_/, "")
                +          key = key.delete_prefix("HTTP_")
                @@ -111 +114 @@
                -      key.upcase != key || # lower-case envs aren't real http headers
                +      key.match?(LOWERCASE_PATTERN) || # lower-case envs aren't real http headers
                @@ -122,2 +125 @@
                -      rack_version = Gem::Version.new(::Rack.release)
                -      return false if rack_version >= Gem::Version.new("3.0")
                +      return false if self.class.rack_3_or_above?
                @@ -125,0 +128,7 @@
                +    end
                +
                +    def self.rack_3_or_above?
                +      return @rack_3_or_above if defined?(@rack_3_or_above)
                +
                +      @rack_3_or_above = defined?(::Rack) &&
                +        Gem::Version.new(::Rack.release) >= Gem::Version.new("3.0")
        lib/sentry/interfaces/stacktrace.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:49.398182202 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace.rb	2026-06-09 02:33:49.410182279 +0000
                @@ -30,4 +30 @@
                -      def initialize(project_root, line, strip_backtrace_load_path = true)
                -        @project_root = project_root
                -        @strip_backtrace_load_path = strip_backtrace_load_path
                -
                +      def initialize(project_root, line, strip_backtrace_load_path = true, filename_cache: nil)
                @@ -39 +36 @@
                -        @filename = compute_filename
                +        @filename = filename_cache&.compute_filename(@abs_path, @in_app, strip_backtrace_load_path)
                @@ -46,16 +42,0 @@
                -      def compute_filename
                -        return if abs_path.nil?
                -        return abs_path unless @strip_backtrace_load_path
                -
                -        prefix =
                -          if under_project_root? && in_app
                -            @project_root
                -          elsif under_project_root?
                -            longest_load_path || @project_root
                -          else
                -            longest_load_path
                -          end
                -
                -        prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
                -      end
                -
                @@ -79,8 +59,0 @@
                -
                -      def under_project_root?
                -        @project_root && abs_path.start_with?(@project_root)
                -      end
                -
                -      def longest_load_path
                -        $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
                -      end
        lib/sentry/interfaces/stacktrace_builder.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:49.398182202 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/interfaces/stacktrace_builder.rb	2026-06-09 02:33:49.410182279 +0000
                @@ -2,0 +3,2 @@
                +require "sentry/utils/filename_cache"
                +
                @@ -22,0 +25,3 @@
                +    # @return [FilenameCache]
                +    attr_reader :filename_cache
                +
                @@ -48,0 +54,2 @@
                +      @in_app_pattern = Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}") if app_dirs_pattern
                +      @filename_cache = FilenameCache.new(project_root)
                @@ -67 +74,10 @@
                -      parsed_lines = parse_backtrace_lines(backtrace).select(&:file)
                +      parsed_lines = parse_backtrace_lines(backtrace)
                +
                +      # Build frames in reverse order, skipping lines without files
                +      # Single pass instead of select + reverse + map + compact
                +      frames = []
                +      i = parsed_lines.size - 1
                +      while i >= 0
                +        line = parsed_lines[i]
                +        i -= 1
                +        next unless line.file
                @@ -69 +84,0 @@
                -      frames = parsed_lines.reverse.map do |line|
                @@ -72,2 +87,2 @@
                -        frame
                -      end.compact
                +        frames << frame if frame
                +      end
                @@ -81 +96 @@
                -      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path)
                +      frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path, filename_cache: @filename_cache)
                @@ -88 +103,2 @@
                -        backtrace, project_root, app_dirs_pattern, &backtrace_cleanup_callback
                +        backtrace, project_root, app_dirs_pattern,
                +        in_app_pattern: @in_app_pattern, &backtrace_cleanup_callback
        lib/sentry/linecache.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/linecache.rb	2026-06-09 02:33:49.398182202 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/linecache.rb	2026-06-09 02:33:49.410182279 +0000
                @@ -15 +15,2 @@
                -      return nil, nil, nil unless valid_path?(filename)
                +      lines = getlines(filename)
                +      return nil, nil, nil unless lines
                @@ -17,4 +18,6 @@
                -      lines = Array.new(2 * context + 1) do |i|
                -        getline(filename, lineno - context + i)
                -      end
                -      [lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]]
                +      first_line = lineno - context
                +      pre = Array.new(context) { |i| line_at(lines, first_line + i) }
                +      context_line = line_at(lines, lineno)
                +      post = Array.new(context) { |i| line_at(lines, lineno + 1 + i) }
                +
                +      [pre, context_line, post]
                @@ -25,3 +28,4 @@
                -    def valid_path?(path)
                -      lines = getlines(path)
                -      !lines.nil?
                +    def line_at(lines, n)
                +      return nil if n < 1
                +
                +      lines[n - 1]
                @@ -31,4 +35,6 @@
                -      @cache[path] ||= begin
                -        File.open(path, "r", &:readlines)
                -      rescue
                -        nil
                +      @cache.fetch(path) do
                +        @cache[path] = begin
                +          File.open(path, "r", &:readlines)
                +        rescue
                +          nil
                +        end
                @@ -36,9 +41,0 @@
                -    end
                -
                -    def getline(path, n)
                -      return nil if n < 1
                -
                -      lines = getlines(path)
                -      return nil if lines.nil?
                -
                -      lines[n - 1]
        lib/sentry/profiler.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/profiler.rb	2026-06-09 02:33:49.399182209 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/profiler.rb	2026-06-09 02:33:49.411182285 +0000
                @@ -28,0 +29 @@
                +      @filename_cache = configuration.stacktrace_builder.filename_cache
        lib/sentry/profiler/helpers.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:49.399182209 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/profiler/helpers.rb	2026-06-09 02:33:49.411182285 +0000
                @@ -12,3 +11,0 @@
                -      # 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
                @@ -16,18 +13 @@
                -        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
                +        @filename_cache.compute_filename(abs_path, in_app, true)
        lib/sentry/release_detector.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/release_detector.rb	2026-06-09 02:33:49.400182215 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/release_detector.rb	2026-06-09 02:33:49.412182292 +0000
                @@ -8,0 +9 @@
                +        detect_release_from_kamal ||
                @@ -31,0 +33,4 @@
                +      end
                +
                +      def detect_release_from_kamal
                +        ENV["KAMAL_VERSION"]
        lib/sentry/telemetry_event_buffer.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:49.401182221 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/telemetry_event_buffer.rb	2026-06-09 02:33:49.412182292 +0000
                @@ -52,0 +53,3 @@
                +      # Prevent ThreadError from re-entrant locking (e.g. transport instrumentation calling Sentry.metrics.*)
                +      return self if @mutex.owned?
                +
        lib/sentry/test_helper.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/test_helper.rb	2026-06-09 02:33:49.401182221 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/test_helper.rb	2026-06-09 02:33:49.413182298 +0000
                @@ -39,0 +40,7 @@
                +      # Install the testing clients on the *main* hub rather than the current
                +      # thread's hub. `Sentry.clone_hub_to_current_thread` (used by
                +      # Sentry::Rack::CaptureExceptions) always clones the main hub, so if we
                +      # only mutated the thread-local hub a request-time clone would observe a
                +      # stale transport.
                +      main_hub = Sentry.get_main_hub
                +
                @@ -42 +49 @@
                -      Sentry.get_current_hub.bind_client(base_client)
                +      main_hub.bind_client(base_client)
                @@ -44 +51 @@
                -      Sentry.get_current_hub.push_scope
                +      main_hub.push_scope
                @@ -46 +53,6 @@
                -      Sentry.get_current_hub.bind_client(test_client)
                +      main_hub.bind_client(test_client)
                +
                +      # Realign the current thread's hub with the main hub so direct
                +      # `sentry_events` reads and any hub the Rack middleware clones from the
                +      # main hub all observe the same DummyTransport.
                +      Thread.current.thread_variable_set(Sentry::THREAD_LOCAL, main_hub)
                @@ -57,2 +69,5 @@
                -      # pop testing layer created by `setup_sentry_test`
                -      # but keep the base layer to avoid nil-pointer errors
                +      # pop the testing layer created by `setup_sentry_test` off the *main*
                +      # hub (that is where `setup_sentry_test` pushed it), keeping the base
                +      # layer to avoid nil-pointer errors. Popping the current thread's hub
                +      # would leave the test layer dangling on the main hub, which the next
                +      # request-time clone would inherit.
                @@ -60,2 +75,3 @@
                -      if Sentry.get_current_hub.instance_variable_get(:@stack).size > 1
                -        Sentry.get_current_hub.pop_scope
                +      main_hub = Sentry.get_main_hub
                +      if main_hub.instance_variable_get(:@stack).size > 1
                +        main_hub.pop_scope
                @@ -69 +85,7 @@
                -      sentry_transport.clear if sentry_transport.respond_to?(:clear)
                +      # Clear every transport reachable from the current thread's hub and the
                +      # main hub (including its base layer). A request-time clone shares the
                +      # main hub's base-layer transport, so clearing only the current
                +      # transport would let stale events survive into the next test.
                +      sentry_test_transports.each do |transport|
                +        transport.clear if transport.respond_to?(:clear)
                +      end
                @@ -83,0 +106,11 @@
                +    end
                +
                +    # Every transport reachable from the current thread's hub and the main
                +    # hub, across all stack layers. Used by `clear_sentry_events` so a stale
                +    # DummyTransport (e.g. the main hub's base layer that a request-time clone
                +    # shares) cannot carry leftover events into the next test.
                +    # @return [Array<Transport>]
                +    def sentry_test_transports
                +      [Sentry.get_current_hub, Sentry.get_main_hub].compact.uniq.flat_map do |hub|
                +        hub.clients.map(&:transport)
                +      end.compact.uniq
        lib/sentry/transport/dummy_transport.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:49.402182228 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/transport/dummy_transport.rb	2026-06-09 02:33:49.413182298 +0000
                @@ -20,0 +21,7 @@
                +
                +    # Empties the captured events and envelopes so `TestHelper.clear_sentry_events`
                +    # also clears the dummy transport instance
                +    def clear
                +      @events.clear
                +      @envelopes.clear
                +    end
        lib/sentry/utils/http_tracing.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:49.403182234 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/utils/http_tracing.rb	2026-06-09 02:33:49.414182305 +0000
                @@ -15 +15,7 @@
                -        Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v }
                +        Sentry.get_trace_propagation_headers&.each do |k, v|
                +          if k == BAGGAGE_HEADER_NAME && req[k]
                +            req[k] = "#{v},#{req[k]}"
                +          else
                +            req[k] = v
                +          end
                +        end
        lib/sentry/vernier/output.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/vernier/output.rb	2026-06-09 02:33:49.404182241 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/vernier/output.rb	2026-06-09 02:33:49.415182311 +0000
                @@ -13 +13 @@
                -      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:)
                +      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:, filename_cache:)
                @@ -17,0 +18 @@
                +        @filename_cache = filename_cache
        lib/sentry/vernier/profiler.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:49.404182241 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/vernier/profiler.rb	2026-06-09 02:33:49.415182311 +0000
                @@ -26,0 +27 @@
                +        @filename_cache = configuration.stacktrace_builder.filename_cache
                @@ -128 +129,2 @@
                -          in_app_pattern: @in_app_pattern
                +          in_app_pattern: @in_app_pattern,
                +          filename_cache: @filename_cache
        lib/sentry/version.rb
                --- /tmp/d20260609-745-42bk4z/sentry-ruby-6.5.0/lib/sentry/version.rb	2026-06-09 02:33:49.404182241 +0000
                +++ /tmp/d20260609-745-42bk4z/sentry-ruby-6.6.1/lib/sentry/version.rb	2026-06-09 02:33:49.415182311 +0000
                @@ -4 +4 @@
                -  VERSION = "6.5.0"
                +  VERSION = "6.6.1"

@dependabot @github

dependabot Bot commented on behalf of github Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #1002.

@dependabot dependabot Bot closed this Jun 10, 2026
@dependabot dependabot Bot deleted the dependabot/bundler/sentry-ruby-6.6.1 branch June 10, 2026 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies ruby Pull requests that update Ruby code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants