sentry-ruby 4.1.0 → 4.1.5.pre.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -7
  3. metadata +31 -59
  4. data/.craft.yml +0 -19
  5. data/.gitignore +0 -11
  6. data/.rspec +0 -3
  7. data/.travis.yml +0 -6
  8. data/CHANGELOG.md +0 -89
  9. data/CODE_OF_CONDUCT.md +0 -74
  10. data/Gemfile +0 -16
  11. data/Rakefile +0 -8
  12. data/bin/console +0 -14
  13. data/bin/setup +0 -8
  14. data/lib/sentry-ruby.rb +0 -141
  15. data/lib/sentry/background_worker.rb +0 -37
  16. data/lib/sentry/backtrace.rb +0 -128
  17. data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
  18. data/lib/sentry/breadcrumb.rb +0 -25
  19. data/lib/sentry/breadcrumb/sentry_logger.rb +0 -87
  20. data/lib/sentry/breadcrumb_buffer.rb +0 -47
  21. data/lib/sentry/client.rb +0 -86
  22. data/lib/sentry/configuration.rb +0 -399
  23. data/lib/sentry/core_ext/object/deep_dup.rb +0 -57
  24. data/lib/sentry/core_ext/object/duplicable.rb +0 -153
  25. data/lib/sentry/dsn.rb +0 -48
  26. data/lib/sentry/event.rb +0 -177
  27. data/lib/sentry/hub.rb +0 -137
  28. data/lib/sentry/interface.rb +0 -22
  29. data/lib/sentry/interfaces/exception.rb +0 -11
  30. data/lib/sentry/interfaces/request.rb +0 -74
  31. data/lib/sentry/interfaces/single_exception.rb +0 -14
  32. data/lib/sentry/interfaces/stacktrace.rb +0 -57
  33. data/lib/sentry/linecache.rb +0 -44
  34. data/lib/sentry/logger.rb +0 -20
  35. data/lib/sentry/rack.rb +0 -4
  36. data/lib/sentry/rack/capture_exceptions.rb +0 -54
  37. data/lib/sentry/rack/interface.rb +0 -22
  38. data/lib/sentry/rake.rb +0 -17
  39. data/lib/sentry/scope.rb +0 -214
  40. data/lib/sentry/span.rb +0 -132
  41. data/lib/sentry/transaction.rb +0 -157
  42. data/lib/sentry/transaction_event.rb +0 -29
  43. data/lib/sentry/transport.rb +0 -87
  44. data/lib/sentry/transport/configuration.rb +0 -21
  45. data/lib/sentry/transport/dummy_transport.rb +0 -14
  46. data/lib/sentry/transport/http_transport.rb +0 -62
  47. data/lib/sentry/utils/exception_cause_chain.rb +0 -20
  48. data/lib/sentry/utils/real_ip.rb +0 -70
  49. data/lib/sentry/utils/request_id.rb +0 -16
  50. data/lib/sentry/version.rb +0 -3
  51. data/sentry-ruby.gemspec +0 -27
