sentry-raven 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sentry-raven might be problematic. Click here for more details.

data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Raven-Ruby
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/sentry-raven.png)](http://badge.fury.io/rb/sentry-raven) [![Build Status](https://secure.travis-ci.org/getsentry/raven-ruby.png?branch=master)](http://travis-ci.org/getsentry/raven-ruby) [![Coverage Status](https://coveralls.io/repos/getsentry/raven-ruby/badge.png?branch=master)](https://coveralls.io/r/getsentry/raven-ruby)
3
+ [![Gem Version](https://img.shields.io/gem/v/sentry-raven.svg)](https://rubygems.org/gems/sentry-raven)
4
+ [![Build Status](https://img.shields.io/travis/getsentry/raven-ruby/master.svg)](https://travis-ci.org/getsentry/raven-ruby)
5
+ [![Coverage Status](https://img.shields.io/coveralls/getsentry/raven-ruby/master.svg)](https://coveralls.io/r/getsentry/raven-ruby)
4
6
 
5
7
  A client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
6
8
 
@@ -18,7 +20,7 @@ gem "sentry-raven" #, :github => "getsentry/raven-ruby"
18
20
 
19
21
  The easiest way to configure Raven is by setting the ``SENTRY_DSN`` environment variable.
20
22
 
21
- You'll find this value on your project settings page, and it should resemble something like ```https://secret:public@app.getsentry.com/9999```.
23
+ You'll find this value on your project settings page, and it should resemble something like ```https://public:secret@app.getsentry.com/9999```.
22
24
 
23
25
  For alternative configuration methods, and other options see [Configuration](#configuration).
24
26
 
@@ -35,6 +37,30 @@ have mixed-in methods for capturing exceptions you've rescued yourself inside of
35
37
  end
36
38
  ```
37
39
 
40
+ #### Delayed::Job
41
+
42
+ The easiest way of enabling Raven for all your delayed jobs is to use [delayed-plugins-raven](https://github.com/qiushihe/delayed-plugins-raven) gem. First add it to your application's Gemfile:
43
+
44
+ ```
45
+ gem 'delayed-plugins-raven'
46
+ ```
47
+
48
+ And then extend your Raven configuration (eg. in ```config/initializers/raven.rb``` file):
49
+
50
+ ```ruby
51
+ require 'raven'
52
+ require 'delayed-plugins-raven'
53
+
54
+ Raven.configure do |config|
55
+ config.dsn = 'https://public:secret@app.getsentry.com/9999'
56
+ ...
57
+ end
58
+
59
+ Delayed::Worker.plugins << Delayed::Plugins::Raven::Plugin
60
+ ```
61
+
62
+ For more configuration options check delayed-plugins-raven [documentation](https://github.com/qiushihe/delayed-plugins-raven).
63
+
38
64
  ### Rails 2
39
65
 
40
66
  No support for Rails 2 yet, but it is being worked on.
@@ -90,15 +116,14 @@ end
90
116
  Additional context can be passed to the capture methods.
91
117
 
92
118
  ```ruby
93
- Raven.capture_message("My event", {
94
- :logger => 'logger',
95
- :extra => {
96
- 'my_custom_variable' => 'value'
119
+ Raven.capture_message "My event",
120
+ logger: 'logger',
121
+ extra: {
122
+ my_custom_variable: 'value'
97
123
  },
98
- :tags => {
99
- 'environment' => 'production',
124
+ tags: {
125
+ environment: 'production'
100
126
  }
101
- })
102
127
  ```
103
128
 
104
129
  The following attributes are available:
@@ -121,13 +146,13 @@ There are three primary methods for providing request context:
121
146
 
122
147
  ```ruby
123
148
  # bind the logged in user
124
- Raven.user_context({'email' => 'foo@example.com'})
149
+ Raven.user_context email: 'foo@example.com'
125
150
 
126
151
  # tag the request with something interesting
127
- Raven.tags_context({'interesting' => 'yes'})
152
+ Raven.tags_context interesting: 'yes'
128
153
 
129
154
  # provide a bit of additional context
130
- Raven.extra_context({'happiness' => 'very'})
155
+ Raven.extra_context happiness: 'very'
131
156
  ```
132
157
 
133
158
  Additionally, if you're using Rack (without the middleware), you can easily provide context with the ``rack_context`` helper:
@@ -139,11 +164,32 @@ Raven.rack_context(env)
139
164
  If you're using the Rack middleware, we've already taken care of cleanup for you, otherwise you'll need to ensure you perform it manually:
140
165
 
141
166
  ```ruby
142
- Raven.context.clear!
167
+ Raven::Context.clear!
143
168
  ```
144
169
 
145
170
  Note: the rack and user context will perform a set operation, whereas tags and extra context will merge with any existing request context.
146
171
 
172
+ ### Authlogic
173
+
174
+ When using Authlogic for authentication, you can provide user context by binding to session ```after_persisting``` and ```after_destroy``` events in ```user_session.rb```:
175
+
176
+ ```ruby
177
+ class UserSession < Authlogic::Session::Base
178
+ # events binding
179
+ after_persisting :raven_set_user_context
180
+ after_destroy :raven_clear_user_context
181
+
182
+ def raven_set_user_context
183
+ Raven.user_context( { 'id' => self.user.id, 'email' => self.user.email, 'username' => self.user.username } )
184
+ end
185
+
186
+ def raven_clear_user_context
187
+ Raven.user_context({})
188
+ end
189
+ end
190
+ ```
191
+
192
+
147
193
  ## Configuration
148
194
 
149
195
  ### SENTRY_DSN
@@ -213,8 +259,25 @@ flag:
213
259
  ```ruby
214
260
  Raven.configure do |config|
215
261
  config.ssl_verification = true
262
+ end
216
263
  ```
217
264
 
265
+ ### Asynchronous Delivery
266
+
267
+ When an error occurs, the notification is immediately sent to Sentry. Raven can be configured
268
+ to send notifications asynchronously:
269
+
270
+ ```ruby
271
+ Raven.configure do |config|
272
+ config.async = lambda { |event|
273
+ Thread.new { Raven.send(event) }
274
+ }
275
+ end
276
+ ```
277
+
278
+ This example uses a thread, but other tools can be used (GirlFriday, Resque, Sidekiq, etc...) as
279
+ long as the `event` argument is eventually passed to `Raven.send`.
280
+
218
281
  ### Logging
219
282
 
220
283
  You can use any logger with Raven - just set config.logger. Raven respects logger
@@ -1,192 +1,3 @@
1
- require 'raven/version'
2
- require 'raven/backtrace'
3
- require 'raven/configuration'
4
- require 'raven/context'
5
- require 'raven/client'
6
- require 'raven/event'
7
- require 'raven/logger'
8
- require 'raven/rack'
9
- require 'raven/interfaces/message'
10
- require 'raven/interfaces/exception'
11
- require 'raven/interfaces/stack_trace'
12
- require 'raven/interfaces/http'
13
- require 'raven/processors/sanitizedata'
1
+ require 'raven/base'
14
2
 
15
- require 'raven/railtie' if defined?(Rails::Railtie)
16
- require 'raven/sidekiq' if defined?(Sidekiq)
17
- require 'raven/tasks' if defined?(Rake)
18
-
19
-
20
- module Raven
21
- class << self
22
- # The client object is responsible for delivering formatted data to the Sentry server.
23
- # Must respond to #send. See Raven::Client.
24
- attr_writer :client
25
-
26
- # A Raven configuration object. Must act like a hash and return sensible
27
- # values for all Raven configuration options. See Raven::Configuration.
28
- attr_writer :configuration
29
-
30
- def context
31
- Context.current
32
- end
33
-
34
- def logger
35
- @logger ||= Logger.new
36
- end
37
-
38
- # The configuration object.
39
- # @see Raven.configure
40
- def configuration
41
- @configuration ||= Configuration.new
42
- end
43
-
44
- # The client object is responsible for delivering formatted data to the Sentry server.
45
- def client
46
- @client ||= Client.new(configuration)
47
- end
48
-
49
- # Tell the log that the client is good to go
50
- def report_ready
51
- self.logger.info "Raven #{VERSION} ready to catch errors"
52
- end
53
-
54
- # Call this method to modify defaults in your initializers.
55
- #
56
- # @example
57
- # Raven.configure do |config|
58
- # config.server = 'http://...'
59
- # end
60
- def configure(silent = false)
61
- if block_given?
62
- yield(configuration)
63
- end
64
-
65
- self.client = Client.new(configuration)
66
- report_ready unless silent
67
- self.client
68
- end
69
-
70
- # Send an event to the configured Sentry server
71
- #
72
- # @example
73
- # evt = Raven::Event.new(:message => "An error")
74
- # Raven.send(evt)
75
- def send(evt)
76
- client.send(evt)
77
- end
78
-
79
- # Capture and process any exceptions from the given block, or globally if
80
- # no block is given
81
- #
82
- # @example
83
- # Raven.capture do
84
- # MyApp.run
85
- # end
86
- def capture(options={}, &block)
87
- if block
88
- begin
89
- block.call
90
- rescue Error => e
91
- raise # Don't capture Raven errors
92
- rescue Exception => e
93
- capture_exception(e, options)
94
- raise
95
- end
96
- else
97
- # Install at_exit hook
98
- at_exit do
99
- if $!
100
- logger.debug "Caught a post-mortem exception: #{$!.inspect}"
101
- capture_exception($!, options)
102
- end
103
- end
104
- end
105
- end
106
-
107
- def capture_exception(exception, options={})
108
- if evt = Event.from_exception(exception, options)
109
- yield evt if block_given?
110
- send(evt)
111
- end
112
- end
113
-
114
- def capture_message(message, options={})
115
- if evt = Event.from_message(message, options)
116
- yield evt if block_given?
117
- send(evt)
118
- end
119
- end
120
-
121
- # Provides extra context to the exception prior to it being handled by
122
- # Raven. An exception can have multiple annotations, which are merged
123
- # together.
124
- #
125
- # The options (annotation) is treated the same as the ``options``
126
- # parameter to ``capture_exception`` or ``Event.from_exception``, and
127
- # can contain the same ``:user``, ``:tags``, etc. options as these
128
- # methods.
129
- #
130
- # These will be merged with the ``options`` parameter to
131
- # ``Event.from_exception`` at the top of execution.
132
- #
133
- # @example
134
- # begin
135
- # raise "Hello"
136
- # rescue => exc
137
- # Raven.annotate_exception(exc, :user => { 'id' => 1,
138
- # 'email' => 'foo@example.com' })
139
- # end
140
- def annotate_exception(exc, options = {})
141
- notes = exc.instance_variable_get(:@__raven_context) || {}
142
- notes.merge!(options)
143
- exc.instance_variable_set(:@__raven_context, notes)
144
- exc
145
- end
146
-
147
- # Bind user context. Merges with existing context (if any).
148
- #
149
- # It is recommending that you send at least the ``id`` and ``email``
150
- # values. All other values are arbitrary.
151
- #
152
- # @example
153
- # Raven.user_context('id' => 1, 'email' => 'foo@example.com')
154
- def user_context(options={})
155
- self.context.user = options
156
- end
157
-
158
- # Bind tags context. Merges with existing context (if any).
159
- #
160
- # Tags are key / value pairs which generally represent things like application version,
161
- # environment, role, and server names.
162
- #
163
- # @example
164
- # Raven.tags_context('my_custom_tag' => 'tag_value')
165
- def tags_context(options={})
166
- self.context.tags.merge!(options)
167
- end
168
-
169
- # Bind extra context. Merges with existing context (if any).
170
- #
171
- # Extra context shows up as Additional Data within Sentry, and is completely arbitrary.
172
- #
173
- # @example
174
- # Raven.tags_context('my_custom_data' => 'value')
175
- def extra_context(options={})
176
- self.context.extra.merge!(options)
177
- end
178
-
179
- def rack_context(env)
180
- if env.empty?
181
- env = nil
182
- end
183
- self.context.rack_env = env
184
- end
185
-
186
- # For cross-language compat
187
- alias :captureException :capture_exception
188
- alias :captureMessage :capture_message
189
- alias :annotateException :annotate_exception
190
- alias :annotate :annotate_exception
191
- end
192
- end
3
+ Raven.inject
@@ -37,7 +37,8 @@ module Raven
37
37
  end
38
38
 
39
39
  def in_app
40
- @in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{APP_DIRS_PATTERN}")
40
+ app_dirs = Raven.configuration.app_dirs_pattern || APP_DIRS_PATTERN
41
+ @in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs}")
41
42
 
42
43
  if self.file =~ @in_app_pattern
43
44
  true
@@ -76,12 +77,12 @@ module Raven
76
77
 
77
78
  filters = opts[:filters] || []
78
79
  filtered_lines = ruby_lines.to_a.map do |line|
79
- filters.inject(line) do |line, proc|
80
+ filters.reduce(line) do |line, proc|
80
81
  proc.call(line)
81
82
  end
82
83
  end.compact
83
84
 
84
- lines = filtered_lines.collect do |unparsed_line|
85
+ lines = filtered_lines.map do |unparsed_line|
85
86
  Line.parse(unparsed_line)
86
87
  end
87
88
 
@@ -93,7 +94,7 @@ module Raven
93
94
  end
94
95
 
95
96
  def inspect
96
- "<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
97
+ "<Backtrace: " + lines.map { |line| line.inspect }.join(", ") + ">"
97
98
  end
98
99
 
99
100
  def to_s
@@ -0,0 +1,212 @@
1
+ require 'raven/version'
2
+ require 'raven/backtrace'
3
+ require 'raven/configuration'
4
+ require 'raven/context'
5
+ require 'raven/client'
6
+ require 'raven/event'
7
+ require 'raven/logger'
8
+ require 'raven/rack'
9
+ require 'raven/interfaces/message'
10
+ require 'raven/interfaces/exception'
11
+ require 'raven/interfaces/stack_trace'
12
+ require 'raven/interfaces/http'
13
+ require 'raven/processors/sanitizedata'
14
+
15
+ module Raven
16
+ class << self
17
+ # The client object is responsible for delivering formatted data to the Sentry server.
18
+ # Must respond to #send. See Raven::Client.
19
+ attr_writer :client
20
+
21
+ # A Raven configuration object. Must act like a hash and return sensible
22
+ # values for all Raven configuration options. See Raven::Configuration.
23
+ attr_writer :configuration
24
+
25
+ def context
26
+ Context.current
27
+ end
28
+
29
+ def logger
30
+ @logger ||= Logger.new
31
+ end
32
+
33
+ # The configuration object.
34
+ # @see Raven.configure
35
+ def configuration
36
+ @configuration ||= Configuration.new
37
+ end
38
+
39
+ # The client object is responsible for delivering formatted data to the Sentry server.
40
+ def client
41
+ @client ||= Client.new(configuration)
42
+ end
43
+
44
+ # Tell the log that the client is good to go
45
+ def report_ready
46
+ self.logger.info "Raven #{VERSION} ready to catch errors"
47
+ end
48
+
49
+ # Call this method to modify defaults in your initializers.
50
+ #
51
+ # @example
52
+ # Raven.configure do |config|
53
+ # config.server = 'http://...'
54
+ # end
55
+ def configure(silent = false)
56
+ yield(configuration) if block_given?
57
+
58
+ self.client = Client.new(configuration)
59
+ report_ready unless silent
60
+ self.client
61
+ end
62
+
63
+ # Send an event to the configured Sentry server
64
+ #
65
+ # @example
66
+ # evt = Raven::Event.new(:message => "An error")
67
+ # Raven.send(evt)
68
+ def send(evt)
69
+ client.send(evt)
70
+ end
71
+
72
+ # Capture and process any exceptions from the given block, or globally if
73
+ # no block is given
74
+ #
75
+ # @example
76
+ # Raven.capture do
77
+ # MyApp.run
78
+ # end
79
+ def capture(options = {}, &block)
80
+ if block
81
+ begin
82
+ block.call
83
+ rescue Error
84
+ raise # Don't capture Raven errors
85
+ rescue Exception => e
86
+ capture_exception(e, options)
87
+ raise
88
+ end
89
+ else
90
+ # Install at_exit hook
91
+ at_exit do
92
+ if $ERROR_INFO
93
+ logger.debug "Caught a post-mortem exception: #{$ERROR_INFO.inspect}"
94
+ capture_exception($ERROR_INFO, options)
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def capture_exception(exception, options = {})
101
+ send_or_skip do
102
+ if evt = Event.from_exception(exception, options)
103
+ yield evt if block_given?
104
+ if configuration.async?
105
+ configuration.async.call(evt)
106
+ else
107
+ send(evt)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ def capture_message(message, options = {})
114
+ send_or_skip do
115
+ if evt = Event.from_message(message, options)
116
+ yield evt if block_given?
117
+ if configuration.async?
118
+ configuration.async.call(evt)
119
+ else
120
+ send(evt)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ def send_or_skip
127
+ if configuration.send_in_current_environment?
128
+ yield if block_given?
129
+ else
130
+ configuration.log_excluded_environment_message
131
+ end
132
+ end
133
+
134
+ # Provides extra context to the exception prior to it being handled by
135
+ # Raven. An exception can have multiple annotations, which are merged
136
+ # together.
137
+ #
138
+ # The options (annotation) is treated the same as the ``options``
139
+ # parameter to ``capture_exception`` or ``Event.from_exception``, and
140
+ # can contain the same ``:user``, ``:tags``, etc. options as these
141
+ # methods.
142
+ #
143
+ # These will be merged with the ``options`` parameter to
144
+ # ``Event.from_exception`` at the top of execution.
145
+ #
146
+ # @example
147
+ # begin
148
+ # raise "Hello"
149
+ # rescue => exc
150
+ # Raven.annotate_exception(exc, :user => { 'id' => 1,
151
+ # 'email' => 'foo@example.com' })
152
+ # end
153
+ def annotate_exception(exc, options = {})
154
+ notes = exc.instance_variable_get(:@__raven_context) || {}
155
+ notes.merge!(options)
156
+ exc.instance_variable_set(:@__raven_context, notes)
157
+ exc
158
+ end
159
+
160
+ # Bind user context. Merges with existing context (if any).
161
+ #
162
+ # It is recommending that you send at least the ``id`` and ``email``
163
+ # values. All other values are arbitrary.
164
+ #
165
+ # @example
166
+ # Raven.user_context('id' => 1, 'email' => 'foo@example.com')
167
+ def user_context(options = {})
168
+ self.context.user = options
169
+ end
170
+
171
+ # Bind tags context. Merges with existing context (if any).
172
+ #
173
+ # Tags are key / value pairs which generally represent things like application version,
174
+ # environment, role, and server names.
175
+ #
176
+ # @example
177
+ # Raven.tags_context('my_custom_tag' => 'tag_value')
178
+ def tags_context(options = {})
179
+ self.context.tags.merge!(options)
180
+ end
181
+
182
+ # Bind extra context. Merges with existing context (if any).
183
+ #
184
+ # Extra context shows up as Additional Data within Sentry, and is completely arbitrary.
185
+ #
186
+ # @example
187
+ # Raven.tags_context('my_custom_data' => 'value')
188
+ def extra_context(options = {})
189
+ self.context.extra.merge!(options)
190
+ end
191
+
192
+ def rack_context(env)
193
+ if env.empty?
194
+ env = nil
195
+ end
196
+ self.context.rack_env = env
197
+ end
198
+
199
+ # Injects rails
200
+ def inject
201
+ require 'raven/railtie' if defined?(Rails::Railtie)
202
+ require 'raven/sidekiq' if defined?(Sidekiq)
203
+ require 'raven/tasks' if defined?(Rake)
204
+ end
205
+
206
+ # For cross-language compat
207
+ alias :captureException :capture_exception
208
+ alias :captureMessage :capture_message
209
+ alias :annotateException :annotate_exception
210
+ alias :annotate :annotate_exception
211
+ end
212
+ end