sentry-raven 1.1.0 → 3.1.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.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/.craft.yml +19 -0
  3. data/.scripts/bump-version.rb +5 -0
  4. data/CHANGELOG.md +703 -0
  5. data/Gemfile +37 -0
  6. data/Makefile +3 -0
  7. data/README.md +116 -18
  8. data/Rakefile +30 -0
  9. data/exe/raven +32 -0
  10. data/lib/raven/backtrace.rb +17 -8
  11. data/lib/raven/base.rb +45 -194
  12. data/lib/raven/breadcrumbs/active_support_logger.rb +25 -0
  13. data/lib/raven/breadcrumbs/logger.rb +3 -0
  14. data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
  15. data/lib/raven/breadcrumbs.rb +76 -0
  16. data/lib/raven/cli.rb +31 -39
  17. data/lib/raven/client.rb +45 -32
  18. data/lib/raven/configuration.rb +427 -130
  19. data/lib/raven/context.rb +33 -6
  20. data/lib/raven/core_ext/object/deep_dup.rb +57 -0
  21. data/lib/raven/core_ext/object/duplicable.rb +153 -0
  22. data/lib/raven/event.rb +194 -206
  23. data/lib/raven/helpers/deprecation_helper.rb +17 -0
  24. data/lib/raven/instance.rb +249 -0
  25. data/lib/raven/integrations/delayed_job.rb +25 -23
  26. data/lib/raven/integrations/rack-timeout.rb +22 -0
  27. data/lib/raven/integrations/rack.rb +40 -24
  28. data/lib/raven/integrations/rails/active_job.rb +52 -20
  29. data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
  30. data/lib/raven/integrations/rails/controller_transaction.rb +13 -0
  31. data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
  32. data/lib/raven/integrations/rails.rb +39 -7
  33. data/lib/raven/integrations/rake.rb +7 -2
  34. data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
  35. data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
  36. data/lib/raven/integrations/sidekiq.rb +6 -48
  37. data/lib/raven/integrations/tasks.rb +1 -1
  38. data/lib/raven/interface.rb +25 -0
  39. data/lib/raven/interfaces/exception.rb +5 -8
  40. data/lib/raven/interfaces/http.rb +5 -12
  41. data/lib/raven/interfaces/message.rb +10 -6
  42. data/lib/raven/interfaces/single_exception.rb +1 -5
  43. data/lib/raven/interfaces/stack_trace.rb +23 -30
  44. data/lib/raven/linecache.rb +35 -23
  45. data/lib/raven/logger.rb +13 -16
  46. data/lib/raven/processor/cookies.rb +27 -7
  47. data/lib/raven/processor/http_headers.rb +55 -0
  48. data/lib/raven/processor/post_data.rb +16 -3
  49. data/lib/raven/processor/removecircularreferences.rb +12 -8
  50. data/lib/raven/processor/removestacktrace.rb +17 -6
  51. data/lib/raven/processor/sanitizedata.rb +92 -37
  52. data/lib/raven/processor/utf8conversion.rb +39 -14
  53. data/lib/raven/processor.rb +5 -1
  54. data/lib/raven/transports/http.rb +31 -22
  55. data/lib/raven/transports/stdout.rb +20 -0
  56. data/lib/raven/transports.rb +6 -10
  57. data/lib/raven/utils/context_filter.rb +42 -0
  58. data/lib/raven/utils/deep_merge.rb +6 -12
  59. data/lib/raven/utils/exception_cause_chain.rb +20 -0
  60. data/lib/raven/utils/real_ip.rb +62 -0
  61. data/lib/raven/utils/request_id.rb +16 -0
  62. data/lib/raven/version.rb +2 -1
  63. data/lib/sentry-raven-without-integrations.rb +6 -1
  64. data/lib/sentry_raven_without_integrations.rb +1 -0
  65. data/sentry-raven.gemspec +28 -0
  66. metadata +44 -127
  67. data/lib/raven/error.rb +0 -4
  68. data/lib/raven/interfaces.rb +0 -34
  69. data/lib/raven/okjson.rb +0 -614
