sentry-ruby-core 4.8.0 → 4.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/Gemfile +2 -0
  4. data/lib/sentry/background_worker.rb +30 -2
  5. data/lib/sentry/backtrace.rb +1 -0
  6. data/lib/sentry/breadcrumb/sentry_logger.rb +2 -0
  7. data/lib/sentry/breadcrumb.rb +2 -0
  8. data/lib/sentry/breadcrumb_buffer.rb +2 -0
  9. data/lib/sentry/client.rb +2 -0
  10. data/lib/sentry/configuration.rb +85 -39
  11. data/lib/sentry/core_ext/object/deep_dup.rb +2 -0
  12. data/lib/sentry/core_ext/object/duplicable.rb +1 -0
  13. data/lib/sentry/dsn.rb +2 -0
  14. data/lib/sentry/envelope.rb +26 -0
  15. data/lib/sentry/exceptions.rb +2 -0
  16. data/lib/sentry/hub.rb +2 -0
  17. data/lib/sentry/integrable.rb +2 -0
  18. data/lib/sentry/interface.rb +2 -0
  19. data/lib/sentry/interfaces/exception.rb +2 -0
  20. data/lib/sentry/interfaces/single_exception.rb +2 -0
  21. data/lib/sentry/interfaces/stacktrace.rb +2 -0
  22. data/lib/sentry/interfaces/stacktrace_builder.rb +2 -0
  23. data/lib/sentry/interfaces/threads.rb +2 -0
  24. data/lib/sentry/linecache.rb +3 -0
  25. data/lib/sentry/net/http.rb +3 -0
  26. data/lib/sentry/rack/capture_exceptions.rb +2 -0
  27. data/lib/sentry/rack.rb +2 -0
  28. data/lib/sentry/rake.rb +16 -6
  29. data/lib/sentry/release_detector.rb +3 -0
  30. data/lib/sentry/scope.rb +8 -4
  31. data/lib/sentry/span.rb +1 -0
  32. data/lib/sentry/transaction.rb +2 -0
  33. data/lib/sentry/transport/configuration.rb +2 -0
  34. data/lib/sentry/transport/dummy_transport.rb +2 -0
  35. data/lib/sentry/transport/http_transport.rb +6 -4
  36. data/lib/sentry/transport.rb +19 -24
  37. data/lib/sentry/utils/argument_checking_helper.rb +2 -0
  38. data/lib/sentry/utils/custom_inspection.rb +2 -0
  39. data/lib/sentry/utils/exception_cause_chain.rb +2 -0
  40. data/lib/sentry/utils/logging_helper.rb +2 -0
  41. data/lib/sentry/utils/real_ip.rb +2 -0
  42. data/lib/sentry/utils/request_id.rb +2 -0
  43. data/lib/sentry/version.rb +3 -1
  44. data/lib/sentry-ruby.rb +82 -28
  45. data/sentry-ruby.gemspec +1 -1
  46. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f675111daf93ba05db7de62dcfa1dd9268f6ba009265de08e0e4f118ffea0c62
4
- data.tar.gz: 2ece2ccaf14be6cc5fa762b77a57cd63dcc3fe52a03987c8c4136a43ec62bbd1
3
+ metadata.gz: '09a04a594b731f8d13770650138f1abd5bce410dad2f4cb4da1a2caa5ef7eba2'
4
+ data.tar.gz: e87cac23635525aa1b53772e262706a10948b52b634fafeedaf241c8b6d90c9a
5
5
  SHA512:
6
- metadata.gz: d5d9405c41879a40ba0c0205fa08e38fa5b3ed243276181239be63f0baa0b739b37ac91ecb86abd76768c4c5a706f1f7b7e47d7eadd357f2116ec2ec9bd913d5
7
- data.tar.gz: abb46869f2eba00f053096e5568829815b02520db31fe9c98bbfabea40b5dcbe6d438ca97287ca7f9b4fee9a4710b49dec73b9196a3650d3a811184a960a09a7
6
+ metadata.gz: db6311ce62c548e835cbc49c7616ac244d853c3206599e1b540035b16da97bf05cd52a81602cf30215f15ee3e675d6857cdba628f87fc631e73d63d9523081d5
7
+ data.tar.gz: ae31de8f2bab17f15f16c8e6fea3fbbc359efc39c5f2ec5afba9fbfccbd4e77c22f051cd2b94278ff9c3ce92289448cccf1af8fc5df5da1fd7f25bb81458ae29
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --exclude lib/sentry/utils/
2
+ --exclude lib/sentry/core_ext
data/Gemfile CHANGED
@@ -22,3 +22,5 @@ gem "benchmark-ips"
22
22
  gem "benchmark_driver"
23
23
  gem "benchmark-ipsa"
24
24
  gem "benchmark-memory"
