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

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: 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