@@ -0,0 +1,73 @@
1
+ require 'logger'
2
+
3
+ module Raven
4
+ module Breadcrumbs
5
+ module SentryLogger
6
+ LEVELS = {
7
+ ::Logger::DEBUG => 'debug',
8
+ ::Logger::INFO => 'info',
9
+ ::Logger::WARN => 'warn',
10
+ ::Logger::ERROR => 'error',
11
+ ::Logger::FATAL => 'fatal'
12
+ }.freeze
13
+
14
+ def add(*args)
15
+ add_breadcrumb(*args)
16
+ super
17
+ end
18
+
19
+ def add_breadcrumb(severity, message = nil, progname = nil)
20
+ message = progname if message.nil? # see Ruby's Logger docs for why
21
+ return if ignored_logger?(progname)
22
+ return if message.nil? || message == ""
23
+
24
+ # some loggers will add leading/trailing space as they (incorrectly, mind you)
25
+ # think of logging as a shortcut to std{out,err}
26
+ message = message.to_s.strip
27
+
28
+ last_crumb = Raven.breadcrumbs.peek
29
+ # try to avoid dupes from logger broadcasts
30
+ if last_crumb.nil? || last_crumb.message != message
31
+ Raven.breadcrumbs.record do |crumb|
32
+ crumb.level = Raven::Breadcrumbs::SentryLogger::LEVELS.fetch(severity, nil)
33
+ crumb.category = progname || 'logger'
34
+ crumb.message = message
35
+ crumb.type =
36
+ if severity >= 3
37
+ "error"
38
+ else
39
+ crumb.level
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def ignored_logger?(progname)
48
+ progname == "sentry" ||
49
+ Raven.configuration.exclude_loggers.include?(progname)
50
+ end
51
+ end
52
+ module OldBreadcrumbsSentryLogger
53
+ def self.included(base)
54
+ base.class_eval do
55
+ include Raven::Breadcrumbs::SentryLogger
56
+ alias_method :add_without_raven, :add
57
+ alias_method :add, :add_with_raven
58
+ end
59
+ end
60
+
61
+ def add_with_raven(*args)
62
+ add_breadcrumb(*args)
63
+ add_without_raven(*args)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ Raven.safely_prepend(
70
+ "Breadcrumbs::SentryLogger",
71
+ :from => Raven,
72
+ :to => ::Logger
73
+ )
@@ -0,0 +1,76 @@
1
+ module Raven
2
+ class Breadcrumb
3
+ attr_accessor :category, :data, :message, :level, :timestamp, :type
4
+
5
+ def initialize
6
+ @category = nil
7
+ @data = {}
8
+ @level = nil
9
+ @message = nil
10
+ @timestamp = Time.now.to_i
11
+ @type = nil
12
+ end
13
+
14
+ def to_hash
15
+ {
16
+ :category => @category,
17
+ :data => @data,
18
+ :level => @level,
19
+ :message => @message,
20
+ :timestamp => @timestamp,
21
+ :type => @type
22
+ }
23
+ end
24
+ end
25
+ end
26
+
27
+ module Raven
28
+ class BreadcrumbBuffer
29
+ include Enumerable
30
+
31
+ attr_accessor :buffer
32
+
33
+ def self.current
34
+ Thread.current[:sentry_breadcrumbs] ||= new
35
+ end
36
+
37
+ def self.clear!
38
+ Thread.current[:sentry_breadcrumbs] = nil
39
+ end
40
+
41
+ def initialize(size = 100)
42
+ @buffer = Array.new(size)
43
+ end
44
+
45
+ def record(crumb = nil)
46
+ if block_given?
47
+ crumb = Breadcrumb.new if crumb.nil?
48
+ yield(crumb)
49
+ end
50
+ @buffer.slice!(0)
51
+ @buffer << crumb
52
+ end
53
+
54
+ def members
55
+ @buffer.compact
56
+ end
57
+
58
+ def peek
59
+ members.last
60
+ end
61
+
62
+ def each(&block)
63
+ members.each(&block)
64
+ end
65
+
66
+ def empty?
67
+ members.none?
68
+ end
69
+
70
+ def to_hash
71
+ {
72
+ :values => members.map(&:to_hash)
73
+ }
74
+ end
75
+ end
76
+ end
data/lib/raven/cli.rb CHANGED
@@ -1,56 +1,48 @@
1
1
  module Raven
2
2
  class CLI
