sentry-ruby-core 4.1.5.pre.beta.1 → 4.2.2

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: 6a30d58f74de8b3fc64399e3d7f741fb30ad9a771ce44e20100a95a90eb7937f
4
- data.tar.gz: 5154472623046d9a2d0819a7c32be2716e73e67d22477213836cc5f421c5ad26
3
+ metadata.gz: 927808cee7826c8aa7535511858722699330cd16b430ad68b7a7b79aaf04546d
4
+ data.tar.gz: 779f0e49611a24e1149fa551ff8988e15ac684bb2e9eb0c70a6c96b33501086d
5
5
  SHA512:
6
- metadata.gz: 32a4049d5cbf0c72a432f784932e8f40ceedf60d762b7365e46ab68d135f53bed0049724a9404dbe4515f3a7557361c8aeb9c0922e1eac0838d963c886ca2982
7
- data.tar.gz: dc838374f8426e6e63852207e68eacf4ee40f7d27ff4e9e7c418c0352658883fc120a53371d118a5c4685b3ec95e2952c9d569c65e3cf288fbd78bbead683b9f
6
+ metadata.gz: d629d892096a9de47f89f62c62487eb536c059c0ce14f6263aa605b50c2eddd0d5ecb48ed5da094444e58a889b8800b3333456cfa3c5e3e6afd4b6ea0512f081
7
+ data.tar.gz: 19a781d62efd5af40367146c976e2a1d886c59fbeddc6d67ad3e4efee15744ef34efd0769abb39317ee6b94d768394f7a6cf468a539d44894e595bd384ffc4cb
data/CHANGELOG.md CHANGED
@@ -1,11 +1,73 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.2.2
4
+
5
+ - Add thread_id to Exception interface [#1291](https://github.com/getsentry/sentry-ruby/pull/1291)
6
+ - always convert trusted proxies to string [#1288](https://github.com/getsentry/sentry-ruby/pull/1288)
7
+ - fixes [#1274](https://github.com/getsentry/sentry-ruby/issues/1274)
8
+
9
+ ## 4.2.1
10
+
11
+ ### Bug Fixes
12
+
13
+ - Ignore invalid values for sentry-trace header that don't match the required format [#1265](https://github.com/getsentry/sentry-ruby/pull/1265)
14
+ - Transaction created by `.from_sentry_trace` should inherit sampling decision [#1269](https://github.com/getsentry/sentry-ruby/pull/1269)
15
+ - Transaction's sample rate should accept any numeric value [#1278](https://github.com/getsentry/sentry-ruby/pull/1278)
16
+
17
+ ## 4.2.0
18
+
19
+ ### Features
20
+
21
+ - Add configuration option for trusted proxies [#1126](https://github.com/getsentry/sentry-ruby/pull/1126)
22
+
23
+ ```ruby
24
+ config.trusted_proxies = ["2.2.2.2"] # this ip address will be skipped when computing users' ip addresses
25
+ ```
26
+
27
+ - Add ThreadsInterface [#1178](https://github.com/getsentry/sentry-ruby/pull/1178)
28
+
29
+ <img width="1029" alt="an exception event that has the new threads interface" src="https://user-images.githubusercontent.com/5079556/103459223-98b64c00-4d48-11eb-9ebb-ee58f15e647e.png">
30
+
31
+ - Support `config.before_breadcrumb` [#1253](https://github.com/getsentry/sentry-ruby/pull/1253)
32
+
33
+ ```ruby
34
+ # this will be called before every breadcrumb is added to the breadcrumb buffer
35
+ # you can use it to
36
+ # - remove the data you don't want to send
37
+ # - add additional info to the data
38
+ config.before_breadcrumb = lambda do |breadcrumb, hint|
39
+ breadcrumb.message = "foo"
40
+ breadcrumb
41
+ end
42
+ ```
43
+
44
+ - Add ability to have many post initialization callbacks [#1261](https://github.com/getsentry/sentry-ruby/pull/1261)
45
+
46
+ ### Bug Fixes
47
+
48
+ - Inspect exception cause by default & don't exclude ActiveJob::DeserializationError [#1180](https://github.com/getsentry/sentry-ruby/pull/1180)
49
+ - Fixes [#1071](https://github.com/getsentry/sentry-ruby/issues/1071)
50
+
51
+ ## 4.1.6
52
+
53
+ - Don't detect project root for Rails apps [#1243](https://github.com/getsentry/sentry-ruby/pull/1243)
54
+ - Separate individual breadcrumb's data serialization [#1250](https://github.com/getsentry/sentry-ruby/pull/1250)
55
+ - Capture sentry-trace with the correct http header key [#1260](https://github.com/getsentry/sentry-ruby/pull/1260)
56
+
57
+ ## 4.1.5
58
+
59
+ - Serialize event hint before passing it to the async block [#1231](https://github.com/getsentry/sentry-ruby/pull/1231)
60
+ - Fixes [#1227](https://github.com/getsentry/sentry-ruby/issues/1227)
61
+ - Require the English library [#1233](https://github.com/getsentry/sentry-ruby/pull/1233) (by @dentarg)
62
+ - Allow `Sentry.init` without block argument [#1235](https://github.com/getsentry/sentry-ruby/pull/1235) (by @sue445)
63
+
3
64
  ## 4.1.5-beta.1
4
65
 
5
66
  - No change
6
67
 
7
68
  ## 4.1.5-beta.0
8
69
 
70
+ - Inline global method [#1213](https://github.com/getsentry/sentry-ruby/pull/1213) (by @tricknotes)
9
71
  - Event message and exception message should have a size limit [#1221](https://github.com/getsentry/sentry-ruby/pull/1221)
10
72
  - Add sentry-ruby-core as a more flexible option [#1226](https://github.com/getsentry/sentry-ruby/pull/1226)
11
73
 
@@ -126,4 +188,3 @@ Fix require reference
126
188
  ## 0.1.0
127
189
 
128
190
  First version
129
-
data/Gemfile CHANGED
@@ -3,6 +3,9 @@ source "https://rubygems.org"
3
3
  gem "sentry-ruby-core", path: "./"
4
4
  gem "sentry-ruby", path: "./"
5
5
 
6
+ # TODO: Remove this if https://github.com/jruby/jruby/issues/6547 is addressed
7
+ gem "i18n", "<= 1.8.7"
8
+
6
9
  gem "rake", "~> 12.0"
7
10
  gem "rspec", "~> 3.0"
8
11
  gem "codecov", "0.2.12"
data/Makefile ADDED
@@ -0,0 +1,4 @@
1
+ build:
2
+ bundle install
3
+ gem build sentry-ruby-core.gemspec
4
+ gem build sentry-ruby.gemspec
data/README.md CHANGED
@@ -26,7 +26,9 @@ The official Ruby-language client and integration layer for the [Sentry](https:/
26
26
 
27
27
  ## Requirements
28
28
 
29
- We test on Ruby 2.4, 2.5, 2.6 and 2.7 at the latest patchlevel/teeny version. We also support JRuby 9.0.
29
+ 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.
30
+
31
+ If you use self-hosted Sentry, please also make sure its version is above `20.6.0`.
30
32
 
31
33
  ## Migrate From sentry-raven
32
34
 
@@ -45,6 +47,7 @@ and depends on the integrations you want to have, you might also want to install
45
47
  ```ruby
46
48
  gem "sentry-rails"
47
49
  gem "sentry-sidekiq"
50
+ gem "sentry-delayed_job"
48
51
  # and mores to come in the future!
49
52
  ```
50
53
 
@@ -134,6 +137,7 @@ We also provide integrations with popular frameworks/libraries with the related
134
137
 
135
138
  - [sentry-rails](https://github.com/getsentry/sentry-ruby/tree/master/sentry-rails)
136
139
  - [sentry-sidekiq](https://github.com/getsentry/sentry-ruby/tree/master/sentry-sidekiq)
140
+ - [sentry-delayed_job](https://github.com/getsentry/sentry-ruby/tree/master/sentry-delayed_job)
137
141
 
138
142
  ### More configuration
139
143
 
@@ -141,32 +145,7 @@ You're all set - but there's a few more settings you may want to know about too!
141
145
 
142
146
  #### Blocking v.s. Non-blocking
143
147
 
144
- **Before version 4.1.0**, `sentry-ruby` sends every event immediately. But it can be configured to send asynchronously:
145
-
146
- ```ruby
147
- config.async = lambda { |event, hint|
148
- Thread.new { Sentry.send_event(event, hint) }
149
- }
150
- ```
151
-
152
- Using a thread to send events will be adequate for truly parallel Ruby platforms such as JRuby, though the benefit on MRI/CRuby will be limited. If the async callback raises an exception, Sentry will attempt to send synchronously.
153
-
154
- Note that the naive example implementation has a major drawback - it can create an infinite number of threads. We recommend creating a background job, using your background job processor, that will send Sentry notifications in the background.
155
-
156
- ```ruby
157
- config.async = lambda { |event, hint| SentryJob.perform_later(event, hint) }
158
-
159
- class SentryJob < ActiveJob::Base
160
- queue_as :default
161
-
162
- def perform(event, hint)
163
- Sentry.send_event(event, hint)
164
- end
165
- end
166
- ```
167
-
168
-
169
- **After version 4.1.0**, `sentry-ruby` sends events asynchronously by default. The functionality works like this:
148
+ `sentry-ruby` sends events asynchronously by default. The functionality works like this:
170
149
 
171
150
  1. When the SDK is initialized, a `Sentry::BackgroundWorker` will be initialized too.
172
151
  2. When an event is passed to `Client#capture_event`, instead of sending it directly with `Client#send_event`, we'll let the worker do it.
@@ -200,6 +179,21 @@ If you want to send a particular event immediately, you can use event hints to d
200
179
  Sentry.capture_message("send me now!", hint: { background: false })
201
180
  ```
202
181
 
182
+ ##### `config.async`
183
+
184
+ You can also use `config.async` to send events with you own worker:
185
+
186
+ ```ruby
187
+ config.async = lambda { |event, hint| SentryJob.perform_later(event, hint) }
188
+ ```
189
+
190
+ And if you use `sentry-rails`, you can directly use the job we defined for you:
191
+
192
+ ```ruby
193
+ config.async = lambda { |event, hint| Sentry::SendEventJob.perform_later(event, hint) }
194
+ ```
195
+
196
+
203
197
  #### Contexts
204
198
 
205
199
  In sentry-ruby, every event will inherit their contextual data from the current scope. So you can enrich the event's data by configuring the current scope like:
data/lib/sentry-ruby.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "English"
1
2
  require "forwardable"
2
3
  require "time"
3
4
 
@@ -65,7 +66,7 @@ module Sentry
65
66
 
66
67
  def init(&block)
67
68
  config = Configuration.new
68
- yield(config)
69
+ yield(config) if block_given?
69
70
  client = Client.new(config)
70
71
  scope = Scope.new
71
72
  hub = Hub.new(client, scope)
@@ -1,5 +1,7 @@
1
1
  module Sentry
2
2
  class Breadcrumb
3
+ DATA_SERIALIZATION_ERROR_MESSAGE = "[data were removed due to serialization issues]"
4
+
3
5
  attr_accessor :category, :data, :message, :level, :timestamp, :type
4
6
 
5
7
  def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
@@ -13,13 +15,30 @@ module Sentry
13
15
 
14
16
  def to_hash
15
17
  {
16
- :category => @category,
17
- :data => @data,
18
- :level => @level,
19
- :message => @message,
20
- :timestamp => @timestamp,
21
- :type => @type
18
+ category: @category,
19
+ data: serialized_data,
20
+ level: @level,
21
+ message: @message,
22
+ timestamp: @timestamp,
23
+ type: @type
22
24
  }
23
25
  end
26
+
27
+ private
28
+
29
+ def serialized_data
30
+ begin
31
+ ::JSON.parse(::JSON.generate(@data))
32
+ rescue Exception => e
33
+ Sentry.logger.debug(LOGGER_PROGNAME) do
34
+ <<~MSG
35
+ can't serialize breadcrumb data because of error: #{e}
36
+ data: #{@data}
37
+ MSG
38
+ end
39
+
40
+ DATA_SERIALIZATION_ERROR_MESSAGE
41
+ end
42
+ end
24
43
  end
25
44
  end
@@ -34,7 +34,7 @@ module Sentry
34
34
 
35
35
  def to_hash
36
36
  {
37
- :values => members.map(&:to_hash)
37
+ values: members.map(&:to_hash)
38
38
  }
39
39
  end
40
40
 
data/lib/sentry/client.rb CHANGED
@@ -32,6 +32,7 @@ module Sentry
32
32
  event_hash = event.to_json_compatible
33
33
 
34
34
  if async_block.arity == 2
35
+ hint = JSON.parse(JSON.generate(hint))
35
36
  async_block.call(event_hash, hint)
36
37
  else
37
38
  async_block.call(event_hash)
@@ -59,12 +60,15 @@ module Sentry
59
60
 
60
61
  Event.new(configuration: configuration, integration_meta: integration_meta).tap do |event|
61
62
  event.add_exception_interface(exception)
63
+ event.add_threads_interface(crashed: true)
62
64
  end
63
65
  end
64
66
 
65
67
  def event_from_message(message, hint = {})
66
68
  integration_meta = Sentry.integrations[hint[:integration]]
67
- Event.new(configuration: configuration, integration_meta: integration_meta, message: message)
69
+ event = Event.new(configuration: configuration, integration_meta: integration_meta, message: message)
70
+ event.add_threads_interface(backtrace: caller)
71
+ event
68
72
  end
69
73
 
70
74
  def event_from_transaction(transaction)
@@ -38,10 +38,19 @@ module Sentry
38
38
  #
39
39
  attr_accessor :backtrace_cleanup_callback
40
40
 
41
+ # Optional Proc, called before adding the breadcrumb to the current scope
42
+ # E.g.: lambda { |breadcrumb, hint| breadcrumb }
43
+ # E.g.: lambda { |breadcrumb, hint| nil }
44
+ # E.g.: lambda { |breadcrumb, hint|
45
+ # breadcrumb.message = 'a'
46
+ # breadcrumb
47
+ # }
48
+ attr_reader :before_breadcrumb
49
+
41
50
  # Optional Proc, called before sending an event to the server/
42
- # E.g.: lambda { |event| event }
43
- # E.g.: lambda { |event| nil }
44
- # E.g.: lambda { |event|
51
+ # E.g.: lambda { |event, hint| event }
52
+ # E.g.: lambda { |event, hint| nil }
53
+ # E.g.: lambda { |event, hint|
45
54
  # event[:message] = 'a'
46
55
  # event
47
56
  # }
@@ -109,6 +118,9 @@ module Sentry
109
118
  # will not be sent to Sentry.
110
119
  attr_accessor :send_default_pii
111
120
 
121
+ # IP ranges for trusted proxies that will be skipped when calculating IP address.
122
+ attr_accessor :trusted_proxies
123
+
112
124
  attr_accessor :server_name
113
125
 
114
126
  # Return a Transport::Configuration object for transport-related configurations.
@@ -153,6 +165,10 @@ module Sentry
153
165
 
154
166
  AVAILABLE_BREADCRUMBS_LOGGERS = [:sentry_logger, :active_support_logger].freeze
155
167
 
168
+ # Post initialization callbacks are called at the end of initialization process
169
+ # allowing extending the configuration of sentry-ruby by multiple extensions
170
+ @@post_initialization_callbacks = []
171
+
156
172
  def initialize
157
173
  self.background_worker_threads = Concurrent.processor_count
158
174
  self.breadcrumbs_logger = []
@@ -161,15 +177,16 @@ module Sentry
161
177
  self.enabled_environments = []
162
178
  self.exclude_loggers = []
163
179
  self.excluded_exceptions = IGNORE_DEFAULT.dup
164
- self.inspect_exception_causes_for_exclusion = false
180
+ self.inspect_exception_causes_for_exclusion = true
165
181
  self.linecache = ::Sentry::LineCache.new
166
182
  self.logger = ::Sentry::Logger.new(STDOUT)
167
- self.project_root = detect_project_root
183
+ self.project_root = Dir.pwd
168
184
 
169
185
  self.release = detect_release
170
186
  self.sample_rate = 1.0
171
187
  self.send_modules = true
172
188
  self.send_default_pii = false
189
+ self.trusted_proxies = []
173
190
  self.dsn = ENV['SENTRY_DSN']
174
191
  self.server_name = server_name_from_env
175
192
 
@@ -178,7 +195,7 @@ module Sentry
178
195
 
179
196
  @transport = Transport::Configuration.new
180
197
  @gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
181
- post_initialization_callback
198
+ run_post_initialization_callbacks
182
199
  end
183
200
 
184
201
  def dsn=(value)
@@ -223,6 +240,14 @@ module Sentry
223
240
  @before_send = value
224
241
  end
225
242
 
243
+ def before_breadcrumb=(value)
244
+ unless value.nil? || value.respond_to?(:call)
245
+ raise ArgumentError, "before_breadcrumb must be callable (or nil to disable)"
246
+ end
247
+
248
+ @before_breadcrumb = value
249
+ end
250
+
226
251
  def environment=(environment)
227
252
  @environment = environment.to_s
228
253
  end
@@ -267,14 +292,6 @@ module Sentry
267
292
 
268
293
  private
269
294
 
270
- def detect_project_root
271
- if defined? Rails.root # we are in a Rails application
272
- Rails.root.to_s
273
- else
274
- Dir.pwd
275
- end
276
- end
277
-
278
295
  def detect_release
279
296
  detect_release_from_env ||
280
297
  detect_release_from_git ||
@@ -390,7 +407,21 @@ module Sentry
390
407
  end
391
408
  end
392
409
 
393
- # allow extensions to extend the Configuration class
394
- def post_initialization_callback; end
410
+ def run_post_initialization_callbacks
411
+ self.class.post_initialization_callbacks.each do |hook|
412
+ instance_eval(&hook)
413
+ end
414
+ end
415
+
416
+ # allow extensions to add their hooks to the Configuration class
417
+ def self.add_post_initialization_callback(&block)
418
+ self.post_initialization_callbacks << block
419
+ end
420
+
421
+ protected
422
+
423
+ def self.post_initialization_callbacks
424
+ @@post_initialization_callbacks
425
+ end
395
426
  end
396
427
  end
data/lib/sentry/event.rb CHANGED
@@ -20,7 +20,7 @@ module Sentry
20
20
  MAX_MESSAGE_SIZE_IN_BYTES = 1024 * 8
21
21
 
22
22
  attr_accessor(*ATTRIBUTES)
23
- attr_reader :configuration, :request, :exception, :stacktrace
23
+ attr_reader :configuration, :request, :exception, :stacktrace, :threads
24
24
 
25
25
  def initialize(configuration:, integration_meta: nil, message: nil)
26
26
  # this needs to go first because some setters rely on configuration
@@ -102,6 +102,7 @@ module Sentry
102
102
  data[:stacktrace] = stacktrace.to_hash if stacktrace
103
103
  data[:request] = request.to_hash if request
104
104
  data[:exception] = exception.to_hash if exception
105
+ data[:threads] = threads.to_hash if threads
105
106
 
106
107
  data
107
108
  end
@@ -114,6 +115,11 @@ module Sentry
114
115
  @request = Sentry::RequestInterface.from_rack(env)
115
116
  end
116
117
 
118
+ def add_threads_interface(backtrace: nil, **options)
119
+ @threads = ThreadsInterface.new(**options)
120
+ @threads.stacktrace = initialize_stacktrace_interface(backtrace) if backtrace
121
+ end
122
+
117
123
  def add_exception_interface(exc)
118
124
  if exc.respond_to?(:sentry_context)
119
125
  @extra.merge!(exc.sentry_context)
@@ -127,6 +133,7 @@ module Sentry
127
133
  int.type = e.class.to_s
128
134
  int.value = e.message.byteslice(0..MAX_MESSAGE_SIZE_IN_BYTES)
129
135
  int.module = e.class.to_s.split('::')[0...-1].join('::')
136
+ int.thread_id = Thread.current.object_id
130
137
 
131
138
  int.stacktrace =
132
139
  if e.backtrace && !backtraces.include?(e.backtrace.object_id)
@@ -166,7 +173,8 @@ module Sentry
166
173
  :remote_addr => env["REMOTE_ADDR"],
167
174
  :client_ip => env["HTTP_CLIENT_IP"],
168
175
  :real_ip => env["HTTP_X_REAL_IP"],
169
- :forwarded_for => env["HTTP_X_FORWARDED_FOR"]
176
+ :forwarded_for => env["HTTP_X_FORWARDED_FOR"],
177
+ :trusted_proxies => configuration.trusted_proxies
170
178
  ).calculate_ip
171
179
  end
172
180
  end
data/lib/sentry/hub.rb CHANGED
@@ -120,7 +120,13 @@ module Sentry
120
120
  event
121
121
  end
122
122
 
123
- def add_breadcrumb(breadcrumb)
123
+ def add_breadcrumb(breadcrumb, hint: {})
124
+ if before_breadcrumb = current_client.configuration.before_breadcrumb
125
+ breadcrumb = before_breadcrumb.call(breadcrumb, hint)
126
+ end
127
+
128
+ return unless breadcrumb
129
+
124
130
  current_scope.add_breadcrumb(breadcrumb)
125
131
  end
126
132
 
@@ -20,3 +20,4 @@ require "sentry/interfaces/exception"
20
20
  require "sentry/interfaces/request"
21
21
  require "sentry/interfaces/single_exception"
22
22
  require "sentry/interfaces/stacktrace"
23
+ require "sentry/interfaces/threads"
@@ -3,6 +3,7 @@ module Sentry
3
3
  attr_accessor :type
4
4
  attr_accessor :value
5
5
  attr_accessor :module
6
+ attr_accessor :thread_id
6
7
  attr_accessor :stacktrace
7
8
 
8
9
  def to_hash
@@ -0,0 +1,26 @@
1
+ module Sentry
2
+ class ThreadsInterface
3
+ attr_accessor :stacktrace
4
+
5
+ def initialize(crashed: false)
6
+ @id = Thread.current.object_id
7
+ @name = Thread.current.name
8
+ @current = true
9
+ @crashed = crashed
10
+ end
11
+
12
+ def to_hash
13
+ {
14
+ values: [
15
+ {
16
+ id: @id,
17
+ name: @name,
18
+ crashed: @crashed,
19
+ current: @current,
20
+ stacktrace: @stacktrace&.to_hash
21
+ }
22
+ ]
23
+ }
24
+ end
25
+ end
26
+ end
@@ -16,12 +16,9 @@ module Sentry
16
16
  scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
17
17
  scope.set_rack_env(env)
18
18
 
19
- span =
20
- if sentry_trace = env["sentry-trace"]
21
- Sentry::Transaction.from_sentry_trace(sentry_trace, name: scope.transaction_name, op: transaction_op)
22
- else
23
- Sentry.start_transaction(name: scope.transaction_name, op: transaction_op)
24
- end
19
+ sentry_trace = env["HTTP_SENTRY_TRACE"]
20
+ span = Sentry::Transaction.from_sentry_trace(sentry_trace, name: scope.transaction_name, op: transaction_op) if sentry_trace
21
+ span ||= Sentry.start_transaction(name: scope.transaction_name, op: transaction_op)
25
22
 
26
23
  scope.set_span(span)
27
24
 
@@ -29,11 +29,12 @@ module Sentry
29
29
  return unless sentry_trace
30
30
 
31
31
  match = SENTRY_TRACE_REGEXP.match(sentry_trace)
32
+ return if match.nil?
32
33
  trace_id, parent_span_id, sampled_flag = match[1..3]
33
34
 
34
35
  sampled = sampled_flag != "0"
35
36
 
36
- new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: sampled, **options)
37
+ new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: sampled, sampled: sampled, **options)
37
38
  end
38
39
 
39
40
  def to_hash
@@ -89,7 +90,7 @@ module Sentry
89
90
  sample_rate = traces_sampler.call(sampling_context)
90
91
  end
91
92
 
92
- unless [true, false].include?(sample_rate) || (sample_rate.is_a?(Float) && sample_rate >= 0.0 && sample_rate <= 1.0)
93
+ unless [true, false].include?(sample_rate) || (sample_rate.is_a?(Numeric) && sample_rate >= 0.0 && sample_rate <= 1.0)
93
94
  @sampled = false
94
95
  logger.warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
95
96
  return
@@ -13,8 +13,8 @@ module Sentry
13
13
  "fc00::/7", # private IPv6 range fc00::/7
14
14
  "10.0.0.0/8", # private IPv4 range 10.x.x.x
15
15
  "172.16.0.0/12", # private IPv4 range 172.16.0.0 .. 172.31.255.255
16
- "192.168.0.0/16" # private IPv4 range 192.168.x.x
17
- ].map { |proxy| IPAddr.new(proxy) }
16
+ "192.168.0.0/16", # private IPv4 range 192.168.x.x
17
+ ]
18
18
 
19
19
  attr_reader :ip
20
20
 
@@ -22,12 +22,14 @@ module Sentry
22
22
  remote_addr: nil,
23
23
  client_ip: nil,
24
24
  real_ip: nil,
25
- forwarded_for: nil
25
+ forwarded_for: nil,
26
+ trusted_proxies: []
26
27
  )
27
28
  @remote_addr = remote_addr
28
29
  @client_ip = client_ip
29
30
  @real_ip = real_ip
30
31
  @forwarded_for = forwarded_for
32
+ @trusted_proxies = (LOCAL_ADDRESSES + Array(trusted_proxies)).map { |proxy| IPAddr.new(proxy.to_s) }.uniq
31
33
  end
32
34
 
33
35
  def calculate_ip
@@ -37,12 +39,16 @@ module Sentry
37
39
  # Could be a CSV list and/or repeated headers that were concatenated.
38
40
  client_ips = ips_from(@client_ip)
39
41
  real_ips = ips_from(@real_ip)
40
- forwarded_ips = ips_from(@forwarded_for)
42
+
43
+ # The first address in this list is the original client, followed by
44
+ # the IPs of successive proxies. We want to search starting from the end
45
+ # until we find the first proxy that we do not trust.
46
+ forwarded_ips = ips_from(@forwarded_for).reverse
41
47
 
42
48
  ips = [client_ips, real_ips, forwarded_ips, remote_addr].flatten.compact
43
49
 
44
50
  # If every single IP option is in the trusted list, just return REMOTE_ADDR
45
- @ip = filter_local_addresses(ips).first || remote_addr
51
+ @ip = filter_trusted_proxy_addresses(ips).first || remote_addr
46
52
  end
47
53
 
48
54
  protected
@@ -62,8 +68,8 @@ module Sentry
62
68
  end
63
69
  end
64
70
 
65
- def filter_local_addresses(ips)
66
- ips.reject { |ip| LOCAL_ADDRESSES.any? { |proxy| proxy === ip } }
71
+ def filter_trusted_proxy_addresses(ips)
72
+ ips.reject { |ip| @trusted_proxies.any? { |proxy| proxy === ip } }
67
73
  end
68
74
  end
69
75
  end
@@ -1,3 +1,3 @@
1
1
  module Sentry
2
- VERSION = "4.1.5-beta.1"
2
+ VERSION = "4.2.2"
3
3
  end
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = spec.homepage
19
- spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/sentry-ruby/CHANGELOG.md"
20
20
 
21
21
  spec.bindir = "exe"
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
data/sentry-ruby.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
 
16
16
  spec.metadata["homepage_uri"] = spec.homepage
17
17
  spec.metadata["source_code_uri"] = spec.homepage
18
- spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
18
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/sentry-ruby/CHANGELOG.md"
19
19
 
20
20
  spec.add_dependency "sentry-ruby-core", Sentry::VERSION
21
21
  spec.add_dependency "faraday", ">= 1.0"
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.1.5.pre.beta.1
4
+ version: 4.2.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-01-21 00:00:00.000000000 Z
11
+ date: 2021-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -49,11 +49,11 @@ files:
49
49
  - ".craft.yml"
50
50
  - ".gitignore"
51
51
  - ".rspec"
52
- - ".travis.yml"
53
52
  - CHANGELOG.md
54
53
  - CODE_OF_CONDUCT.md
55
54
  - Gemfile
56
55
  - LICENSE.txt
56
+ - Makefile
57
57
  - README.md
58
58
  - Rakefile
59
59
  - bin/console
@@ -78,6 +78,7 @@ files:
78
78
  - lib/sentry/interfaces/request.rb
79
79
  - lib/sentry/interfaces/single_exception.rb
80
80
  - lib/sentry/interfaces/stacktrace.rb
81
+ - lib/sentry/interfaces/threads.rb
81
82
  - lib/sentry/linecache.rb
82
83
  - lib/sentry/logger.rb
83
84
  - lib/sentry/rack.rb
@@ -105,7 +106,7 @@ licenses:
105
106
  metadata:
106
107
  homepage_uri: https://github.com/getsentry/sentry-ruby
107
108
  source_code_uri: https://github.com/getsentry/sentry-ruby
108
- changelog_uri: https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md
109
+ changelog_uri: https://github.com/getsentry/sentry-ruby/blob/master/sentry-ruby/CHANGELOG.md
109
110
  post_install_message:
110
111
  rdoc_options: []
111
112
  require_paths:
@@ -117,9 +118,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
118
  version: '2.4'
118
119
  required_rubygems_version: !ruby/object:Gem::Requirement
119
120
  requirements:
120
- - - ">"
121
+ - - ">="
121
122
  - !ruby/object:Gem::Version
122
- version: 1.3.1
123
+ version: '0'
123
124
  requirements: []
124
125
  rubygems_version: 3.0.3
125
126
  signing_key:
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.6.5
6
- before_install: gem install bundler -v 2.1.1