sentry-ruby-core 5.1.0 → 5.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8b9d0c43497ccc151613d208b6e9a51489586a41cbb7849cbcfcd3e5795765f
4
- data.tar.gz: 79e7e9f621b2fe8bfc1c1dc292a16392e499925c13bdc1c31c3f8e05240f42e0
3
+ metadata.gz: 896f183ea604d1e6857591eff87175f8bb8a83dd1e40fc3e80982a71dd3abe0e
4
+ data.tar.gz: ffc931b4d436be3c5b1858260a5e2a0508d75455c23d0971bd0f1d2a02f0e178
5
5
  SHA512:
6
- metadata.gz: 3def5710a658f0365dbe11292f548aafcaf6d467d04abd5e0973035c5c3243307d49347b829ae0aa93d459c2bf4036813ec2a4589471c8da21d438318144c0aa
7
- data.tar.gz: 99eab89037a4e468c7bb257d33aaf85ec8830102aa233a9af4c5091c92d67726f4ffab47b3eeedba07f079b4b3600145458e9283274532b534824acd21236617
6
+ metadata.gz: 467c2493df9a8ba98148b1d467d313bfc23defd9b34a9355242b01ed7ac4f092932b19607ad79e16883f83ba9b1fa53b736872f920f4fb0590761fcdbfc12a25
7
+ data.tar.gz: 074c4ac8eff86f456646ceef087433abf38a81ad1e8a3d0cec465caddf5a4e96459ed9c641854f7dba37ac9e851fde8f7e09798f35420f4d12586b89039282d4
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source "https://rubygems.org"
2
+ git_source(:github) { |name| "https://github.com/#{name}.git" }
2
3
 
3
4
  gem "sentry-ruby-core", path: "./"
4
5
  gem "sentry-ruby", path: "./"
@@ -207,6 +207,10 @@ module Sentry
207
207
  # @return [Boolean]
208
208
  attr_accessor :send_client_reports
209
209
 
210
+ # Track sessions in request/response cycles automatically
211
+ # @return [Boolean]
212
+ attr_accessor :auto_session_tracking
213
+
210
214
  # these are not config options
211
215
  # @!visibility private
212
216
  attr_reader :errors, :gem_specs
@@ -261,6 +265,7 @@ module Sentry
261
265
  self.send_default_pii = false
262
266
  self.skip_rake_integration = false
263
267
  self.send_client_reports = true
268
+ self.auto_session_tracking = true
264
269
  self.trusted_proxies = []
265
270
  self.dsn = ENV['SENTRY_DSN']
266
271
  self.server_name = server_name_from_env
@@ -3,24 +3,43 @@
3
3
  module Sentry
4
4
  # @api private
5
5
  class Envelope
6
- def initialize(headers)
6
+ class Item
7
+ attr_accessor :headers, :payload
8
+
9
+ def initialize(headers, payload)
10
+ @headers = headers
11
+ @payload = payload
12
+ end
13
+
14
+ def type
15
+ @headers[:type] || 'event'
16
+ end
17
+
18
+ def to_s
19
+ <<~ITEM
20
+ #{JSON.generate(@headers)}
21
+ #{JSON.generate(@payload)}
22
+ ITEM
23
+ end
24
+ end
25
+
26
+ attr_accessor :headers, :items
27
+
28
+ def initialize(headers = {})
7
29
  @headers = headers
8
30
  @items = []
9
31
  end
10
32
 
11
33
  def add_item(headers, payload)
12
- @items << [headers, payload]
34
+ @items << Item.new(headers, payload)
13
35
  end
14
36
 
15
- def to_s
16
- payload = @items.map do |item_headers, item_payload|
17
- <<~ENVELOPE
18
- #{JSON.generate(item_headers)}
19
- #{JSON.generate(item_payload)}
20
- ENVELOPE
21
- end.join("\n")
37
+ def item_types
38
+ @items.map(&:type)
39
+ end
22
40
 
23
- "#{JSON.generate(@headers)}\n#{payload}"
41
+ def event_id
42
+ @headers[:event_id]
24
43
  end
25
44
  end
26
45
  end
