sentry-ruby-core 5.5.0 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -0
- data/lib/sentry/configuration.rb +11 -0
- data/lib/sentry/hub.rb +22 -1
- data/lib/sentry/interfaces/request.rb +2 -14
- data/lib/sentry/interfaces/single_exception.rb +9 -1
- data/lib/sentry/net/http.rb +13 -30
- data/lib/sentry/rack/capture_exceptions.rb +1 -1
- data/lib/sentry/redis.rb +14 -16
- data/lib/sentry/span.rb +10 -11
- data/lib/sentry/transaction.rb +44 -15
- data/lib/sentry/transaction_event.rb +1 -0
- data/lib/sentry/utils/encoding_helper.rb +22 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +3 -16
- metadata +5 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2b278a33d0084cedcfbe91b489c53c56dee24543e5a319d764aff94cc41c579a
         | 
| 4 | 
            +
              data.tar.gz: 923f906cd698d18f2fcb419bfeb2d1262c4165e6a8ffe2484de7027a90e69644
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 47f71f658582bb3b81918b96780e118c4bc161c78f9d0c3e060a80fd6e75258824fc6be690d57899445fdc03f9cbf5c3693ad7754fcc9d96ba2d1480b0222444
         | 
| 7 | 
            +
              data.tar.gz: 14b28401b32d9ce9ee7ac0351de736d0d9f11221010e61091e4976b71a58b1fef61ca4e282ec31a714e040148197c5fab46f0a0e39e475ea1f6dd0196b5f104d
         | 
    
        data/README.md
    CHANGED
    
    | @@ -20,6 +20,7 @@ Sentry SDK for Ruby | |
