sentry-ruby 5.4.2 → 5.16.1
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/.rspec +0 -1
- data/Gemfile +13 -14
- data/README.md +11 -8
- data/Rakefile +8 -1
- data/lib/sentry/background_worker.rb +8 -1
- data/lib/sentry/backpressure_monitor.rb +75 -0
- data/lib/sentry/backtrace.rb +1 -1
- data/lib/sentry/baggage.rb +70 -0
- data/lib/sentry/breadcrumb.rb +8 -2
- data/lib/sentry/check_in_event.rb +60 -0
- data/lib/sentry/client.rb +77 -19
- data/lib/sentry/configuration.rb +177 -29
- data/lib/sentry/cron/configuration.rb +23 -0
- data/lib/sentry/cron/monitor_check_ins.rb +75 -0
- data/lib/sentry/cron/monitor_config.rb +53 -0
- data/lib/sentry/cron/monitor_schedule.rb +42 -0
- data/lib/sentry/envelope.rb +2 -5
- data/lib/sentry/event.rb +7 -29
- data/lib/sentry/hub.rb +100 -4
- data/lib/sentry/integrable.rb +6 -0
- data/lib/sentry/interfaces/request.rb +6 -16
- data/lib/sentry/interfaces/single_exception.rb +13 -3
- data/lib/sentry/net/http.rb +37 -46
- data/lib/sentry/profiler.rb +233 -0
- data/lib/sentry/propagation_context.rb +134 -0
- data/lib/sentry/puma.rb +32 -0
- data/lib/sentry/rack/capture_exceptions.rb +4 -5
- data/lib/sentry/rake.rb +1 -14
- data/lib/sentry/redis.rb +41 -23
- data/lib/sentry/release_detector.rb +1 -1
- data/lib/sentry/scope.rb +81 -16
- data/lib/sentry/session.rb +5 -7
- data/lib/sentry/span.rb +57 -10
- data/lib/sentry/test_helper.rb +19 -11
- data/lib/sentry/transaction.rb +183 -30
- data/lib/sentry/transaction_event.rb +51 -0
- data/lib/sentry/transport/configuration.rb +74 -1
- data/lib/sentry/transport/http_transport.rb +68 -37
- data/lib/sentry/transport/spotlight_transport.rb +50 -0
- data/lib/sentry/transport.rb +39 -24
- data/lib/sentry/utils/argument_checking_helper.rb +9 -3
- data/lib/sentry/utils/encoding_helper.rb +22 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +116 -41
- metadata +14 -3
- data/CODE_OF_CONDUCT.md +0 -74
    
        data/lib/sentry/configuration.rb
    CHANGED
    
    | @@ -7,6 +7,7 @@ require 'sentry/utils/custom_inspection' | |
| 7 7 | 
             
            require "sentry/dsn"
         | 
| 8 8 | 
             
            require "sentry/release_detector"
         | 
| 9 9 | 
             
            require "sentry/transport/configuration"
         | 
| 10 | 
            +
            require "sentry/cron/configuration"
         | 
| 10 11 | 
             
            require "sentry/linecache"
         | 
| 11 12 | 
             
            require "sentry/interfaces/stacktrace_builder"
         | 
| 12 13 |  | 
| @@ -14,6 +15,8 @@ module Sentry | |
| 14 15 | 
             
              class Configuration
         | 
| 15 16 | 
             
                include CustomInspection
         | 
| 16 17 | 
             
                include LoggingHelper
         | 
| 18 | 
            +
                include ArgumentCheckingHelper
         | 
| 19 | 
            +
             | 
| 17 20 | 
             
                # Directories to be recognized as part of your app. e.g. if you
         | 
| 18 21 | 
             
                # have an `engines` dir at the root of your project, you may want
         | 
| 19 22 | 
             
                # to set this to something like /(app|config|engines|lib)/
         | 
| @@ -38,6 +41,13 @@ module Sentry | |
| 38 41 | 
             
                # @return [Integer]
         | 
| 39 42 | 
             
                attr_accessor :background_worker_threads
         | 
| 40 43 |  | 
| 44 | 
            +
                # The maximum queue size for the background worker.
         | 
| 45 | 
            +
                # Jobs will be rejected above this limit.
         | 
| 46 | 
            +
                #
         | 
| 47 | 
            +
                # Default is {BackgroundWorker::DEFAULT_MAX_QUEUE}.
         | 
| 48 | 
            +
                # @return [Integer]
         | 
| 49 | 
            +
                attr_accessor :background_worker_max_queue
         | 
| 50 | 
            +
             | 
| 41 51 | 
             
                # a proc/lambda that takes an array of stack traces
         | 
| 42 52 | 
             
                # it'll be used to silence (reduce) backtrace of the exception
         | 
| 43 53 | 
             
                #
         | 
| @@ -72,6 +82,19 @@ module Sentry | |
| 72 82 | 
             
                # @return [Proc]
         | 