data/lib/sentry/event.rb CHANGED
@@ -23,6 +23,7 @@ module Sentry
23
23
  WRITER_ATTRIBUTES = SERIALIZEABLE_ATTRIBUTES - %i(type timestamp level)
24
24
 
25
25
  MAX_MESSAGE_SIZE_IN_BYTES = 1024 * 8
26
+ MAX_SERIALIZED_PAYLOAD_SIZE = 1024 * 200
26
27
 
27
28
  SKIP_INSPECTION_ATTRIBUTES = [:@modules, :@stacktrace_builder, :@send_default_pii, :@trusted_proxies, :@rack_env_whitelist]
28
29
 
data/lib/sentry/hub.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "sentry/scope"
4
4
  require "sentry/client"
5
+ require "sentry/session"
5
6
 
6
7
  module Sentry
7
8
  class Hub
@@ -94,6 +95,8 @@ module Sentry
94
95
  def capture_exception(exception, **options, &block)
95
96
  check_argument_type!(exception, ::Exception)
96
97
 
98
+ return if Sentry.exception_captured?(exception)
99
+
97
100
  return unless current_client
98
101
 
99
102
  options[:hint] ||= {}
@@ -102,9 +105,11 @@ module Sentry
102
105
 
103
106
  return unless event
104
107
 
108
+ current_scope.session&.update_from_exception(event.exception)
109
+
105
110
  capture_event(event, **options, &block).tap do
106
111
  # mark the exception as captured so we can use this information to avoid duplicated capturing
107
- exception.instance_variable_set(:@__sentry_captured, true)
112
+ exception.instance_variable_set(Sentry::CAPTURED_SIGNATURE, true)
108
113
  end
109
114
  end
110
115
 
@@ -141,7 +146,6 @@ module Sentry
141
146
 
142
147
  event = current_client.capture_event(event, scope, hint)
143
148
 
144
-
145
149
  if event && configuration.debug
146
150
  configuration.log_debug(event.to_json_compatible)
147
151
  end
@@ -173,6 +177,30 @@ module Sentry
173
177
  configuration.background_worker_threads = original_background_worker_threads
174
178
  end
175
179
 
180
+ def start_session
181
+ return unless current_scope
182
+ current_scope.set_session(Session.new)
183
+ end
184
+
185
+ def end_session
186
+ return unless current_scope
187
+ session = current_scope.session
188
+ current_scope.set_session(nil)
189
+
190
+ return unless session
191
+ session.close
192
+ Sentry.session_flusher.add_session(session)
193
+ end
194
+
195
+ def with_session_tracking(&block)
196
+ return yield unless configuration.auto_session_tracking
197
+
198
+ start_session
199
+ yield
200
+ ensure
201
+ end_session
202
+ end
203
+
176
204
  private
177
205
 
178
206
  def current_layer
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require "set"
2
3
 
3
4
  module Sentry
4
5
  class ExceptionInterface < Interface
@@ -14,30 +14,32 @@ module Sentry
14
14
  Sentry.clone_hub_to_current_thread
15
15
 
16
16
  Sentry.with_scope do |scope|
17
- scope.clear_breadcrumbs
18
- scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
19
- scope.set_rack_env(env)
20
-
21
- transaction = start_transaction(env, scope)
22
- scope.set_span(transaction) if transaction
23
-
24
- begin
25
- response = @app.call(env)
26
- rescue Sentry::Error
27
- finish_transaction(transaction, 500)
28
- raise # Don't capture Sentry errors
29
- rescue Exception => e
30
- capture_exception(e)
31
- finish_transaction(transaction, 500)
32
- raise
17
+ Sentry.with_session_tracking do
18
+ scope.clear_breadcrumbs
19
+ scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
20
+ scope.set_rack_env(env)
21
+
22
+ transaction = start_transaction(env, scope)
23
+ scope.set_span(transaction) if transaction
24
+
25
+ begin
26
+ response = @app.call(env)
27
+ rescue Sentry::Error
28
+ finish_transaction(transaction, 500)
29
+ raise # Don't capture Sentry errors
30
+ rescue Exception => e
31
+ capture_exception(e)
32
+ finish_transaction(transaction, 500)
33
+ raise
34
+ end
35
+
36
+ exception = collect_exception(env)
37
+ capture_exception(exception) if exception
38
+
39
+ finish_transaction(transaction, response[0])
40
+
41
+ response
33
42
  end