@@ -1,47 +0,0 @@
1
- require "sentry/breadcrumb"
2
-
3
- module Sentry
4
- class BreadcrumbBuffer
5
- include Enumerable
6
-
7
- attr_accessor :buffer
8
-
9
- def initialize(size = 100)
10
- @buffer = Array.new(size)
11
- end
12
-
13
- def record(crumb)
14
- yield(crumb) if block_given?
15
- @buffer.slice!(0)
16
- @buffer << crumb
17
- end
18
-
19
- def members
20
- @buffer.compact
21
- end
22
-
23
- def peek
24
- members.last
25
- end
26
-
27
- def each(&block)
28
- members.each(&block)
29
- end
30
-
31
- def empty?
32
- members.none?
33
- end
34
-
35
- def to_hash
36
- {
37
- :values => members.map(&:to_hash)
38
- }
39
- end
40
-
41
- def dup
42
- copy = super
43
- copy.buffer = buffer.deep_dup
44
- copy
45
- end
46
- end
47
- end
@@ -1,86 +0,0 @@
1
- require "sentry/transport"
2
-
3
- module Sentry
4
- class Client
5
- attr_reader :transport, :configuration
6
-
7
- def initialize(configuration)
8
- @configuration = configuration
9
-
10
- if transport_class = configuration.transport.transport_class
11
- @transport = transport_class.new(configuration)
12
- else
13
- @transport =
14
- case configuration.dsn&.scheme
15
- when 'http', 'https'
16
- HTTPTransport.new(configuration)
17
- else
18
- DummyTransport.new(configuration)
19
- end
20
- end
21
- end
22
-
23
- def capture_event(event, scope, hint = {})
24
- return false unless configuration.sending_allowed?
25
-
26
- scope.apply_to_event(event, hint)
27
-
28
- if configuration.async?
29
- begin
30
- # We have to convert to a JSON-like hash, because background job
31
- # processors (esp ActiveJob) may not like weird types in the event hash
32
- configuration.async.call(event.to_json_compatible)
33
- rescue => e
34
- configuration.logger.error(LOGGER_PROGNAME) { "async event sending failed: #{e.message}" }
35
- send_event(event, hint)
36
- end
37
- else
38
- if hint.fetch(:background, true)
39
- Sentry.background_worker.perform do
40
- send_event(event, hint)
41
- end
42
- else
43
- send_event(event, hint)
44
- end
45
- end
46
-
47
- event
48
- end
49
-
50
- def event_from_exception(exception)
51
- return unless @configuration.exception_class_allowed?(exception)
52
-
53
- Event.new(configuration: configuration).tap do |event|
54
- event.add_exception_interface(exception)
55
- end
56
- end
57
-
58
- def event_from_message(message)
59
- Event.new(configuration: configuration, message: message)
60
- end
61
-
62
- def event_from_transaction(transaction)
63
- TransactionEvent.new(configuration: configuration).tap do |event|
64
- event.transaction = transaction.name
65
- event.contexts.merge!(trace: transaction.get_trace_context)
66
- event.timestamp = transaction.timestamp
67
- event.start_timestamp = transaction.start_timestamp
68
-
69
- finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
70
- event.spans = finished_spans.map(&:to_hash)
71
- end
72
- end
73
-
74
- def send_event(event, hint = nil)
75
- event = configuration.before_send.call(event, hint) if configuration.before_send
76
- if event.nil?
77
- configuration.logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
78
- return
79
- end
80
-
81
- transport.send_event(event)
82
-
83
- event
84
- end
85
- end
86
- end
@@ -1,399 +0,0 @@
1
- require "concurrent/utility/processor_counter"
2
-
3
- require "sentry/utils/exception_cause_chain"
4
- require "sentry/dsn"
5
- require "sentry/transport/configuration"
6
- require "sentry/linecache"
7
-
8
- module Sentry
9
- class Configuration
10
- # Directories to be recognized as part of your app. e.g. if you
11
- # have an `engines` dir at the root of your project, you may want
12
- # to set this to something like /(app|config|engines|lib)/
13
- attr_accessor :app_dirs_pattern
14
-
15
- # Provide an object that responds to `call` to send events asynchronously.
16
- # E.g.: lambda { |event| Thread.new { Sentry.send_event(event) } }
17
- attr_reader :async
18
- alias async? async
19
-
20
- # to send events in a non-blocking way, sentry-ruby has its own background worker
21
- # by default, the worker holds a thread pool that has [the number of processors] threads
22
- # but you can configure it with this configuration option
23
- # E.g.: config.background_worker_threads = 5
24
- #
25
- # if you want to send events synchronously, set the value to 0
26
- # E.g.: config.background_worker_threads = 0
27
- attr_accessor :background_worker_threads
28
-
29
- # a proc/lambda that takes an array of stack traces
30
- # it'll be used to silence (reduce) backtrace of the exception
31
- #
32
- # for example:
33
- #
34
- # ```ruby
35
- # Sentry.configuration.backtrace_cleanup_callback = lambda do |backtrace|
36
- # Rails.backtrace_cleaner.clean(backtrace)
37
- # end
38
- # ```
39
- #
40
- attr_accessor :backtrace_cleanup_callback
41
-
42
- # Optional Proc, called before sending an event to the server/
43
- # E.g.: lambda { |event| event }
44
- # E.g.: lambda { |event| nil }
45
- # E.g.: lambda { |event|
46
- # event[:message] = 'a'
47
- # event
48
- # }
49
- attr_reader :before_send
50
-
51
- # An array of breadcrumbs loggers to be used. Available options are:
52
- # - :sentry_logger
53
- # - :active_support_logger
54
- attr_reader :breadcrumbs_logger
55
-
56
- # Number of lines of code context to capture, or nil for none
57
- attr_accessor :context_lines
58
-
59
- # RACK_ENV by default.
60
- attr_reader :environment
61
-
62
- # the dsn value, whether it's set via `config.dsn=` or `ENV["SENTRY_DSN"]`
63
- attr_reader :dsn
64
-
65
- # Whitelist of enabled_environments that will send notifications to Sentry. Array of Strings.
66
- attr_accessor :enabled_environments
67
-
68
- # Logger 'progname's to exclude from breadcrumbs
69
- attr_accessor :exclude_loggers
70
-
71
- # Array of exception classes that should never be sent. See IGNORE_DEFAULT.
72
- # You should probably append to this rather than overwrite it.
73
- attr_accessor :excluded_exceptions
74
-
75
- # Boolean to check nested exceptions when deciding if to exclude. Defaults to false
76
- attr_accessor :inspect_exception_causes_for_exclusion
77
- alias inspect_exception_causes_for_exclusion? inspect_exception_causes_for_exclusion
78
-
79
- # You may provide your own LineCache for matching paths with source files.
80
- # This may be useful if you need to get source code from places other than
81
- # the disk. See Sentry::LineCache for the required interface you must implement.
82
- attr_accessor :linecache
83
-
84
- # Logger used by Sentry. In Rails, this is the Rails logger, otherwise
85
- # Sentry provides its own Sentry::Logger.
86
- attr_accessor :logger
87
-
88
- # Project directory root for in_app detection. Could be Rails root, etc.
89
- # Set automatically for Rails.
90
- attr_reader :project_root
91
-
92
- # Array of rack env parameters to be included in the event sent to sentry.
93
- attr_accessor :rack_env_whitelist
94
-
95
- # Release tag to be passed with every event sent to Sentry.
96
- # We automatically try to set this to a git SHA or Capistrano release.
97
- attr_accessor :release
98
-
99
- # The sampling factor to apply to events. A value of 0.0 will not send
100
- # any events, and a value of 1.0 will send 100% of events.
101
- attr_accessor :sample_rate
102
-
103
- # Include module versions in reports - boolean.
104
- attr_accessor :send_modules
105
-
106
- # When send_default_pii's value is false (default), sensitive information like
107
- # - user ip
108
- # - user cookie
109
- # - request body
110
- # will not be sent to Sentry.
111
- attr_accessor :send_default_pii
112
-
113
- attr_accessor :server_name
114
-
115
- # Return a Transport::Configuration object for transport-related configurations.
116
- attr_reader :transport
117
-
118
- # Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
119
- attr_accessor :traces_sample_rate
120
-
121
- # Take a Proc that controls the sample rate for every tracing event, e.g.
122
- # ```
123
- # lambda do |tracing_context|
124
- # # tracing_context[:transaction_context] contains the information about the transaction
125
- # # tracing_context[:parent_sampled] contains the transaction's parent's sample decision
126
- # true # return value can be a boolean or a float between 0.0 and 1.0
127
- # end
128
- # ```
129
- attr_accessor :traces_sampler
130
-
131
- # these are not config options
132
- attr_reader :errors, :gem_specs
133
-
134
- # Most of these errors generate 4XX responses. In general, Sentry clients
135
- # only automatically report 5xx responses.
136
- IGNORE_DEFAULT = [
137
- 'CGI::Session::CookieStore::TamperedWithCookie',
138
- 'Mongoid::Errors::DocumentNotFound',
139
- 'Rack::QueryParser::InvalidParameterError',
140
- 'Rack::QueryParser::ParameterTypeError',
141
- 'Sinatra::NotFound'
142
- ].freeze
143
-
144
- RACK_ENV_WHITELIST_DEFAULT = %w(
145
- REMOTE_ADDR
146
- SERVER_NAME
147
- SERVER_PORT
148
- ).freeze
149
-
150
- HEROKU_DYNO_METADATA_MESSAGE = "You are running on Heroku but haven't enabled Dyno Metadata. For Sentry's "\
151
- "release detection to work correctly, please run `heroku labs:enable runtime-dyno-metadata`".freeze
152
-
153
- LOG_PREFIX = "** [Sentry] ".freeze
154
- MODULE_SEPARATOR = "::".freeze
155
-
156
- AVAILABLE_BREADCRUMBS_LOGGERS = [:sentry_logger, :active_support_logger].freeze
157
-
158
- def initialize
159
- self.async = false
160
- self.background_worker_threads = Concurrent.processor_count
161
- self.breadcrumbs_logger = []
162
- self.context_lines = 3
163
- self.environment = environment_from_env
164
- self.enabled_environments = []
165
- self.exclude_loggers = []
166
- self.excluded_exceptions = IGNORE_DEFAULT.dup
167
- self.inspect_exception_causes_for_exclusion = false
168
- self.linecache = ::Sentry::LineCache.new
169
- self.logger = ::Sentry::Logger.new(STDOUT)
170
- self.project_root = detect_project_root
171
-
172
- self.release = detect_release
173
- self.sample_rate = 1.0
174
- self.send_modules = true
175
- self.send_default_pii = false
176
- self.dsn = ENV['SENTRY_DSN']
177
- self.server_name = server_name_from_env
178
-
179
- self.before_send = false
180
- self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
181
-
182
- @transport = Transport::Configuration.new
183
- @gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
184
- post_initialization_callback
185
- end
186
-
187
- def dsn=(value)
188
- return if value.nil? || value.empty?
189
-
190
- @dsn = DSN.new(value)
191
- end
192
-
193
- alias server= dsn=
194
-
195
-
196
- def async=(value)
197
- unless value == false || value.respond_to?(:call)
198
- raise(ArgumentError, "async must be callable (or false to disable)")
199
- end
200
-
201
- @async = value
202
- end
203
-
204
- def breadcrumbs_logger=(logger)
205
- loggers =
206
- if logger.is_a?(Array)
207
- logger
208
- else
209
- unless AVAILABLE_BREADCRUMBS_LOGGERS.include?(logger)
210
- raise Sentry::Error, "Unsupported breadcrumbs logger. Supported loggers: #{AVAILABLE_BREADCRUMBS_LOGGERS}"
211
- end
212
-
213
- Array(logger)
214
- end
215
-
216
- require "sentry/breadcrumb/sentry_logger" if loggers.include?(:sentry_logger)
217
-
218
- @breadcrumbs_logger = logger
219
- end
220
-
221
- def before_send=(value)
222
- unless value == false || value.respond_to?(:call)
223
- raise ArgumentError, "before_send must be callable (or false to disable)"
224
- end
225
-
226
- @before_send = value
227
- end
228
-
229
- def environment=(environment)
230
- @environment = environment.to_s
231
- end
232
-
233
- def sending_allowed?
234
- @errors = []
235
-
236
- valid? &&
237
- capture_in_environment? &&
238
- sample_allowed?
239
- end
240
-
241
- def error_messages
242
- @errors = [@errors[0]] + @errors[1..-1].map(&:downcase) # fix case of all but first
243
- @errors.join(", ")
244
- end
245
-
246
- def project_root=(root_dir)
247
- @project_root = root_dir
248
- end
249
-
250
- def exception_class_allowed?(exc)
251
- if exc.is_a?(Sentry::Error)
252
- # Try to prevent error reporting loops
253
- logger.debug(LOGGER_PROGNAME) { "Refusing to capture Sentry error: #{exc.inspect}" }
254
- false
255
- elsif excluded_exception?(exc)
256
- logger.debug(LOGGER_PROGNAME) { "User excluded error: #{exc.inspect}" }
257
- false
258
- else
259
- true
260
- end
261
- end
262
-
263
- def enabled_in_current_env?
264
- enabled_environments.empty? || enabled_environments.include?(environment)
265
- end
266
-
267
- def tracing_enabled?
268
- !!((@traces_sample_rate && @traces_sample_rate > 0.0) || @traces_sampler)
269
- end
270
-
271
- private
272
-
273
- def detect_project_root
274
- if defined? Rails.root # we are in a Rails application
275
- Rails.root.to_s
276
- else
277
- Dir.pwd
278
- end
279
- end
280
-
281
- def detect_release
282
- detect_release_from_env ||
283
- detect_release_from_git ||
284
- detect_release_from_capistrano ||
285
- detect_release_from_heroku
286
- rescue => e
287
- logger.error(LOGGER_PROGNAME) { "Error detecting release: #{e.message}" }
288
- end
289
-
290
- def excluded_exception?(incoming_exception)
291
- excluded_exception_classes.any? do |excluded_exception|
292
- matches_exception?(excluded_exception, incoming_exception)
293
- end
294
- end
295
-
296
- def excluded_exception_classes
297
- @excluded_exception_classes ||= excluded_exceptions.map { |e| get_exception_class(e) }
298
- end
299
-
300
- def get_exception_class(x)
301
- x.is_a?(Module) ? x : safe_const_get(x)
302
- end
303
-
304
- def matches_exception?(excluded_exception_class, incoming_exception)
305
- if inspect_exception_causes_for_exclusion?
306
- Sentry::Utils::ExceptionCauseChain.exception_to_array(incoming_exception).any? { |cause| excluded_exception_class === cause }
307
- else
308
- excluded_exception_class === incoming_exception
309
- end
310
- end
311
-
312
- def safe_const_get(x)
313
- x = x.to_s unless x.is_a?(String)
314
- Object.const_get(x)
315
- rescue NameError # There's no way to safely ask if a constant exist for an unknown string
316
- nil
317
- end
318
-
319
- def detect_release_from_heroku
320
- return unless running_on_heroku?
321
- return if ENV['CI']
322
- logger.warn(LOGGER_PROGNAME) { HEROKU_DYNO_METADATA_MESSAGE } && return unless ENV['HEROKU_SLUG_COMMIT']
323
-
324
- ENV['HEROKU_SLUG_COMMIT']
325
- end
326
-
327
- def running_on_heroku?
328
- File.directory?("/etc/heroku")
329
- end
330
-
331
- def detect_release_from_capistrano
332
- revision_file = File.join(project_root, 'REVISION')
333
- revision_log = File.join(project_root, '..', 'revisions.log')
334
-
335
- if File.exist?(revision_file)
336
- File.read(revision_file).strip
337
- elsif File.exist?(revision_log)
338
- File.open(revision_log).to_a.last.strip.sub(/.*as release ([0-9]+).*/, '\1')
339
- end
340
- end
341
-
342
- def detect_release_from_git
343
- Sentry.sys_command("git rev-parse --short HEAD") if File.directory?(".git")
344
- end
345
-
346
- def detect_release_from_env
347
- ENV['SENTRY_RELEASE']
348
- end
349
-
350
- def capture_in_environment?
351
- return true if enabled_in_current_env?
352
-
353
- @errors << "Not configured to send/capture in environment '#{environment}'"
354
- false
355
- end
356
-
357
- def valid?
358
- if @dsn&.valid?
359
- true
360
- else
361
- @errors << "DSN not set or not valid"
362
- false
363
- end
364
- end
365
-
366
- def sample_allowed?
367
- return true if sample_rate == 1.0
368
-
369
- if Random::DEFAULT.rand >= sample_rate
370
- @errors << "Excluded by random sample"
371
- false
372
- else
373
- true
374
- end
375
- end
376
-
377
- # Try to resolve the hostname to an FQDN, but fall back to whatever
378
- # the load name is.
379
- def resolve_hostname
380
- Socket.gethostname ||
381
- Socket.gethostbyname(hostname).first rescue server_name
382
- end
383
-
384
- def environment_from_env
385
- ENV['SENTRY_CURRENT_ENV'] || ENV['SENTRY_ENVIRONMENT'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
386
- end
387
-
388
- def server_name_from_env
389
- if running_on_heroku?
390
- ENV['DYNO']
391
- else
392
- resolve_hostname
393
- end
394
- end
395
-
396
- # allow extensions to extend the Configuration class
397
- def post_initialization_callback; end
398
- end
399
- end