sentry-raven 2.6.3 → 2.7.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
  SHA1:
3
- metadata.gz: 29f898ece848c6fd9bf471b62dbfb990c41f30a1
4
- data.tar.gz: d290053185690206a198fb29ace1e6443534be7b
3
+ metadata.gz: 720bbe2b86e0c01584514a17c2f6299bb1313af1
4
+ data.tar.gz: 0410c196dffd1e8d0617ff1d01335c120b9dfa3c
5
5
  SHA512:
6
- metadata.gz: 7eb80ee3da6a36d2e8304dfcbf8f5d339340d401543d4c8fd9ae9340c923e49a889e6d0266c55bbc316183c882b595fba05c52e8422c560d36d4a2c2f049784a
7
- data.tar.gz: a4489464ff92761b746fd3b6be2ef384eb06a2d365ccf6e386e5feb46ca25fcb92ed8e4970e9aef5e684cf4b56d61f83ea6ca8dbacf344ece036227c0145425e
6
+ metadata.gz: 81eb505ebd43d3946a29ecd8e73ea67349c64907eee5821e1259e36353b6b204c7a42c7b584a4f2e93b1d45ee4a5fddf43c7c1f8315f5e63ff123caad2f73656
7
+ data.tar.gz: f81baee39e752d97874a88f6c37457325d0ab3baa9a8d3b54a495842bf08095879940854965023cda72397d85ee00e8839b51c6bd7954a0c8668143df57c0c2f
data/.rspec CHANGED
@@ -1,2 +1 @@
1
1
  --colour
2
- --format documentation
@@ -7,7 +7,7 @@ AllCops:
7
7
  - 'vendor/**/*'
8
8
 
9
9
  Metrics/ClassLength:
10
- Max: 248
10
+ Max: 262
11
11
  CountComments: false
12
12
 
13
13
  Metrics/AbcSize:
@@ -8,9 +8,9 @@ branches:
8
8
  only: [master]
9
9
 
10
10
  rvm:
11
- - 2.2.7
12
- - 2.3.4
13
- - 2.4.1
11
+ - 2.2.8
12
+ - 2.3.5
13
+ - 2.4.2
14
14
 
15
15
  env:
16
16
  - RAILS_VERSION=4
@@ -24,6 +24,7 @@ addons:
24
24
 
25
25
  before_install:
26
26
  - service haveged start
27
+ - gem install bundler
27
28
 
28
29
  matrix:
29
30
  include:
@@ -31,9 +32,9 @@ matrix:
31
32
  env: RAILS_VERSION=4
32
33
  - rvm: jruby-1.7.27
33
34
  env: JRUBY_OPTS="--dev" RAILS_VERSION=4
34
- - rvm: jruby-9.1.12.0
35
+ - rvm: jruby-9.1.13.0
35
36
  env: JRUBY_OPTS="--dev -J-Djruby.launch.inproc=true -J-Xmx1024M" RAILS_VERSION=4
36
- - rvm: jruby-9.1.12.0
37
+ - rvm: jruby-9.1.13.0
37
38
  env: JRUBY_OPTS="--dev -J-Djruby.launch.inproc=true -J-Xmx1024M" RAILS_VERSION=5
38
39
  - rvm: ruby-head
39
40
  env: RAILS_VERSION=0
data/README.md CHANGED
@@ -89,9 +89,6 @@ config.async = lambda { |event| SentryJob.perform_later(event) }
89
89
  class SentryJob < ActiveJob::Base
90
90
  queue_as :default
91
91
 
92
- # Important for ActiveJob! Otherwise, we can get caught in an infinite loop.
93
- rescue_from(ActiveJob::DeserializationError) { |e| Rails.logger.error e }
94
-
95
92
  def perform(event)
96
93
  Raven.send_event(event)
97
94
  end