34
-
35
- exception = collect_exception(env)
36
- capture_exception(exception) if exception
37
-
38
- finish_transaction(transaction, response[0])
39
-
40
- response
41
43
  end
42
44
  end
43
45
 
@@ -59,7 +61,7 @@ module Sentry
59
61
  sentry_trace = env["HTTP_SENTRY_TRACE"]
60
62
  options = { name: scope.transaction_name, op: transaction_op }
61
63
  transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, **options) if sentry_trace
62
- Sentry.start_transaction(transaction: transaction, **options)
64
+ Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
63
65
  end
64
66
 
65
67
 
data/lib/sentry/redis.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  module Sentry
4
4
  # @api private
5
5
  class Redis
6
- OP_NAME ||= "db.redis.command"
7
- LOGGER_NAME ||= :redis_logger
6
+ OP_NAME = "db.redis.command"
7
+ LOGGER_NAME = :redis_logger
8
8
 
9
9
  def initialize(commands, host, port, db)
10
10
  @commands, @host, @port, @db = commands, host, port, db
@@ -60,9 +60,11 @@ module Sentry
60
60
 
61
61
  def parsed_commands
62
62
  commands.map do |statement|
63
- command, key, *_values = statement
63
+ command, key, *arguments = statement
64
64
 
65
- { command: command.to_s.upcase, key: key }
65
+ { command: command.to_s.upcase, key: key }.tap do |command_set|
66
+ command_set[:arguments] = arguments.join(" ") if Sentry.configuration.send_default_pii
67
+ end
66
68
  end
67
69
  end
68
70
 
data/lib/sentry/scope.rb CHANGED
@@ -7,7 +7,7 @@ module Sentry
7
7
  class Scope
8
8
  include ArgumentCheckingHelper
9
9
 
10
- ATTRIBUTES = [:transaction_names, :contexts, :extra, :tags, :user, :level, :breadcrumbs, :fingerprint, :event_processors, :rack_env, :span]
10
+ ATTRIBUTES = [:transaction_names, :contexts, :extra, :tags, :user, :level, :breadcrumbs, :fingerprint, :event_processors, :rack_env, :span, :session]
11
11
 
12
12
  attr_reader(*ATTRIBUTES)
13
13
 
@@ -76,6 +76,7 @@ module Sentry
76
76
  copy.transaction_names = transaction_names.deep_dup
77
77
  copy.fingerprint = fingerprint.deep_dup
78
78
  copy.span = span.deep_dup
79
+ copy.session = session.deep_dup
79
80
  copy
80
81
  end
81
82
 
@@ -173,7 +174,7 @@ module Sentry
173
174
  def set_contexts(contexts_hash)
174
175
  check_argument_type!(contexts_hash, Hash)
175
176
  @contexts.merge!(contexts_hash) do |key, old, new|
176
- new.merge(old)
177
+ old.merge(new)
177
178
  end
178
179
  end
179
180
 
@@ -198,6 +199,13 @@ module Sentry
198
199
  @transaction_names << transaction_name
199
200
  end
200
201
 
202
+ # Sets the currently active session on the scope.
203
+ # @param session [Session, nil]
204
+ # @return [void]
205
+ def set_session(session)
206
+ @session = session
207
+ end
208
+
201
209
  # Returns current transaction name.
202
210
  # The "transaction" here does not refer to `Transaction` objects.
203
211
  # @return [String, nil]
@@ -251,6 +259,7 @@ module Sentry
251
259
  @event_processors = []
252
260
  @rack_env = {}
253
261
  @span = nil
262
+ @session = nil
254
263
  set_new_breadcrumb_buffer
255
264
  end