| 73 83 | 
             
                attr_reader :before_send
         | 
| 74 84 |  | 
| 85 | 
            +
                # Optional Proc, called before sending an event to the server
         | 
| 86 | 
            +
                # @example
         | 
| 87 | 
            +
                #   config.before_send_transaction = lambda do |event, hint|
         | 
| 88 | 
            +
                #     # skip unimportant transactions or strip sensitive data
         | 
| 89 | 
            +
                #     if event.transaction == "/healthcheck/route"
         | 
| 90 | 
            +
                #       nil
         | 
| 91 | 
            +
                #     else
         | 
| 92 | 
            +
                #       event
         | 
| 93 | 
            +
                #     end
         | 
| 94 | 
            +
                #   end
         | 
| 95 | 
            +
                # @return [Proc]
         | 
| 96 | 
            +
                attr_reader :before_send_transaction
         | 
| 97 | 
            +
             | 
| 75 98 | 
             
                # An array of breadcrumbs loggers to be used. Available options are:
         | 
| 76 99 | 
             
                # - :sentry_logger
         | 
| 77 100 | 
             
                # - :http_logger
         | 
| @@ -84,10 +107,6 @@ module Sentry | |
| 84 107 | 
             
                # @return [Array<Symbol>]
         | 
| 85 108 | 
             
                attr_reader :breadcrumbs_logger
         | 
| 86 109 |  | 
| 87 | 
            -
                # Whether to capture local variables from the raised exception's frame. Default is false.
         | 
| 88 | 
            -
                # @return [Boolean]
         | 
| 89 | 
            -
                attr_accessor :capture_exception_frame_locals
         | 
| 90 | 
            -
             | 
| 91 110 | 
             
                # Max number of breadcrumbs a breadcrumb buffer can hold
         | 
| 92 111 | 
             
                # @return [Integer]
         | 
| 93 112 | 
             
                attr_accessor :max_breadcrumbs
         | 
| @@ -127,6 +146,30 @@ module Sentry | |
| 127 146 | 
             
                attr_accessor :inspect_exception_causes_for_exclusion
         | 
| 128 147 | 
             
                alias inspect_exception_causes_for_exclusion? inspect_exception_causes_for_exclusion
         | 
| 129 148 |  | 
| 149 | 
            +
                # Whether to capture local variables from the raised exception's frame. Default is false.
         | 
| 150 | 
            +
                # @return [Boolean]
         | 
| 151 | 
            +
                attr_accessor :include_local_variables
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                # Whether to capture events and traces into Spotlight. Default is false.
         | 
| 154 | 
            +
                # If you set this to true, Sentry will send events and traces to the local
         | 
| 155 | 
            +
                # Sidecar proxy at http://localhost:8969/stream.
         | 
| 156 | 
            +
                # If you want to use a different Sidecar proxy address, set this to String
         | 
| 157 | 
            +
                # with the proxy URL.
         | 
| 158 | 
            +
                # @return [Boolean, String]
         | 
| 159 | 
            +
                attr_accessor :spotlight
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                # @deprecated Use {#include_local_variables} instead.
         | 
| 162 | 
            +
                alias_method :capture_exception_frame_locals, :include_local_variables
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                # @deprecated Use {#include_local_variables=} instead.
         | 
| 165 | 
            +
                def capture_exception_frame_locals=(value)
         | 
| 166 | 
            +
                  log_warn <<~MSG
         | 
| 167 | 
            +
                    `capture_exception_frame_locals` is now deprecated in favor of `include_local_variables`.
         | 
| 168 | 
            +
                  MSG
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                  self.include_local_variables = value
         | 
| 171 | 
            +
                end
         | 
| 172 | 
            +
             | 
| 130 173 | 
             
                # You may provide your own LineCache for matching paths with source files.
         | 
| 131 174 | 
             
                # This may be useful if you need to get source code from places other than the disk.
         | 
| 132 175 | 
             
                # @see LineCache
         | 
| @@ -154,7 +197,7 @@ module Sentry | |
| 154 197 | 
             
                # Release tag to be passed with every event sent to Sentry.
         | 
| 155 198 | 
             
                # We automatically try to set this to a git SHA or Capistrano release.
         | 
| 156 199 | 
             
                # @return [String]
         | 
| 157 | 
            -
                 | 
| 200 | 
            +
                attr_reader :release
         | 
| 158 201 |  | 
| 159 202 | 
             
                # The sampling factor to apply to events. A value of 0.0 will not send
         | 
| 160 203 | 
             
                # any events, and a value of 1.0 will send 100% of events.
         | 
| @@ -184,13 +227,17 @@ module Sentry | |
| 184 227 | 
             
                # @return [String]
         | 
| 185 228 | 
             
                attr_accessor :server_name
         | 
| 186 229 |  | 
| 187 | 
            -
                #  | 
| 188 | 
            -
                # @return [Transport]
         | 
| 230 | 
            +
                # Transport related configuration.
         | 