3
- def self.test(dsn = nil)
4
- require 'logger'
5
-
6
- logger = ::Logger.new(STDOUT)
7
- logger.level = ::Logger::ERROR
8
- logger.formatter = proc do |_severity, _datetime, _progname, msg|
9
- "-> #{msg}\n"
10
- end
11
-
12
- Raven.configuration.logger = logger
13
- Raven.configuration.timeout = 5
14
- Raven.configuration.dsn = dsn if dsn
3
+ def self.test(dsn = nil, silent = false, config = nil)
4
+ config ||= Raven.configuration
5
+
6
+ config.logger = if silent
7
+ ::Logger.new(nil)
8
+ else
9
+ logger = ::Logger.new(STDOUT)
10
+ logger.formatter = proc do |_severity, _datetime, _progname, msg|
11
+ "-> #{msg}\n"
12
+ end
13
+ logger
14
+ end
15
+
16
+ config.timeout = 5
17
+ config.dsn = dsn if dsn
15
18
 
16
19
  # wipe out env settings to ensure we send the event
17
- unless Raven.configuration.send_in_current_environment?
18
- env_name = Raven.configuration.environments.pop || 'production'
19
- puts "Setting environment to #{env_name}"
20
- Raven.configuration.current_environment = env_name
20
+ unless config.capture_allowed?
21
+ env_name = config.environments.last || 'production'
22
+ config.current_environment = env_name
21
23
  end
22
24
 
23
- Raven.configuration.verify!
25
+ instance = Raven::Instance.new(nil, config)
24
26
 
25
- puts "Sending a test event:"
26
- puts ""
27
+ instance.logger.debug "Sending a test event:"
28
+ instance.logger.debug ""
27
29
 
28
30
  begin
29
31
  1 / 0
30
- rescue ZeroDivisionError => exception
31
- evt = Raven.capture_exception(exception)
32
+ rescue ZeroDivisionError => e
33
+ evt = instance.capture_exception(e)
32
34
  end
33
35
 
34
- if evt && !(evt.is_a? Thread)
35
- if evt.is_a? Hash
36
- puts "-> event ID: #{evt[:event_id]}"
37
- else
38
- puts "-> event ID: #{evt.id}"
39
- end
40
- elsif evt #async configuration
41
- if evt.value.is_a? Hash
42
- puts "-> event ID: #{evt.value[:event_id]}"
43
- else
44
- puts "-> event ID: #{evt.value.id}"
45
- end
36
+ if evt
37
+ instance.logger.debug "-> event ID: #{evt.id}"
38
+ instance.logger.debug ""
39
+ instance.logger.debug "Done!"
40
+ evt
46
41
  else
47
- puts ""
48
- puts "An error occurred while attempting to send the event."
49
- exit 1
42
+ instance.logger.debug ""
43
+ instance.logger.debug "An error occurred while attempting to send the event."
44
+ false
50
45
  end
51
-
52
- puts ""
53
- puts "Done!"
54
46
  end
55
47
  end
56
48
  end
data/lib/raven/client.rb CHANGED
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
- require 'zlib'
2
+
3
3
  require 'base64'
4
+ require 'json'
5
+ require 'zlib'
4
6
 
5
- require 'raven/version'
6
- require 'raven/okjson'
7
- require 'raven/transports/http'
7
+ require "raven/transports"
8
8
 
9
9
  module Raven
10
10
  # Encodes events and sends them to the Sentry server.
11
11
  class Client
12
- PROTOCOL_VERSION = '5'.freeze
13
- USER_AGENT = "raven-ruby/#{Raven::VERSION}".freeze
14
- CONTENT_TYPE = 'application/json'.freeze
12
+ PROTOCOL_VERSION = '5'
13
+ USER_AGENT = "raven-ruby/#{Raven::VERSION}"
14
+ CONTENT_TYPE = 'application/json'
15
15
 
16
16
  attr_accessor :configuration
17
17
 
@@ -21,8 +21,14 @@ module Raven
21
21
  @state = ClientState.new
22
22
  end
23
23
 
24
- def send_event(event)
25
- return false unless configuration_allows_sending
24
+ def send_event(event, hint = nil)
25
+ return false unless configuration.sending_allowed?(event)
26
+
27
+ event = configuration.before_send.call(event, hint) if configuration.before_send
28
+ if event.nil?
29
+ configuration.logger.info "Discarded event because before_send returned nil"
30
+ return
31
+ end
26
32
 
27
33
  # Convert to hash
28
34
  event = event.to_hash
@@ -32,13 +38,14 @@ module Raven
32
38
  return
33
39
  end
34
40
 
35
- Raven.logger.debug "Sending event #{event[:event_id]} to Sentry"
41
+ event_id = event[:event_id] || event['event_id']
42
+ configuration.logger.info "Sending event #{event_id} to Sentry"
36
43
 