256
265
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ class Session
5
+ attr_reader :started, :status
6
+
7
+ # TODO-neel add :crashed after adding handled mechanism
8
+ STATUSES = %i(ok errored exited)
9
+ AGGREGATE_STATUSES = %i(errored exited)
10
+
11
+ def initialize
12
+ @started = Sentry.utc_now
13
+ @status = :ok
14
+ end
15
+
16
+ # TODO-neel add :crashed after adding handled mechanism
17
+ def update_from_exception(_exception = nil)
18
+ @status = :errored
19
+ end
20
+
21
+ def close
22
+ @status = :exited if @status == :ok
23
+ end
24
+
25
+ # truncate seconds from the timestamp since we only care about
26
+ # minute level granularity for aggregation
27
+ def aggregation_key
28
+ Time.utc(started.year, started.month, started.day, started.hour, started.min)
29
+ end
30
+
31
+ def deep_dup
32
+ dup
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ class SessionFlusher
5
+ include LoggingHelper
6
+
7
+ FLUSH_INTERVAL = 60
8
+
9
+ def initialize(configuration, client)
10
+ @thread = nil
11
+ @client = client
12
+ @pending_aggregates = {}
13
+ @release = configuration.release
14
+ @environment = configuration.environment
15
+ @logger = configuration.logger
16
+
17
+ log_debug("[Sessions] Sessions won't be captured without a valid release") unless @release
18
+ end
19
+
20
+ def flush
21
+ return if @pending_aggregates.empty?
22
+ envelope = pending_envelope
23
+
24
+ Sentry.background_worker.perform do
25
+ @client.transport.send_envelope(envelope)
26
+ end
27
+
28
+ @pending_aggregates = {}
29
+ end
30
+
31
+ def add_session(session)
32
+ return unless @release
33
+
34
+ ensure_thread
35
+
36
+ return unless Session::AGGREGATE_STATUSES.include?(session.status)
37
+ @pending_aggregates[session.aggregation_key] ||= init_aggregates(session.aggregation_key)
38
+ @pending_aggregates[session.aggregation_key][session.status] += 1
39
+ end
40
+
41
+ def kill
42
+ @thread&.kill
43
+ end
44
+
45
+ private
46
+
47
+ def init_aggregates(aggregation_key)
48
+ aggregates = { started: aggregation_key.iso8601 }
49
+ Session::AGGREGATE_STATUSES.each { |k| aggregates[k] = 0 }
50
+ aggregates
51
+ end
52
+
53
+ def pending_envelope
54
+ envelope = Envelope.new
55
+
56
+ header = { type: 'sessions' }
57
+ payload = { attrs: attrs, aggregates: @pending_aggregates.values }
58
+
59
+ envelope.add_item(header, payload)
60
+ envelope
61
+ end
62
+
63
+ def attrs
64
+ { release: @release, environment: @environment }
65
+ end
66
+
67
+ def ensure_thread
68
+ return if @thread&.alive?
69
+
70
+ @thread = Thread.new do
71
+ loop do
72
+ sleep(FLUSH_INTERVAL)
73
+ flush
74
+ end
75
+ end
76
+ end
77
+
78
+ end
79
+ end
@@ -25,6 +25,7 @@ module Sentry
25
25
  def initialize(configuration:, integration_meta: nil, message: nil)
26
26
  super
27
27
  @type = TYPE
28
+ self.level = nil
28
29
  end
29
30
 
30
31
  # Sets the event's start_timestamp.
@@ -2,15 +2,20 @@
2
2
 
3
3
  module Sentry
4
4
  class DummyTransport < Transport
5
- attr_accessor :events
5
+ attr_accessor :events, :envelopes
6
6
 
7
7
  def initialize(*)
8
8
  super
9
9
  @events = []
10
+ @envelopes = []
10
11
  end
11
12
 
12
13
  def send_event(event)
13
14
  @events << event
14
15
  end
16
+
17
+ def send_envelope(envelope)
18
+ @envelopes << envelope
19
+ end
15
20
  end
16
21
  end
@@ -46,23 +46,59 @@ module Sentry
46
46
  end
47
47
 
48
48
  def send_event(event)
49
- event_hash = event.to_hash
50
- item_type = get_item_type(event_hash)
49
+ envelope = envelope_from_event(event)
50
+ send_envelope(envelope)
51
51
 
52
- if is_rate_limited?(item_type)
53
- log_info("Envelope [#{item_type}] not sent: rate limiting")
54
- record_lost_event(:ratelimit_backoff, item_type)
52
+ event
53
+ end
54
+
55
+ def send_envelope(envelope)
56
+ reject_rate_limited_items(envelope)
55
57
 