| 231 | 
            +
                # @return [Transport::Configuration]
         | 
| 189 232 | 
             
                attr_reader :transport
         | 
| 190 233 |  | 
| 234 | 
            +
                # Cron related configuration.
         | 
| 235 | 
            +
                # @return [Cron::Configuration]
         | 
| 236 | 
            +
                attr_reader :cron
         | 
| 237 | 
            +
             | 
| 191 238 | 
             
                # Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
         | 
| 192 | 
            -
                # @return [Float]
         | 
| 193 | 
            -
                 | 
| 239 | 
            +
                # @return [Float, nil]
         | 
| 240 | 
            +
                attr_reader :traces_sample_rate
         | 
| 194 241 |  | 
| 195 242 | 
             
                # Take a Proc that controls the sample rate for every tracing event, e.g.
         | 
| 196 243 | 
             
                # @example
         | 
| @@ -202,6 +249,11 @@ module Sentry | |
| 202 249 | 
             
                # @return [Proc]
         | 
| 203 250 | 
             
                attr_accessor :traces_sampler
         | 
| 204 251 |  | 
| 252 | 
            +
                # Easier way to use performance tracing
         | 
| 253 | 
            +
                # If set to true, will set traces_sample_rate to 1.0
         | 
| 254 | 
            +
                # @return [Boolean, nil]
         | 
| 255 | 
            +
                attr_reader :enable_tracing
         | 
| 256 | 
            +
             | 
| 205 257 | 
             
                # Send diagnostic client reports about dropped events, true by default
         | 
| 206 258 | 
             
                # tries to attach to an existing envelope max once every 30s
         | 
| 207 259 | 
             
                # @return [Boolean]
         | 
| @@ -211,10 +263,45 @@ module Sentry | |
| 211 263 | 
             
                # @return [Boolean]
         | 
| 212 264 | 
             
                attr_accessor :auto_session_tracking
         | 
| 213 265 |  | 
| 266 | 
            +
                # Whether to downsample transactions automatically because of backpressure.
         | 
| 267 | 
            +
                # Starts a new monitor thread to check health of the SDK every 10 seconds.
         | 
| 268 | 
            +
                # Default is false
         | 
| 269 | 
            +
                # @return [Boolean]
         | 
| 270 | 
            +
                attr_accessor :enable_backpressure_handling
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                # Allowlist of outgoing request targets to which sentry-trace and baggage headers are attached.
         | 
| 273 | 
            +
                # Default is all (/.*/)
         | 
| 274 | 
            +
                # @return [Array<String, Regexp>]
         | 
| 275 | 
            +
                attr_accessor :trace_propagation_targets
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                # The instrumenter to use, :sentry or :otel
         | 
| 278 | 
            +
                # @return [Symbol]
         | 
| 279 | 
            +
                attr_reader :instrumenter
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                # Take a float between 0.0 and 1.0 as the sample rate for capturing profiles.
         | 
| 282 | 
            +
                # Note that this rate is relative to traces_sample_rate / traces_sampler,
         | 
| 283 | 
            +
                # i.e. the profile is sampled by this rate after the transaction is sampled.
         | 
| 284 | 
            +
                # @return [Float, nil]
         | 
| 285 | 
            +
                attr_reader :profiles_sample_rate
         | 
| 286 | 
            +
             | 
| 287 | 
            +
                # Array of patches to apply.
         | 
| 288 | 
            +
                # Default is {DEFAULT_PATCHES}
         | 
| 289 | 
            +
                # @return [Array<Symbol>]
         | 
| 290 | 
            +
                attr_accessor :enabled_patches
         | 
| 291 | 
            +
             | 
| 214 292 | 
             
                # these are not config options
         | 
| 215 293 | 
             
                # @!visibility private
         | 
| 216 294 | 
             
                attr_reader :errors, :gem_specs
         | 
| 217 295 |  | 
| 296 | 
            +
                # These exceptions could enter Puma's `lowlevel_error_handler` callback and the SDK's Puma integration
         | 
| 297 | 
            +
                # But they are mostly considered as noise and should be ignored by default
         | 
| 298 | 
            +
                # Please see https://github.com/getsentry/sentry-ruby/pull/2026 for more information
         | 
| 299 | 
            +
                PUMA_IGNORE_DEFAULT = [
         | 
| 300 | 
            +
                  'Puma::MiniSSL::SSLError',
         | 
| 301 | 
            +
                  'Puma::HttpParserError',
         | 
| 302 | 
            +
                  'Puma::HttpParserError501'
         | 
| 303 | 
            +
                ].freeze
         | 
| 304 | 
            +
             | 
| 218 305 | 
             
                # Most of these errors generate 4XX responses. In general, Sentry clients
         | 
| 219 306 | 
             
                # only automatically report 5xx responses.
         | 
