sentry-raven 1.1.0 → 1.2.0

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.
@@ -100,6 +100,9 @@ module Raven
100
100
  # Deprecated accessor
101
101
  attr_accessor :catch_debugged_exceptions
102
102
 
103
+ # Turns on ActiveSupport breadcrumbs integration
104
+ attr_accessor :rails_activesupport_breadcrumbs
105
+
103
106
  # Provide a configurable callback to determine event capture
104
107
  attr_accessor :should_capture
105
108
 
@@ -109,6 +112,9 @@ module Raven
109
112
  # Sanitize values that look like credit card numbers
110
113
  attr_accessor :sanitize_credit_cards
111
114
 
115
+ # Logger 'progname's to exclude from breadcrumbs
116
+ attr_accessor :exclude_loggers
117
+
112
118
  IGNORE_DEFAULT = [
113
119
  'AbstractController::ActionNotFound',
114
120
  'ActionController::InvalidAuthenticityToken',
@@ -137,16 +143,18 @@ module Raven
137
143
  self.processors = DEFAULT_PROCESSORS.dup
138
144
  self.ssl_verification = true
139
145
  self.encoding = 'gzip'
140
- self.timeout = 1
146
+ self.timeout = 2
141
147
  self.open_timeout = 1
142
148
  self.proxy = nil
143
149
  self.tags = {}
144
150
  self.async = false
145
151
  self.rails_report_rescued_exceptions = true
152
+ self.rails_activesupport_breadcrumbs = false
146
153
  self.transport_failure_callback = false
147
154
  self.sanitize_fields = []
148
155
  self.sanitize_credit_cards = true
149
156
  self.environments = []
157
+ self.exclude_loggers = []
150
158
 
151
159
  self.release = detect_release
152
160
 
@@ -31,6 +31,7 @@ module Raven
31
31
  def initialize(init = {})
32
32
  @configuration = Raven.configuration
33
33
  @interfaces = {}
34
+ @breadcrumbs = Raven.breadcrumbs
34
35
  @context = Raven.context
35
36
  @id = generate_event_id
36
37
  @project = nil
@@ -224,6 +225,7 @@ module Raven
224
225
  data[:extra] = @extra if @extra
225
226
  data[:tags] = @tags if @tags
226
227
  data[:user] = @user if @user
228
+ data[:breadcrumbs] = @breadcrumbs.to_hash unless @breadcrumbs.empty?
227
229
  data[:checksum] = @checksum if @checksum
228
230
  @interfaces.each_pair do |name, int_data|
229
231
  data[name.to_sym] = int_data.to_hash
@@ -0,0 +1,223 @@
1
+ require 'raven/base'
2
+ require 'English'
3
+
4
+ module Raven
5
+ # A copy of Raven's base module class methods, minus some of the integration
6
+ # and global hooks since it's meant to be used explicitly. Useful for
7
+ # sending errors to multiple sentry projects in a large application.
8
+ #
9
+ # @example
10
+ # class Foo
11
+ # def initialize
12
+ # @other_raven = Raven::Instance.new
13
+ # @other_raven.configure do |config|
14
+ # config.server = 'http://...'
15
+ # end
16
+ # end
17
+ #
18
+ # def foo
19
+ # # ...
20
+ # rescue => e
21
+ # @other_raven.capture_exception(e)
22
+ # end
23
+ # end
24
+ class Instance
25
+ # The client object is responsible for delivering formatted data to the
26
+ # Sentry server. Must respond to #send. See Raven::Client.
27
+ attr_writer :client
28
+
29
+ # A Raven configuration object. Must act like a hash and return sensible
30
+ # values for all Raven configuration options. See Raven::Configuration.
31
+ attr_writer :configuration
32
+
33
+ def initialize(context = nil)
34
+ @context = @explicit_context = context
35
+ end
36
+
37
+ def context
38
+ if @explicit_context
39
+ @context ||= Context.new
40
+ else
41
+ Context.current
42
+ end
43
+ end
44
+
45
+ def logger
46
+ @logger ||= Logger.new
47
+ end
48
+
49
+ # The configuration object.
50
+ # @see Raven.configure
51
+ def configuration
52
+ @configuration ||= Configuration.new
53
+ end
54
+
55
+ # The client object is responsible for delivering formatted data to the
56
+ # Sentry server.
57
+ def client
58
+ @client ||= Client.new(configuration)
59
+ end
60
+
61
+ # Tell the log that the client is good to go
62
+ def report_status
63
+ return if client.configuration.silence_ready
64
+ if client.configuration.send_in_current_environment?
65
+ logger.info "Raven #{VERSION} ready to catch errors"
66
+ else
67
+ logger.info "Raven #{VERSION} configured not to send errors."
68
+ end
69
+ end
70
+
71
+ # Call this method to modify defaults in your initializers.
72
+ #
73
+ # @example
74
+ # Raven.configure do |config|
75
+ # config.server = 'http://...'
76
+ # end
77
+ def configure
78
+ yield(configuration) if block_given?
79
+
80
+ self.client = Client.new(configuration)
81
+ report_status
82
+ client
83
+ end
84
+
85
+ # Send an event to the configured Sentry server
86
+ #
87
+ # @example
88
+ # evt = Raven::Event.new(:message => "An error")
89
+ # Raven.send_event(evt)
90
+ def send_event(event)
91
+ client.send_event(event)
92
+ end
93
+
94
+ # Capture and process any exceptions from the given block.
95
+ #
96
+ # @example
97
+ # Raven.capture do
98
+ # MyApp.run
99
+ # end
100
+ def capture(options = {})
101
+ if block_given?
102
+ begin
103
+ yield
104
+ rescue Error
105
+ raise # Don't capture Raven errors
106
+ rescue Exception => e
107
+ capture_type(e, options)
108
+ raise
109
+ end
110
+ else
111
+ install_at_exit_hook(options)
112
+ end
113
+ end
114
+
115
+ def capture_type(obj, options = {})
116
+ return false unless should_capture?(obj)
117
+ message_or_exc = obj.is_a?(String) ? "message" : "exception"
118
+ if (evt = Event.send("from_" + message_or_exc, obj, options))
119
+ yield evt if block_given?
120
+ if configuration.async?
121
+ configuration.async.call(evt)
122
+ else
123
+ send_event(evt)
124
+ end
125
+ Thread.current["sentry_#{object_id}_last_event_id".to_sym] = evt.id
126
+ evt
127
+ end
128
+ end
129
+
130
+ def last_event_id
131
+ Thread.current["sentry_#{object_id}_last_event_id".to_sym]
132
+ end
133
+
134
+ def should_capture?(message_or_exc)
135
+ if configuration.should_capture
136
+ configuration.should_capture.call(*[message_or_exc])
137
+ else
138
+ true
139
+ end
140
+ end
141
+
142
+ # Provides extra context to the exception prior to it being handled by
143
+ # Raven. An exception can have multiple annotations, which are merged
144
+ # together.
145
+ #
146
+ # The options (annotation) is treated the same as the ``options``
147
+ # parameter to ``capture_exception`` or ``Event.from_exception``, and
148
+ # can contain the same ``:user``, ``:tags``, etc. options as these
149
+ # methods.
150
+ #
151
+ # These will be merged with the ``options`` parameter to
152
+ # ``Event.from_exception`` at the top of execution.
153
+ #
154
+ # @example
155
+ # begin
156
+ # raise "Hello"
157
+ # rescue => exc
158
+ # Raven.annotate_exception(exc, :user => { 'id' => 1,
159
+ # 'email' => 'foo@example.com' })
160
+ # end
161
+ def annotate_exception(exc, options = {})
162
+ notes = (exc.instance_variable_defined?(:@__raven_context) && exc.instance_variable_get(:@__raven_context)) || {}
163
+ notes.merge!(options)
164
+ exc.instance_variable_set(:@__raven_context, notes)
165
+ exc
166
+ end
167
+
168
+ # Bind user context. Merges with existing context (if any).
169
+ #
170
+ # It is recommending that you send at least the ``id`` and ``email``
171
+ # values. All other values are arbitrary.
172
+ #
173
+ # @example
174
+ # Raven.user_context('id' => 1, 'email' => 'foo@example.com')
175
+ def user_context(options = nil)
176
+ context.user = options || {}
177
+ end
178
+
179
+ # Bind tags context. Merges with existing context (if any).
180
+ #
181
+ # Tags are key / value pairs which generally represent things like
182
+ # application version, environment, role, and server names.
183
+ #
184
+ # @example
185
+ # Raven.tags_context('my_custom_tag' => 'tag_value')
186
+ def tags_context(options = nil)
187
+ context.tags.merge!(options || {})
188
+ end
189
+
190
+ # Bind extra context. Merges with existing context (if any).
191
+ #
192
+ # Extra context shows up as Additional Data within Sentry, and is
193
+ # completely arbitrary.
194
+ #
195
+ # @example
196
+ # Raven.extra_context('my_custom_data' => 'value')
197
+ def extra_context(options = nil)
198
+ context.extra.merge!(options || {})
199
+ end
200
+
201
+ def rack_context(env)
202
+ env = nil if env.empty?
203
+
204
+ context.rack_env = env
205
+ end
206
+
207
+ def breadcrumbs
208
+ BreadcrumbBuffer.current
209
+ end
210
+
211
+ private
212
+
213
+ def install_at_exit_hook(options)
214
+ at_exit do
215
+ exception = $ERROR_INFO
216
+ if exception
217
+ logger.debug "Caught a post-mortem exception: #{exception.inspect}"
218
+ capture_type(exception, options)
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
@@ -43,6 +43,7 @@ module Raven
43
43
  def call(env)
44
44
  # clear context at the beginning of the request to ensure a clean slate
45
45
  Context.clear!
46
+ BreadcrumbBuffer.clear!
46
47
 
47
48
  # store the current environment in our local context for arbitrary
48
49
  # callers
@@ -13,26 +13,37 @@ module Raven
13
13
  ActiveSupport.on_load :action_controller do
14
14
  include Raven::Rails::ControllerMethods
15
15
  if ::Rails::VERSION::STRING >= "4.0.0"
16
- Raven.rails_safely_prepend("StreamingReporter", :to => ActionController::Live)
16
+ Raven.safely_prepend(
17
+ "StreamingReporter",
18
+ :from => Raven::Rails::Overrides,
19
+ :to => ActionController::Live
20
+ )
17
21
  end
18
22
  end
19
23
  end
20
24
 
21
25
  initializer 'raven.action_view' do
22
26
  ActiveSupport.on_load :action_view do
23
- Raven.rails_safely_prepend("StreamingReporter", :to => ActionView::StreamingTemplateRenderer::Body)
27
+ Raven.safely_prepend(
28
+ "StreamingReporter",
29
+ :from => Raven::Rails::Overrides,
30
+ :to => ActionView::StreamingTemplateRenderer::Body
31
+ )
24
32
  end
25
33
  end
26
34
 
27
- config.before_initialize do
35
+ config.after_initialize do
28
36
  Raven.configure do |config|
29
37
  config.logger ||= ::Rails.logger
30
38
  config.project_root ||= ::Rails.root
31
- config.release = config.detect_release # if project_root has changed, need to re-check
39
+ config.release ||= config.detect_release # if project_root has changed, need to re-check
40
+ end
41
+
42
+ if Raven.configuration.rails_activesupport_breadcrumbs
43
+ require 'raven/breadcrumbs/activesupport'
44
+ Raven::ActiveSupportBreadcrumbs.inject
32
45
  end
33
- end
34
46
 
35
- config.after_initialize do
36
47
  if Raven.configuration.rails_report_rescued_exceptions
37
48
  require 'raven/integrations/rails/overrides/debug_exceptions_catcher'
38
49
  if defined?(::ActionDispatch::DebugExceptions)
@@ -40,7 +51,12 @@ module Raven
40
51
  elsif defined?(::ActionDispatch::ShowExceptions)
41
52
  exceptions_class = ::ActionDispatch::ShowExceptions
42
53
  end
43
- Raven.rails_safely_prepend("DebugExceptionsCatcher", :to => exceptions_class)
54
+
55
+ Raven.safely_prepend(
56
+ "DebugExceptionsCatcher",
57
+ :from => Raven::Rails::Overrides,
58
+ :to => exceptions_class
59
+ )
44
60
  end
45
61
  end
46
62
 
@@ -1,8 +1,18 @@
1
1
  # frozen_string_literal: true
2
+ require 'logger'
3
+
2
4
  module Raven
3
5
  class Logger
4
6
  LOG_PREFIX = "** [Raven] ".freeze
5
7
 
8
+ LEVELS = {
9
+ :debug => ::Logger::DEBUG,
10
+ :info => ::Logger::INFO,
11
+ :warn => ::Logger::WARN,
12
+ :error => ::Logger::ERROR,
13
+ :fatal => ::Logger::FATAL
14
+ }.freeze
15
+
6
16
  [
7
17
  :fatal,
8
18
  :error,
@@ -16,7 +26,7 @@ module Raven
16
26
  logger = Raven.configuration[:logger]
17
27
  logger = ::Logger.new(STDOUT) if logger.nil?
18
28
 
19
- logger.send(level, "#{LOG_PREFIX}#{msg}") if logger
29
+ logger.add(LEVELS[level], "#{LOG_PREFIX}#{msg}", "sentry") if logger
20
30
  end
21
31
  end
22
32
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'json'
3
+
3
4
  module Raven
4
5
  class Processor::SanitizeData < Processor
5
6
  STRING_MASK = '********'.freeze
@@ -72,8 +73,8 @@ module Raven
72
73
 
73
74
  def parse_json_or_nil(string)
74
75
  begin
75
- OkJson.decode(string)
76
- rescue Raven::OkJson::Error, NoMethodError
76
+ JSON.parse(string)
77
+ rescue JSON::ParserError, NoMethodError
77
78
  nil
78
79
  end
79
80
  end
@@ -18,13 +18,11 @@ module Raven
18
18
  project_id = configuration[:project_id]
19
19
  path = configuration[:path] + "/"
20
20
 
21
- response = conn.post "#{path}api/#{project_id}/store/" do |req|
21
+ conn.post "#{path}api/#{project_id}/store/" do |req|
22
22
  req.headers['Content-Type'] = options[:content_type]
23
23
  req.headers['X-Sentry-Auth'] = auth_header
24
24
  req.body = data
25
25
  end
26
- Raven.logger.warn "Error from Sentry server (#{response.status}): #{response.body}" unless response.status == 200
27
- response
28
26
  end
29
27
 
30
28
  private
@@ -42,6 +40,7 @@ module Raven
42
40
  :url => configuration[:server],
43
41
  :ssl => ssl_configuration
44
42
  ) do |builder|
43
+ builder.response :raise_error
45
44
  builder.adapter(*adapter)
46
45
  end
47
46
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module Raven
3
- VERSION = "1.1.0".freeze
3
+ # Freezing this constant breaks in 1.9.x
4
+ VERSION = "1.2.0" # rubocop:disable Style/MutableConstant
4
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-raven
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-07 00:00:00.000000000 Z
11
+ date: 2016-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.7.6
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.10.x
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: 0.7.6
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.10.x
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: rake
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -42,16 +48,16 @@ dependencies:
42
48
  name: rubocop
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - ">="
51
+ - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '0'
53
+ version: 0.41.1
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
- - - ">="
58
+ - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: '0'
60
+ version: 0.41.1
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: rspec
57
63
  requirement: !ruby/object:Gem::Requirement
@@ -80,34 +86,6 @@ dependencies:
80
86
  - - ">="
81
87
  - !ruby/object:Gem::Version
82
88
  version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: mime-types
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rest-client
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
89
  - !ruby/object:Gem::Dependency
112
90
  name: timecop
113
91
  requirement: !ruby/object:Gem::Requirement
@@ -149,12 +127,16 @@ files:
149
127
  - lib/raven.rb
150
128
  - lib/raven/backtrace.rb
151
129
  - lib/raven/base.rb
130
+ - lib/raven/breadcrumbs.rb
131
+ - lib/raven/breadcrumbs/activesupport.rb
132
+ - lib/raven/breadcrumbs/logger.rb
152
133
  - lib/raven/cli.rb
153
134
  - lib/raven/client.rb
154
135
  - lib/raven/configuration.rb
155
136
  - lib/raven/context.rb
156
137
  - lib/raven/error.rb
157
138
  - lib/raven/event.rb
139
+ - lib/raven/instance.rb
158
140
  - lib/raven/integrations/delayed_job.rb
159
141
  - lib/raven/integrations/rack.rb
160
142
  - lib/raven/integrations/rails.rb
@@ -174,7 +156,6 @@ files:
174
156
  - lib/raven/interfaces/stack_trace.rb
175
157
  - lib/raven/linecache.rb
176
158
  - lib/raven/logger.rb
177
- - lib/raven/okjson.rb
178
159
  - lib/raven/processor.rb
179
160
  - lib/raven/processor/cookies.rb
180
161
  - lib/raven/processor/post_data.rb
@@ -214,4 +195,3 @@ signing_key:
214
195
  specification_version: 4
215
196
  summary: A gem that provides a client interface for the Sentry error logger
216
197
  test_files: []
217
- has_rdoc: true