56
- return
58
+ return if envelope.items.empty?
59
+
60
+ data, serialized_items = serialize_envelope(envelope)
61
+
62
+ if data
63
+ log_info("[Transport] Sending envelope with items [#{serialized_items.map(&:type).join(', ')}] #{envelope.event_id} to Sentry")
64
+ send_data(data)
57
65
  end
66
+ end
58
67
 
59
- encoded_data = encode(event)
68
+ def serialize_envelope(envelope)
69
+ serialized_items = []
70
+ serialized_results = []
60
71
 
61
- return nil unless encoded_data
72
+ envelope.items.each do |item|
73
+ result = item.to_s
62
74
 
63
- send_data(encoded_data)
75
+ if result.bytesize > Event::MAX_SERIALIZED_PAYLOAD_SIZE
76
+ if item.payload.key?(:breadcrumbs)
77
+ item.payload.delete(:breadcrumbs)
78
+ elsif item.payload.key?("breadcrumbs")
79
+ item.payload.delete("breadcrumbs")
80
+ end
64
81
 
65
- event
82
+ result = item.to_s
83
+ end
84
+
85
+ if result.bytesize > Event::MAX_SERIALIZED_PAYLOAD_SIZE
86
+ size_breakdown = item.payload.map do |key, value|
87
+ "#{key}: #{JSON.generate(value).bytesize}"
88
+ end.join(", ")
89
+
90
+ log_debug("Envelope item [#{item.type}] is still oversized without breadcrumbs: {#{size_breakdown}}")
91
+
92
+ next
93
+ end
94
+
95
+ serialized_results << result
96
+ serialized_items << item
97
+ end
98
+
99
+ data = [JSON.generate(envelope.headers), *serialized_results].join("\n") unless serialized_results.empty?
100
+
101
+ [data, serialized_items]
66
102
  end
67
103
 
68
104
  def is_rate_limited?(item_type)
@@ -71,6 +107,8 @@ module Sentry
71
107
  case item_type
72
108
  when "transaction"
73
109
  @rate_limits["transaction"]
110
+ when "sessions"
111
+ @rate_limits["session"]
74
112
  else
75
113
  @rate_limits["error"]
76
114
  end
@@ -106,7 +144,7 @@ module Sentry
106
144
  'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
107
145
  end
108
146
 
109
- def encode(event)
147
+ def envelope_from_event(event)
110
148
  # Convert to hash
111
149
  event_payload = event.to_hash
112
150
  event_id = event_payload[:event_id] || event_payload["event_id"]
@@ -129,9 +167,7 @@ module Sentry
129
167
  client_report_headers, client_report_payload = fetch_pending_client_report
130
168
  envelope.add_item(client_report_headers, client_report_payload) if client_report_headers
131
169
 
132
- log_info("Sending envelope [#{item_type}] #{event_id} to Sentry")
133
-
134
- envelope.to_s
170
+ envelope
135
171
  end
136
172
 
137
173
  def record_lost_event(reason, item_type)
@@ -173,6 +209,19 @@ module Sentry
173
209
 
174
210
  [item_header, item_payload]
175
211
  end
212
+
213
+ def reject_rate_limited_items(envelope)
214
+ envelope.items.reject! do |item|
215
+ if is_rate_limited?(item.type)
216
+ log_info("[Transport] Envelope item [#{item.type}] not sent: rate limiting")
217
+ record_lost_event(:ratelimit_backoff, item.type)
218
+
219
+ true
220
+ else
221
+ false
222
+ end
223
+ end
224
+ end
176
225
  end
177
226
  end
178
227
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- VERSION = "5.1.0"
4
+ VERSION = "5.2.1"
5
5
  end
data/lib/sentry-ruby.rb CHANGED
@@ -17,6 +17,7 @@ require "sentry/span"
17
17
  require "sentry/transaction"
18
18
  require "sentry/hub"
19
19
  require "sentry/background_worker"
20
+ require "sentry/session_flusher"
20
21
 