37
44
  content_type, encoded_data = encode(event)
38
45
 
39
46
  begin
40
47
  transport.send_event(generate_auth_header, encoded_data,
41
- :content_type => content_type)
48
+ :content_type => content_type)
42
49
  successful_send
43
50
  rescue => e
44
51
  failed_send(e, event)
@@ -53,6 +60,8 @@ module Raven
53
60
  case configuration.scheme
54
61
  when 'http', 'https'
55
62
  Transports::HTTP.new(configuration)
63
+ when 'stdout'
64
+ Transports::Stdout.new(configuration)
56
65
  when 'dummy'
57
66
  Transports::Dummy.new(configuration)
58
67
  else
@@ -62,18 +71,9 @@ module Raven
62
71
 
63
72
  private
64
73
 
65
- def configuration_allows_sending
66
- if configuration.send_in_current_environment?
67
- true
68
- else
69
- configuration.log_excluded_environment_message
70
- false
71
- end
72
- end
73
-
74
74
  def encode(event)
75
- hash = @processors.reduce(event.to_hash) { |memo, p| p.process(memo) }
76
- encoded = OkJson.encode(hash)
75
+ hash = @processors.reduce(event.to_hash) { |a, e| e.process(a) }
76
+ encoded = JSON.fast_generate(hash)
77
77
 
78
78
  case configuration.encoding
79
79
  when 'gzip'
@@ -83,8 +83,20 @@ module Raven
83
83
  end
84
84
  end
85
85
 
86
+ def get_message_from_exception(event)
87
+ (
88
+ event &&
89
+ event[:exception] &&
90
+ event[:exception][:values] &&
91
+ event[:exception][:values][0] &&
92
+ event[:exception][:values][0][:type] &&
93
+ event[:exception][:values][0][:value] &&
94
+ "#{event[:exception][:values][0][:type]}: #{event[:exception][:values][0][:value]}"
95
+ )
96
+ end
97
+
86
98
  def get_log_message(event)
87
- (event && event[:message]) || '<no message value>'
99
+ (event && event[:message]) || (event && event['message']) || get_message_from_exception(event) || '<no message value>'
88
100
  end
89
101
 
90
102
  def generate_auth_header
@@ -93,9 +105,9 @@ module Raven
93
105
  'sentry_version' => PROTOCOL_VERSION,
94
106
  'sentry_client' => USER_AGENT,
95
107
  'sentry_timestamp' => now,
96
- 'sentry_key' => configuration.public_key,
97
- 'sentry_secret' => configuration.secret_key
108
+ 'sentry_key' => configuration.public_key
98
109
  }
110
+ fields['sentry_secret'] = configuration.secret_key unless configuration.secret_key.nil?
99
111
  'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
100
112
  end
101
113
 
@@ -104,15 +116,16 @@ module Raven
104
116
  end
105
117
 
106
118
  def failed_send(e, event)
107
- @state.failure
108
119
  if e # exception was raised
109
- Raven.logger.error "Unable to record event with remote Sentry server (#{e.class} - #{e.message})"
110
- e.backtrace[0..10].each { |line| Raven.logger.error(line) }
120
+ @state.failure
121
+ configuration.logger.warn "Unable to record event with remote Sentry server (#{e.class} - #{e.message}):\n#{e.backtrace[0..10].join("\n")}"
111
122
  else
112
- Raven.logger.error "Not sending event due to previous failure(s)."
123
+ configuration.logger.warn "Not sending event due to previous failure(s)."
113
124
  end
114
- Raven.logger.error("Failed to submit event: #{get_log_message(event)}")
115
- configuration.transport_failure_callback.call(event) if configuration.transport_failure_callback
125
+ configuration.logger.warn("Failed to submit event: #{get_log_message(event)}")
126
+
127
+ # configuration.transport_failure_callback can be false & nil
128
+ configuration.transport_failure_callback.call(event, e) if configuration.transport_failure_callback # rubocop:disable Style/SafeNavigation
116
129
  end
117
130
  end
118
131
 
@@ -124,7 +137,7 @@ module Raven
124
137
  def should_try?
125
138
  return true if @status == :online
126
139
 
127
- interval = @retry_after || [@retry_number, 6].min ** 2
140
+ interval = @retry_after || [@retry_number, 6].min**2
128
141
  return true if Time.now - @last_check >= interval
129
142
 
130
143
  false