| 20 20 | 
             
            | [](https://rubygems.org/gems/sentry-sidekiq) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-sidekiq/) |
         | 
| 21 21 | 
             
            | [](https://rubygems.org/gems/sentry-delayed_job) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-delayed_job/) |
         | 
| 22 22 | 
             
            | [](https://rubygems.org/gems/sentry-resque) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-resque/) |
         | 
| 23 | 
            +
            | [](https://rubygems.org/gems/sentry-opentelemetry) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-opentelemetry/) |
         | 
| 23 24 |  | 
| 24 25 |  | 
| 25 26 |  | 
| @@ -51,6 +52,7 @@ gem "sentry-rails" | |
| 51 52 | 
             
            gem "sentry-sidekiq"
         | 
| 52 53 | 
             
            gem "sentry-delayed_job"
         | 
| 53 54 | 
             
            gem "sentry-resque"
         | 
| 55 | 
            +
            gem "sentry-opentelemetry"
         | 
| 54 56 | 
             
            ```
         | 
| 55 57 |  | 
| 56 58 | 
             
            ### Configuration
         | 
| @@ -88,6 +90,7 @@ To learn more about sampling transactions, please visit the [official documentat | |
| 88 90 | 
             
            - [Sidekiq](https://docs.sentry.io/platforms/ruby/guides/sidekiq/)
         | 
| 89 91 | 
             
            - [DelayedJob](https://docs.sentry.io/platforms/ruby/guides/delayed_job/)
         | 
| 90 92 | 
             
            - [Resque](https://docs.sentry.io/platforms/ruby/guides/resque/)
         | 
| 93 | 
            +
            - [OpenTemeletry](https://docs.sentry.io/platforms/ruby/performance/instrumentation/opentelemetry/)
         | 
| 91 94 |  | 
| 92 95 | 
             
            ### Enriching Events
         | 
| 93 96 |  | 
    
        data/lib/sentry/configuration.rb
    CHANGED
    
    | @@ -211,6 +211,10 @@ module Sentry | |
| 211 211 | 
             
                # @return [Boolean]
         | 
| 212 212 | 
             
                attr_accessor :auto_session_tracking
         | 
| 213 213 |  | 
| 214 | 
            +
                # The instrumenter to use, :sentry or :otel
         | 
| 215 | 
            +
                # @return [Symbol]
         | 
| 216 | 
            +
                attr_reader :instrumenter
         | 
| 217 | 
            +
             | 
| 214 218 | 
             
                # these are not config options
         | 
| 215 219 | 
             
                # @!visibility private
         | 
| 216 220 | 
             
                attr_reader :errors, :gem_specs
         | 
| @@ -237,6 +241,8 @@ module Sentry | |
| 237 241 | 
             
                MODULE_SEPARATOR = "::".freeze
         | 
| 238 242 | 
             
                SKIP_INSPECTION_ATTRIBUTES = [:@linecache, :@stacktrace_builder]
         | 
| 239 243 |  | 
| 244 | 
            +
                INSTRUMENTERS = [:sentry, :otel]
         | 
| 245 | 
            +
             | 
| 240 246 | 
             
                # Post initialization callbacks are called at the end of initialization process
         | 
| 241 247 | 
             
                # allowing extending the configuration of sentry-ruby by multiple extensions
         | 
| 242 248 | 
             
                @@post_initialization_callbacks = []
         | 
| @@ -269,6 +275,7 @@ module Sentry | |
| 269 275 | 
             
                  self.trusted_proxies = []
         | 
| 270 276 | 
             
                  self.dsn = ENV['SENTRY_DSN']
         | 
| 271 277 | 
             
                  self.server_name = server_name_from_env
         | 
| 278 | 
            +
                  self.instrumenter = :sentry
         | 
| 272 279 |  | 
| 273 280 | 
             
                  self.before_send = nil
         | 
| 274 281 | 
             
                  self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
         | 
| @@ -332,6 +339,10 @@ module Sentry | |
| 332 339 | 
             
                  @environment = environment.to_s
         | 
| 333 340 | 
             
                end
         | 
| 334 341 |  | 
| 342 | 
            +
                def instrumenter=(instrumenter)
         | 
| 343 | 
            +
                  @instrumenter = INSTRUMENTERS.include?(instrumenter) ? instrumenter : :sentry
         | 
| 344 | 
            +
                end
         | 
| 345 | 
            +
             | 
| 335 346 | 
             
                def sending_allowed?
         | 
| 336 347 | 
             
                  @errors = []
         | 
| 337 348 |  | 
    
        data/lib/sentry/hub.rb
    CHANGED
    
    | @@ -76,8 +76,9 @@ module Sentry | |
| 76 76 | 
             
                  @stack.pop
         | 
| 77 77 | 
             
                end
         | 
| 78 78 |  | 
| 79 | 
            -
                def start_transaction(transaction: nil, custom_sampling_context: {}, **options)
         | 
| 79 | 
            +
                def start_transaction(transaction: nil, custom_sampling_context: {}, instrumenter: :sentry, **options)
         | 
| 80 80 | 
             
                  return unless configuration.tracing_enabled?
         | 
| 81 | 
            +
                  return unless instrumenter == configuration.instrumenter
         | 
| 81 82 |  | 
| 82 83 | 
             
                  transaction ||= Transaction.new(**options.merge(hub: self))
         | 
| 83 84 |  | 
| @@ -92,6 +93,26 @@ module Sentry | |
| 92 93 | 
             
                  transaction
         | 
| 93 94 | 
             
                end
         | 
| 94 95 |  | 
| 96 | 
            +
                def with_child_span(instrumenter: :sentry, **attributes, &block)
         | 
| 97 | 
            +
                  return yield(nil) unless instrumenter == configuration.instrumenter
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  current_span = current_scope.get_span
         | 
| 100 | 
            +
                  return yield(nil) unless current_span
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  result = nil
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  begin
         | 
| 105 | 
            +
                    current_span.with_child_span(**attributes) do |child_span|
         | 
| 106 | 
            +
                      current_scope.set_span(child_span)
         | 
| 107 | 
            +
                      result = yield(child_span)
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
                  ensure
         | 
| 110 | 
            +
                    current_scope.set_span(current_span)
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  result
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
             | 
| 95 116 | 
             
                def capture_exception(exception, **options, &block)
         | 
| 96 117 | 
             
                  check_argument_type!(exception, ::Exception)
         | 
| 97 118 |  | 
| @@ -73,7 +73,7 @@ module Sentry | |
| 73 73 | 
             
                    request.POST
         | 
| 74 74 | 
             
                  elsif request.body # JSON requests, etc
         | 
| 75 75 | 
             
                    data = request.body.read(MAX_BODY_LIMIT)
         | 
| 76 | 
            -
                    data = encode_to_utf_8(data.to_s)
         | 
| 76 | 
            +
                    data = Utils::EncodingHelper.encode_to_utf_8(data.to_s)
         | 
| 77 77 | 
             
                    request.body.rewind
         | 
| 78 78 | 
             
                    data
         | 
| 79 79 | 
             
                  end
         | 
| @@ -94,7 +94,7 @@ module Sentry | |
| 94 94 | 
             
                      key = key.sub(/^HTTP_/, "")
         | 
| 95 95 | 
             
                      key = key.split('_').map(&:capitalize).join('-')
         | 
| 96 96 |  | 
| 97 | 
            -
                      memo[key] = encode_to_utf_8(value.to_s)
         | 
| 97 | 
            +
                      memo[key] = Utils::EncodingHelper.encode_to_utf_8(value.to_s)
         | 
| 98 98 | 
             
                    rescue StandardError => e
         | 
| 99 99 | 
             
                      # Rails adds objects to the Rack env that can sometimes raise exceptions
         | 
| 100 100 | 
             
                      # when `to_s` is called.
         | 
| @@ -105,18 +105,6 @@ module Sentry | |
| 105 105 | 
             
                  end
         | 
| 106 106 | 
             
                end
         | 
| 107 107 |  | 
| 108 | 
            -
                def encode_to_utf_8(value)
         | 
| 109 | 
            -
                  if value.encoding != Encoding::UTF_8 && value.respond_to?(:force_encoding)
         | 
| 110 | 
            -
                    value = value.dup.force_encoding(Encoding::UTF_8)
         | 
| 111 | 
            -
                  end
         | 
| 112 | 
            -
             | 
| 113 | 
            -
                  if !value.valid_encoding?
         | 
| 114 | 
            -
                    value = value.scrub
         | 
| 115 | 
            -
                  end
         | 
| 116 | 
            -
             | 
| 117 | 
            -
                  value
         | 
| 118 | 
            -
                end
         | 
| 119 | 
            -
             | 
| 120 108 | 
             
                def is_skippable_header?(key)
         | 
| 121 109 | 
             
                  key.upcase != key || # lower-case envs aren't real http headers
         | 
| 122 110 | 
             
                    key == "HTTP_COOKIE" || # Cookies don't go here, they go somewhere else
         | 
| @@ -15,7 +15,15 @@ module Sentry | |
| 15 15 |  | 
| 16 16 | 
             
                def initialize(exception:, stacktrace: nil)
         | 
| 17 17 | 
             
                  @type = exception.class.to_s
         | 
| 18 | 
            -
                   | 
| 18 | 
            +
                  exception_message =
         | 
| 19 | 
            +
                    if exception.respond_to?(:detailed_message)
         | 
| 20 | 
            +
                      exception.detailed_message(highlight: false)
         | 
| 21 | 
            +
                    else
         | 
| 22 | 
            +
                      exception.message || ""
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  @value = exception_message.byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES)
         | 
| 26 | 
            +
             | 
| 19 27 | 
             
                  @module = exception.class.to_s.split('::')[0...-1].join('::')
         | 
| 20 28 | 
             
                  @thread_id = Thread.current.object_id
         | 
| 21 29 | 
             
                  @stacktrace = stacktrace
         | 
    
        data/lib/sentry/net/http.rb
    CHANGED
    
    | @@ -26,14 +26,21 @@ module Sentry | |
| 26 26 | 
             
                  #
         | 
| 27 27 | 
             
                  # So we're only instrumenting request when `Net::HTTP` is already started
         | 
| 28 28 | 
             
                  def request(req, body = nil, &block)
         | 
| 29 | 
            -
                    return super unless started?
         | 
| 29 | 
            +
                    return super unless started? && Sentry.initialized?
         | 
| 30 | 
            +
                    return super if from_sentry_sdk?
         | 
| 30 31 |  | 
| 31 | 
            -
                     | 
| 32 | 
            -
             | 
| 32 | 
            +
                    Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |sentry_span|
         | 
| 33 | 
            +
                      set_sentry_trace_header(req, sentry_span)
         | 
| 33 34 |  | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 35 | 
            +
                      super.tap do |res|
         | 
| 36 | 
            +
                        record_sentry_breadcrumb(req, res)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                        if sentry_span
         | 
| 39 | 
            +
                          request_info = extract_request_info(req)
         | 
| 40 | 
            +
                          sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
         | 
| 41 | 
            +
                          sentry_span.set_data(:status, res.code.to_i)
         | 
| 42 | 
            +
                        end
         | 
| 43 | 
            +
                      end
         | 
| 37 44 | 
             
                    end
         | 
| 38 45 | 
             
                  end
         | 
| 39 46 |  | 
| @@ -53,7 +60,6 @@ module Sentry | |
| 53 60 |  | 
| 54 61 | 
             
                  def record_sentry_breadcrumb(req, res)
         | 
| 55 62 | 
             
                    return unless Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger)
         | 
| 56 | 
            -
                    return if from_sentry_sdk?
         | 
| 57 63 |  | 
| 58 64 | 
             
                    request_info = extract_request_info(req)
         | 
| 59 65 |  | 
| @@ -69,29 +75,6 @@ module Sentry | |
| 69 75 | 
             
                    Sentry.add_breadcrumb(crumb)
         | 
| 70 76 | 
             
                  end
         | 
| 71 77 |  | 
| 72 | 
            -
                  def record_sentry_span(req, res, sentry_span)
         | 
| 73 | 
            -
                    return unless Sentry.initialized? && sentry_span
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                    request_info = extract_request_info(req)
         | 
| 76 | 
            -
                    sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
         | 
| 77 | 
            -
                    sentry_span.set_data(:status, res.code.to_i)
         | 
| 78 | 
            -
                    finish_sentry_span(sentry_span)
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  def start_sentry_span
         | 
| 82 | 
            -
                    return unless Sentry.initialized? && span = Sentry.get_current_scope.get_span
         | 
| 83 | 
            -
                    return if from_sentry_sdk?
         | 
| 84 | 
            -
                    return if span.sampled == false
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                    span.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
         | 
| 87 | 
            -
                  end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                  def finish_sentry_span(sentry_span)
         | 
| 90 | 
            -
                    return unless Sentry.initialized? && sentry_span
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                    sentry_span.set_timestamp(Sentry.utc_now.to_f)
         | 
| 93 | 
            -
                  end
         | 
| 94 | 
            -
             | 
| 95 78 | 
             
                  def from_sentry_sdk?
         | 
| 96 79 | 
             
                    dsn = Sentry.configuration.dsn
         | 
| 97 80 | 
             
                    dsn && dsn.host == self.address
         | 
    
        data/lib/sentry/redis.rb
    CHANGED
    
    | @@ -3,7 +3,7 @@ | |
| 3 3 | 
             
            module Sentry
         | 
| 4 4 | 
             
              # @api private
         | 
| 5 5 | 
             
              class Redis
         | 
| 6 | 
            -
                OP_NAME = "db.redis | 
| 6 | 
            +
                OP_NAME = "db.redis"
         | 
| 7 7 | 
             
                LOGGER_NAME = :redis_logger
         | 
| 8 8 |  | 
| 9 9 | 
             
                def initialize(commands, host, port, db)
         | 
| @@ -13,9 +13,14 @@ module Sentry | |
| 13 13 | 
             
                def instrument
         | 
| 14 14 | 
             
                  return yield unless Sentry.initialized?
         | 
| 15 15 |  | 
| 16 | 
            -
                   | 
| 16 | 
            +
                  Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |span|
         | 
| 17 17 | 
             
                    yield.tap do
         | 
| 18 18 | 
             
                      record_breadcrumb
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                      if span
         | 
| 21 | 
            +
                        span.set_description(commands_description)
         | 
| 22 | 
            +
                        span.set_data(:server, server_description)
         | 
| 23 | 
            +
                      end
         | 
| 19 24 | 
             
                    end
         | 
| 20 25 | 
             
                  end
         | 
| 21 26 | 
             
                end
         | 
| @@ -24,18 +29,6 @@ module Sentry | |
| 24 29 |  | 
| 25 30 | 
             
                attr_reader :commands, :host, :port, :db
         | 
| 26 31 |  | 
| 27 | 
            -
                def record_span
         | 
| 28 | 
            -
                  return yield unless (transaction = Sentry.get_current_scope.get_transaction) && transaction.sampled
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                  sentry_span = transaction.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                  yield.tap do
         | 
| 33 | 
            -
                    sentry_span.set_description(commands_description)
         | 
| 34 | 
            -
                    sentry_span.set_data(:server, server_description)
         | 
| 35 | 
            -
                    sentry_span.set_timestamp(Sentry.utc_now.to_f)
         | 
| 36 | 
            -
                  end
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 32 | 
             
                def record_breadcrumb
         | 
| 40 33 | 
             
                  return unless Sentry.configuration.breadcrumbs_logger.include?(LOGGER_NAME)
         | 
| 41 34 |  | 
| @@ -61,10 +54,15 @@ module Sentry | |
| 61 54 | 
             
                def parsed_commands
         | 
| 62 55 | 
             
                  commands.map do |statement|
         | 
| 63 56 | 
             
                    command, key, *arguments = statement
         | 
| 57 | 
            +
                    command_set = { command: command.to_s.upcase, key: key }
         | 
| 64 58 |  | 
| 65 | 
            -
                     | 
| 66 | 
            -
                      command_set[:arguments] = arguments | 
| 59 | 
            +
                    if Sentry.configuration.send_default_pii
         | 
| 60 | 
            +
                      command_set[:arguments] = arguments
         | 
| 61 | 
            +
                                                .select { |a| Utils::EncodingHelper.valid_utf_8?(a) }
         | 
| 62 | 
            +
                                                .join(" ")
         | 
| 67 63 | 
             
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    command_set
         | 
| 68 66 | 
             
                  end
         | 
| 69 67 | 
             
                end
         | 
| 70 68 |  | 
    
        data/lib/sentry/span.rb
    CHANGED
    
    | @@ -60,25 +60,28 @@ module Sentry | |
| 60 60 | 
             
                # The Transaction object the Span belongs to.
         | 
| 61 61 | 
             
                # Every span needs to be attached to a Transaction and their child spans will also inherit the same transaction.
         | 
| 62 62 | 
             
                # @return [Transaction]
         | 
| 63 | 
            -
                 | 
| 63 | 
            +
                attr_reader :transaction
         | 
| 64 64 |  | 
| 65 65 | 
             
                def initialize(
         | 
| 66 | 
            +
                  transaction:,
         | 
| 66 67 | 
             
                  description: nil,
         | 
| 67 68 | 
             
                  op: nil,
         | 
| 68 69 | 
             
                  status: nil,
         | 
| 69 70 | 
             
                  trace_id: nil,
         | 
| 71 | 
            +
                  span_id: nil,
         | 
| 70 72 | 
             
                  parent_span_id: nil,
         | 
| 71 73 | 
             
                  sampled: nil,
         | 
| 72 74 | 
             
                  start_timestamp: nil,
         | 
| 73 75 | 
             
                  timestamp: nil
         | 
| 74 76 | 
             
                )
         | 
| 75 77 | 
             
                  @trace_id = trace_id || SecureRandom.uuid.delete("-")
         | 
| 76 | 
            -
                  @span_id = SecureRandom.hex(8)
         | 
| 78 | 
            +
                  @span_id = span_id || SecureRandom.hex(8)
         | 
| 77 79 | 
             
                  @parent_span_id = parent_span_id
         | 
| 78 80 | 
             
                  @sampled = sampled
         | 
| 79 81 | 
             
                  @start_timestamp = start_timestamp || Sentry.utc_now.to_f
         | 
| 80 82 | 
             
                  @timestamp = timestamp
         | 
| 81 83 | 
             
                  @description = description
         | 
| 84 | 
            +
                  @transaction = transaction
         | 
| 82 85 | 
             
                  @op = op
         | 
| 83 86 | 
             
                  @status = status
         | 
| 84 87 | 
             
                  @data = {}
         | 
| @@ -87,11 +90,8 @@ module Sentry | |
| 87 90 |  | 
| 88 91 | 
             
                # Finishes the span by adding a timestamp.
         | 
| 89 92 | 
             
                # @return [self]
         | 
| 90 | 
            -
                def finish
         | 
| 91 | 
            -
                   | 
| 92 | 
            -
                  return if @timestamp
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                  @timestamp = Sentry.utc_now.to_f
         | 
| 93 | 
            +
                def finish(end_timestamp: nil)
         | 
| 94 | 
            +
                  @timestamp = end_timestamp || @timestamp || Sentry.utc_now.to_f
         | 
| 95 95 | 
             
                  self
         | 
| 96 96 | 
             
                end
         | 
| 97 97 |  | 
| @@ -105,10 +105,10 @@ module Sentry | |
| 105 105 | 
             
                end
         | 
| 106 106 |  | 
| 107 107 | 
             
                # Generates a W3C Baggage header string for distributed tracing
         | 
| 108 | 
            -
                # from the incoming baggage stored on the  | 
| 108 | 
            +
                # from the incoming baggage stored on the transaction.
         | 
| 109 109 | 
             
                # @return [String, nil]
         | 
| 110 110 | 
             
                def to_baggage
         | 
| 111 | 
            -
                  transaction | 
| 111 | 
            +
                  transaction.get_baggage&.serialize
         | 
| 112 112 | 
             
                end
         | 
| 113 113 |  | 
| 114 114 | 
             
                # @return [Hash]
         | 
| @@ -143,9 +143,8 @@ module Sentry | |
| 143 143 | 
             
                # Starts a child span with given attributes.
         | 
| 144 144 | 
             
                # @param attributes [Hash] the attributes for the child span.
         | 
| 145 145 | 
             
                def start_child(**attributes)
         | 
| 146 | 
            -
                  attributes = attributes.dup.merge(trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
         | 
| 146 | 
            +
                  attributes = attributes.dup.merge(transaction: @transaction, trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
         | 
| 147 147 | 
             
                  new_span = Span.new(**attributes)
         | 
| 148 | 
            -
                  new_span.transaction = transaction
         | 
| 149 148 | 
             
                  new_span.span_recorder = span_recorder
         | 
| 150 149 |  | 
| 151 150 | 
             
                  if span_recorder
         | 
    
        data/lib/sentry/transaction.rb
    CHANGED
    
    | @@ -50,6 +50,10 @@ module Sentry | |
| 50 50 | 
             
                # @return [Float, nil]
         | 
| 51 51 | 
             
                attr_reader :effective_sample_rate
         | 
| 52 52 |  | 
| 53 | 
            +
                # Additional contexts stored directly on the transaction object.
         | 
| 54 | 
            +
                # @return [Hash]
         | 
| 55 | 
            +
                attr_reader :contexts
         | 
| 56 | 
            +
             | 
| 53 57 | 
             
                def initialize(
         | 
| 54 58 | 
             
                  hub:,
         | 
| 55 59 | 
             
                  name: nil,
         | 
| @@ -58,12 +62,10 @@ module Sentry | |
| 58 62 | 
             
                  baggage: nil,
         | 
| 59 63 | 
             
                  **options
         | 
| 60 64 | 
             
                )
         | 
| 61 | 
            -
                  super(**options)
         | 
| 65 | 
            +
                  super(transaction: self, **options)
         | 
| 62 66 |  | 
| 63 | 
            -
                   | 
| 64 | 
            -
                  @source = SOURCES.include?(source) ? source.to_sym : :custom
         | 
| 67 | 
            +
                  set_name(name, source: source)
         | 
| 65 68 | 
             
                  @parent_sampled = parent_sampled
         | 
| 66 | 
            -
                  @transaction = self
         | 
| 67 69 | 
             
                  @hub = hub
         | 
| 68 70 | 
             
                  @baggage = baggage
         | 
| 69 71 | 
             
                  @configuration = hub.configuration # to be removed
         | 
| @@ -75,6 +77,7 @@ module Sentry | |
| 75 77 | 
             
                  @environment = hub.configuration.environment
         | 
| 76 78 | 
             
                  @dsn = hub.configuration.dsn
         | 
| 77 79 | 
             
                  @effective_sample_rate = nil
         | 
| 80 | 
            +
                  @contexts = {}
         | 
| 78 81 | 
             
                  init_span_recorder
         | 
| 79 82 | 
             
                end
         | 
| 80 83 |  | 
| @@ -92,16 +95,10 @@ module Sentry | |
| 92 95 | 
             
                  return unless hub.configuration.tracing_enabled?
         | 
| 93 96 | 
             
                  return unless sentry_trace
         | 
| 94 97 |  | 
| 95 | 
            -
                   | 
| 96 | 
            -
                  return  | 
| 97 | 
            -
                  trace_id, parent_span_id, sampled_flag = match[1..3]
         | 
| 98 | 
            +
                  sentry_trace_data = extract_sentry_trace(sentry_trace)
         | 
| 99 | 
            +
                  return unless sentry_trace_data
         | 
| 98 100 |  | 
| 99 | 
            -
                  parent_sampled =
         | 
| 100 | 
            -
                    if sampled_flag.nil?
         | 
| 101 | 
            -
                      nil
         | 
| 102 | 
            -
                    else
         | 
| 103 | 
            -
                      sampled_flag != "0"
         | 
| 104 | 
            -
                    end
         | 
| 101 | 
            +
                  trace_id, parent_span_id, parent_sampled = sentry_trace_data
         | 
| 105 102 |  | 
| 106 103 | 
             
                  baggage = if baggage && !baggage.empty?
         | 
| 107 104 | 
             
                              Baggage.from_incoming_header(baggage)
         | 
| @@ -124,6 +121,20 @@ module Sentry | |
| 124 121 | 
             
                  )
         | 
| 125 122 | 
             
                end
         | 
| 126 123 |  | 
| 124 | 
            +
                # Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
         | 
| 125 | 
            +
                #
         | 
| 126 | 
            +
                # @param sentry_trace [String] the sentry-trace header value from the previous transaction.
         | 
| 127 | 
            +
                # @return [Array, nil]
         | 
| 128 | 
            +
                def self.extract_sentry_trace(sentry_trace)
         | 
| 129 | 
            +
                  match = SENTRY_TRACE_REGEXP.match(sentry_trace)
         | 
| 130 | 
            +
                  return nil if match.nil?
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                  trace_id, parent_span_id, sampled_flag = match[1..3]
         | 
| 133 | 
            +
                  parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0"
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                  [trace_id, parent_span_id, parent_sampled]
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 127 138 | 
             
                # @return [Hash]
         | 
| 128 139 | 
             
                def to_hash
         | 
| 129 140 | 
             
                  hash = super
         | 
| @@ -211,7 +222,7 @@ module Sentry | |
| 211 222 | 
             
                # Finishes the transaction's recording and send it to Sentry.
         | 
| 212 223 | 
             
                # @param hub [Hub] the hub that'll send this transaction. (Deprecated)
         | 
| 213 224 | 
             
                # @return [TransactionEvent]
         | 
| 214 | 
            -
                def finish(hub: nil)
         | 
| 225 | 
            +
                def finish(hub: nil, end_timestamp: nil)
         | 
| 215 226 | 
             
                  if hub
         | 
| 216 227 | 
             
                    log_warn(
         | 
| 217 228 | 
             
                      <<~MSG
         | 
| @@ -223,7 +234,7 @@ module Sentry | |
| 223 234 |  | 
| 224 235 | 
             
                  hub ||= @hub
         | 
| 225 236 |  | 
| 226 | 
            -
                  super() | 
| 237 | 
            +
                  super(end_timestamp: end_timestamp)
         | 
| 227 238 |  | 
| 228 239 | 
             
                  if @name.nil?
         | 
| 229 240 | 
             
                    @name = UNLABELD_NAME
         | 
| @@ -245,6 +256,24 @@ module Sentry | |
| 245 256 | 
             
                  @baggage
         | 
| 246 257 | 
             
                end
         | 
| 247 258 |  | 
| 259 | 
            +
                # Set the transaction name directly.
         | 
| 260 | 
            +
                # Considered internal api since it bypasses the usual scope logic.
         | 
| 261 | 
            +
                # @param name [String]
         | 
| 262 | 
            +
                # @param source [Symbol]
         | 
| 263 | 
            +
                # @return [void]
         | 
| 264 | 
            +
                def set_name(name, source: :custom)
         | 
| 265 | 
            +
                  @name = name
         | 
| 266 | 
            +
                  @source = SOURCES.include?(source) ? source.to_sym : :custom
         | 
| 267 | 
            +
                end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                # Set contexts directly on the transaction.
         | 
| 270 | 
            +
                # @param key [String, Symbol]
         | 
| 271 | 
            +
                # @param value [Object]
         | 
| 272 | 
            +
                # @return [void]
         | 
| 273 | 
            +
                def set_context(key, value)
         | 
| 274 | 
            +
                  @contexts[key] = value
         | 
| 275 | 
            +
                end
         | 
| 276 | 
            +
             | 
| 248 277 | 
             
                protected
         | 
| 249 278 |  | 
| 250 279 | 
             
                def init_span_recorder(limit = 1000)
         | 
| @@ -19,6 +19,7 @@ module Sentry | |
| 19 19 |  | 
| 20 20 | 
             
                  self.transaction = transaction.name
         | 
| 21 21 | 
             
                  self.transaction_info = { source: transaction.source }
         | 
| 22 | 
            +
                  self.contexts.merge!(transaction.contexts)
         | 
| 22 23 | 
             
                  self.contexts.merge!(trace: transaction.get_trace_context)
         | 
| 23 24 | 
             
                  self.timestamp = transaction.timestamp
         | 
| 24 25 | 
             
                  self.start_timestamp = transaction.start_timestamp
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Sentry
         | 
| 4 | 
            +
              module Utils
         | 
| 5 | 
            +
                module EncodingHelper
         | 
| 6 | 
            +
                  def self.encode_to_utf_8(value)
         | 
| 7 | 
            +
                    if value.encoding != Encoding::UTF_8 && value.respond_to?(:force_encoding)
         | 
| 8 | 
            +
                      value = value.dup.force_encoding(Encoding::UTF_8)
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    value = value.scrub unless value.valid_encoding?
         | 
| 12 | 
            +
                    value
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def self.valid_utf_8?(value)
         | 
| 16 | 
            +
                    return true unless value.respond_to?(:force_encoding)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    value.dup.force_encoding(Encoding::UTF_8).valid_encoding?
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
    
        data/lib/sentry/version.rb
    CHANGED
    
    
    
        data/lib/sentry-ruby.rb
    CHANGED
    
    | @@ -8,6 +8,7 @@ require "sentry/version" | |
| 8 8 | 
             
            require "sentry/exceptions"
         | 
| 9 9 | 
             
            require "sentry/core_ext/object/deep_dup"
         | 
| 10 10 | 
             
            require "sentry/utils/argument_checking_helper"
         | 
| 11 | 
            +
            require "sentry/utils/encoding_helper"
         | 
| 11 12 | 
             
            require "sentry/utils/logging_helper"
         | 
| 12 13 | 
             
            require "sentry/configuration"
         | 
| 13 14 | 
             
            require "sentry/logger"
         | 
| @@ -441,22 +442,8 @@ module Sentry | |
| 441 442 | 
             
                #   end
         | 
| 442 443 | 
             
                #
         | 
| 443 444 | 
             
                def with_child_span(**attributes, &block)
         | 
| 444 | 
            -
                   | 
| 445 | 
            -
             | 
| 446 | 
            -
             | 
| 447 | 
            -
                    begin
         | 
| 448 | 
            -
                      current_span.with_child_span(**attributes) do |child_span|
         | 
| 449 | 
            -
                        get_current_scope.set_span(child_span)
         | 
| 450 | 
            -
                        result = yield(child_span)
         | 
| 451 | 
            -
                      end
         | 
| 452 | 
            -
                    ensure
         | 
| 453 | 
            -
                      get_current_scope.set_span(current_span)
         | 
| 454 | 
            -
                    end
         | 
| 455 | 
            -
             | 
| 456 | 
            -
                    result
         | 
| 457 | 
            -
                  else
         | 
| 458 | 
            -
                    yield(nil)
         | 
| 459 | 
            -
                  end
         | 
| 445 | 
            +
                  return yield(nil) unless Sentry.initialized?
         | 
| 446 | 
            +
                  get_current_hub.with_child_span(**attributes, &block)
         | 
| 460 447 | 
             
                end
         | 
| 461 448 |  | 
| 462 449 | 
             
                # Returns the id of the lastly reported Sentry::Event.
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: sentry-ruby-core
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 5. | 
| 4 | 
            +
              version: 5.7.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sentry Team
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022- | 
| 11 | 
            +
            date: 2022-12-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: sentry-ruby
         | 
| @@ -16,14 +16,14 @@ dependencies: | |
| 16 16 | 
             
                requirements:
         | 
| 17 17 | 
             
                - - '='
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: 5. | 
| 19 | 
            +
                    version: 5.7.0
         | 
| 20 20 | 
             
              type: :runtime
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 24 | 
             
                - - '='
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: 5. | 
| 26 | 
            +
                    version: 5.7.0
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 28 | 
             
              name: concurrent-ruby
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -104,6 +104,7 @@ files: | |
| 104 104 | 
             
            - lib/sentry/transport/http_transport.rb
         | 
| 105 105 | 
             
            - lib/sentry/utils/argument_checking_helper.rb
         | 
| 106 106 | 
             
            - lib/sentry/utils/custom_inspection.rb
         | 
| 107 | 
            +
            - lib/sentry/utils/encoding_helper.rb
         | 
| 107 108 | 
             
            - lib/sentry/utils/exception_cause_chain.rb
         | 
| 108 109 | 
             
            - lib/sentry/utils/logging_helper.rb
         | 
| 109 110 | 
             
            - lib/sentry/utils/real_ip.rb
         |