| 220 307 | 
             
                IGNORE_DEFAULT = [
         | 
| @@ -237,23 +324,39 @@ module Sentry | |
| 237 324 | 
             
                MODULE_SEPARATOR = "::".freeze
         | 
| 238 325 | 
             
                SKIP_INSPECTION_ATTRIBUTES = [:@linecache, :@stacktrace_builder]
         | 
| 239 326 |  | 
| 240 | 
            -
                 | 
| 241 | 
            -
             | 
| 242 | 
            -
                 | 
| 327 | 
            +
                INSTRUMENTERS = [:sentry, :otel]
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                PROPAGATION_TARGETS_MATCH_ALL = /.*/.freeze
         | 
| 330 | 
            +
             | 
| 331 | 
            +
                DEFAULT_PATCHES = %i(redis puma http).freeze
         | 
| 332 | 
            +
             | 
| 333 | 
            +
                class << self
         | 
| 334 | 
            +
                  # Post initialization callbacks are called at the end of initialization process
         | 
| 335 | 
            +
                  # allowing extending the configuration of sentry-ruby by multiple extensions
         | 
| 336 | 
            +
                  def post_initialization_callbacks
         | 
| 337 | 
            +
                    @post_initialization_callbacks ||= []
         | 
| 338 | 
            +
                  end
         | 
| 339 | 
            +
             | 
| 340 | 
            +
                # allow extensions to add their hooks to the Configuration class
         | 
| 341 | 
            +
                  def add_post_initialization_callback(&block)
         | 
| 342 | 
            +
                    post_initialization_callbacks << block
         | 
| 343 | 
            +
                  end
         | 
| 344 | 
            +
                end
         | 
| 243 345 |  | 
| 244 346 | 
             
                def initialize
         | 
| 245 347 | 
             
                  self.app_dirs_pattern = nil
         | 
| 246 348 | 
             
                  self.debug = false
         | 
| 247 349 | 
             
                  self.background_worker_threads = Concurrent.processor_count
         | 
| 350 | 
            +
                  self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE
         | 
| 248 351 | 
             
                  self.backtrace_cleanup_callback = nil
         | 
| 249 352 | 
             
                  self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
         | 
| 250 353 | 
             
                  self.breadcrumbs_logger = []
         | 
| 251 354 | 
             
                  self.context_lines = 3
         | 
| 252 | 
            -
                  self. | 
| 355 | 
            +
                  self.include_local_variables = false
         | 
| 253 356 | 
             
                  self.environment = environment_from_env
         | 
| 254 357 | 
             
                  self.enabled_environments = []
         | 
| 255 358 | 
             
                  self.exclude_loggers = []
         | 
| 256 | 
            -
                  self.excluded_exceptions = IGNORE_DEFAULT | 
| 359 | 
            +
                  self.excluded_exceptions = IGNORE_DEFAULT + PUMA_IGNORE_DEFAULT
         | 
| 257 360 | 
             
                  self.inspect_exception_causes_for_exclusion = true
         | 
| 258 361 | 
             
                  self.linecache = ::Sentry::LineCache.new
         | 
| 259 362 | 
             
                  self.logger = ::Sentry::Logger.new(STDOUT)
         | 
| @@ -266,16 +369,23 @@ module Sentry | |
| 266 369 | 
             
                  self.skip_rake_integration = false
         | 
| 267 370 | 
             
                  self.send_client_reports = true
         | 
| 268 371 | 
             
                  self.auto_session_tracking = true
         | 
| 372 | 
            +
                  self.enable_backpressure_handling = false
         | 
| 269 373 | 
             
                  self.trusted_proxies = []
         | 
| 270 374 | 
             
                  self.dsn = ENV['SENTRY_DSN']
         | 
| 375 | 
            +
                  self.spotlight = false
         | 
| 271 376 | 
             
                  self.server_name = server_name_from_env
         | 
| 377 | 
            +
                  self.instrumenter = :sentry
         | 
| 378 | 
            +
                  self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL]
         | 
| 379 | 
            +
                  self.enabled_patches = DEFAULT_PATCHES.dup
         | 
| 272 380 |  | 
| 273 381 | 
             
                  self.before_send = nil
         | 
| 382 | 
            +
                  self.before_send_transaction = nil
         | 
| 274 383 | 
             
                  self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
         | 
| 275 | 
            -
                  self.traces_sample_rate = nil
         | 
| 276 384 | 
             
                  self.traces_sampler = nil
         | 
| 385 | 
            +
                  self.enable_tracing = nil
         | 
| 277 386 |  | 
| 278 387 | 
             
                  @transport = Transport::Configuration.new
         | 
| 388 | 
            +
                  @cron = Cron::Configuration.new
         | 
| 279 389 | 
             
                  @gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
         | 
| 280 390 |  | 
| 281 391 | 
             
                  run_post_initialization_callbacks
         | 
| @@ -287,6 +397,12 @@ module Sentry | |
| 287 397 |  | 
| 288 398 | 
             
                alias server= dsn=
         | 
