sentry-ruby-core 5.2.0 → 5.3.1

Sign up to get free protection for your applications and to get access to all the features.
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