sentry-raven 0.15.6 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -3
- data/lib/raven/backtrace.rb +10 -10
- data/lib/raven/base.rb +7 -9
- data/lib/raven/client.rb +11 -18
- data/lib/raven/configuration.rb +41 -4
- data/lib/raven/event.rb +113 -104
- data/lib/raven/integrations/rack.rb +1 -2
- data/lib/raven/integrations/rails.rb +4 -4
- data/lib/raven/processor/cookies.rb +16 -0
- data/lib/raven/processor/post_data.rb +11 -0
- data/lib/raven/utils/deep_merge.rb +28 -0
- data/lib/raven/version.rb +1 -1
- metadata +19 -17
- data/lib/raven/backports/uri.rb +0 -104
- data/lib/raven/transports/udp.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6c29eda4efffb38e92186b8494c5fb0fb07ac72
|
4
|
+
data.tar.gz: ffbb210ae9749c1a97a27ac15ff1770ef360b561
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e0ed89962c85c679bff0339d347d4b8f0ea17bb7ecef9b1de75693b5775783bbe5c5751c2f4113571efa05161d4f082b827bce8f0b8b7b3a7d731925fcab4b6
|
7
|
+
data.tar.gz: efbb4e689d8eed60136e7caffb3070e1fc001f371bdc23eeb576e8fe437327173e3eea99a172891954d56fb35d4c2aecc24d6bece917be8ca93d9802e9efdfdd
|
data/README.md
CHANGED
@@ -7,14 +7,20 @@ A client and integration layer for the [Sentry](https://github.com/getsentry/sen
|
|
7
7
|
|
8
8
|
## Requirements
|
9
9
|
|
10
|
-
We test on Ruby
|
10
|
+
We test on Ruby 1.9, 2.2 and 2.3 at the latest patchlevel/teeny version. Our Rails integration works with Rails 4.2+. JRuby support is experimental - check TravisCI to see if the build is passing or failing.
|
11
11
|
|
12
12
|
## Getting Started
|
13
|
+
|
13
14
|
### Install
|
15
|
+
|
14
16
|
```ruby
|
15
|
-
gem "sentry-raven"
|
17
|
+
gem "sentry-raven"
|
16
18
|
```
|
17
|
-
|
19
|
+
|
20
|
+
### Raven only runs when SENTRY_DSN is set
|
21
|
+
|
22
|
+
Raven will capture and send exceptions to the Sentry server whenever its DSN is set. This makes environment-based configuration easy - if you don't want to send errors in a certain environment, just don't set the DSN in that environment!
|
23
|
+
|
18
24
|
```bash
|
19
25
|
# Set your SENTRY_DSN environment variable.
|
20
26
|
export SENTRY_DSN=http://public:secret@example.com/project-id
|
@@ -25,10 +31,19 @@ Raven.configure do |config|
|
|
25
31
|
config.dsn = 'http://public:secret@example.com/project-id'
|
26
32
|
end
|
27
33
|
```
|
34
|
+
|
35
|
+
### Raven doesn't report some kinds of data by default.
|
36
|
+
|
37
|
+
Raven ignores some exceptions by default - most of these are related to 404s or controller actions not being found. [For a complete list, see the `IGNORE_DEFAULT` constant](https://github.com/getsentry/raven-ruby/blob/master/lib/raven/configuration.rb).
|
38
|
+
|
39
|
+
Raven doesn't report POST data or cookies by default. In addition, it will attempt to remove any obviously sensitive data, such as credit card or Social Security numbers. For more information about how Sentry processes your data, [check out the documentation on the `processors` config setting.](https://docs.getsentry.com/hosted/clients/ruby/config/)
|
40
|
+
|
28
41
|
### Call
|
42
|
+
|
29
43
|
If you use Rails, you're already done - no more configuration required! Check [Integrations](https://docs.getsentry.com/hosted/clients/ruby/integrations/) for more details on other gems Sentry integrates with automatically.
|
30
44
|
|
31
45
|
Otherwise, Raven supports two methods of capturing exceptions:
|
46
|
+
|
32
47
|
```ruby
|
33
48
|
Raven.capture do
|
34
49
|
# capture any exceptions which happen during execution of this block
|
data/lib/raven/backtrace.rb
CHANGED
@@ -12,8 +12,6 @@ module Raven
|
|
12
12
|
# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
|
13
13
|
JAVA_INPUT_FORMAT = %r{^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$}
|
14
14
|
|
15
|
-
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/
|
16
|
-
|
17
15
|
# The file portion of the line (such as app/models/user.rb)
|
18
16
|
attr_reader :file
|
19
17
|
|
@@ -49,20 +47,13 @@ module Raven
|
|
49
47
|
end
|
50
48
|
|
51
49
|
def in_app
|
52
|
-
|
53
|
-
@in_app_pattern ||= Regexp.new("^(#{project_root}/)?#{app_dirs}")
|
54
|
-
|
55
|
-
if self.file =~ @in_app_pattern
|
50
|
+
if self.file =~ self.class.in_app_pattern
|
56
51
|
true
|
57
52
|
else
|
58
53
|
false
|
59
54
|
end
|
60
55
|
end
|
61
56
|
|
62
|
-
def project_root
|
63
|
-
@project_root ||= Raven.configuration.project_root && Raven.configuration.project_root.to_s
|
64
|
-
end
|
65
|
-
|
66
57
|
# Reconstructs the line in a readable fashion
|
67
58
|
def to_s
|
68
59
|
"#{file}:#{number}:in `#{method}'"
|
@@ -76,11 +67,20 @@ module Raven
|
|
76
67
|
"<Line:#{self}>"
|
77
68
|
end
|
78
69
|
|
70
|
+
def self.in_app_pattern
|
71
|
+
@in_app_pattern ||= begin
|
72
|
+
project_root = Raven.configuration.project_root && Raven.configuration.project_root.to_s
|
73
|
+
Regexp.new("^(#{project_root}/)?#{Raven.configuration.app_dirs_pattern || APP_DIRS_PATTERN}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
79
77
|
private
|
80
78
|
|
81
79
|
attr_writer :file, :number, :method, :module_name
|
82
80
|
end
|
83
81
|
|
82
|
+
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/
|
83
|
+
|
84
84
|
# holder for an Array of Backtrace::Line instances
|
85
85
|
attr_reader :lines
|
86
86
|
|
data/lib/raven/base.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
require 'raven/version'
|
2
2
|
require 'raven/backtrace'
|
3
|
+
require 'raven/processor'
|
4
|
+
require 'raven/processor/sanitizedata'
|
5
|
+
require 'raven/processor/removecircularreferences'
|
6
|
+
require 'raven/processor/utf8conversion'
|
7
|
+
require 'raven/processor/cookies'
|
8
|
+
require 'raven/processor/post_data'
|
3
9
|
require 'raven/configuration'
|
4
10
|
require 'raven/context'
|
5
11
|
require 'raven/client'
|
@@ -10,15 +16,7 @@ require 'raven/interfaces/exception'
|
|
10
16
|
require 'raven/interfaces/single_exception'
|
11
17
|
require 'raven/interfaces/stack_trace'
|
12
18
|
require 'raven/interfaces/http'
|
13
|
-
require 'raven/
|
14
|
-
require 'raven/processor/sanitizedata'
|
15
|
-
require 'raven/processor/removecircularreferences'
|
16
|
-
require 'raven/processor/utf8conversion'
|
17
|
-
|
18
|
-
major, minor, patch = RUBY_VERSION.split('.').map(&:to_i)
|
19
|
-
if (major == 1 && minor < 9) || (major == 1 && minor == 9 && patch < 2)
|
20
|
-
require 'raven/backports/uri'
|
21
|
-
end
|
19
|
+
require 'raven/utils/deep_merge'
|
22
20
|
|
23
21
|
module Raven
|
24
22
|
AVAILABLE_INTEGRATIONS = %w[delayed_job railties sidekiq rack rake].freeze
|
data/lib/raven/client.rb
CHANGED
@@ -5,7 +5,6 @@ require 'base64'
|
|
5
5
|
require 'raven/version'
|
6
6
|
require 'raven/okjson'
|
7
7
|
require 'raven/transports/http'
|
8
|
-
require 'raven/transports/udp'
|
9
8
|
|
10
9
|
module Raven
|
11
10
|
# Encodes events and sends them to the Sentry server.
|
@@ -28,8 +27,8 @@ module Raven
|
|
28
27
|
# Convert to hash
|
29
28
|
event = event.to_hash
|
30
29
|
|
31
|
-
|
32
|
-
|
30
|
+
unless @state.should_try?
|
31
|
+
failed_send(nil, event)
|
33
32
|
return
|
34
33
|
end
|
35
34
|
|
@@ -40,21 +39,18 @@ module Raven
|
|
40
39
|
begin
|
41
40
|
transport.send_event(generate_auth_header, encoded_data,
|
42
41
|
:content_type => content_type)
|
42
|
+
successful_send
|
43
43
|
rescue => e
|
44
44
|
failed_send(e, event)
|
45
45
|
return
|
46
46
|
end
|
47
47
|
|
48
|
-
successful_send
|
49
|
-
|
50
48
|
event
|
51
49
|
end
|
52
50
|
|
53
51
|
def transport
|
54
52
|
@transport ||=
|
55
53
|
case configuration.scheme
|
56
|
-
when 'udp'
|
57
|
-
Transports::UDP.new(configuration)
|
58
54
|
when 'http', 'https'
|
59
55
|
Transports::HTTP.new(configuration)
|
60
56
|
when 'dummy'
|
@@ -81,7 +77,7 @@ module Raven
|
|
81
77
|
|
82
78
|
case configuration.encoding
|
83
79
|
when 'gzip'
|
84
|
-
['application/octet-stream', strict_encode64(Zlib::Deflate.deflate(encoded))]
|
80
|
+
['application/octet-stream', Base64.strict_encode64(Zlib::Deflate.deflate(encoded))]
|
85
81
|
else
|
86
82
|
['application/json', encoded]
|
87
83
|
end
|
@@ -103,23 +99,20 @@ module Raven
|
|
103
99
|
'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
|
104
100
|
end
|
105
101
|
|
106
|
-
def strict_encode64(string)
|
107
|
-
if Base64.respond_to? :strict_encode64
|
108
|
-
Base64.strict_encode64 string
|
109
|
-
else # Ruby 1.8
|
110
|
-
Base64.encode64(string)[0..-2]
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
102
|
def successful_send
|
115
103
|
@state.success
|
116
104
|
end
|
117
105
|
|
118
106
|
def failed_send(e, event)
|
119
107
|
@state.failure
|
120
|
-
|
121
|
-
|
108
|
+
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) }
|
111
|
+
else
|
112
|
+
Raven.logger.error "Not sending event due to previous failure(s)."
|
113
|
+
end
|
122
114
|
Raven.logger.error("Failed to submit event: #{get_log_message(event)}")
|
115
|
+
configuration.transport_failure_callback.call(event) if configuration.transport_failure_callback
|
123
116
|
end
|
124
117
|
end
|
125
118
|
|
data/lib/raven/configuration.rb
CHANGED
@@ -84,13 +84,20 @@ module Raven
|
|
84
84
|
# Optional Proc to be used to send events asynchronously.
|
85
85
|
attr_reader :async
|
86
86
|
|
87
|
+
# Optional Proc, called when the Sentry server cannot be contacted for any reason
|
88
|
+
attr_accessor :transport_failure_callback
|
89
|
+
|
87
90
|
# Directories to be recognized as part of your app. e.g. if you
|
88
91
|
# have an `engines` dir at the root of your project, you may want
|
89
92
|
# to set this to something like /(app|config|engines|lib)/
|
90
93
|
attr_accessor :app_dirs_pattern
|
91
94
|
|
92
|
-
#
|
93
|
-
# ActionDispatch::
|
95
|
+
# Rails catches exceptions in the ActionDispatch::ShowExceptions or
|
96
|
+
# ActionDispatch::DebugExceptions middlewares, depending on the environment.
|
97
|
+
# When `rails_report_rescued_exceptions` is true (it is by default), Raven
|
98
|
+
# will report exceptions even when they are rescued by these middlewares.
|
99
|
+
attr_accessor :rails_report_rescued_exceptions
|
100
|
+
# Deprecated accessor
|
94
101
|
attr_accessor :catch_debugged_exceptions
|
95
102
|
|
96
103
|
# Provide a configurable callback to determine event capture
|
@@ -113,13 +120,21 @@ module Raven
|
|
113
120
|
'Sinatra::NotFound',
|
114
121
|
].freeze
|
115
122
|
|
123
|
+
DEFAULT_PROCESSORS = [
|
124
|
+
Raven::Processor::RemoveCircularReferences,
|
125
|
+
Raven::Processor::UTF8Conversion,
|
126
|
+
Raven::Processor::SanitizeData,
|
127
|
+
Raven::Processor::Cookies,
|
128
|
+
Raven::Processor::PostData,
|
129
|
+
].freeze
|
130
|
+
|
116
131
|
def initialize
|
117
132
|
self.server = ENV['SENTRY_DSN'] if ENV['SENTRY_DSN']
|
118
133
|
@context_lines = 3
|
119
134
|
self.current_environment = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
|
120
135
|
self.send_modules = true
|
121
136
|
self.excluded_exceptions = IGNORE_DEFAULT.dup
|
122
|
-
self.processors =
|
137
|
+
self.processors = DEFAULT_PROCESSORS.dup
|
123
138
|
self.ssl_verification = true
|
124
139
|
self.encoding = 'gzip'
|
125
140
|
self.timeout = 1
|
@@ -127,12 +142,17 @@ module Raven
|
|
127
142
|
self.proxy = nil
|
128
143
|
self.tags = {}
|
129
144
|
self.async = false
|
130
|
-
self.
|
145
|
+
self.rails_report_rescued_exceptions = true
|
146
|
+
self.transport_failure_callback = false
|
131
147
|
self.sanitize_fields = []
|
132
148
|
self.sanitize_credit_cards = true
|
133
149
|
self.environments = []
|
134
150
|
|
135
151
|
self.release = detect_release
|
152
|
+
|
153
|
+
# Try to resolve the hostname to an FQDN, but fall back to whatever the load name is
|
154
|
+
self.server_name = Socket.gethostname
|
155
|
+
self.server_name = Socket.gethostbyname(hostname).first rescue server_name
|
136
156
|
end
|
137
157
|
|
138
158
|
def server=(value)
|
@@ -171,6 +191,11 @@ module Raven
|
|
171
191
|
|
172
192
|
alias async? async
|
173
193
|
|
194
|
+
def transport_failure_callback=(value)
|
195
|
+
raise ArgumentError.new("transport_failure_callback must be callable (or false to disable)") unless value == false || value.respond_to?(:call)
|
196
|
+
@transport_failure_callback = value
|
197
|
+
end
|
198
|
+
|
174
199
|
# Allows config options to be read like a hash
|
175
200
|
#
|
176
201
|
# @param [Symbol] option Key for a given attribute
|
@@ -203,6 +228,18 @@ module Raven
|
|
203
228
|
detect_release_from_git
|
204
229
|
end
|
205
230
|
|
231
|
+
def project_root=(root_dir)
|
232
|
+
@project_root = root_dir
|
233
|
+
Backtrace::Line.instance_variable_set(:@in_app_pattern, nil) # blow away cache
|
234
|
+
end
|
235
|
+
|
236
|
+
def catch_debugged_exceptions=(boolean)
|
237
|
+
Raven.logger.warn "DEPRECATION WARNING: catch_debugged_exceptions has been \
|
238
|
+
renamed to rails_report_rescued_exceptions. catch_debugged_exceptions will \
|
239
|
+
be removed in raven-ruby 0.17.0"
|
240
|
+
self.rails_report_rescued_exceptions = boolean
|
241
|
+
end
|
242
|
+
|
206
243
|
private
|
207
244
|
|
208
245
|
def detect_release_from_heroku
|
data/lib/raven/event.rb
CHANGED
@@ -40,7 +40,7 @@ module Raven
|
|
40
40
|
@level = :error
|
41
41
|
@logger = ''
|
42
42
|
@culprit = nil
|
43
|
-
@server_name = @configuration.server_name
|
43
|
+
@server_name = @configuration.server_name
|
44
44
|
@release = @configuration.release
|
45
45
|
@modules = list_gem_specs if @configuration.send_modules
|
46
46
|
@user = {}
|
@@ -69,10 +69,118 @@ module Raven
|
|
69
69
|
@level = LOG_LEVELS[@level.to_s.downcase] if @level.is_a?(String) || @level.is_a?(Symbol)
|
70
70
|
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
class << self
|
73
|
+
def from_exception(exc, options = {}, &block)
|
74
|
+
exception_context = get_exception_context(exc) || {}
|
75
|
+
options = Raven::Utils::DeepMergeHash.deep_merge(exception_context, options)
|
76
|
+
|
77
|
+
configuration = options[:configuration] || Raven.configuration
|
78
|
+
if exc.is_a?(Raven::Error)
|
79
|
+
# Try to prevent error reporting loops
|
80
|
+
Raven.logger.info "Refusing to capture Raven error: #{exc.inspect}"
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
if configuration[:excluded_exceptions].any? { |x| (x === exc rescue false) || x == exc.class.name }
|
84
|
+
Raven.logger.info "User excluded error: #{exc.inspect}"
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
|
88
|
+
new(options) do |evt|
|
89
|
+
evt.configuration = configuration
|
90
|
+
evt.message = "#{exc.class}: #{exc.message}"
|
91
|
+
evt.level = options[:level] || :error
|
92
|
+
|
93
|
+
add_exception_interface(evt, exc)
|
94
|
+
|
95
|
+
yield evt if block
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def from_message(message, options = {})
|
100
|
+
configuration = options[:configuration] || Raven.configuration
|
101
|
+
new(options) do |evt|
|
102
|
+
evt.configuration = configuration
|
103
|
+
evt.message = message
|
104
|
+
evt.level = options[:level] || :error
|
105
|
+
evt.interface :message do |int|
|
106
|
+
int.message = message
|
107
|
+
end
|
108
|
+
if options[:backtrace]
|
109
|
+
evt.interface(:stacktrace) do |int|
|
110
|
+
stacktrace_interface_from(int, evt, options[:backtrace])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def get_exception_context(exc)
|
119
|
+
if exc.instance_variable_defined?(:@__raven_context)
|
120
|
+
exc.instance_variable_get(:@__raven_context)
|
121
|
+
elsif exc.respond_to?(:raven_context)
|
122
|
+
exc.raven_context
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_exception_interface(evt, exc)
|
127
|
+
evt.interface(:exception) do |exc_int|
|
128
|
+
exceptions = [exc]
|
129
|
+
context = Set.new [exc.object_id]
|
130
|
+
|
131
|
+
while exc.respond_to?(:cause) && exc.cause
|
132
|
+
exc = exc.cause
|
133
|
+
if context.include?(exc.object_id)
|
134
|
+
break
|
135
|
+
end
|
136
|
+
exceptions << exc
|
137
|
+
context.add(exc.object_id)
|
138
|
+
end
|
139
|
+
exceptions.reverse!
|
140
|
+
|
141
|
+
exc_int.values = exceptions.map do |e|
|
142
|
+
SingleExceptionInterface.new do |int|
|
143
|
+
int.type = e.class.to_s
|
144
|
+
int.value = e.to_s
|
145
|
+
int.module = e.class.to_s.split('::')[0...-1].join('::')
|
146
|
+
|
147
|
+
int.stacktrace =
|
148
|
+
if e.backtrace
|
149
|
+
StacktraceInterface.new do |stacktrace|
|
150
|
+
stacktrace_interface_from(stacktrace, evt, e.backtrace)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def stacktrace_interface_from(int, evt, backtrace)
|
159
|
+
backtrace = Backtrace.parse(backtrace)
|
160
|
+
|
161
|
+
int.frames = []
|
162
|
+
backtrace.lines.reverse_each do |line|
|
163
|
+
frame = StacktraceInterface::Frame.new
|
164
|
+
frame.abs_path = line.file if line.file
|
165
|
+
frame.function = line.method if line.method
|
166
|
+
frame.lineno = line.number
|
167
|
+
frame.in_app = line.in_app
|
168
|
+
frame.module = line.module_name if line.module_name
|
169
|
+
|
170
|
+
if evt.configuration[:context_lines] && frame.abs_path
|
171
|
+
frame.pre_context, frame.context_line, frame.post_context = \
|
172
|
+
evt.get_file_context(frame.abs_path, frame.lineno, evt.configuration[:context_lines])
|
173
|
+
end
|
174
|
+
|
175
|
+
int.frames << frame if frame.filename
|
176
|
+
end
|
177
|
+
|
178
|
+
evt.culprit = evt.get_culprit(int.frames)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Because linecache can go to hell
|
182
|
+
def _source_lines(_path, _from, _to)
|
183
|
+
end
|
76
184
|
end
|
77
185
|
|
78
186
|
def list_gem_specs
|
@@ -121,105 +229,6 @@ module Raven
|
|
121
229
|
data
|
122
230
|
end
|
123
231
|
|
124
|
-
def self.from_exception(exc, options = {}, &block)
|
125
|
-
notes = (exc.instance_variable_defined?(:@__raven_context) && exc.instance_variable_get(:@__raven_context)) || {}
|
126
|
-
options = notes.merge(options)
|
127
|
-
|
128
|
-
configuration = options[:configuration] || Raven.configuration
|
129
|
-
if exc.is_a?(Raven::Error)
|
130
|
-
# Try to prevent error reporting loops
|
131
|
-
Raven.logger.info "Refusing to capture Raven error: #{exc.inspect}"
|
132
|
-
return nil
|
133
|
-
end
|
134
|
-
if configuration[:excluded_exceptions].any? { |x| (x === exc rescue false) || x == exc.class.name }
|
135
|
-
Raven.logger.info "User excluded error: #{exc.inspect}"
|
136
|
-
return nil
|
137
|
-
end
|
138
|
-
|
139
|
-
new(options) do |evt|
|
140
|
-
evt.configuration = configuration
|
141
|
-
evt.message = "#{exc.class}: #{exc.message}"
|
142
|
-
evt.level = options[:level] || :error
|
143
|
-
|
144
|
-
add_exception_interface(evt, exc)
|
145
|
-
|
146
|
-
block.call(evt) if block
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.from_message(message, options = {})
|
151
|
-
configuration = options[:configuration] || Raven.configuration
|
152
|
-
new(options) do |evt|
|
153
|
-
evt.configuration = configuration
|
154
|
-
evt.message = message
|
155
|
-
evt.level = options[:level] || :error
|
156
|
-
evt.interface :message do |int|
|
157
|
-
int.message = message
|
158
|
-
end
|
159
|
-
if options[:backtrace]
|
160
|
-
evt.interface(:stacktrace) do |int|
|
161
|
-
stacktrace_interface_from(int, evt, options[:backtrace])
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def self.add_exception_interface(evt, exc)
|
168
|
-
evt.interface(:exception) do |exc_int|
|
169
|
-
exceptions = [exc]
|
170
|
-
context = Set.new [exc.object_id]
|
171
|
-
while exc.respond_to?(:cause) && exc.cause
|
172
|
-
exceptions << exc.cause
|
173
|
-
exc = exc.cause
|
174
|
-
# TODO(dcramer): ideally this would log to inform the user
|
175
|
-
if context.include?(exc.object_id)
|
176
|
-
break
|
177
|
-
end
|
178
|
-
context.add(exc.object_id)
|
179
|
-
end
|
180
|
-
exceptions.reverse!
|
181
|
-
|
182
|
-
exc_int.values = exceptions.map do |e|
|
183
|
-
SingleExceptionInterface.new do |int|
|
184
|
-
int.type = e.class.to_s
|
185
|
-
int.value = e.to_s
|
186
|
-
int.module = e.class.to_s.split('::')[0...-1].join('::')
|
187
|
-
|
188
|
-
int.stacktrace =
|
189
|
-
if e.backtrace
|
190
|
-
StacktraceInterface.new do |stacktrace|
|
191
|
-
stacktrace_interface_from(stacktrace, evt, e.backtrace)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
def self.stacktrace_interface_from(int, evt, backtrace)
|
200
|
-
backtrace = Backtrace.parse(backtrace)
|
201
|
-
int.frames = backtrace.lines.reverse.map do |line|
|
202
|
-
StacktraceInterface::Frame.new.tap do |frame|
|
203
|
-
frame.abs_path = line.file if line.file
|
204
|
-
frame.function = line.method if line.method
|
205
|
-
frame.lineno = line.number
|
206
|
-
frame.in_app = line.in_app
|
207
|
-
frame.module = line.module_name if line.module_name
|
208
|
-
|
209
|
-
if evt.configuration[:context_lines] && frame.abs_path
|
210
|
-
frame.pre_context, frame.context_line, frame.post_context = \
|
211
|
-
evt.get_file_context(frame.abs_path, frame.lineno, evt.configuration[:context_lines])
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end.select(&:filename)
|
215
|
-
|
216
|
-
evt.culprit = evt.get_culprit(int.frames)
|
217
|
-
end
|
218
|
-
|
219
|
-
# Because linecache can go to hell
|
220
|
-
def self._source_lines(_path, _from, _to)
|
221
|
-
end
|
222
|
-
|
223
232
|
def get_file_context(filename, lineno, context)
|
224
233
|
return nil, nil, nil unless Raven::LineCache.is_valid_file(filename)
|
225
234
|
lines = Array.new(2 * context + 1) do |i|
|
@@ -113,10 +113,9 @@ module Raven
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def format_env_for_sentry(env_hash)
|
116
|
-
|
116
|
+
env_hash.select do |k, _v|
|
117
117
|
%w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? k.to_s
|
118
118
|
end
|
119
|
-
Hash[trimmed_hash] # select returns an Array in Ruby 1.8
|
120
119
|
end
|
121
120
|
end
|
122
121
|
|
@@ -22,7 +22,7 @@ module Raven
|
|
22
22
|
end
|
23
23
|
|
24
24
|
config.after_initialize do
|
25
|
-
if Raven.configuration.
|
25
|
+
if Raven.configuration.rails_report_rescued_exceptions
|
26
26
|
require 'raven/integrations/rails/middleware/debug_exceptions_catcher'
|
27
27
|
if defined?(::ActionDispatch::DebugExceptions)
|
28
28
|
exceptions_class = ::ActionDispatch::DebugExceptions
|
@@ -30,10 +30,10 @@ module Raven
|
|
30
30
|
exceptions_class = ::ActionDispatch::ShowExceptions
|
31
31
|
end
|
32
32
|
unless exceptions_class.nil?
|
33
|
-
if
|
34
|
-
exceptions_class.send(:include, Raven::Rails::Middleware::OldDebugExceptionsCatcher)
|
35
|
-
else
|
33
|
+
if exceptions_class.respond_to?(:prepend, true)
|
36
34
|
exceptions_class.send(:prepend, Raven::Rails::Middleware::DebugExceptionsCatcher)
|
35
|
+
else
|
36
|
+
exceptions_class.send(:include, Raven::Rails::Middleware::OldDebugExceptionsCatcher)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Raven
|
2
|
+
class Processor::Cookies < Processor
|
3
|
+
def process(data)
|
4
|
+
if data[:request]
|
5
|
+
# Remove possibly sensitive cookies
|
6
|
+
data[:request][:cookies] = nil if data[:request][:cookies]
|
7
|
+
|
8
|
+
if data[:request][:headers] && data[:request][:headers]["Cookie"]
|
9
|
+
data[:request][:headers]["Cookie"] = nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
data
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Raven
|
2
|
+
module Utils
|
3
|
+
# ported from ActiveSupport
|
4
|
+
module DeepMergeHash
|
5
|
+
def self.deep_merge(hash, other_hash, &block)
|
6
|
+
deep_merge!(hash, other_hash, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.deep_merge!(hash, other_hash, &block)
|
10
|
+
other_hash.each_pair do |current_key, other_value|
|
11
|
+
this_value = hash[current_key]
|
12
|
+
|
13
|
+
hash[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
|
14
|
+
this_value.deep_merge(other_value, &block)
|
15
|
+
else
|
16
|
+
if block_given? && key?(current_key)
|
17
|
+
block.call(current_key, this_value, other_value)
|
18
|
+
else
|
19
|
+
other_value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
hash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/raven/version.rb
CHANGED
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: 0.
|
4
|
+
version: 1.0.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-02
|
11
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -42,30 +42,30 @@ dependencies:
|
|
42
42
|
name: rubocop
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec-rails
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: mime-types
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rest-client
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,7 +147,6 @@ files:
|
|
147
147
|
- LICENSE
|
148
148
|
- README.md
|
149
149
|
- lib/raven.rb
|
150
|
-
- lib/raven/backports/uri.rb
|
151
150
|
- lib/raven/backtrace.rb
|
152
151
|
- lib/raven/base.rb
|
153
152
|
- lib/raven/cli.rb
|
@@ -176,6 +175,8 @@ files:
|
|
176
175
|
- lib/raven/logger.rb
|
177
176
|
- lib/raven/okjson.rb
|
178
177
|
- lib/raven/processor.rb
|
178
|
+
- lib/raven/processor/cookies.rb
|
179
|
+
- lib/raven/processor/post_data.rb
|
179
180
|
- lib/raven/processor/removecircularreferences.rb
|
180
181
|
- lib/raven/processor/removestacktrace.rb
|
181
182
|
- lib/raven/processor/sanitizedata.rb
|
@@ -183,7 +184,7 @@ files:
|
|
183
184
|
- lib/raven/transports.rb
|
184
185
|
- lib/raven/transports/dummy.rb
|
185
186
|
- lib/raven/transports/http.rb
|
186
|
-
- lib/raven/
|
187
|
+
- lib/raven/utils/deep_merge.rb
|
187
188
|
- lib/raven/version.rb
|
188
189
|
- lib/sentry-raven-without-integrations.rb
|
189
190
|
- lib/sentry-raven.rb
|
@@ -199,7 +200,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
199
200
|
requirements:
|
200
201
|
- - ">="
|
201
202
|
- !ruby/object:Gem::Version
|
202
|
-
version: 1.
|
203
|
+
version: 1.9.0
|
203
204
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
205
|
requirements:
|
205
206
|
- - ">="
|
@@ -212,3 +213,4 @@ signing_key:
|
|
212
213
|
specification_version: 4
|
213
214
|
summary: A gem that provides a client interface for the Sentry error logger
|
214
215
|
test_files: []
|
216
|
+
has_rdoc: true
|
data/lib/raven/backports/uri.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# :stopdoc:
|
2
|
-
|
3
|
-
# Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x
|
4
|
-
#
|
5
|
-
# https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
module URI
|
10
|
-
TBLENCWWWCOMP_ = {} # :nodoc:
|
11
|
-
256.times do |i|
|
12
|
-
TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
|
13
|
-
end
|
14
|
-
TBLENCWWWCOMP_[' '] = '+'
|
15
|
-
TBLENCWWWCOMP_.freeze
|
16
|
-
TBLDECWWWCOMP_ = {} # :nodoc:
|
17
|
-
256.times do |i|
|
18
|
-
h, l = i>>4, i&15
|
19
|
-
TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
|
20
|
-
TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
|
21
|
-
TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
|
22
|
-
TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
|
23
|
-
end
|
24
|
-
TBLDECWWWCOMP_['+'] = ' '
|
25
|
-
TBLDECWWWCOMP_.freeze
|
26
|
-
|
27
|
-
# Encode given +s+ to URL-encoded form data.
|
28
|
-
#
|
29
|
-
# This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
|
30
|
-
# (ASCII space) to + and converts others to %XX.
|
31
|
-
#
|
32
|
-
# This is an implementation of
|
33
|
-
# http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
|
34
|
-
#
|
35
|
-
# See URI.decode_www_form_component, URI.encode_www_form
|
36
|
-
def self.encode_www_form_component(s)
|
37
|
-
str = s.to_s
|
38
|
-
if RUBY_VERSION < "1.9" && $KCODE =~ /u/i
|
39
|
-
str.gsub(/([^ a-zA-Z0-9_.-]+)/) do
|
40
|
-
'%' + $1.unpack('H2' * Rack::Utils.bytesize($1)).join('%').upcase
|
41
|
-
end.tr(' ', '+')
|
42
|
-
else
|
43
|
-
str.gsub(/[^*\-.0-9A-Z_a-z]/) {|m| TBLENCWWWCOMP_[m]}
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Decode given +str+ of URL-encoded form data.
|
48
|
-
#
|
49
|
-
# This decodes + to SP.
|
50
|
-
#
|
51
|
-
# See URI.encode_www_form_component, URI.decode_www_form
|
52
|
-
def self.decode_www_form_component(str, enc = nil)
|
53
|
-
raise ArgumentError, "invalid %-encoding (#{str})" unless /\A(?:%[0-9a-fA-F]{2}|[^%])*\z/ =~ str
|
54
|
-
str.gsub(/\+|%[0-9a-fA-F]{2}/) {|m| TBLDECWWWCOMP_[m]}
|
55
|
-
end
|
56
|
-
|
57
|
-
# Generate URL-encoded form data from given +enum+.
|
58
|
-
#
|
59
|
-
# This generates application/x-www-form-urlencoded data defined in HTML5
|
60
|
-
# from given an Enumerable object.
|
61
|
-
#
|
62
|
-
# This internally uses URI.encode_www_form_component(str).
|
63
|
-
#
|
64
|
-
# This method doesn't convert the encoding of given items, so convert them
|
65
|
-
# before call this method if you want to send data as other than original
|
66
|
-
# encoding or mixed encoding data. (Strings which are encoded in an HTML5
|
67
|
-
# ASCII incompatible encoding are converted to UTF-8.)
|
68
|
-
#
|
69
|
-
# This method doesn't handle files. When you send a file, use
|
70
|
-
# multipart/form-data.
|
71
|
-
#
|
72
|
-
# This is an implementation of
|
73
|
-
# http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
|
74
|
-
#
|
75
|
-
# URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
|
76
|
-
# #=> "q=ruby&lang=en"
|
77
|
-
# URI.encode_www_form("q" => "ruby", "lang" => "en")
|
78
|
-
# #=> "q=ruby&lang=en"
|
79
|
-
# URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en")
|
80
|
-
# #=> "q=ruby&q=perl&lang=en"
|
81
|
-
# URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]])
|
82
|
-
# #=> "q=ruby&q=perl&lang=en"
|
83
|
-
#
|
84
|
-
# See URI.encode_www_form_component, URI.decode_www_form
|
85
|
-
def self.encode_www_form(enum)
|
86
|
-
enum.map do |k,v|
|
87
|
-
if v.nil?
|
88
|
-
encode_www_form_component(k)
|
89
|
-
elsif v.respond_to?(:to_ary)
|
90
|
-
v.to_ary.map do |w|
|
91
|
-
str = encode_www_form_component(k)
|
92
|
-
unless w.nil?
|
93
|
-
str << '='
|
94
|
-
str << encode_www_form_component(w)
|
95
|
-
end
|
96
|
-
end.join('&')
|
97
|
-
else
|
98
|
-
str = encode_www_form_component(k)
|
99
|
-
str << '='
|
100
|
-
str << encode_www_form_component(v)
|
101
|
-
end
|
102
|
-
end.join('&')
|
103
|
-
end
|
104
|
-
end
|
data/lib/raven/transports/udp.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
|
3
|
-
require 'raven/transports'
|
4
|
-
require 'raven/error'
|
5
|
-
|
6
|
-
module Raven
|
7
|
-
module Transports
|
8
|
-
class UDP < Transport
|
9
|
-
def send_event(auth_header, data, _options = {})
|
10
|
-
conn.send "#{auth_header}\n\n#{data}", 0
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def conn
|
16
|
-
@conn ||= begin
|
17
|
-
sock = UDPSocket.new
|
18
|
-
sock.connect(self.configuration.host, self.configuration.port)
|
19
|
-
sock
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def verify_configuration
|
24
|
-
super
|
25
|
-
raise Error.new('No port specified') unless self.configuration.port
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|