| 289 399 |  | 
| 400 | 
            +
                def release=(value)
         | 
| 401 | 
            +
                  check_argument_type!(value, String, NilClass)
         | 
| 402 | 
            +
             | 
| 403 | 
            +
                  @release = value
         | 
| 404 | 
            +
                end
         | 
| 405 | 
            +
             | 
| 290 406 | 
             
                def async=(value)
         | 
| 291 407 | 
             
                  check_callable!("async", value)
         | 
| 292 408 |  | 
| @@ -322,6 +438,12 @@ module Sentry | |
| 322 438 | 
             
                  @before_send = value
         | 
| 323 439 | 
             
                end
         | 
| 324 440 |  | 
| 441 | 
            +
                def before_send_transaction=(value)
         | 
| 442 | 
            +
                  check_callable!("before_send_transaction", value)
         | 
| 443 | 
            +
             | 
| 444 | 
            +
                  @before_send_transaction = value
         | 
| 445 | 
            +
                end
         | 
| 446 | 
            +
             | 
| 325 447 | 
             
                def before_breadcrumb=(value)
         | 
| 326 448 | 
             
                  check_callable!("before_breadcrumb", value)
         | 
| 327 449 |  | 
| @@ -332,10 +454,34 @@ module Sentry | |
| 332 454 | 
             
                  @environment = environment.to_s
         | 
| 333 455 | 
             
                end
         | 
| 334 456 |  | 
| 457 | 
            +
                def instrumenter=(instrumenter)
         | 
| 458 | 
            +
                  @instrumenter = INSTRUMENTERS.include?(instrumenter) ? instrumenter : :sentry
         | 
| 459 | 
            +
                end
         | 
| 460 | 
            +
             | 
| 461 | 
            +
                def enable_tracing=(enable_tracing)
         | 
| 462 | 
            +
                  @enable_tracing = enable_tracing
         | 
| 463 | 
            +
                  @traces_sample_rate ||= 1.0 if enable_tracing
         | 
| 464 | 
            +
                end
         | 
| 465 | 
            +
             | 
| 466 | 
            +
                def is_numeric_or_nil?(value)
         | 
| 467 | 
            +
                  value.is_a?(Numeric) || value.nil?
         | 
| 468 | 
            +
                end
         | 
| 469 | 
            +
             | 
| 470 | 
            +
                def traces_sample_rate=(traces_sample_rate)
         | 
| 471 | 
            +
                  raise ArgumentError, "traces_sample_rate must be a Numeric or nil" unless is_numeric_or_nil?(traces_sample_rate)
         | 
| 472 | 
            +
                  @traces_sample_rate = traces_sample_rate
         | 
| 473 | 
            +
                end
         | 
| 474 | 
            +
             | 
| 475 | 
            +
                def profiles_sample_rate=(profiles_sample_rate)
         | 
| 476 | 
            +
                  raise ArgumentError, "profiles_sample_rate must be a Numeric or nil" unless is_numeric_or_nil?(profiles_sample_rate)
         | 
| 477 | 
            +
                  log_warn("Please make sure to include the 'stackprof' gem in your Gemfile to use Profiling with Sentry.") unless defined?(StackProf)
         | 
| 478 | 
            +
                  @profiles_sample_rate = profiles_sample_rate
         | 
| 479 | 
            +
                end
         | 
| 480 | 
            +
             | 
| 335 481 | 
             
                def sending_allowed?
         | 
| 336 482 | 
             
                  @errors = []
         | 
| 337 483 |  | 
| 338 | 
            -
                  valid? && capture_in_environment?
         | 
| 484 | 
            +
                  spotlight || (valid? && capture_in_environment?)
         | 
| 339 485 | 
             
                end
         | 
| 340 486 |  | 
| 341 487 | 
             
                def sample_allowed?
         | 
| @@ -361,8 +507,21 @@ module Sentry | |
| 361 507 | 
             
                  enabled_environments.empty? || enabled_environments.include?(environment)
         | 
| 362 508 | 
             
                end
         | 
| 363 509 |  | 
| 510 | 
            +
                def valid_sample_rate?(sample_rate)
         | 
| 511 | 
            +
                  return false unless sample_rate.is_a?(Numeric)
         | 
| 512 | 
            +
                  sample_rate >= 0.0 && sample_rate <= 1.0
         | 
| 513 | 
            +
                end
         | 
| 514 | 
            +
             | 
| 364 515 | 
             
                def tracing_enabled?
         | 