@@ -1,3 +1,25 @@
1
+ 2.7.1
2
+ -----
3
+
4
+ * BUGFIX: Fixed LocalJumpError in Rails controllers [@nateberkopec w/@frodsan, #774]
5
+
6
+ 2.7.0
7
+ -----
8
+
9
+ * FEATURE: Add random sampling. [@nateberkopec, #734]
10
+ * FEATURE: Transactions. See Context docs for usage. [@nateberkopec, #743]
11
+ * FEATURE: You can set the current environment for Sentry via `SENTRY_CURRENT_ENV` env variable. Useful if your staging environment's RACK_ENV is "production", for example. [@tijmenb, #736]
12
+
13
+ * BUGFIX: Fix wrapped classnames in old versions of Sidekiq and ActiveJob [@nateberkopec, #702]
14
+ * BUGFIX: Server names on Heroku were pretty useless before - now they follow the dyno name ("worker.1", "web.2") [@nateberkopec, #703]
15
+ * BUGFIX: ActiveJob::DeserializationError is now ignored by default. Not doing so can cause infinite loops if you are using an ActiveJob async callback. [@nateberkopec, #701]
16
+ * BUGFIX: Binary conversion to UTF-8 when binary is frozen is fixed [@nateberkopec, #757]
17
+ * BUGFIX: Our credit-card regex now matches Sentry's server behavior, which means it does not censor milliseconds since the epoch [@nateberkopec, #771]
18
+
19
+ * REFACTOR: We now use an updated port of Rails' deep_merge which should be 5-10% faster [@nateberkopec, #770]
20
+ * REFACTOR: Tests have been cleaned up, and now run in random order. [@nateberkopec]
21
+ * REFACTOR: Raven::Event has been refactored a bit [@nateberkopec]
22
+
1
23
  2.6.3
2
24
  -----
3
25
 
@@ -1,3 +1,5 @@
1
+ .. versionadded:: 1.2
2
+
1
3
  Breadcrumbs
2
4
  ===========
3
5
 
@@ -38,3 +40,12 @@ Appropriate places to inject Breadcrumbs may be places like your HTTP library:
38
40
  end
39
41
  end
40
42
  end
43
+
44
+ .. versionadded:: 2.6
45
+
46
+ The breadcrumb buffer is publicly accessible if you wish to manipulate it beyond
47
+ what is possible with the ``record`` method.
48
+
49
+ .. sourcecode:: ruby
50
+
51
+ Raven.breadcrumbs.buffer # Array of breadcrumbs
@@ -23,7 +23,12 @@ Optional settings
23
23
  Thread.new { Raven.send_event(event) }
24
24
  }
25
25
 
26
- 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. Threads also won't report any exceptions raised inside of them, so be careful!
26
+ 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.
27
+
28
+ The example above is extremely basic. For example, exceptions in Rake tasks
29
+ will not be reported because the Rake task will probably exit before the thread
30
+ can completely send the event to Sentry. Threads also won't report any
31
+ exceptions raised inside of them, so be careful!
27
32
 
28
33
  If the async callback raises an exception, Raven will attempt to send synchronously.
29
34
 
@@ -40,9 +45,6 @@ Optional settings
40
45
  class SentryJob < ActiveJob::Base
41
46
  queue_as :default
42
47
 
43
- # Important! Otherwise, we can get caught in an infinite loop.
44
- rescue_from(ActiveJob::DeserializationError) { |e| Rails.logger.error e }
45
-
46
48
  def perform(event)
47
49
  Raven.send_event(event)
48
50
  end
@@ -68,7 +70,7 @@ Optional settings
68
70
 
69
71
  config.environments = %w[ production ]
70
72
 
71
- Sentry automatically sets the current environment to RAILS_ENV, or if it is not present, RACK_ENV. If you are using Sentry outside of Rack or Rails, or wish to override environment detection, you'll need to set the current environment yourself:
73
+ Sentry automatically sets the current environment to RAILS_ENV, or if it is not present, RACK_ENV. If you are using Sentry outside of Rack or Rails, or wish to override environment detection, you'll need to set the current environment by setting SENTRY_CURRENT_ENV or configuring the client yourself:
72
74
 
73
75
  .. code-block:: ruby
74
76
 
@@ -183,6 +185,16 @@ Optional settings
183
185
 
184
186
  config.release = '721e41770371db95eee98ca2707686226b993eda'
185
187
 
188
+ .. describe:: sample_rate
189
+
190
+ The sampling factor to apply to events. A value of 0.00 will deny sending
191
+ any events, and a value of 1.00 will send 100% of events.
192
+
193
+ .. code-block:: ruby
194
+
195
+ # send 50% of events
196
+ config.sample_rate = 0.5
197
+
186
198
  .. describe:: should_capture
187
199
 
188
200
  By providing a proc or lambda, you can control what events are captured. Events are passed to the Proc or lambda you provide - returning false will stop the event from sending to Sentry:
@@ -25,6 +25,7 @@ The following attributes are available:
25
25
  * ``tags``: a mapping of tags describing this event
26
26
  * ``extra``: a mapping of arbitrary context
27
27
  * ``user``: a mapping of user context
28
+ * ``transaction``: An array of strings. The final element in the array represents the current transaction, e.g. "HelloController#hello_world" for a Rails controller.
28
29
 
29
30
  Providing Request Context
30
31
  -------------------------
@@ -116,3 +117,25 @@ for you, otherwise you'll need to ensure you perform it manually:
116
117
 
117
118
  Note: the rack and user context will perform a set operation, whereas tags
118
119
  and extra context will merge with any existing request context.
120
+
121
+ Transactions
122
+ ~~~~~~~~~~~~
123
+
124
+ The "transaction" is intended to represent the action the event occurred during.
125
+ In Rack, this will be the request URL. In Rails, it's the controller name and
126
+ action ("HelloController#hello_world").
127
+
128
+ Transactions are modeled as a stack. The top item in the stack (i.e. the last
129
+ element of the array) will be used as the ``transaction`` for any events:
130
+
131
+ .. sourcecode:: ruby
132
+
133
+ Raven.context.transactions.push "User Import"
134
+ # import some users
135
+ Raven.context.transactions.pop
136
+
137
+ Transactions may also be overridden/set explicitly during event creation:
138
+
139
+ .. sourcecode:: ruby
140
+
141
+ Raven.capture_exception(exception, transaction: "User Import")
@@ -104,6 +104,7 @@ the library and the client integrations.
104
104
 
105
105
  breadcrumbs
106
106
  context
107
+ processors
107
108
  integrations/index
108
109
 
109
110
  Resources:
@@ -23,7 +23,7 @@ Puma provides a config option for handling low level errors.
23
23
  ex,
24
24
  :message => ex.message,
25
25
  :extra => { :puma => env },
26
- :culprit => "Puma"
26
+ :transaction => "Puma"
27
27
  )
28
28
  # note the below is just a Rack response
29
29
  [500, {}, ["An error has occurred, and engineers have been informed. Please reload the page. If you continue to have problems, contact support@example.com\n"]]
@@ -0,0 +1,124 @@
1
+ Processors
2
+ ==========
3
+
4
+ Raven Ruby contains several "processors", which scrub data before it is sent to Sentry.
5
+ Processors remove invalid or sensitive data. The following are the processors
6
+ which are enabled by default (and are applied to all outgoing data in this order):
7
+
8
+ RemoveCircularReferences
9
+ Many Ruby JSON implementations simply throw an exception if they detect a
10
+ circular reference. This processor removes circular references from hashes
11
+ and arrays.
12
+
13
+ UTF8Conversion
14
+ Many Ruby JSON implementations will throw exceptions if data is not in a
15
+ consistent UTF-8 format. This processor looks for invalid encodings and fixes
16
+ them.
17
+
18
+ SanitizeData
19
+ Censors any data which looks like a password, social security number or credit
20
+ card number. Can be configured to scrub other data.
21
+
22
+ Cookies
23
+ Removes any HTTP cookies from the Sentry event data.
24
+
25
+ PostData
26
+ Removes any HTTP Post request bodies.
27
+
28
+ HTTPHeaders
29
+ Removes all HTTP headers which match a regex. By default, this will only remove the
30
+ "Authorization" header, but can be configured to remove others.
31
+
32
+ Finally, another processor is included in the source but is not turned on by default,
33
+ RemoveStackTrace.
34
+
35
+ To remove stacktraces from events:
36
+
37
+ .. sourcecode:: ruby
38
+
39
+ Raven.configure do |config|
40
+ config.processors += [Raven::Processor::RemoveStacktrace]
41
+ end
42
+
43
+ Writing Your Own Processor
44
+ --------------------------
45
+
46
+ Processors are simple to write and understand. As an example, let's say that we
47
+ send user API keys to a background job (using Sidekiq), and if the background job
48
+ raises an exception, we want to make sure that the API key is removed from the
49
+ event data.
50
+
51
+ This is what a basic processor might look like:
52
+
53
+ .. sourcecode:: ruby
54
+
55
+ class MyJobProcessor < Raven::Processor
56
+ def process(data)
57
+ return data unless data["extra"]["arguments"] &&
58
+ data["extra"]["arguments"].first["sensitive_parameter"]
59
+
60
+ data["extra"]["arguments"].first["sensitive_parameter"] = STRING_MASK
61
+ data
62
+ end
63
+ end
64
+
65
+ Processors should inherit from the ``Raven::Processor`` class. This ensures that the
66
+ processor has access to its client (all processors have a ``client`` instance method,
67
+ which will be populated with the current ``Raven::Client`` when the processor
68
+ is initialized), and gives you a few convenient constants for masking data.
69
+
70
+ Processors must have a method called ``process`` defined. It must accept one
71
+ argument, which will be the Raven event data hash. The method must return a hash,
72
+ which represents the data after it has been modified by the processor.
73
+
74
+ To help you in writing your own processor, here is what the Event data hash looks
75
+ like (slightly modified/concatenated) when it is passed to the processor:
76
+
77
+ .. sourcecode:: ruby
78
+
79
+ {
80
+ "environment" => "default",
81
+ "event_id" => "02ea6d3d35c840b1a8f339ba896917e3",
82
+ "extra" => {
83
+ "server" => {
84
+ # server related information
85
+ }
86
+ "active_job" => "MyActiveJob",
87
+ "arguments" => [ {"sensitive_parameter": "sensitive"} ],
88
+ "job_id" => "cbc2c146-0486-4e98-b81c-1a251d636b34",
89
+ },
90
+ "modules" => {
91
+ "rake"=>"12.0.0",
92
+ "concurrent-ruby"=>"1.0.5",
93
+ "i18n"=>"0.8.6",
94
+ "minitest"=>"5.10.3",
95
+ # ...
96
+ },
97
+ "platform" => "ruby",
98
+ "release" => "e4d5ced",
99
+ "sdk" => {"name"=>"raven-ruby", "version"=>"2.6.3"},
100
+ "server_name" => "myserver.local",
101
+ "timestamp" => "2017-10-09T19:53:20",
102
+ "exception" => {
103
+ # A very large and complex exception object
104
+ }
105
+ }
106
+
107
+ However, it will probably be more helpful if you use a debugger, such as `pry`, to
108
+ inspect the event data hash for yourself.
109
+
110
+ The example processor given above looks for the ActiveJob arguments hash, looks for
111
+ a particular value, and then replaces it with the string mask. There is a fast return
112
+ if the event does not contain the ActiveJob data we're looking for, using Ruby 2.3+'s
113
+ safe navigation operator.
114
+
115
+ Once you have your processor written, you simply need to add it to the processor chain:
116
+
117
+ .. sourcecode:: ruby
118
+
119
+ Raven.configure do |config|
120
+ config.processors += MyJobProcessor
121
+ end
122
+
123
+ For more information about writing processors, read the code for the default
124
+ processors, located in ``lib/processor``.
@@ -5,6 +5,7 @@ module Raven
5
5
  class Backtrace
6
6
  # Handles backtrace parsing line by line
7
7
  class Line
8
+ RB_EXTENSION = ".rb".freeze
8
9
  # regexp (optional leading X: on windows, or JRuby9000 class-prefix)
9
10
  RUBY_INPUT_FORMAT = /
10
11
  ^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
@@ -34,7 +35,7 @@ module Raven
34
35
  ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
35
36
  if ruby_match
36
37
  _, file, number, method = ruby_match.to_a
37
- file.sub!(/\.class$/, ".rb")
38
+ file.sub!(/\.class$/, RB_EXTENSION)
38
39
  module_name = nil
39
40
  else
40
41
  java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
@@ -12,12 +12,15 @@ require 'raven/configuration'
12
12
  require 'raven/context'
13
13
  require 'raven/client'
14
14
  require 'raven/event'
15
+ require 'raven/linecache'
15
16
  require 'raven/logger'
16
17
  require 'raven/interfaces/message'
17
18
  require 'raven/interfaces/exception'
18
19
  require 'raven/interfaces/single_exception'
19
20
  require 'raven/interfaces/stack_trace'
20
21
  require 'raven/interfaces/http'
22
+ require 'raven/transports'
23
+ require 'raven/transports/http'
21
24
  require 'raven/utils/deep_merge'
22
25
  require 'raven/utils/real_ip'
23
26
  require 'raven/instance'
@@ -28,6 +31,9 @@ require 'English'
28
31
  module Raven
29
32
  AVAILABLE_INTEGRATIONS = %w(delayed_job railties sidekiq rack rack-timeout rake).freeze
30
33
 
34
+ class Error < StandardError
35
+ end
36
+
31
37
  class << self
32
38
  extend Forwardable
33
39
 
@@ -53,7 +53,7 @@ module Raven
53
53
 
54
54
  instance.logger.debug ""
55
55
  instance.logger.debug "Done!"
56
- true
56
+ evt
57
57
  end
58
58
  end
59
59
  end
@@ -3,9 +3,6 @@ require 'base64'
3
3
  require 'json'
4
4
  require 'zlib'
5
5
 
6
- require 'raven/version'
7
- require 'raven/transports/http'
8
-
9
6
  module Raven
10
7
  # Encodes events and sends them to the Sentry server.
11
8
  class Client
@@ -91,6 +91,10 @@ module Raven
91
91
  # We automatically try to set this to a git SHA or Capistrano release.
92
92
  attr_accessor :release
93
93
 
94
+ # The sampling factor to apply to events. A value of 0.0 will not send
95
+ # any events, and a value of 1.0 will send 100% of events.
96
+ attr_accessor :sample_rate
97
+
94
98
  # Boolean - sanitize values that look like credit card numbers
95
99
  attr_accessor :sanitize_credit_cards
96
100
 
@@ -161,7 +165,8 @@ module Raven
161
165
  'ActiveRecord::RecordNotFound',
162
166
  'CGI::Session::CookieStore::TamperedWithCookie',
163
167
  'Mongoid::Errors::DocumentNotFound',
164
- 'Sinatra::NotFound'
168
+ 'Sinatra::NotFound',
169
+ 'ActiveJob::DeserializationError'
165
170
  ].freeze
166
171
 
167
172
  # Note the order - we have to remove circular references and bad characters
@@ -176,11 +181,12 @@ module Raven
176
181
  ].freeze
177
182
 
178
183
  LOG_PREFIX = "** [Raven] ".freeze
184
+ MODULE_SEPARATOR = "::".freeze
179
185
 
180
186
  def initialize
181
187
  self.async = false
182
188
  self.context_lines = 3
183
- self.current_environment = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
189
+ self.current_environment = ENV['SENTRY_CURRENT_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
184
190
  self.encoding = 'gzip'
185
191
  self.environments = []
186
192
  self.exclude_loggers = []
@@ -194,13 +200,14 @@ module Raven
194
200
  self.rails_activesupport_breadcrumbs = false
195
201
  self.rails_report_rescued_exceptions = true
196
202
  self.release = detect_release
203
+ self.sample_rate = 1.0
197
204
  self.sanitize_credit_cards = true
198
205
  self.sanitize_fields = []
199
206
  self.sanitize_fields_excluded = []
200
207
  self.sanitize_http_headers = []
201
208
  self.send_modules = true
202
209
  self.server = ENV['SENTRY_DSN'] if ENV['SENTRY_DSN']
203
- self.server_name = resolve_hostname
210
+ self.server_name = heroku_dyno_name || resolve_hostname
204
211
  self.should_capture = false
205
212
  self.ssl_verification = true
206
213
  self.tags = {}
@@ -273,7 +280,8 @@ module Raven
273
280
 
274
281
  valid? &&
275
282
  capture_in_current_environment? &&
276
- capture_allowed_by_callback?(message_or_exc)
283
+ capture_allowed_by_callback?(message_or_exc) &&
284
+ sample_allowed?
277
285
  end
278
286
  # If we cannot capture, we cannot send.
279
287
  alias sending_allowed? capture_allowed?
@@ -304,8 +312,41 @@ module Raven
304
312
  end
305
313
  end
306
314
 
315
+ def exception_class_allowed?(exc)
316
+ if exc.is_a?(Raven::Error)
317
+ # Try to prevent error reporting loops
318
+ logger.debug "Refusing to capture Raven error: #{exc.inspect}"
319
+ false
320
+ elsif excluded_exception?(exc)
321
+ logger.debug "User excluded error: #{exc.inspect}"
322
+ false
323
+ else
324
+ true
325
+ end
326
+ end
327
+
307
328
  private
308
329
 
330
+ def excluded_exception?(exc)
331
+ excluded_exceptions.any? { |x| get_exception_class(x) === exc }
332
+ end
333
+
334
+ def get_exception_class(x)
335
+ x.is_a?(Module) ? x : qualified_const_get(x)
336
+ end
337
+
338
+ # In Ruby <2.0 const_get can't lookup "SomeModule::SomeClass" in one go
339
+ def qualified_const_get(x)
340
+ x = x.to_s
341
+ if !x.match(/::/)
342
+ Object.const_get(x)
343
+ else
344
+ x.split(MODULE_SEPARATOR).reject(&:empty?).inject(Object) { |a, e| a.const_get(e) }
345
+ end
346
+ rescue NameError # There's no way to safely ask if a constant exist for an unknown string
347
+ nil
348
+ end
349
+
309
350
  def detect_release_from_heroku
310
351
  return unless running_on_heroku?
311
352
  logger.warn(heroku_dyno_metadata_message) && return unless ENV['HEROKU_SLUG_COMMIT']
@@ -361,6 +402,21 @@ module Raven
361
402
  false
362
403
  end
363
404
 
405
+ def heroku_dyno_name
406
+ return unless running_on_heroku?
407
+ ENV['DYNO']
408
+ end
409
+
410
+ def sample_allowed?
411
+ return true if sample_rate == 1.0
412
+ if Random::DEFAULT.rand >= sample_rate
413
+ @errors << "Excluded by random sample"
414
+ false
415
+ else
416
+ true
417
+ end
418
+ end
419
+
364
420
  # Try to resolve the hostname to an FQDN, but fall back to whatever
365
421
  # the load name is.
366
422
  def resolve_hostname