sentry-ruby 5.8.0 → 5.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ced2a96562a5dc27766fb35a62e43f302dd46eeabd16eae2a52106cc2151ee0
4
- data.tar.gz: 14f4b9a532cc0d1f401ee0bcb942787951f107358e9fbfadc2b1c655d00da3b2
3
+ metadata.gz: 1d89549da043b049e2dd6f5c73ac6ec0c3dd98ded247be2035316e45110bde88
4
+ data.tar.gz: 38844c5d5521bcf40a749d77667e91fa5b819d98951e4a02ebc807724b91c3a9
5
5
  SHA512:
6
- metadata.gz: 8816a3439fd547d260e538d16c3db3f440bbdae35ec8108e2338ccd712497cbca0413ce1a365862ab510a787f5d3cae8a58eab2273dd06588284d77a5afac898
7
- data.tar.gz: 4d5e8d3fe56644431b33fbec3eeaf4ceec01eb85b21bd2abfa5a0d8bc4c812aef9beb06b89048525186f00170677b160154414d5cb9b8972725532ba35277130
6
+ metadata.gz: 1cc2ac4f8394b8dcafd30d2aa4bbd863e313a04953d5b072997783c54fa76285bff16b77e23ca7f6b22644f9d1a69ad2484c844b7e6bf6deefbf3cbcd874ffbf
7
+ data.tar.gz: c30a0fd380e11f93edc599320a3884464e9d0568327512e514d1586f120b217091f67912531167738efb64ffd55cec960c6083dc894556796a00f2f5c79e13f9
data/Gemfile CHANGED
@@ -10,6 +10,8 @@ gem "rack", "~> #{Gem::Version.new(rack_version)}" unless rack_version == "0"
10
10
  redis_rb_version = ENV.fetch("REDIS_RB_VERSION", "5.0")
11
11
  gem "redis", "~> #{redis_rb_version}"
12
12
 
13
+ gem "puma"
14
+
13
15
  gem "rake", "~> 12.0"
14
16
  gem "rspec", "~> 3.0"
15
17
  gem "rspec-retry"
@@ -17,9 +19,19 @@ gem "timecop"
17
19
  gem "simplecov"
18
20
  gem "simplecov-cobertura", "~> 1.4"
19
21
  gem "rexml"
22
+ gem "stackprof" unless RUBY_PLATFORM == "java"
23
+
24
+ ruby_version = Gem::Version.new(RUBY_VERSION)
25
+
26
+ if ruby_version >= Gem::Version.new("2.6.0")
27
+ gem "debug", github: "ruby/debug", platform: :ruby
28
+ gem "irb"
29
+
30
+ if ruby_version >= Gem::Version.new("3.0.0")
31
+ gem "ruby-lsp-rspec"
32
+ end
33
+ end
20
34
 
21
- gem "object_tracer"
22
- gem "debug", github: "ruby/debug", platform: :ruby if RUBY_VERSION.to_f >= 2.6
23
35
  gem "pry"
24
36
 
25
37
  gem "benchmark-ips"
data/README.md CHANGED
@@ -13,14 +13,14 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he
13
13
  Sentry SDK for Ruby
14
14
  ===========
15
15
 