| 365 | 
            -
                  !!((@traces_sample_rate | 
| 516 | 
            +
                  valid_sampler = !!((valid_sample_rate?(@traces_sample_rate)) || @traces_sampler)
         | 
| 517 | 
            +
             | 
| 518 | 
            +
                  (@enable_tracing != false) && valid_sampler && sending_allowed?
         | 
| 519 | 
            +
                end
         | 
| 520 | 
            +
             | 
| 521 | 
            +
                def profiling_enabled?
         | 
| 522 | 
            +
                  valid_sampler = !!(valid_sample_rate?(@profiles_sample_rate))
         | 
| 523 | 
            +
             | 
| 524 | 
            +
                  tracing_enabled? && valid_sampler && sending_allowed?
         | 
| 366 525 | 
             
                end
         | 
| 367 526 |  | 
| 368 527 | 
             
                # @return [String, nil]
         | 
| @@ -390,7 +549,7 @@ module Sentry | |
| 390 549 | 
             
                def detect_release
         | 
| 391 550 | 
             
                  return unless sending_allowed?
         | 
| 392 551 |  | 
| 393 | 
            -
                   | 
| 552 | 
            +
                  @release ||= ReleaseDetector.detect_release(project_root: project_root, running_on_heroku: running_on_heroku?)
         | 
| 394 553 |  | 
| 395 554 | 
             
                  if running_on_heroku? && release.nil?
         | 
| 396 555 | 
             
                    log_warn(HEROKU_DYNO_METADATA_MESSAGE)
         | 
| @@ -487,16 +646,5 @@ module Sentry | |
| 487 646 | 
             
                    instance_eval(&hook)
         | 
| 488 647 | 
             
                  end
         | 
| 489 648 | 
             
                end
         | 
| 490 | 
            -
             | 
| 491 | 
            -
                # allow extensions to add their hooks to the Configuration class
         | 
| 492 | 
            -
                def self.add_post_initialization_callback(&block)
         | 
| 493 | 
            -
                  self.post_initialization_callbacks << block
         | 
| 494 | 
            -
                end
         | 
| 495 | 
            -
             | 
| 496 | 
            -
                protected
         | 
| 497 | 
            -
             | 
| 498 | 
            -
                def self.post_initialization_callbacks
         | 
| 499 | 
            -
                  @@post_initialization_callbacks
         | 
| 500 | 
            -
                end
         | 
| 501 649 | 
             
              end
         | 
| 502 650 | 
             
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Sentry
         | 
| 4 | 
            +
              module Cron
         | 
| 5 | 
            +
                class Configuration
         | 
| 6 | 
            +
                  # Defaults set here will apply to all {Cron::MonitorConfig} objects unless overwritten.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  # How long (in minutes) after the expected checkin time will we wait
         | 
| 9 | 
            +
                  # until we consider the checkin to have been missed.
         | 
| 10 | 
            +
                  # @return [Integer, nil]
         | 
| 11 | 
            +
                  attr_accessor :default_checkin_margin
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  # How long (in minutes) is the checkin allowed to run for in in_progress
         | 
| 14 | 
            +
                  # before it is considered failed.
         | 
| 15 | 
            +
                  # @return [Integer, nil]
         | 
| 16 | 
            +
                  attr_accessor :default_max_runtime
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  # tz database style timezone string
         | 
| 19 | 
            +
                  # @return [String, nil]
         | 
| 20 | 
            +
                  attr_accessor :default_timezone
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,75 @@ | |
| 1 | 
            +
            module Sentry
         | 
| 2 | 
            +
              module Cron
         | 
| 3 | 
            +
                module MonitorCheckIns
         | 
| 4 | 
            +
                  MAX_SLUG_LENGTH = 50
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  module Patch
         | 
| 7 | 
            +
                    def perform(*args, **opts)
         | 
| 8 | 
            +
                      slug = self.class.sentry_monitor_slug
         | 
| 9 | 
            +
                      monitor_config = self.class.sentry_monitor_config
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                      check_in_id = Sentry.capture_check_in(slug,
         | 
| 12 | 
            +
                                                            :in_progress,
         | 
| 13 | 
            +
                                                            monitor_config: monitor_config)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      start = Sentry.utc_now.to_i
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      begin
         | 
| 18 | 
            +
                        # need to do this on ruby <= 2.6 sadly
         | 
| 19 | 
            +
                        ret = method(:perform).super_method.arity == 0 ? super() : super
         | 
| 20 | 
            +
                        duration = Sentry.utc_now.to_i - start
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                        Sentry.capture_check_in(slug,
         | 
| 23 | 
            +
                                                :ok,
         | 
| 24 | 
            +
                                                check_in_id: check_in_id,
         | 
| 25 | 
            +
                                                duration: duration,
         | 
| 26 | 
            +
                                                monitor_config: monitor_config)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                        ret
         | 
| 29 | 
            +
                      rescue Exception
         | 
| 30 | 
            +
                        duration = Sentry.utc_now.to_i - start
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                        Sentry.capture_check_in(slug,
         | 
| 33 | 
            +
                                                :error,
         | 
| 34 | 
            +
                                                check_in_id: check_in_id,
         | 
| 35 | 
            +
                                                duration: duration,
         | 
| 36 | 
            +
                                                monitor_config: monitor_config)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                        raise
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  module ClassMethods
         | 
| 44 | 
            +
                    def sentry_monitor_check_ins(slug: nil, monitor_config: nil)
         | 
| 45 | 
            +
                      if monitor_config && Sentry.configuration
         | 
| 46 | 
            +
                        cron_config = Sentry.configuration.cron
         | 
| 47 | 
            +
                        monitor_config.checkin_margin ||= cron_config.default_checkin_margin
         | 
| 48 | 
            +
                        monitor_config.max_runtime ||= cron_config.default_max_runtime
         | 
| 49 | 
            +
                        monitor_config.timezone ||= cron_config.default_timezone
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                      @sentry_monitor_slug = slug
         | 
| 53 | 
            +
                      @sentry_monitor_config = monitor_config
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                      prepend Patch
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    def sentry_monitor_slug(name: self.name)
         | 
| 59 | 
            +
                      @sentry_monitor_slug ||= begin
         | 
| 60 | 
            +
                        slug = name.gsub('::', '-').downcase
         | 
| 61 | 
            +
                        slug[-MAX_SLUG_LENGTH..-1] || slug
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    def sentry_monitor_config
         | 
| 66 | 
            +
                      @sentry_monitor_config
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  def self.included(base)
         | 
| 71 | 
            +
                    base.extend(ClassMethods)
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
            end
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'sentry/cron/monitor_schedule'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Sentry
         | 
| 6 | 
            +
              module Cron
         | 
| 7 | 
            +
                class MonitorConfig
         | 
| 8 | 
            +
                  # The monitor schedule configuration
         | 
| 9 | 
            +
                  # @return [MonitorSchedule::Crontab, MonitorSchedule::Interval]
         | 
| 10 | 
            +
                  attr_accessor :schedule
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # How long (in minutes) after the expected checkin time will we wait
         | 
| 13 | 
            +
                  # until we consider the checkin to have been missed.
         | 
| 14 | 
            +
                  # @return [Integer, nil]
         | 
| 15 | 
            +
                  attr_accessor :checkin_margin
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  # How long (in minutes) is the checkin allowed to run for in in_progress
         | 
| 18 | 
            +
                  # before it is considered failed.
         | 
| 19 | 
            +
                  # @return [Integer, nil]
         | 
| 20 | 
            +
                  attr_accessor :max_runtime
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # tz database style timezone string
         | 
| 23 | 
            +
                  # @return [String, nil]
         | 
| 24 | 
            +
                  attr_accessor :timezone
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def initialize(schedule, checkin_margin: nil, max_runtime: nil, timezone: nil)
         | 
| 27 | 
            +
                    @schedule = schedule
         | 
| 28 | 
            +
                    @checkin_margin = checkin_margin
         | 
| 29 | 
            +
                    @max_runtime = max_runtime
         | 
| 30 | 
            +
                    @timezone = timezone
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def self.from_crontab(crontab, **options)
         | 
| 34 | 
            +
                    new(MonitorSchedule::Crontab.new(crontab), **options)
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def self.from_interval(num, unit, **options)
         | 
| 38 | 
            +
                    return nil unless MonitorSchedule::Interval::VALID_UNITS.include?(unit)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    new(MonitorSchedule::Interval.new(num, unit), **options)
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def to_hash
         | 
| 44 | 
            +
                    {
         | 
| 45 | 
            +
                      schedule: schedule.to_hash,
         | 
| 46 | 
            +
                      checkin_margin: checkin_margin,
         | 
| 47 | 
            +
                      max_runtime: max_runtime,
         | 
| 48 | 
            +
                      timezone: timezone
         | 
| 49 | 
            +
                    }.compact
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Sentry
         | 
| 4 | 
            +
              module Cron
         | 
| 5 | 
            +
                module MonitorSchedule
         | 
| 6 | 
            +
                  class Crontab
         | 
| 7 | 
            +
                    # A crontab formatted string such as "0 * * * *".
         | 
| 8 | 
            +
                    # @return [String]
         | 
| 9 | 
            +
                    attr_accessor :value
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def initialize(value)
         | 
| 12 | 
            +
                      @value = value
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    def to_hash
         | 
| 16 | 
            +
                      { type: :crontab, value: value }
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  class Interval
         | 
| 21 | 
            +
                    # The number representing duration of the interval.
         | 
| 22 | 
            +
                    # @return [Integer]
         | 
| 23 | 
            +
                    attr_accessor :value
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    # The unit representing duration of the interval.
         | 
| 26 | 
            +
                    # @return [Symbol]
         | 
| 27 | 
            +
                    attr_accessor :unit
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    VALID_UNITS = %i(year month week day hour minute)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def initialize(value, unit)
         | 
| 32 | 
            +
                      @value = value
         | 
| 33 | 
            +
                      @unit = unit
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    def to_hash
         | 
| 37 | 
            +
                      { type: :interval, value: value, unit: unit }
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
    
        data/lib/sentry/envelope.rb
    CHANGED
    
    | @@ -5,7 +5,7 @@ module Sentry | |
| 5 5 | 
             
              class Envelope
         | 
| 6 6 | 
             
                class Item
         | 
| 7 7 | 
             
                  STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD = 500
         | 
| 8 | 
            -
                  MAX_SERIALIZED_PAYLOAD_SIZE = 1024 *  | 
| 8 | 
            +
                  MAX_SERIALIZED_PAYLOAD_SIZE = 1024 * 1000
         | 
| 9 9 |  | 
| 10 10 | 
             
                  attr_accessor :headers, :payload
         | 
| 11 11 |  | 
| @@ -19,10 +19,7 @@ module Sentry | |
| 19 19 | 
             
                  end
         | 
| 20 20 |  | 
| 21 21 | 
             
                  def to_s
         | 
| 22 | 
            -
                     | 
| 23 | 
            -
                      #{JSON.generate(@headers)}
         | 
| 24 | 
            -
                      #{JSON.generate(@payload)}
         | 
| 25 | 
            -
                    ITEM
         | 
| 22 | 
            +
                    [JSON.generate(@headers), JSON.generate(@payload)].join("\n")
         | 
| 26 23 | 
             
                  end
         | 
| 27 24 |  | 
| 28 25 | 
             
                  def serialize
         | 
    
        data/lib/sentry/event.rb
    CHANGED
    
    | @@ -18,7 +18,7 @@ module Sentry | |
| 18 18 | 
             
                  event_id level timestamp
         | 
| 19 19 | 
             
                  release environment server_name modules
         | 
| 20 20 | 
             
                  message user tags contexts extra
         | 
| 21 | 
            -
                  fingerprint breadcrumbs transaction
         | 
| 21 | 
            +
                  fingerprint breadcrumbs transaction transaction_info
         | 
| 22 22 | 
             
                  platform sdk type
         | 
| 23 23 | 
             
                )
         | 
| 24 24 |  | 
| @@ -37,6 +37,11 @@ module Sentry | |
| 37 37 | 
             
                # @return [RequestInterface]
         | 
| 38 38 | 
             
                attr_reader :request
         | 
| 39 39 |  | 
| 40 | 
            +
                # Dynamic Sampling Context (DSC) that gets attached
         | 
| 41 | 
            +
                # as the trace envelope header in the transport.
         | 
| 42 | 
            +
                # @return [Hash, nil]
         | 
| 43 | 
            +
                attr_accessor :dynamic_sampling_context
         | 
| 44 | 
            +
             | 
| 40 45 | 
             
                # @param configuration [Configuration]
         | 
| 41 46 | 
             
                # @param integration_meta [Hash, nil]
         | 
| 42 47 | 
             
                # @param message [String, nil]
         | 
| @@ -54,6 +59,7 @@ module Sentry | |
| 54 59 | 
             
                  @tags          = {}
         | 
| 55 60 |  | 
| 56 61 | 
             
                  @fingerprint = []
         | 
| 62 | 
            +
                  @dynamic_sampling_context = nil
         | 
| 57 63 |  | 
| 58 64 | 
             
                  # configuration data that's directly used by events
         | 
| 59 65 | 
             
                  @server_name = configuration.server_name
         | 
| @@ -70,34 +76,6 @@ module Sentry | |
| 70 76 | 
             
                  @message = (message || "").byteslice(0..MAX_MESSAGE_SIZE_IN_BYTES)
         | 
| 71 77 | 
             
                end
         | 
| 72 78 |  | 
| 73 | 
            -
                class << self
         | 
| 74 | 
            -
                  # @!visibility private
         | 
| 75 | 
            -
                  def get_log_message(event_hash)
         | 
| 76 | 
            -
                    message = event_hash[:message] || event_hash['message']
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                    return message unless message.nil? || message.empty?
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                    message = get_message_from_exception(event_hash)
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                    return message unless message.nil? || message.empty?
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                    message = event_hash[:transaction] || event_hash["transaction"]
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                    return message unless message.nil? || message.empty?
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                    '<no message value>'
         | 
| 89 | 
            -
                  end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                  # @!visibility private
         | 
| 92 | 
            -
                  def get_message_from_exception(event_hash)
         | 
| 93 | 
            -
                    if exception = event_hash.dig(:exception, :values, 0)
         | 
| 94 | 
            -
                      "#{exception[:type]}: #{exception[:value]}"
         | 
| 95 | 
            -
                    elsif exception = event_hash.dig("exception", "values", 0)
         | 
| 96 | 
            -
                      "#{exception["type"]}: #{exception["value"]}"
         | 
| 97 | 
            -
                    end
         | 
| 98 | 
            -
                  end
         | 
| 99 | 
            -
                end
         | 
| 100 | 
            -
             | 
| 101 79 | 
             
                # @deprecated This method will be removed in v5.0.0. Please just use Sentry.configuration
         | 
| 102 80 | 
             
                # @return [Configuration]
         | 
| 103 81 | 
             
                def configuration
         |