21
22
  [
22
23
  "sentry/rake",
@@ -31,6 +32,8 @@ end
31
32
  module Sentry
32
33
  META = { "name" => "sentry.ruby", "version" => Sentry::VERSION }.freeze
33
34
 
35
+ CAPTURED_SIGNATURE = :@__sentry_captured
36
+
34
37
  LOGGER_PROGNAME = "sentry".freeze
35
38
 
36
39
  SENTRY_TRACE_HEADER_NAME = "sentry-trace".freeze
@@ -59,6 +62,10 @@ module Sentry
59
62
  # @return [BackgroundWorker]
60
63
  attr_accessor :background_worker
61
64
 
65
+ # @!attribute [r] session_flusher
66
+ # @return [SessionFlusher]
67
+ attr_reader :session_flusher
68
+
62
69
  ##### Patch Registration #####
63
70
 
64
71
  # @!visibility private
@@ -92,6 +99,14 @@ module Sentry
92
99
  # @param name [String] name of the integration
93
100
  # @param version [String] version of the integration
94
101
  def register_integration(name, version)
102
+ if initialized?
103
+ logger.warn(LOGGER_PROGNAME) do
104
+ <<~MSG
105
+ Integration '#{name}' is loaded after the SDK is initialized, which can cause expected behavior. Please make sure all integrations are loaded before SDK initialization.
106
+ MSG
107
+ end
108
+ end
109
+
95
110
  meta = { name: "sentry.ruby.#{name}", version: version }.freeze
96
111
  integrations[name.to_s] = meta
97
112
  end
@@ -187,11 +202,18 @@ module Sentry
187
202
  @main_hub = hub
188
203
  @background_worker = Sentry::BackgroundWorker.new(config)
189
204
 
205
+ @session_flusher = if config.auto_session_tracking
206
+ Sentry::SessionFlusher.new(config, client)
207
+ else
208
+ nil
209
+ end
210
+
190
211
  if config.capture_exception_frame_locals
191
212
  exception_locals_tp.enable
192
213
  end
193
214
 
194
215
  at_exit do
216
+ @session_flusher&.kill
195
217
  @background_worker.shutdown
196
218
  end
197
219
  end
@@ -308,6 +330,26 @@ module Sentry
308
330
  get_current_hub.with_scope(&block)
309
331
  end
310
332
 
333
+ # Wrap a given block with session tracking.
334
+ # Aggregate sessions in minutely buckets will be recorded
335
+ # around this block and flushed every minute.
336
+ #
337
+ # @example
338
+ # Sentry.with_session_tracking do
339
+ # a = 1 + 1 # new session recorded with :exited status
340
+ # end
341
+ #
342
+ # Sentry.with_session_tracking do
343
+ # 1 / 0
344
+ # rescue => e
345
+ # Sentry.capture_exception(e) # new session recorded with :errored status
346
+ # end
347
+ # @return [void]
348
+ def with_session_tracking(&block)
349
+ return yield unless initialized?
350
+ get_current_hub.with_session_tracking(&block)
351
+ end
352
+
311
353
  # Takes an exception and reports it to Sentry via the currently active hub.
312
354
  #
313
355
  # @yieldparam scope [Scope]
@@ -350,6 +392,13 @@ module Sentry
350
392
  get_current_hub.last_event_id
351
393
  end
352
394
 
395
+ # Checks if the exception object has been captured by the SDK.
396
+ #
397
+ # @return [Boolean]
398
+ def exception_captured?(exc)
399
+ return false unless initialized?
400
+ !!exc.instance_variable_get(CAPTURED_SIGNATURE)
401
+ end
353
402
 
354
403
  ##### Helpers #####
355
404
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-ruby-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 5.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-10 00:00:00.000000000 Z
11
+ date: 2022-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -76,6 +76,8 @@ files:
76
76
  - lib/sentry/redis.rb
77
77
  - lib/sentry/release_detector.rb
78
78
  - lib/sentry/scope.rb
79
+ - lib/sentry/session.rb
80
+ - lib/sentry/session_flusher.rb
79
81
  - lib/sentry/span.rb
80
82
  - lib/sentry/transaction.rb
81
83
  - lib/sentry/transaction_event.rb