16
- | current version | build | coverage | downloads |
17
- | --- | ----- | -------- | --------- |
18
- | [![Gem Version](https://img.shields.io/gem/v/sentry-ruby?label=sentry-ruby)](https://rubygems.org/gems/sentry-ruby) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-ruby%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-ruby.svg)](https://rubygems.org/gems/sentry-ruby/) |
19
- | [![Gem Version](https://img.shields.io/gem/v/sentry-rails?label=sentry-rails)](https://rubygems.org/gems/sentry-rails) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-rails%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-rails.svg)](https://rubygems.org/gems/sentry-rails/) |
20
- | [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://rubygems.org/gems/sentry-sidekiq) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-sidekiq%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-sidekiq.svg)](https://rubygems.org/gems/sentry-sidekiq/) |
21
- | [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://rubygems.org/gems/sentry-delayed_job) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-delayed_job%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-delayed_job.svg)](https://rubygems.org/gems/sentry-delayed_job/) |
22
- | [![Gem Version](https://img.shields.io/gem/v/sentry-resque?label=sentry-resque)](https://rubygems.org/gems/sentry-resque) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-resque%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-resque.svg)](https://rubygems.org/gems/sentry-resque/) |
23
- | [![Gem Version](https://img.shields.io/gem/v/sentry-opentelemetry?label=sentry-opentelemetry)](https://rubygems.org/gems/sentry-opentelemetry) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-opentelemetry%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-opentelemetry.svg)](https://rubygems.org/gems/sentry-opentelemetry/) |
16
+ | current version | build | coverage | downloads |
17
+ | --- | ----- | -------- | --------- |
18
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-ruby?label=sentry-ruby)](https://rubygems.org/gems/sentry-ruby) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-ruby.svg)](https://rubygems.org/gems/sentry-ruby/) |
19
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-rails?label=sentry-rails)](https://rubygems.org/gems/sentry-rails) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-rails.svg)](https://rubygems.org/gems/sentry-rails/) |
20
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://rubygems.org/gems/sentry-sidekiq) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-sidekiq.svg)](https://rubygems.org/gems/sentry-sidekiq/) |
21
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://rubygems.org/gems/sentry-delayed_job) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-delayed_job.svg)](https://rubygems.org/gems/sentry-delayed_job/) |
22
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-resque?label=sentry-resque)](https://rubygems.org/gems/sentry-resque) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-resque.svg)](https://rubygems.org/gems/sentry-resque/) |
23
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-opentelemetry?label=sentry-opentelemetry)](https://rubygems.org/gems/sentry-opentelemetry) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-opentelemetry.svg)](https://rubygems.org/gems/sentry-opentelemetry/) |
24
24
 
25
25
 
26
26
 
@@ -33,7 +33,7 @@ If you're using `sentry-raven`, we recommend you to migrate to this new SDK. You
33
33
 
34
34
  ## Requirements
35
35
 
36
- We test on Ruby 2.4, 2.5, 2.6, 2.7, 3.0, and 3.1 at the latest patchlevel/teeny version. We also support JRuby 9.0.
36
+ We test from Ruby 2.4 to Ruby 3.2 at the latest patchlevel/teeny version. We also support JRuby 9.0.
37
37
 
38
38
  If you use self-hosted Sentry, please also make sure its version is above `20.6.0`.
39
39
 
data/Rakefile CHANGED
@@ -8,6 +8,13 @@ require "rspec/core/rake_task"
8
8
 
9
9
  RSpec::Core::RakeTask.new(:spec).tap do |task|
10
10
  task.rspec_opts = "--order rand"
11
+ task.exclude_pattern = "spec/isolated/**/*_spec.rb"
11
12
  end
12
13
 
13
- task :default => :spec
14
+ task :isolated_specs do
15
+ Dir["spec/isolated/*"].each do |file|
16
+ sh "bundle exec rspec #{file}"
17
+ end
18
+ end
19
+
20
+ task :default => [:spec, :isolated_specs]
@@ -76,7 +76,7 @@ module Sentry
76
76
  end
77
77
  end
78
78
 
79
- APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/.freeze
79
+ APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze
80
80
 
81
81
  # holder for an Array of Backtrace::Line instances
82
82
  attr_reader :lines
@@ -8,17 +8,6 @@ module Sentry
8
8
  SENTRY_PREFIX = 'sentry-'
9
9
  SENTRY_PREFIX_REGEX = /^sentry-/.freeze
10
10
 
11
- DSC_KEYS = %w(
12
- trace_id
13
- public_key
14
- sample_rate
15
- release
16
- environment
17
- transaction
18
- user_id
19
- user_segment
20
- ).freeze
21
-
22
11
  # @return [Hash]
23
12
  attr_reader :items
24
13
 
@@ -68,7 +57,7 @@ module Sentry
68
57
  # hash to be used in the trace envelope header.
69
58
  # @return [Hash]
70
59
  def dynamic_sampling_context
71
- @items.select { |k, _v| DSC_KEYS.include?(k) }
60
+ @items
72
61
  end
73
62
 
74
63
  # Serialize the Baggage object back to a string.
@@ -9,7 +9,7 @@ module Sentry
9
9
  # @return [Hash, nil]
10
10
  attr_accessor :data
11
11
  # @return [String, nil]
12
- attr_accessor :level
12
+ attr_reader :level
13
13
  # @return [Time, Integer, nil]
14
14
  attr_accessor :timestamp
15
15
  # @return [String, nil]
@@ -26,10 +26,10 @@ module Sentry
26
26
  def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
27
27
  @category = category
28
28
  @data = data || {}
29
- @level = level
30
29
  @timestamp = timestamp || Sentry.utc_now.to_i
31
30
  @type = type
32
31
  self.message = message
32
+ self.level = level
33
33
  end
34
34
 
35
35
  # @return [Hash]
@@ -50,6 +50,12 @@ module Sentry
50
50
  @message = (message || "").byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES)
51
51
  end
52
52
 
53
+ # @param level [String]
54
+ # @return [void]
55
+ def level=(level) # needed to meet the Sentry spec
56
+ @level = level == "warn" ? "warning" : level
57
+ end
58
+
53
59
  private
54
60
 
55
61
  def serialized_data
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'sentry/cron/monitor_config'
5
+
6
+ module Sentry
7
+ class CheckInEvent < Event
8
+ TYPE = 'check_in'
9
+
10
+ # uuid to identify this check-in.
11
+ # @return [String]
12
+ attr_accessor :check_in_id
13
+
14
+ # Identifier of the monitor for this check-in.
15
+ # @return [String]
16
+ attr_accessor :monitor_slug
17
+
18
+ # Duration of this check since it has started in seconds.
19
+ # @return [Integer, nil]
20
+ attr_accessor :duration
21
+
22
+ # Monitor configuration to support upserts.
23
+ # @return [Cron::MonitorConfig, nil]
24
+ attr_accessor :monitor_config
25
+
26
+ # Status of this check-in.
27
+ # @return [Symbol]
28
+ attr_accessor :status
29
+
30
+ VALID_STATUSES = %i(ok in_progress error)
31
+
32
+ def initialize(
33
+ slug:,
34
+ status:,
35
+ duration: nil,
36
+ monitor_config: nil,
37
+ check_in_id: nil,
38
+ **options
39
+ )
40
+ super(**options)
41
+
42
+ self.monitor_slug = slug
43
+ self.status = status
44
+ self.duration = duration
45
+ self.monitor_config = monitor_config
46
+ self.check_in_id = check_in_id || SecureRandom.uuid.delete('-')
47
+ end
48
+
49
+ # @return [Hash]
50
+ def to_hash
51
+ data = super
52
+ data[:check_in_id] = check_in_id
53
+ data[:monitor_slug] = monitor_slug
54
+ data[:status] = status
55
+ data[:duration] = duration if duration
56
+ data[:monitor_config] = monitor_config.to_hash if monitor_config
57
+ data
58
+ end
59
+ end
60
+ end
data/lib/sentry/client.rb CHANGED
@@ -76,7 +76,10 @@ module Sentry
76
76
  # @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
77
77
  # @return [Event, nil]
78
78
  def event_from_exception(exception, hint = {})
79
- return unless @configuration.sending_allowed? && @configuration.exception_class_allowed?(exception)
79
+ return unless @configuration.sending_allowed?
80
+
81
+ ignore_exclusions = hint.delete(:ignore_exclusions) { false }
82
+ return if !ignore_exclusions && !@configuration.exception_class_allowed?(exception)
80
83
 
81
84
  integration_meta = Sentry.integrations[hint[:integration]]
82
85
 
@@ -101,6 +104,37 @@ module Sentry
101
104
  event
102
105
  end
103
106
 
107
+ # Initializes a CheckInEvent object with the given options.
108
+ #
109
+ # @param slug [String] identifier of this monitor
110
+ # @param status [Symbol] status of this check-in, one of {CheckInEvent::VALID_STATUSES}
111
+ # @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
112
+ # @param duration [Integer, nil] seconds elapsed since this monitor started
113
+ # @param monitor_config [Cron::MonitorConfig, nil] configuration for this monitor
114
+ # @param check_in_id [String, nil] for updating the status of an existing monitor
115
+ #
116
+ # @return [Event]
117
+ def event_from_check_in(
118
+ slug,
119
+ status,
120
+ hint = {},
121
+ duration: nil,
122
+ monitor_config: nil,
123
+ check_in_id: nil
124
+ )
125
+ return unless configuration.sending_allowed?
126
+
127
+ CheckInEvent.new(
128
+ configuration: configuration,
129
+ integration_meta: Sentry.integrations[hint[:integration]],
130
+ slug: slug,
131
+ status: status,
132
+ duration: duration,
133
+ monitor_config: monitor_config,
134
+ check_in_id: check_in_id
135
+ )
136
+ end
137
+
104
138
  # Initializes an Event object with the given Transaction object.
105
139
  # @param transaction [Transaction] the transaction to be recorded.
106
140
  # @return [TransactionEvent]
@@ -145,6 +179,8 @@ module Sentry
145
179
  raise
146
180
  end
147
181
 
182
+ # @deprecated use Sentry.get_traceparent instead.
183
+ #
148
184
  # Generates a Sentry trace for distribted tracing from the given Span.
149
185
  # Returns `nil` if `config.propagate_traces` is `false`.
150
186
  # @param span [Span] the span to generate trace from.
@@ -157,7 +193,9 @@ module Sentry
157
193
  trace
158
194
  end
159
195
 
160
- # Generates a W3C Baggage header for distribted tracing from the given Span.
196
+ # @deprecated Use Sentry.get_baggage instead.
197
+ #
198
+ # Generates a W3C Baggage header for distributed tracing from the given Span.
161
199
  # Returns `nil` if `config.propagate_traces` is `false`.
162
200
  # @param span [Span] the span to generate trace from.
163
201
  # @return [String, nil]
@@ -14,6 +14,8 @@ module Sentry
14
14
  class Configuration
15
15
  include CustomInspection
16
16
  include LoggingHelper
17
+ include ArgumentCheckingHelper
18
+
17
19
  # Directories to be recognized as part of your app. e.g. if you
18
20
  # have an `engines` dir at the root of your project, you may want
19
21
  # to set this to something like /(app|config|engines|lib)/
@@ -179,7 +181,7 @@ module Sentry
179
181
  # Release tag to be passed with every event sent to Sentry.
180
182
  # We automatically try to set this to a git SHA or Capistrano release.
181
183
  # @return [String]
182
- attr_accessor :release
184
+ attr_reader :release
183
185
 
184
186
  # The sampling factor to apply to events. A value of 0.0 will not send
185
187
  # any events, and a value of 1.0 will send 100% of events.
@@ -214,8 +216,8 @@ module Sentry
214
216
  attr_reader :transport
215
217
 
216
218
  # Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
217
- # @return [Float]
218
- attr_accessor :traces_sample_rate
219
+ # @return [Float, nil]
220
+ attr_reader :traces_sample_rate
219
221
 
220
222
  # Take a Proc that controls the sample rate for every tracing event, e.g.
221
223
  # @example
@@ -227,6 +229,11 @@ module Sentry
227
229
  # @return [Proc]
228
230
  attr_accessor :traces_sampler
229
231
 
232
+ # Easier way to use performance tracing
233
+ # If set to true, will set traces_sample_rate to 1.0
234
+ # @return [Boolean, nil]
235
+ attr_reader :enable_tracing
236
+
230
237
  # Send diagnostic client reports about dropped events, true by default
231
238
  # tries to attach to an existing envelope max once every 30s
232
239
  # @return [Boolean]
@@ -236,14 +243,39 @@ module Sentry
236
243
  # @return [Boolean]
237
244
  attr_accessor :auto_session_tracking
238
245
 
246
+ # Allowlist of outgoing request targets to which sentry-trace and baggage headers are attached.
247
+ # Default is all (/.*/)
248
+ # @return [Array<String, Regexp>]
249
+ attr_accessor :trace_propagation_targets
250
+
239
251
  # The instrumenter to use, :sentry or :otel
240
252
  # @return [Symbol]
241
253
  attr_reader :instrumenter
242
254
 
255
+ # Take a float between 0.0 and 1.0 as the sample rate for capturing profiles.
256
+ # Note that this rate is relative to traces_sample_rate / traces_sampler,
257
+ # i.e. the profile is sampled by this rate after the transaction is sampled.
258
+ # @return [Float, nil]
259
+ attr_reader :profiles_sample_rate
260
+
261
+ # Array of patches to apply.
262
+ # Default is {DEFAULT_PATCHES}
263
+ # @return [Array<Symbol>]
264
+ attr_accessor :enabled_patches
265
+
243
266
  # these are not config options
244
267
  # @!visibility private
245
268
  attr_reader :errors, :gem_specs
246
269
 
270
+ # These exceptions could enter Puma's `lowlevel_error_handler` callback and the SDK's Puma integration
271
+ # But they are mostly considered as noise and should be ignored by default
272
+ # Please see https://github.com/getsentry/sentry-ruby/pull/2026 for more information
273
+ PUMA_IGNORE_DEFAULT = [
274
+ 'Puma::MiniSSL::SSLError',
275
+ 'Puma::HttpParserError',
276
+ 'Puma::HttpParserError501'
277
+ ].freeze
278
+
247
279
  # Most of these errors generate 4XX responses. In general, Sentry clients
248
280
  # only automatically report 5xx responses.
249
281
  IGNORE_DEFAULT = [
@@ -268,6 +300,10 @@ module Sentry
268
300
 
269
301
  INSTRUMENTERS = [:sentry, :otel]
270
302
 
303
+ PROPAGATION_TARGETS_MATCH_ALL = /.*/.freeze
304
+
305
+ DEFAULT_PATCHES = %i(redis puma http).freeze
306
+
271
307
  class << self
272
308
  # Post initialization callbacks are called at the end of initialization process
273
309
  # allowing extending the configuration of sentry-ruby by multiple extensions
@@ -293,7 +329,7 @@ module Sentry
293
329
  self.environment = environment_from_env
294
330
  self.enabled_environments = []
295
331
  self.exclude_loggers = []
296
- self.excluded_exceptions = IGNORE_DEFAULT.dup
332
+ self.excluded_exceptions = IGNORE_DEFAULT + PUMA_IGNORE_DEFAULT
297
333
  self.inspect_exception_causes_for_exclusion = true
298
334
  self.linecache = ::Sentry::LineCache.new
299
335
  self.logger = ::Sentry::Logger.new(STDOUT)
@@ -310,12 +346,14 @@ module Sentry
310
346
  self.dsn = ENV['SENTRY_DSN']
311
347
  self.server_name = server_name_from_env
312
348
  self.instrumenter = :sentry
349
+ self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL]
350
+ self.enabled_patches = DEFAULT_PATCHES.dup
313
351
 
314
352
  self.before_send = nil
315
353
  self.before_send_transaction = nil
316
354
  self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
317
- self.traces_sample_rate = nil
318
355
  self.traces_sampler = nil
356
+ self.enable_tracing = nil
319
357
 
320
358
  @transport = Transport::Configuration.new
321
359
  @gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
@@ -329,6 +367,12 @@ module Sentry
329
367
 
330
368
  alias server= dsn=
331
369
 
370
+ def release=(value)
371
+ check_argument_type!(value, String, NilClass)
372
+
373
+ @release = value
374
+ end
375
+
332
376
  def async=(value)
333
377
  check_callable!("async", value)
334
378
 
@@ -384,6 +428,26 @@ module Sentry
384
428
  @instrumenter = INSTRUMENTERS.include?(instrumenter) ? instrumenter : :sentry
385
429
  end
386
430
 
431
+ def enable_tracing=(enable_tracing)
432
+ @enable_tracing = enable_tracing
433
+ @traces_sample_rate ||= 1.0 if enable_tracing
434
+ end
435
+
436
+ def is_numeric_or_nil?(value)
437
+ value.is_a?(Numeric) || value.nil?
438
+ end
439
+
440
+ def traces_sample_rate=(traces_sample_rate)
441
+ raise ArgumentError, "traces_sample_rate must be a Numeric or nil" unless is_numeric_or_nil?(traces_sample_rate)
442
+ @traces_sample_rate = traces_sample_rate
443
+ end
444
+
445
+ def profiles_sample_rate=(profiles_sample_rate)
446
+ raise ArgumentError, "profiles_sample_rate must be a Numeric or nil" unless is_numeric_or_nil?(profiles_sample_rate)
447
+ log_info("Please make sure to include the 'stackprof' gem in your Gemfile to use Profiling with Sentry.") unless defined?(StackProf)
448
+ @profiles_sample_rate = profiles_sample_rate
449
+ end
450
+
387
451
  def sending_allowed?
388
452
  @errors = []
389
453
 
@@ -413,8 +477,21 @@ module Sentry
413
477
  enabled_environments.empty? || enabled_environments.include?(environment)
414
478
  end
415
479
 
480
+ def valid_sample_rate?(sample_rate)
481
+ return false unless sample_rate.is_a?(Numeric)
482
+ sample_rate >= 0.0 && sample_rate <= 1.0
483
+ end
484
+
416
485
  def tracing_enabled?
417
- !!((@traces_sample_rate && @traces_sample_rate >= 0.0 && @traces_sample_rate <= 1.0) || @traces_sampler) && sending_allowed?
486
+ valid_sampler = !!((valid_sample_rate?(@traces_sample_rate)) || @traces_sampler)
487
+
488
+ (@enable_tracing != false) && valid_sampler && sending_allowed?
489
+ end
490
+
491
+ def profiling_enabled?
492
+ valid_sampler = !!(valid_sample_rate?(@profiles_sample_rate))
493
+
494
+ tracing_enabled? && valid_sampler && sending_allowed?
418
495
  end
419
496
 
420
497
  # @return [String, nil]
@@ -442,7 +519,7 @@ module Sentry
442
519
  def detect_release
443
520
  return unless sending_allowed?
444
521
 
445
- self.release ||= ReleaseDetector.detect_release(project_root: project_root, running_on_heroku: running_on_heroku?)
522
+ @release ||= ReleaseDetector.detect_release(project_root: project_root, running_on_heroku: running_on_heroku?)
446
523
 
447
524
  if running_on_heroku? && release.nil?
448
525
  log_warn(HEROKU_DYNO_METADATA_MESSAGE)
@@ -0,0 +1,61 @@
1
+ module Sentry
2
+ module Cron
3
+ module MonitorCheckIns
4
+ module Patch
5
+ def perform(*args)
6
+ slug = self.class.sentry_monitor_slug || self.class.name
7
+ monitor_config = self.class.sentry_monitor_config
8
+
9
+ check_in_id = Sentry.capture_check_in(slug,
10
+ :in_progress,
11
+ monitor_config: monitor_config)
12
+
13
+ start = Sentry.utc_now.to_i
14
+ ret = super
15
+ duration = Sentry.utc_now.to_i - start
16
+
17
+ Sentry.capture_check_in(slug,
18
+ :ok,
19
+ check_in_id: check_in_id,
20
+ duration: duration,
21
+ monitor_config: monitor_config)
22
+
23
+ ret
24
+ rescue Exception
25
+ duration = Sentry.utc_now.to_i - start
26
+
27
+ Sentry.capture_check_in(slug,
28
+ :error,
29
+ check_in_id: check_in_id,
30
+ duration: duration,
31
+ monitor_config: monitor_config)
32
+
33
+ raise
34
+ end
35
+ end
36
+
37
+ module ClassMethods
38
+ def sentry_monitor_check_ins(slug: nil, monitor_config: nil)
39
+ @sentry_monitor_slug = slug
40
+ @sentry_monitor_config = monitor_config
41
+
42
+ prepend Patch
43
+ end
44
+
45
+ def sentry_monitor_slug
46
+ @sentry_monitor_slug
47
+ end
48
+
49
+ def sentry_monitor_config
50
+ @sentry_monitor_config
51
+ end
52
+ end
53
+
54
+ extend ClassMethods
55
+
56
+ def self.included(base)
57
+ base.extend(ClassMethods)
58
+ end
59
+ end
60
+ end
61
+ 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
@@ -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 * 200
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
- <<~ITEM
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