25
+
26
+ gem "yard", "~> 0.9.27"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "concurrent/executor/thread_pool_executor"
2
4
  require "concurrent/executor/immediate_executor"
3
5
  require "concurrent/configuration"
@@ -7,11 +9,15 @@ module Sentry
7
9
  include LoggingHelper
8
10
 
9
11
  attr_reader :max_queue, :number_of_threads, :logger
12
+ attr_accessor :shutdown_timeout
10
13
 
11
14
  def initialize(configuration)
12
15
  @max_queue = 30
16
+ @shutdown_timeout = 1
13
17
  @number_of_threads = configuration.background_worker_threads
14
18
  @logger = configuration.logger
19
+ @debug = configuration.debug
20
+ @shutdown_callback = nil
15
21
 
16
22
  @executor =
17
23
  if configuration.async
@@ -23,19 +29,41 @@ module Sentry
23
29
  else
24
30
  log_debug("initialized a background worker with #{@number_of_threads} threads")
25
31
 
26
- Concurrent::ThreadPoolExecutor.new(
32
+ executor = Concurrent::ThreadPoolExecutor.new(
27
33
  min_threads: 0,
28
34
  max_threads: @number_of_threads,
29
35
  max_queue: @max_queue,
30
36
  fallback_policy: :discard
31
37
  )
38
+
39
+ @shutdown_callback = proc do
40
+ executor.shutdown
41
+ executor.wait_for_termination(@shutdown_timeout)
42
+ end
43
+
44
+ executor
32
45
  end
33
46
  end
34
47
 
48
+ # if you want to monkey-patch this method, please override `_perform` instead
35
49
  def perform(&block)
36
50
  @executor.post do
37
- block.call
51
+ begin
52
+ _perform(&block)
53
+ rescue Exception => e
54
+ log_error("exception happened in background worker", e, debug: @debug)
55
+ end
38
56
  end
39
57
  end
58
+
59
+ def shutdown
60
+ @shutdown_callback&.call
61
+ end
62
+
63
+ private
64
+
65
+ def _perform(&block)
66
+ block.call
67
+ end
40
68
  end
41
69
  end
@@ -4,6 +4,7 @@
4
4
 
5
5
  module Sentry
6
6
  # Front end to parsing the backtrace for each notice
7
+ # @api private
7
8
  class Backtrace
8
9
  # Handles backtrace parsing line by line
9
10
  class Line
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
 
3
5
  module Sentry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class Breadcrumb
3
5
  DATA_SERIALIZATION_ERROR_MESSAGE = "[data were removed due to serialization issues]"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "sentry/breadcrumb"
2
4
 
3
5
  module Sentry
data/lib/sentry/client.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "sentry/transport"
2
4
 
3
5
  module Sentry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "concurrent/utility/processor_counter"
2
4
 
3
5
  require "sentry/utils/exception_cause_chain"
@@ -15,10 +17,15 @@ module Sentry
15
17
  # Directories to be recognized as part of your app. e.g. if you
16
18
  # have an `engines` dir at the root of your project, you may want
17
19
  # to set this to something like /(app|config|engines|lib)/
20
+ #
21
+ # @return [Regexp, nil]
18
22
  attr_accessor :app_dirs_pattern
19
23
 
20
24
  # Provide an object that responds to `call` to send events asynchronously.
21
25
  # E.g.: lambda { |event| Thread.new { Sentry.send_event(event) } }
26
+ #
27
+ # @deprecated It will be removed in the next major release. Please read https://github.com/getsentry/sentry-ruby/issues/1522 for more information
28
+ # @return [Proc, nil]
22
29
  attr_reader :async
23
30
 
24
31
  # to send events in a non-blocking way, sentry-ruby has its own background worker
@@ -28,74 +35,94 @@ module Sentry
28
35
  #
29
36
  # if you want to send events synchronously, set the value to 0
30
37
  # E.g.: config.background_worker_threads = 0
38
+ # @return [Integer]
31
39
  attr_accessor :background_worker_threads
32
40
 
33
41
  # a proc/lambda that takes an array of stack traces
34
42
  # it'll be used to silence (reduce) backtrace of the exception
35
43
  #
36
- # for example:
37
- #
38
- # ```ruby
39
- # Sentry.configuration.backtrace_cleanup_callback = lambda do |backtrace|
40
- # Rails.backtrace_cleaner.clean(backtrace)
41
- # end
42
- # ```
44
+ # @example
45
+ # config.backtrace_cleanup_callback = lambda do |backtrace|
46
+ # Rails.backtrace_cleaner.clean(backtrace)
47
+ # end
43
48
  #
49
+ # @return [Proc]
44
50
  attr_accessor :backtrace_cleanup_callback
45
51
 
46
52
  # Optional Proc, called before adding the breadcrumb to the current scope
47
- # E.g.: lambda { |breadcrumb, hint| breadcrumb }
48
- # E.g.: lambda { |breadcrumb, hint| nil }
49
- # E.g.: lambda { |breadcrumb, hint|
50
- # breadcrumb.message = 'a'
51
- # breadcrumb
52
- # }
53
+ # @example
54
+ # config.before = lambda do |breadcrumb, hint|
55
+ # breadcrumb.message = 'a'
56
+ # breadcrumb
57
+ # end
58
+ # @return [Proc]
53
59
  attr_reader :before_breadcrumb
54
60
 
55
- # Optional Proc, called before sending an event to the server/
56
- # E.g.: lambda { |event, hint| event }
57
- # E.g.: lambda { |event, hint| nil }
58
- # E.g.: lambda { |event, hint|
59
- # event[:message] = 'a'
60
- # event
61
- # }
61
+ # Optional Proc, called before sending an event to the server
62
+ # @example
63
+ # config.before_send = lambda do |event, hint|
64
+ # # skip ZeroDivisionError exceptions
65
+ # # note: hint[:exception] would be a String if you use async callback
66
+ # if hint[:exception].is_a?(ZeroDivisionError)
67
+ # nil
68
+ # else
69
+ # event
70
+ # end
71
+ # end
72
+ # @return [Proc]
62
73
  attr_reader :before_send
63
74
 
64
75
  # An array of breadcrumbs loggers to be used. Available options are:
65
76
  # - :sentry_logger
77
+ # - :http_logger
78
+ #
79
+ # And if you also use sentry-rails:
66
80
  # - :active_support_logger
81
+ # - :monotonic_active_support_logger
82
+ #
83
+ # @return [Array<Symbol>]
67
84
  attr_reader :breadcrumbs_logger
68
85
 
69
86
  # Whether to capture local variables from the raised exception's frame. Default is false.
87
+ # @return [Boolean]
70
88
  attr_accessor :capture_exception_frame_locals
71
89
 
72
90
  # Max number of breadcrumbs a breadcrumb buffer can hold
91
+ # @return [Integer]
73
92
  attr_accessor :max_breadcrumbs
74
93
 
75
94
  # Number of lines of code context to capture, or nil for none
95
+ # @return [Integer, nil]
76
96
  attr_accessor :context_lines
77
97
 
78
98
  # RACK_ENV by default.
99
+ # @return [String]
79
100
  attr_reader :environment
80
101
 
81
102
  # Whether the SDK should run in the debugging mode. Default is false.
82
103
  # If set to true, SDK errors will be logged with backtrace
104
+ # @return [Boolean]
83
105
  attr_accessor :debug
84
106
 
85
107
  # the dsn value, whether it's set via `config.dsn=` or `ENV["SENTRY_DSN"]`
108
+ # @return [String]
86
109
  attr_reader :dsn
87
110
 
88
111
  # Whitelist of enabled_environments that will send notifications to Sentry. Array of Strings.
112
+ # @return [Array<String>]
89
113
  attr_accessor :enabled_environments
90
114
 
91
115
  # Logger 'progname's to exclude from breadcrumbs
116
+ # @return [Array<String>]
92
117
  attr_accessor :exclude_loggers
93
118
 
94
119
  # Array of exception classes that should never be sent. See IGNORE_DEFAULT.
95
120
  # You should probably append to this rather than overwrite it.
121
+ # @return [Array<String>]
96
122
  attr_accessor :excluded_exceptions
97
123
 
98
124
  # Boolean to check nested exceptions when deciding if to exclude. Defaults to true
125
+ # @return [Boolean]
99
126
  attr_accessor :inspect_exception_causes_for_exclusion
100
127
  alias inspect_exception_causes_for_exclusion? inspect_exception_causes_for_exclusion
101
128
 
@@ -106,65 +133,80 @@ module Sentry
106
133
 
107
134
  # Logger used by Sentry. In Rails, this is the Rails logger, otherwise
108
135
  # Sentry provides its own Sentry::Logger.
136
+ # @return [Logger]
109
137
  attr_accessor :logger
110
138
 
111
139
  # Project directory root for in_app detection. Could be Rails root, etc.
112
140
  # Set automatically for Rails.
141
+ # @return [String]
113
142
  attr_accessor :project_root
114
143
 
115
144
  # Insert sentry-trace to outgoing requests' headers
145
+ # @return [Boolean]
116
146
  attr_accessor :propagate_traces
117
147
 
118
148
  # Array of rack env parameters to be included in the event sent to sentry.
149
+ # @return [Array<String>]
119
150
  attr_accessor :rack_env_whitelist
120
151
 
121
152
  # Release tag to be passed with every event sent to Sentry.
122
153
  # We automatically try to set this to a git SHA or Capistrano release.
154
+ # @return [String]
123
155
  attr_accessor :release
124
156
 
125
157
  # The sampling factor to apply to events. A value of 0.0 will not send
126
158
  # any events, and a value of 1.0 will send 100% of events.
159
+ # @return [Float]
127
160
  attr_accessor :sample_rate
128
161
 
129
162
  # Include module versions in reports - boolean.
163
+ # @return [Boolean]
130
164
  attr_accessor :send_modules
131
165
 
132
166
  # When send_default_pii's value is false (default), sensitive information like
133
167
  # - user ip
134
168
  # - user cookie
135
169
  # - request body
170
+ # - query string
136
171
  # will not be sent to Sentry.
172
+ # @return [Boolean]
137
173
  attr_accessor :send_default_pii
138
174
 
139
175
  # Allow to skip Sentry emails within rake tasks
176
+ # @return [Boolean]
140
177
  attr_accessor :skip_rake_integration
141
178
 
142
179
  # IP ranges for trusted proxies that will be skipped when calculating IP address.
143
180
  attr_accessor :trusted_proxies
144
181
 
182
+ # @return [String]
145
183
  attr_accessor :server_name
146
184
 
147
185
  # Return a Transport::Configuration object for transport-related configurations.
186
+ # @return [Transport]
148
187
  attr_reader :transport
149
188
 
150
189
  # Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
190
+ # @return [Float]
151
191
  attr_accessor :traces_sample_rate
152
192
 
153
193
  # Take a Proc that controls the sample rate for every tracing event, e.g.
154
- # ```
155
- # lambda do |tracing_context|
156
- # # tracing_context[:transaction_context] contains the information about the transaction
157
- # # tracing_context[:parent_sampled] contains the transaction's parent's sample decision
158
- # true # return value can be a boolean or a float between 0.0 and 1.0
159
- # end
160
- # ```
194
+ # @example
195
+ # config.traces_sampler = lambda do |tracing_context|
196
+ # # tracing_context[:transaction_context] contains the information about the transaction
197
+ # # tracing_context[:parent_sampled] contains the transaction's parent's sample decision
198
+ # true # return value can be a boolean or a float between 0.0 and 1.0
199
+ # end
200
+ # @return [Proc]
161
201
  attr_accessor :traces_sampler
162
202
 
163
203
  # Send diagnostic client reports about dropped events, true by default
164
204
  # tries to attach to an existing envelope max once every 30s
205
+ # @return [Boolean]
165
206
  attr_accessor :send_client_reports
166
207
 
167
208
  # these are not config options
209
+ # @!visibility private
168
210
  attr_reader :errors, :gem_specs
169
211
 
170
212
  # Most of these errors generate 4XX responses. In general, Sentry clients
@@ -285,11 +327,6 @@ module Sentry
285
327
  Random.rand < sample_rate
286
328
  end
287
329
 
288
- def error_messages
289
- @errors = [@errors[0]] + @errors[1..-1].map(&:downcase) # fix case of all but first
290
- @errors.join(", ")
291
- end
292
-
293
330
  def exception_class_allowed?(exc)
294
331
  if exc.is_a?(Sentry::Error)
295
332
  # Try to prevent error reporting loops
@@ -311,6 +348,17 @@ module Sentry
311
348
  !!((@traces_sample_rate && @traces_sample_rate >= 0.0 && @traces_sample_rate <= 1.0) || @traces_sampler) && sending_allowed?
312
349
  end
313
350
 
351
+ # @return [String, nil]
352
+ def csp_report_uri
353
+ if dsn && dsn.valid?
354
+ uri = dsn.csp_report_uri
355
+ uri += "&sentry_release=#{CGI.escape(release)}" if release && !release.empty?
356
+ uri += "&sentry_environment=#{CGI.escape(environment)}" if environment && !environment.empty?
357
+ uri
358
+ end
359
+ end
360
+
361
+ # @api private
314
362
  def stacktrace_builder
315
363
  @stacktrace_builder ||= StacktraceBuilder.new(
316
364
  project_root: @project_root.to_s,
@@ -321,6 +369,7 @@ module Sentry
321
369
  )
322
370
  end
323
371
 
372
+ # @api private
324
373
  def detect_release
325
374
  return unless sending_allowed?
326
375
 
@@ -333,13 +382,10 @@ module Sentry
333
382
  log_error("Error detecting release", e, debug: debug)
334
383
  end
335
384
 
336
- def csp_report_uri
337
- if dsn && dsn.valid?
338
- uri = dsn.csp_report_uri
339
- uri += "&sentry_release=#{CGI.escape(release)}" if release && !release.empty?
340
- uri += "&sentry_environment=#{CGI.escape(environment)}" if environment && !environment.empty?
341
- uri
342
- end
385
+ # @api private
386
+ def error_messages
387
+ @errors = [@errors[0]] + @errors[1..-1].map(&:downcase) # fix case of all but first
388
+ @errors.join(", ")
343
389
  end
344
390
 
345
391
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  return if Object.method_defined?(:deep_dup)
2
4
 
3
5
  require 'sentry/core_ext/object/duplicable'
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  return if Object.method_defined?(:duplicable?)
3
4
 
4
5
  #########################################
data/lib/sentry/dsn.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "uri"
2
4
 
3
5
  module Sentry
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ # @api private
5
+ class Envelope
6
+ def initialize(headers)
7
+ @headers = headers
8
+ @items = []
9
+ end
10
+
11
+ def add_item(headers, payload)
12
+ @items << [headers, payload]
13
+ end
14
+
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")
22
+
23
+ "#{JSON.generate(@headers)}\n#{payload}"
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class Error < StandardError
3
5
  end
data/lib/sentry/hub.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "sentry/scope"
2
4
  require "sentry/client"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  module Integrable
3
5
  def register_integration(name:, version:)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class Interface
3
5
  def self.inherited(klass)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class ExceptionInterface < Interface
3
5
  def initialize(values:)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "sentry/utils/exception_cause_chain"
2
4
 
3
5
  module Sentry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class StacktraceInterface
3
5
  attr_reader :frames
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class StacktraceBuilder
3
5
  attr_reader :project_root, :app_dirs_pattern, :linecache, :context_lines, :backtrace_cleanup_callback
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class ThreadsInterface
3
5
  def initialize(crashed: false, stacktrace: nil)
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
4
+ # @api private
2
5
  class LineCache
3
6
  def initialize
4
7
  @cache = {}
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "net/http"
2
4
 
3
5
  module Sentry
6
+ # @api private
4
7
  module Net
5
8
  module HTTP
6
9
  OP_NAME = "net.http"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  module Rack
3
5
  class CaptureExceptions
data/lib/sentry/rack.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack'
2
4
 
3
5
  require 'sentry/rack/capture_exceptions'
data/lib/sentry/rake.rb CHANGED
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rake"
2
4
  require "rake/task"
3
5
 
4
6
  module Sentry
5
7
  module Rake
6
8
  module Application
9
+ # @api private
7
10
  def display_error_message(ex)
8
- Sentry.capture_exception(ex, hint: { background: false }) do |scope|
11
+ Sentry.capture_exception(ex) do |scope|
9
12
  task_name = top_level_tasks.join(' ')
10
13
  scope.set_transaction_name(task_name)
11
14
  scope.set_tag("rake_task", task_name)
@@ -16,16 +19,23 @@ module Sentry
16
19
  end
17
20
 
18
21
  module Task
22
+ # @api private
19
23
  def execute(args=nil)
20
24
  return super unless Sentry.initialized? && Sentry.get_current_hub
21
25
 
22
- Sentry.get_current_hub.with_background_worker_disabled do
23
- super
24
- end
26
+ super
25
27
  end
26
28
  end
27
29
  end
28
30
  end
29
31
 
30
- Rake::Application.prepend(Sentry::Rake::Application)
31
- Rake::Task.prepend(Sentry::Rake::Task)
32
+ # @api private
33
+ module Rake
34
+ class Application
35
+ prepend(Sentry::Rake::Application)
36
+ end
37
+
38
+ class Task
39
+ prepend(Sentry::Rake::Task)
40
+ end
41
+ end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
4
+ # @api private
2
5
  class ReleaseDetector
3
6
  class << self
4
7
  def detect_release(project_root:, running_on_heroku:)
data/lib/sentry/scope.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "sentry/breadcrumb_buffer"
2
4
  require "etc"
3
5
 
@@ -112,7 +114,7 @@ module Sentry
112
114
  end
113
115
 
114
116
  def set_extra(key, value)
115
- @extra.merge!(key => value)
117
+ set_extras(key => value)
116
118
  end
117
119
 
118
120
  def set_tags(tags_hash)
@@ -121,17 +123,19 @@ module Sentry
121
123
  end
122
124
 
123
125
  def set_tag(key, value)
124
- @tags.merge!(key => value)
126
+ set_tags(key => value)
125
127
  end
126
128
 
127
129
  def set_contexts(contexts_hash)
128
130
  check_argument_type!(contexts_hash, Hash)
129
- @contexts.merge!(contexts_hash)
131
+ @contexts.merge!(contexts_hash) do |key, old, new|
132
+ new.merge(old)
133
+ end
130
134
  end
131
135
 
132
136
  def set_context(key, value)
133
137
  check_argument_type!(value, Hash)
134
- @contexts.merge!(key => value)
138
+ set_contexts(key => value)
135
139
  end
136
140
 
137
141
  def set_level(level)
data/lib/sentry/span.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "securerandom"
3
4
 
4
5
  module Sentry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class Transaction < Span
3
5
  SENTRY_TRACE_REGEXP = Regexp.new(
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class Transport
3
5
  class Configuration
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  class DummyTransport < Transport
3
5
  attr_accessor :events
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'zlib'
3
5
 
@@ -139,10 +141,10 @@ module Sentry
139
141
  end
140
142
 
141
143
  def ssl_configuration
142
- (@transport_configuration.ssl || {}).merge(
143
- :verify => @transport_configuration.ssl_verification,
144
- :ca_file => @transport_configuration.ssl_ca_file
145
- )
144
+ {
145
+ verify: @transport_configuration.ssl_verification,
146
+ ca_file: @transport_configuration.ssl_ca_file
147
+ }.merge(@transport_configuration.ssl || {})
146
148
  end
147
149
  end
148
150
  end
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
  require "base64"
5
+ require "sentry/envelope"
3
6
 
4
7
  module Sentry
5
8
  class Transport
@@ -103,31 +106,29 @@ module Sentry
103
106
  def encode(event)
104
107
  # Convert to hash
105
108
  event_payload = event.to_hash
106
-
107
109
  event_id = event_payload[:event_id] || event_payload["event_id"]
108
110
  item_type = get_item_type(event_payload)
109
111
 
110
- envelope_header = {
111
- event_id: event_id,
112
- dsn: @dsn.to_s,
113
- sdk: Sentry.sdk_meta,
114
- sent_at: Sentry.utc_now.iso8601
115
- }
116
-
117
- event_header = { type: item_type, content_type: 'application/json' }
112
+ envelope = Envelope.new(
113
+ {
114
+ event_id: event_id,
115
+ dsn: @dsn.to_s,
116
+ sdk: Sentry.sdk_meta,
117
+ sent_at: Sentry.utc_now.iso8601
118
+ }
119
+ )
118
120
 
119
- envelope = <<~ENVELOPE
120
- #{JSON.generate(envelope_header)}
121
- #{JSON.generate(event_header)}
122
- #{JSON.generate(event_payload)}
123
- ENVELOPE
121
+ envelope.add_item(
122
+ { type: item_type, content_type: 'application/json' },
123
+ event_payload
124
+ )
124
125
 
125
- client_report = fetch_pending_client_report
126
- envelope << client_report if client_report
126
+ client_report_headers, client_report_payload = fetch_pending_client_report
127
+ envelope.add_item(client_report_headers, client_report_payload) if client_report_headers
127
128
 
128
129
  log_info("Sending envelope [#{item_type}] #{event_id} to Sentry")
129
130
 
130
- envelope
131
+ envelope.to_s
131
132
  end
132
133
 
133
134
  def record_lost_event(reason, item_type)
@@ -159,21 +160,15 @@ module Sentry
159
160
  end
160
161
 
161
162
  item_header = { type: 'client_report' }
162
-
163
163
  item_payload = {
164
164
  timestamp: Sentry.utc_now.iso8601,
165
165
  discarded_events: discarded_events_hash
166
166
  }
167
167
 
168
- client_report_item = <<~CLIENT_REPORT_ITEM
169
- #{JSON.generate(item_header)}
170
- #{JSON.generate(item_payload)}
171
- CLIENT_REPORT_ITEM
172
-
173
168
  @discarded_events = Hash.new(0)
174
169
  @last_client_report_sent = Time.now
175
170
 
176
- client_report_item
171
+ [item_header, item_payload]
177
172
  end
178
173
  end
179
174
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  module ArgumentCheckingHelper
3
5
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  module CustomInspection
3
5
  def inspect
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  module Utils
3
5
  module ExceptionCauseChain
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  module LoggingHelper
3
5
  def log_error(message, exception, debug: false)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ipaddr'
2
4
 
3
5
  # Based on ActionDispatch::RemoteIp. All security-related precautions from that
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
4
  module Utils
3
5
  module RequestId
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sentry
2
- VERSION = "4.8.0"
4
+ VERSION = "4.8.2"
3
5
  end
data/lib/sentry-ruby.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "English"
2
4
  require "forwardable"
3
5
  require "time"
@@ -37,6 +39,7 @@ module Sentry
37
39
  THREAD_LOCAL = :sentry_hub
38
40
 
39
41
  class << self
42
+ # @!visibility private
40
43
  def exception_locals_tp
41
44
  @exception_locals_tp ||= TracePoint.new(:raise) do |tp|
42
45
  exception = tp.raised_exception
@@ -53,46 +56,60 @@ module Sentry
53
56
  end
54
57
  end
55
58
 
59
+ # @!attribute [rw] background_worker
60
+ # @return [BackgroundWorker]
56
61
  attr_accessor :background_worker
57
62
 
58
63
  ##### Patch Registration #####
59
- #
64
+
65
+ # @!visibility private
60
66
  def register_patch(&block)
61
67
  registered_patches << block
62
68
  end
63
69
 
70
+ # @!visibility private
64
71
  def apply_patches(config)
65
72
  registered_patches.each do |patch|
66
73
  patch.call(config)
67
74
  end
68
75
  end
69
76
 
77
+ # @!visibility private
70
78
  def registered_patches
71
79
  @registered_patches ||= []
72
80
  end
73
81
 
74
82
  ##### Integrations #####
75
- #
83
+
76
84
  # Returns a hash that contains all the integrations that have been registered to the main SDK.
85
+ #
86
+ # @return [Hash{String=>Hash}]
77
87
  def integrations
78
88
  @integrations ||= {}
79
89
  end
80
90
 
81
91
  # Registers the SDK integration with its name and version.
92
+ #
93
+ # @param name [String] name of the integration
94
+ # @param version [String] version of the integration
82
95
  def register_integration(name, version)
83
96
  meta = { name: "sentry.ruby.#{name}", version: version }.freeze
84
97
  integrations[name.to_s] = meta
85
98
  end
86
99
 
87
100
  ##### Method Delegation #####
88
- #
101
+
89
102
  extend Forwardable
90
103
 
91
104
  def_delegators :get_current_client, :configuration, :send_event
92
105
  def_delegators :get_current_scope, :set_tags, :set_extras, :set_user, :set_context
93
106
 
94
107
  ##### Main APIs #####
108
+
109
+ # Initializes the SDK with given configuration.
95
110
  #
111
+ # @yieldparam config [Configuration]
112
+ # @return [void]
96
113
  def init(&block)
97
114
  config = Configuration.new
98
115
  yield(config) if block_given?
@@ -108,26 +125,42 @@ module Sentry
108
125
  if config.capture_exception_frame_locals
109
126
  exception_locals_tp.enable
110
127
  end
128
+
129
+ at_exit do
130
+ @background_worker.shutdown
131
+ end
132
+ end
133
+
134
+ # Returns true if the SDK is initialized.
135
+ #
136
+ # @return [Boolean]
137
+ def initialized?
138
+ !!@main_hub
111
139
  end
112
140
 
113
141
  # Returns an uri for security policy reporting that's generated from the given DSN
114
142
  # (To learn more about security policy reporting: https://docs.sentry.io/product/security-policy-reporting/)
115
143
  #
116
144
  # It returns nil if
145
+ # - The SDK is not initialized yet.
146
+ # - The DSN is not provided or is invalid.
117
147
  #
118
- # 1. The SDK is not initialized yet.
119
- # 2. The DSN is not provided or is invalid.
148
+ # @return [String, nil]
120
149
  def csp_report_uri
121
150
  return unless initialized?
122
151
  configuration.csp_report_uri
123
152
  end
124
153
 
125
154
  # Returns the main thread's active hub.
155
+ #
156
+ # @return [Hub]
126
157
  def get_main_hub
127
158
  @main_hub
128
159
  end
129
160
 
130
161
  # Takes an instance of Sentry::Breadcrumb and stores it to the current active scope.
162
+ #
163
+ # @return [Breadcrumb, nil]
131
164
  def add_breadcrumb(breadcrumb, **options)
132
165
  get_current_hub&.add_breadcrumb(breadcrumb, **options)
133
166
  end
@@ -135,6 +168,8 @@ module Sentry
135
168
  # Returns the current active hub.
136
169
  # If the current thread doesn't have an active hub, it will clone the main thread's active hub,
137
170
  # stores it in the current thread, and then returns it.
171
+ #
172
+ # @return [Hub]
138
173
  def get_current_hub
139
174
  # we need to assign a hub to the current thread if it doesn't have one yet
140
175
  #
@@ -145,85 +180,105 @@ module Sentry
145
180
  end
146
181
 
147
182
  # Returns the current active client.
183
+ # @return [Client, nil]
148
184
  def get_current_client
149
185
  get_current_hub&.current_client
150
186
  end
151
187
 
152
188
  # Returns the current active scope.
189
+ #
190
+ # @return [Scope, nil]
153
191
  def get_current_scope
154
192
  get_current_hub&.current_scope
155
193
  end
156
194
 
157
195
  # Clones the main thread's active hub and stores it to the current thread.
196
+ #
197
+ # @return [void]
158
198
  def clone_hub_to_current_thread
159
199
  Thread.current.thread_variable_set(THREAD_LOCAL, get_main_hub.clone)
160
200
  end
161
201
 
162
202
  # Takes a block and yields the current active scope.
163
203
  #
164
- # ```ruby
165
- # Sentry.configure_scope do |scope|
166
- # scope.set_tags(foo: "bar")
167
- # end
204
+ # @example
205
+ # Sentry.configure_scope do |scope|
206
+ # scope.set_tags(foo: "bar")
207
+ # end
168
208
  #
169
- # Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
170
- # ```
209
+ # Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
171
210
  #
211
+ # @yieldparam scope [Scope]
212
+ # @return [void]
172
213
  def configure_scope(&block)
173
214
  get_current_hub&.configure_scope(&block)
174
215
  end
175
216
 
176
217
  # Takes a block and yields a temporary scope.
177
218
  # The temporary scope will inherit all the attributes from the current active scope and replace it to be the active
178
- # scope inside the block. For example:
219
+ # scope inside the block.
179
220
  #
180
- # ```ruby
181
- # Sentry.configure_scope do |scope|
182
- # scope.set_tags(foo: "bar")
183
- # end
221
+ # @example
222
+ # Sentry.configure_scope do |scope|
223
+ # scope.set_tags(foo: "bar")
224
+ # end
184
225
  #
185
- # Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
226
+ # Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
186
227
  #
187
- # Sentry.with_scope do |temp_scope|
188
- # temp_scope.set_tags(foo: "baz")
189
- # Sentry.capture_message("test message 2") # this event will have tags { foo: "baz" }
190
- # end
228
+ # Sentry.with_scope do |temp_scope|
229
+ # temp_scope.set_tags(foo: "baz")
230
+ # Sentry.capture_message("test message 2") # this event will have tags { foo: "baz" }
231
+ # end
191
232
  #
192
- # Sentry.capture_message("test message 3") # this event will have tags { foo: "bar" }
193
- # ```
233
+ # Sentry.capture_message("test message 3") # this event will have tags { foo: "bar" }
194
234
  #
235
+ # @yieldparam scope [Scope]
236
+ # @return [void]
195
237
  def with_scope(&block)
196
238
  get_current_hub&.with_scope(&block)
197
239
  end
198
240
 
199
241
  # Takes an exception and reports it to Sentry via the currently active hub.
242
+ #
243
+ # @yieldparam scope [Scope]
244
+ # @return [Event, nil]
200
245
  def capture_exception(exception, **options, &block)
201
246
  get_current_hub&.capture_exception(exception, **options, &block)
202
247
  end
203
248
 
204
249
  # Takes a message string and reports it to Sentry via the currently active hub.
250
+ #
251
+ # @yieldparam scope [Scope]
252
+ # @return [Event, nil]
205
253
  def capture_message(message, **options, &block)
206
254
  get_current_hub&.capture_message(message, **options, &block)
207
255
  end
208
256
 
209
257
  # Takes an instance of Sentry::Event and dispatches it to the currently active hub.
258
+ #
259
+ # @return [Event, nil]
210
260
  def capture_event(event)
211
261
  get_current_hub&.capture_event(event)
212
262
  end
213
263
 
214
264
  # Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
265
+ #
266
+ # @return [Transaction, nil]
215
267
  def start_transaction(**options)
216
268
  get_current_hub&.start_transaction(**options)
217
269
  end
218
270
 
219
271
  # Returns the id of the lastly reported Sentry::Event.
272
+ #
273
+ # @return [String, nil]
220
274
  def last_event_id
221
275
  get_current_hub&.last_event_id
222
276
  end
223
277
 
224
278
 
225
279
  ##### Helpers #####
226
- #
280
+
281
+ # @!visibility private
227
282
  def sys_command(command)
228
283
  result = `#{command} 2>&1` rescue nil
229
284
  return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0)
@@ -231,18 +286,17 @@ module Sentry
231
286
  result.strip
232
287
  end
233
288
 
234
- def initialized?
235
- !!@main_hub
236
- end
237
-
289
+ # @!visibility private
238
290
  def logger
239
291
  configuration.logger
240
292
  end
241
293
 
294
+ # @!visibility private
242
295
  def sdk_meta
243
296
  META
244
297
  end
245
298
 
299
+ # @!visibility private
246
300
  def utc_now
247
301
  Time.now.utc
248
302
  end
data/sentry-ruby.gemspec CHANGED
@@ -18,6 +18,6 @@ Gem::Specification.new do |spec|
18
18
  spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
19
19
 
20
20
  spec.add_dependency "sentry-ruby-core", Sentry::VERSION
21
- spec.add_dependency "faraday", ">= 1.0"
21
+ spec.add_dependency "faraday", "~> 1.0"
22
22
  spec.add_dependency "concurrent-ruby", '~> 1.0', '>= 1.0.2'
23
23
  end
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: 4.8.0
4
+ version: 4.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-11 00:00:00.000000000 Z
11
+ date: 2022-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -48,6 +48,7 @@ extra_rdoc_files:
48
48
  files:
49
49
  - ".gitignore"
50
50
  - ".rspec"
51
+ - ".yardopts"
51
52
  - CHANGELOG.md
52
53
  - CODE_OF_CONDUCT.md
53
54
  - Gemfile
@@ -68,6 +69,7 @@ files:
68
69
  - lib/sentry/core_ext/object/deep_dup.rb
69
70
  - lib/sentry/core_ext/object/duplicable.rb
70
71
  - lib/sentry/dsn.rb
72
+ - lib/sentry/envelope.rb
71
73
  - lib/sentry/event.rb
72
74
  - lib/sentry/exceptions.rb
73
75
  - lib/sentry/hub.rb