sentry-ruby-core 5.2.0 → 5.3.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: c6a629d8aa998cef5638cd40e3dc9e0ad24770d0c31540b327c669e9fb84aedd
4
- data.tar.gz: e373b601b401fddca9307a32ea1dda36bc4994209c68b19748e89f128a598e80
3
+ metadata.gz: d28ef3b3cde342fa483586f73025f48b729b9ee09bd9835589ffa2d2d62717ff
4
+ data.tar.gz: 46eb28e37a955cfa60ed8ab517ab4398a89a310af7897d1543dd817e010f125e
5
5
  SHA512:
6
- metadata.gz: 2cfd2f1fe582578b74bc23610931d95bf7a86c35c696c658d55fb4f40ddfdd129c36bae415bc73efef20ecfb435f33ba72e3b46a96f536c0c61692d8c8cb34e2
7
- data.tar.gz: f10f71edc8bef7a57426de73e0cf2a1aea855c89ec2900a065986d33f064216f7da74c0cf9f7dd41c08dcb18224a61c6c43bad67548a327ca593b73b526e3d8a
6
+ metadata.gz: 693b0955dc1dacb5ea6c087e0ec2d331f51c995dd8b2adfa886fbe9b7af33c1f0a0248e750b02a85899808c34cab688cffacf6951c29e06b60336dcffc354777
7
+ data.tar.gz: 92b40e64205151ef7f6d530ae27fe179678824dd7f5f4cf567a8671385df076f24b1576df5e7edfb5921a230605cb447349724872f791b8b84eb6d13c050413c
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: "./"
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  <p align="center">
2
- <a href="https://sentry.io" target="_blank" align="center">
3
- <img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280">
2
+ <a href="https://sentry.io/?utm_source=github&utm_medium=logo" target="_blank">
3
+ <picture>
4
+ <source srcset="https://sentry-brand.storage.googleapis.com/sentry-logo-white.png" media="(prefers-color-scheme: dark)" />
5
+ <source srcset="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" />
6
+ <img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" alt="Sentry" width="280">
7
+ </picture>
4
8
  </a>
5
- <br />
6
9
  </p>
7
10
 
8
11
  _Bad software is everywhere, and we're tired of it. Sentry is on a mission to help developers write better software faster, so we can get back to enjoying technology. If you want to join us [<kbd>**Check out our open positions**</kbd>](https://sentry.io/careers/)_
@@ -29,7 +32,7 @@ If you're using `sentry-raven`, we recommend you to migrate to this new SDK. You
29
32
 
30
33
  ## Requirements
31
34
 
32
- We test on Ruby 2.4, 2.5, 2.6, 2.7, and 3.0 at the latest patchlevel/teeny version. We also support JRuby 9.0.
35
+ 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.
33
36
 
34
37
  If you use self-hosted Sentry, please also make sure its version is above `20.6.0`.
35
38
 
@@ -52,13 +55,11 @@ gem "sentry-resque"
52
55
 
53
56
  ### Configuration
54
57
 
55
- You can use `Sentry.init` to initialize and configure your SDK:
56
-
58
+ You need to use Sentry.init to initialize and configure your SDK:
57
59
  ```ruby
58
60
  Sentry.init do |config|
59
61
  config.dsn = "MY_DSN"
60
62
  end
61
-
62
63
  ```
63
64
 
