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 +4 -4
- data/Gemfile +14 -2
- data/README.md +9 -9
- data/Rakefile +8 -1
- data/lib/sentry/backtrace.rb +1 -1
- data/lib/sentry/baggage.rb +1 -12
- data/lib/sentry/breadcrumb.rb +8 -2
- data/lib/sentry/check_in_event.rb +60 -0
- data/lib/sentry/client.rb +40 -2
- data/lib/sentry/configuration.rb +84 -7
- data/lib/sentry/cron/monitor_check_ins.rb +61 -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 +6 -0
- data/lib/sentry/hub.rb +78 -3
- data/lib/sentry/integrable.rb +6 -0
- data/lib/sentry/interfaces/single_exception.rb +4 -3
- data/lib/sentry/net/http.rb +21 -22
- 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 +1 -4
- data/lib/sentry/redis.rb +9 -8
- data/lib/sentry/scope.rb +23 -3
- data/lib/sentry/span.rb +39 -2
- data/lib/sentry/test_helper.rb +18 -12
- data/lib/sentry/transaction.rb +24 -17
- data/lib/sentry/transaction_event.rb +30 -3
- data/lib/sentry/transport.rb +11 -3
- data/lib/sentry/utils/argument_checking_helper.rb +9 -3
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +72 -5
- metadata +9 -3
- data/CODE_OF_CONDUCT.md +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d89549da043b049e2dd6f5c73ac6ec0c3dd98ded247be2035316e45110bde88
|
4
|
+
data.tar.gz: 38844c5d5521bcf40a749d77667e91fa5b819d98951e4a02ebc807724b91c3a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
17
|
-
| ---
|
18
|
-
| [](https://rubygems.org/gems/sentry-ruby)
|
19
|
-
| [](https://rubygems.org/gems/sentry-rails)
|
20
|
-
| [](https://rubygems.org/gems/sentry-sidekiq)
|
21
|
-
| [](https://rubygems.org/gems/sentry-delayed_job)
|
22
|
-
| [](https://rubygems.org/gems/sentry-resque)
|
23
|
-
| [](https://rubygems.org/gems/sentry-opentelemetry) | [](https://rubygems.org/gems/sentry-ruby) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-ruby/) |
|
19
|
+
| [](https://rubygems.org/gems/sentry-rails) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-rails/) |
|
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
|
+
| [](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
|
+
| [](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/) |
|
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
|
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 :
|
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]
|
data/lib/sentry/backtrace.rb
CHANGED
data/lib/sentry/baggage.rb
CHANGED
@@ -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
|
60
|
+
@items
|
72
61
|
end
|
73
62
|
|
74
63
|
# Serialize the Baggage object back to a string.
|
data/lib/sentry/breadcrumb.rb
CHANGED
@@ -9,7 +9,7 @@ module Sentry
|
|
9
9
|
# @return [Hash, nil]
|
10
10
|
attr_accessor :data
|
11
11
|
# @return [String, nil]
|
12
|
-
|
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?
|
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
|
-
#
|
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]
|
data/lib/sentry/configuration.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
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
|