64
65
  To learn more about available configuration options, please visit the [official documentation](https://docs.sentry.io/platforms/ruby/configuration/options/).
@@ -29,7 +29,7 @@ module Sentry
29
29
  log_debug("config.background_worker_threads is set to 0, all events will be sent synchronously")
30
30
  Concurrent::ImmediateExecutor.new
31
31
  else
32
- log_debug("initialized a background worker with #{@number_of_threads} threads")
32
+ log_debug("Initializing the background worker with #{@number_of_threads} threads")
33
33
 
34
34
  executor = Concurrent::ThreadPoolExecutor.new(
35
35
  min_threads: 0,
@@ -59,6 +59,7 @@ module Sentry
59
59
  end
60
60
 
61
61
  def shutdown
62
+ log_debug("Shutting down background worker")
62
63
  @shutdown_callback&.call
63
64
  end
64
65
 
data/lib/sentry/client.rb CHANGED
@@ -80,9 +80,10 @@ module Sentry
80
80
 
81
81
  integration_meta = Sentry.integrations[hint[:integration]]
82
82
 
83
- Event.new(configuration: configuration, integration_meta: integration_meta).tap do |event|
83
+ ErrorEvent.new(configuration: configuration, integration_meta: integration_meta).tap do |event|
84
84
  event.add_exception_interface(exception)
85
85
  event.add_threads_interface(crashed: true)
86
+ event.level = :error
86
87
  end
87
88
  end
88
89
 
@@ -94,8 +95,9 @@ module Sentry
94
95
  return unless @configuration.sending_allowed?
95
96
 
96
97
  integration_meta = Sentry.integrations[hint[:integration]]
97
- event = Event.new(configuration: configuration, integration_meta: integration_meta, message: message)
98
+ event = ErrorEvent.new(configuration: configuration, integration_meta: integration_meta, message: message)
98
99
  event.add_threads_interface(backtrace: backtrace || caller)
100
+ event.level = :error
99
101
  event
100
102
  end
101
103
 
@@ -133,7 +135,7 @@ module Sentry
133
135
 
134
136
  event
135
137
  rescue => e
136
- loggable_event_type = (event_type || "event").capitalize
138
+ loggable_event_type = event_type.capitalize
137
139
  log_error("#{loggable_event_type} sending failed", e, debug: configuration.debug)
138
140
 
139
141
  event_info = Event.get_log_message(event.to_hash)
@@ -174,8 +176,7 @@ module Sentry
174
176
  async_block.call(event_hash)
175
177
  end
176
178
  rescue => e
177
- loggable_event_type = event_hash["type"] || "event"
178
- log_error("Async #{loggable_event_type} sending failed", e, debug: configuration.debug)
179
+ log_error("Async #{event_hash["type"]} sending failed", e, debug: configuration.debug)
179
180
  send_event(event, hint)
180
181
  end
181
182
  end
@@ -290,6 +290,16 @@ module Sentry
290
290
  def async=(value)
291
291
  check_callable!("async", value)
292
292
 
293
+ log_warn <<~MSG
294
+
295
+ sentry-ruby now sends events asynchronously by default with its background worker (supported since 4.1.0).
296
+ The `config.async` callback has become redundant while continuing to cause issues.
297
+ (The problems of `async` are detailed in https://github.com/getsentry/sentry-ruby/issues/1522)
298
+
299
+ Therefore, we encourage you to remove it and let the background worker take care of async job sending.
300
+ It's deprecation is planned in the next major release (6.0), which is scheduled around the 3rd quarter of 2022.
301
+ MSG
302
+
293
303
  @async = value
294
304
  end
295
305
 
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ # ErrorEvent represents error or normal message events.
5
+ class ErrorEvent < Event
6
+ # @return [ExceptionInterface]
7
+ attr_reader :exception
8
+
9
+ # @return [ThreadsInterface]
10
+ attr_reader :threads
11
+
12
+ # @return [Hash]
13
+ def to_hash
14
+ data = super
15
+ data[:threads] = threads.to_hash if threads
16
+ data[:exception] = exception.to_hash if exception
17
+ data
18
+ end
19
+
20
+ # @!visibility private
21
+ def add_threads_interface(backtrace: nil, **options)
22
+ @threads = ThreadsInterface.build(
23
+ backtrace: backtrace,
24
+ stacktrace_builder: @stacktrace_builder,
25
+ **options
26
+ )
27
+ end
28
+
29
+ # @!visibility private
30
+ def add_exception_interface(exception)
31
+ if exception.respond_to?(:sentry_context)
32
+ @extra.merge!(exception.sentry_context)
33
+ end
34
+
35
+ @exception = Sentry::ExceptionInterface.build(exception: exception, stacktrace_builder: @stacktrace_builder)
36
+ end
37
+ end
38
+ end
data/lib/sentry/event.rb CHANGED
@@ -9,7 +9,10 @@ require 'sentry/utils/request_id'
9
9
  require 'sentry/utils/custom_inspection'
10
10
 
11
11
  module Sentry
12
+ # This is an abstract class that defines the shared attributes of an event.
13
+ # Please don't use it directly. The user-facing classes are its child classes.
12
14
  class Event
15
+ TYPE = "event"
13
16
  # These are readable attributes.
14
17
  SERIALIZEABLE_ATTRIBUTES = %i(
15
18
  event_id level timestamp
@@ -35,12 +38,6 @@ module Sentry
35
38
  # @return [RequestInterface]
36
39
  attr_reader :request
37
40
 
38
- # @return [ExceptionInterface]
39
- attr_reader :exception
40
-
41
- # @return [ThreadsInterface]
42
- attr_reader :threads
43
-
44
41
  # @param configuration [Configuration]
45
42
  # @param integration_meta [Hash, nil]
46
43
  # @param message [String, nil]
@@ -49,6 +46,7 @@ module Sentry
49
46
  @event_id = SecureRandom.uuid.delete("-")
50
47
  @timestamp = Sentry.utc_now.iso8601
51
48
  @platform = :ruby
49
+ @type = self.class::TYPE
52
50
  @sdk = integration_meta || Sentry.sdk_meta
53
51
 
54
52
  @user = {}
@@ -71,8 +69,6 @@ module Sentry
71
69
  @rack_env_whitelist = configuration.rack_env_whitelist
72
70
 
73
71
  @message = (message || "").byteslice(0..MAX_MESSAGE_SIZE_IN_BYTES)
74
-
75
- self.level = :error
76
72
  end
77
73
 
78
74
  class << self
@@ -146,9 +142,6 @@ module Sentry
146
142
  data = serialize_attributes
147
143
  data[:breadcrumbs] = breadcrumbs.to_hash if breadcrumbs
148
144
  data[:request] = request.to_hash if request
149
- data[:exception] = exception.to_hash if exception
150
- data[:threads] = threads.to_hash if threads
151
-
152
145
  data
153
146
  end
154
147
 
@@ -157,24 +150,6 @@ module Sentry
157
150
  JSON.parse(JSON.generate(to_hash))
158
151
  end
159
152
 
160
- # @!visibility private
161
- def add_threads_interface(backtrace: nil, **options)
162
- @threads = ThreadsInterface.build(
163
- backtrace: backtrace,
164
- stacktrace_builder: @stacktrace_builder,
165
- **options
166
- )
167
- end
168
-
169
- # @!visibility private
170
- def add_exception_interface(exception)
171
- if exception.respond_to?(:sentry_context)
172
- @extra.merge!(exception.sentry_context)
173
- end
174
-
175
- @exception = Sentry::ExceptionInterface.build(exception: exception, stacktrace_builder: @stacktrace_builder)
176
- end
177
-
178
153
  private
179
154
 
180
155
  def add_request_interface(env)
data/lib/sentry/hub.rb CHANGED
@@ -150,7 +150,7 @@ module Sentry
150
150
  configuration.log_debug(event.to_json_compatible)
151
151
  end
152
152
 
153
- @last_event_id = event&.event_id
153
+ @last_event_id = event&.event_id unless event.is_a?(Sentry::TransactionEvent)
154
154
  event
155
155
  end
156
156
 
@@ -74,11 +74,11 @@ module Sentry
74
74
  end
75
75
 
76
76
  def start_sentry_span
77
- return unless Sentry.initialized? && transaction = Sentry.get_current_scope.get_transaction
77
+ return unless Sentry.initialized? && span = Sentry.get_current_scope.get_span
78
78
  return if from_sentry_sdk?
79
- return if transaction.sampled == false
79
+ return if span.sampled == false
80
80
 
81
- transaction.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
81
+ span.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
82
82
  end
83
83
 
84
84
  def finish_sentry_span(sentry_span)
@@ -39,6 +39,7 @@ module Sentry
39
39
  end
40
40
 
41
41
  def kill
42
+ log_debug("Killing session flusher")
42
43
  @thread&.kill
43
44
  end
44
45
 
@@ -1,31 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
+ # TransactionEvent represents events that carry transaction data (type: "transaction").
4
5
  class TransactionEvent < Event
5
6
  TYPE = "transaction"
6
7
 
7
- SERIALIZEABLE_ATTRIBUTES = %i(
8
- event_id level timestamp start_timestamp
9
- release environment server_name modules
10
- user tags contexts extra
11
- transaction platform sdk type
12
- )
13
-
14
- WRITER_ATTRIBUTES = SERIALIZEABLE_ATTRIBUTES - %i(type timestamp start_timestamp level)
15
-
16
- attr_writer(*WRITER_ATTRIBUTES)
17
- attr_reader(*SERIALIZEABLE_ATTRIBUTES)
18
-
19
8
  # @return [<Array[Span]>]
20
9
  attr_accessor :spans
21
10
 
22
- # @param configuration [Configuration]
23
- # @param integration_meta [Hash, nil]
24
- # @param message [String, nil]
25
- def initialize(configuration:, integration_meta: nil, message: nil)
26
- super
27
- @type = TYPE
28
- end
11
+ # @return [Float, nil]
12
+ attr_reader :start_timestamp
29
13
 
30
14
  # Sets the event's start_timestamp.
31
15
  # @param time [Time, Float]
@@ -38,6 +22,7 @@ module Sentry
38
22
  def to_hash
39
23
  data = super
40
24
  data[:spans] = @spans.map(&:to_hash) if @spans
25
+ data[:start_timestamp] = @start_timestamp
41
26
  data
42
27
  end
43
28
  end
@@ -130,7 +130,7 @@ module Sentry
130
130
  server = URI(@dsn.server)
131
131
 
132
132
  connection =
133
- if proxy = @transport_configuration.proxy
133
+ if proxy = normalize_proxy(@transport_configuration.proxy)
134
134
  ::Net::HTTP.new(server.hostname, server.port, proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
135
135
  else
136
136
  ::Net::HTTP.new(server.hostname, server.port, nil)
@@ -148,6 +148,20 @@ module Sentry
148
148
  connection
149
149
  end
150
150
 
151
+ def normalize_proxy(proxy)
152
+ return proxy unless proxy
153
+
154
+ case proxy
155
+ when String
156
+ uri = URI(proxy)
157
+ { uri: uri, user: uri.user, password: uri.password }
158
+ when URI
159
+ { uri: proxy, user: proxy.user, password: proxy.password }
160
+ when Hash
161
+ proxy
162
+ end
163
+ end
164
+
151
165
  def ssl_configuration
152
166
  configuration = {
153
167
  verify: @transport_configuration.ssl_verification,
@@ -73,7 +73,12 @@ module Sentry
73
73
  result = item.to_s
74
74
 
75
75
  if result.bytesize > Event::MAX_SERIALIZED_PAYLOAD_SIZE
76
- item.payload.delete(:breadcrumbs)
76
+ if item.payload.key?(:breadcrumbs)
77
+ item.payload.delete(:breadcrumbs)
78
+ elsif item.payload.key?("breadcrumbs")
79
+ item.payload.delete("breadcrumbs")
80
+ end
81
+
77
82
  result = item.to_s
78
83
  end
79
84
 
@@ -143,7 +148,7 @@ module Sentry
143
148
  # Convert to hash
144
149
  event_payload = event.to_hash
145
150
  event_id = event_payload[:event_id] || event_payload["event_id"]
146
- item_type = get_item_type(event_payload)
151
+ item_type = event_payload[:type] || event_payload["type"]
147
152
 
148
153
  envelope = Envelope.new(
149
154
  {
@@ -169,16 +174,11 @@ module Sentry
169
174
  return unless @send_client_reports
170
175
  return unless CLIENT_REPORT_REASONS.include?(reason)
171
176
 
172
- item_type ||= 'event'
173
177
  @discarded_events[[reason, item_type]] += 1
174
178
  end
175
179
 
176
180
  private
177
181
 
178
- def get_item_type(event_hash)
179
- event_hash[:type] || event_hash["type"] || "event"
180
- end
181
-
182
182
  def fetch_pending_client_report
183
183
  return nil unless @send_client_reports
184
184
  return nil if @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- VERSION = "5.2.0"
4
+ VERSION = "5.3.1"
5
5
  end
data/lib/sentry-ruby.rb CHANGED
@@ -12,6 +12,7 @@ require "sentry/utils/logging_helper"
12
12
  require "sentry/configuration"
13
13
  require "sentry/logger"
14
14
  require "sentry/event"
15
+ require "sentry/error_event"
15
16
  require "sentry/transaction_event"
16
17
  require "sentry/span"
17
18
  require "sentry/transaction"
@@ -99,6 +100,14 @@ module Sentry
99
100
  # @param name [String] name of the integration
100
101
  # @param version [String] version of the integration
101
102
  def register_integration(name, version)
103
+ if initialized?
104
+ logger.warn(LOGGER_PROGNAME) do
105
+ <<~MSG
106
+ Integration '#{name}' is loaded after the SDK is initialized, which can cause unexpected behavior. Please make sure all integrations are loaded before SDK initialization.
107
+ MSG
108
+ end
109
+ end
110
+
102
111
  meta = { name: "sentry.ruby.#{name}", version: version }.freeze
103
112
  integrations[name.to_s] = meta
104
113
  end
@@ -376,6 +385,38 @@ module Sentry
376
385
  get_current_hub.start_transaction(**options)
377
386
  end
378
387
 
388
+ # Records the block's execution as a child of the current span.
389
+ # If the current scope doesn't have a span, the block would still be executed but the yield param will be nil.
390
+ # @param attributes [Hash] attributes for the child span.
391
+ # @yieldparam child_span [Span, nil]
392
+ # @return yield result
393
+ #
394
+ # @example
395
+ # Sentry.with_child_span(op: "my operation") do |child_span|
396
+ # child_span.set_data(operation_data)
397
+ # child_span.set_description(operation_detail)
398
+ # # result will be returned
399
+ # end
400
+ #
401
+ def with_child_span(**attributes, &block)
402
+ if Sentry.initialized? && current_span = get_current_scope.get_span
403
+ result = nil
404
+
405
+ begin
406
+ current_span.with_child_span(**attributes) do |child_span|
407
+ get_current_scope.set_span(child_span)
408
+ result = yield(child_span)
409
+ end
410
+ ensure
411
+ get_current_scope.set_span(current_span)
412
+ end
413
+
414
+ result
415
+ else
416
+ yield(nil)
417
+ end
418
+ end
419
+
379
420
  # Returns the id of the lastly reported Sentry::Event.
380
421
  #
381
422
  # @return [String, nil]
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.2.0
4
+ version: 5.3.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-03-08 00:00:00.000000000 Z
11
+ date: 2022-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -56,6 +56,7 @@ files:
56
56
  - lib/sentry/core_ext/object/duplicable.rb
57
57
  - lib/sentry/dsn.rb
58
58
  - lib/sentry/envelope.rb
59
+ - lib/sentry/error_event.rb
59
60
  - lib/sentry/event.rb
60
61
  - lib/sentry/exceptions.rb
61
62
  - lib/sentry/hub.rb