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 +76 -13
- data/lib/raven.rb +2 -191
- data/lib/raven/backtrace.rb +5 -4
- data/lib/raven/base.rb +212 -0
- data/lib/raven/cli.rb +7 -9
- data/lib/raven/client.rb +8 -9
- data/lib/raven/configuration.rb +20 -3
- data/lib/raven/error.rb +0 -2
- data/lib/raven/event.rb +16 -19
- data/lib/raven/interfaces.rb +2 -3
- data/lib/raven/interfaces/exception.rb +0 -3
- data/lib/raven/interfaces/http.rb +10 -11
- data/lib/raven/interfaces/message.rb +0 -2
- data/lib/raven/interfaces/stack_trace.rb +7 -10
- data/lib/raven/linecache.rb +1 -3
- data/lib/raven/logger.rb +2 -4
- data/lib/raven/okjson.rb +2 -0
- data/lib/raven/processor.rb +0 -2
- data/lib/raven/processors/sanitizedata.rb +4 -3
- data/lib/raven/rack.rb +2 -4
- data/lib/raven/railtie.rb +0 -1
- data/lib/raven/sidekiq.rb +15 -10
- data/lib/raven/tasks.rb +3 -4
- data/lib/raven/transports.rb +1 -6
- data/lib/raven/transports/http.rb +1 -6
- data/lib/raven/transports/udp.rb +0 -5
- data/lib/raven/version.rb +1 -1
- data/lib/sentry-raven.rb +1 -1
- metadata +26 -14
data/lib/raven/cli.rb
CHANGED
@@ -2,7 +2,7 @@ require 'raven'
|
|
2
2
|
|
3
3
|
module Raven
|
4
4
|
class CLI
|
5
|
-
def self.test(dsn=nil)
|
5
|
+
def self.test(dsn = nil)
|
6
6
|
require 'logger'
|
7
7
|
|
8
8
|
logger = ::Logger.new(STDOUT)
|
@@ -13,26 +13,24 @@ module Raven
|
|
13
13
|
|
14
14
|
Raven.configuration.logger = logger
|
15
15
|
|
16
|
-
if dsn
|
17
|
-
Raven.configuration.dsn = dsn
|
18
|
-
end
|
16
|
+
Raven.configuration.dsn = dsn if dsn
|
19
17
|
|
20
18
|
# wipe out env settings to ensure we send the event
|
21
|
-
|
19
|
+
unless Raven.configuration.send_in_current_environment?
|
22
20
|
environments = Raven.configuration.environments
|
23
21
|
env_name = (environments && environments[0]) || 'production'
|
24
22
|
puts "Setting environment to #{env_name}"
|
25
23
|
Raven.configuration.current_environment = env_name
|
26
24
|
end
|
27
25
|
|
28
|
-
|
26
|
+
unless Raven.configuration.server
|
29
27
|
puts "Your client is not configured!"
|
30
28
|
exit 1
|
31
29
|
end
|
32
30
|
|
33
31
|
puts "Client configuration:"
|
34
32
|
['server', 'project_id', 'public_key', 'secret_key'].each do |key|
|
35
|
-
|
33
|
+
unless Raven.configuration[key]
|
36
34
|
puts "Missing configuration for #{key}"
|
37
35
|
exit 1
|
38
36
|
end
|
@@ -48,7 +46,7 @@ module Raven
|
|
48
46
|
evt = Raven.capture_exception(exception)
|
49
47
|
end
|
50
48
|
|
51
|
-
if evt
|
49
|
+
if evt
|
52
50
|
puts "-> event ID: #{evt.id}"
|
53
51
|
else
|
54
52
|
puts ""
|
@@ -60,4 +58,4 @@ module Raven
|
|
60
58
|
puts "Done!"
|
61
59
|
end
|
62
60
|
end
|
63
|
-
end
|
61
|
+
end
|
data/lib/raven/client.rb
CHANGED
@@ -22,8 +22,8 @@ module Raven
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def send(event)
|
25
|
-
|
26
|
-
|
25
|
+
unless configuration.send_in_current_environment?
|
26
|
+
configuration.log_excluded_environment_message
|
27
27
|
return
|
28
28
|
end
|
29
29
|
|
@@ -34,17 +34,17 @@ module Raven
|
|
34
34
|
content_type, encoded_data = encode(event)
|
35
35
|
begin
|
36
36
|
transport.send(generate_auth_header(encoded_data), encoded_data,
|
37
|
-
|
37
|
+
:content_type => content_type)
|
38
38
|
rescue => e
|
39
39
|
Raven.logger.error "Unable to record event with remote Sentry server (#{e.class} - #{e.message})"
|
40
40
|
e.backtrace[0..10].each { |line| Raven.logger.error(line) }
|
41
41
|
return
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
event
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
private
|
48
48
|
|
49
49
|
def encode(event)
|
50
50
|
hash = event.to_hash
|
@@ -67,7 +67,8 @@ module Raven
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def transport
|
70
|
-
@transport ||=
|
70
|
+
@transport ||=
|
71
|
+
case self.configuration.scheme
|
71
72
|
when 'udp'
|
72
73
|
Transports::UDP.new self.configuration
|
73
74
|
when 'http', 'https'
|
@@ -86,9 +87,7 @@ module Raven
|
|
86
87
|
'sentry_key' => self.configuration.public_key,
|
87
88
|
'sentry_secret' => self.configuration.secret_key,
|
88
89
|
}
|
89
|
-
'Sentry ' + fields.map{|key, value| "#{key}=#{value}"}.join(', ')
|
90
|
+
'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
|
90
91
|
end
|
91
|
-
|
92
92
|
end
|
93
|
-
|
94
93
|
end
|
data/lib/raven/configuration.rb
CHANGED
@@ -67,9 +67,15 @@ module Raven
|
|
67
67
|
# DEPRECATED: This option is now ignored as we use our own adapter.
|
68
68
|
attr_accessor :json_adapter
|
69
69
|
|
70
|
-
# Default tags for events
|
70
|
+
# Default tags for events
|
71
71
|
attr_accessor :tags
|
72
72
|
|
73
|
+
# Optional Proc to be used to send events asynchronously.
|
74
|
+
attr_reader :async
|
75
|
+
|
76
|
+
# Exceptions from these directories to be ignored
|
77
|
+
attr_accessor :app_dirs_pattern
|
78
|
+
|
73
79
|
IGNORE_DEFAULT = ['ActiveRecord::RecordNotFound',
|
74
80
|
'ActionController::RoutingError',
|
75
81
|
'ActionController::InvalidAuthenticityToken',
|
@@ -90,10 +96,11 @@ module Raven
|
|
90
96
|
self.timeout = 1
|
91
97
|
self.open_timeout = 1
|
92
98
|
self.tags = {}
|
99
|
+
self.async = false
|
93
100
|
end
|
94
101
|
|
95
102
|
def server=(value)
|
96
|
-
uri = URI
|
103
|
+
uri = URI.parse(value)
|
97
104
|
uri_path = uri.path.split('/')
|
98
105
|
|
99
106
|
if uri.user
|
@@ -110,7 +117,7 @@ module Raven
|
|
110
117
|
|
111
118
|
# For anyone who wants to read the base server string
|
112
119
|
@server = "#{@scheme}://#{@host}"
|
113
|
-
@server << ":#{@port}" unless @port == {'http'=>80,'https'=>443}[@scheme]
|
120
|
+
@server << ":#{@port}" unless @port == { 'http' => 80, 'https' => 443 }[@scheme]
|
114
121
|
@server << @path
|
115
122
|
end
|
116
123
|
|
@@ -121,6 +128,13 @@ module Raven
|
|
121
128
|
|
122
129
|
alias_method :dsn=, :server=
|
123
130
|
|
131
|
+
def async=(value)
|
132
|
+
raise ArgumentError.new("async must be callable (or false to disable)") unless (value == false || value.respond_to?(:call))
|
133
|
+
@async = value
|
134
|
+
end
|
135
|
+
|
136
|
+
alias_method :async?, :async
|
137
|
+
|
124
138
|
# Allows config options to be read like a hash
|
125
139
|
#
|
126
140
|
# @param [Symbol] option Key for a given attribute
|
@@ -140,5 +154,8 @@ module Raven
|
|
140
154
|
end
|
141
155
|
end
|
142
156
|
|
157
|
+
def log_excluded_environment_message
|
158
|
+
Raven.logger.debug "Event not sent due to excluded environment: #{current_environment}"
|
159
|
+
end
|
143
160
|
end
|
144
161
|
end
|
data/lib/raven/error.rb
CHANGED
data/lib/raven/event.rb
CHANGED
@@ -26,7 +26,7 @@ module Raven
|
|
26
26
|
attr_accessor :project, :message, :timestamp, :level
|
27
27
|
attr_accessor :logger, :culprit, :server_name, :modules, :extra, :tags
|
28
28
|
|
29
|
-
def initialize(options={}, &block)
|
29
|
+
def initialize(options = {}, &block)
|
30
30
|
@configuration = options[:configuration] || Raven.configuration
|
31
31
|
@interfaces = {}
|
32
32
|
|
@@ -41,9 +41,8 @@ module Raven
|
|
41
41
|
@culprit = options[:culprit]
|
42
42
|
@server_name = options[:server_name] || @configuration.server_name || get_hostname
|
43
43
|
|
44
|
-
if @configuration.send_modules
|
45
|
-
|
46
|
-
end
|
44
|
+
options[:modules] ||= get_modules if @configuration.send_modules
|
45
|
+
|
47
46
|
@modules = options[:modules]
|
48
47
|
|
49
48
|
@user = options[:user] || {}
|
@@ -79,11 +78,11 @@ module Raven
|
|
79
78
|
|
80
79
|
def get_modules
|
81
80
|
# Older versions of Rubygems don't support iterating over all specs
|
82
|
-
Hash[Gem::Specification.map {|spec| [spec.name, spec.version.to_s]}] if Gem::Specification.respond_to?(:map)
|
81
|
+
Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
83
82
|
end
|
84
83
|
|
85
|
-
def interface(name, value=nil, &block)
|
86
|
-
int = Raven
|
84
|
+
def interface(name, value = nil, &block)
|
85
|
+
int = Raven.find_interface(name)
|
87
86
|
raise Error.new("Unknown interface: #{name}") unless int
|
88
87
|
@interfaces[int.name] = int.new(value, &block) if value || block
|
89
88
|
@interfaces[int.name]
|
@@ -119,7 +118,7 @@ module Raven
|
|
119
118
|
data
|
120
119
|
end
|
121
120
|
|
122
|
-
def self.from_exception(exc, options={}, &block)
|
121
|
+
def self.from_exception(exc, options = {}, &block)
|
123
122
|
notes = exc.instance_variable_get(:@__raven_context) || {}
|
124
123
|
options = notes.merge(options)
|
125
124
|
|
@@ -140,21 +139,21 @@ module Raven
|
|
140
139
|
evt.message = "#{exc.class.to_s}: #{exc.message}"
|
141
140
|
evt.level = options[:level] || :error
|
142
141
|
evt.parse_exception(exc)
|
143
|
-
if
|
142
|
+
if exc.backtrace
|
144
143
|
evt.interface :stack_trace do |int|
|
145
144
|
backtrace = Backtrace.parse(exc.backtrace)
|
146
|
-
int.frames = backtrace.lines.reverse.map
|
145
|
+
int.frames = backtrace.lines.reverse.map do |line|
|
147
146
|
int.frame do |frame|
|
148
147
|
frame.abs_path = line.file
|
149
148
|
frame.function = line.method
|
150
149
|
frame.lineno = line.number
|
151
150
|
frame.in_app = line.in_app
|
152
|
-
if context_lines
|
151
|
+
if context_lines && frame.abs_path
|
153
152
|
frame.pre_context, frame.context_line, frame.post_context = \
|
154
153
|
evt.get_file_context(frame.abs_path, frame.lineno, context_lines)
|
155
154
|
end
|
156
155
|
end
|
157
|
-
|
156
|
+
end.select { |f| f.filename }
|
158
157
|
evt.culprit = evt.get_culprit(int.frames)
|
159
158
|
end
|
160
159
|
end
|
@@ -162,7 +161,7 @@ module Raven
|
|
162
161
|
end
|
163
162
|
end
|
164
163
|
|
165
|
-
def self.from_message(message, options={})
|
164
|
+
def self.from_message(message, options = {})
|
166
165
|
new(options) do |evt|
|
167
166
|
evt.message = message
|
168
167
|
evt.level = options[:level] || :error
|
@@ -178,20 +177,20 @@ module Raven
|
|
178
177
|
|
179
178
|
def get_file_context(filename, lineno, context)
|
180
179
|
lines = (2 * context + 1).times.map do |i|
|
181
|
-
Raven::LineCache
|
180
|
+
Raven::LineCache.getline(filename, lineno - context + i)
|
182
181
|
end
|
183
|
-
[lines[0..(context-1)], lines[context], lines[(context+1)..-1]]
|
182
|
+
[lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]]
|
184
183
|
end
|
185
184
|
|
186
185
|
def get_culprit(frames)
|
187
|
-
lastframe = frames.reverse.
|
186
|
+
lastframe = frames.reverse.find { |f| f.in_app } || frames.last
|
188
187
|
"#{lastframe.filename} in #{lastframe.function} at line #{lastframe.lineno}" if lastframe
|
189
188
|
end
|
190
189
|
|
191
190
|
def parse_exception(exception)
|
192
191
|
interface(:exception) do |int|
|
193
192
|
int.type = exception.class.to_s
|
194
|
-
int.value = exception.
|
193
|
+
int.value = exception.to_s
|
195
194
|
int.module = exception.class.to_s.split('::')[0...-1].join('::')
|
196
195
|
end
|
197
196
|
end
|
@@ -203,7 +202,5 @@ module Raven
|
|
203
202
|
alias :capture_exception :from_exception
|
204
203
|
alias :capture_message :from_message
|
205
204
|
end
|
206
|
-
|
207
|
-
private
|
208
205
|
end
|
209
206
|
end
|
data/lib/raven/interfaces.rb
CHANGED
@@ -5,7 +5,7 @@ module Raven
|
|
5
5
|
INTERFACES = {}
|
6
6
|
|
7
7
|
class Interface < Hashie::Dash
|
8
|
-
def initialize(attributes={}, &block)
|
8
|
+
def initialize(attributes = {}, &block)
|
9
9
|
@check_required = false
|
10
10
|
super(attributes)
|
11
11
|
block.call(self) if block
|
@@ -17,7 +17,7 @@ module Raven
|
|
17
17
|
super if @check_required
|
18
18
|
end
|
19
19
|
|
20
|
-
def self.name(value=nil)
|
20
|
+
def self.name(value = nil)
|
21
21
|
@interface_name = value if value
|
22
22
|
@interface_name
|
23
23
|
end
|
@@ -33,5 +33,4 @@ module Raven
|
|
33
33
|
def self.find_interface(name)
|
34
34
|
INTERFACES[name.to_s]
|
35
35
|
end
|
36
|
-
|
37
36
|
end
|
@@ -1,16 +1,13 @@
|
|
1
1
|
require 'raven/interfaces'
|
2
2
|
|
3
3
|
module Raven
|
4
|
-
|
5
4
|
class ExceptionInterface < Interface
|
6
5
|
|
7
6
|
name 'sentry.interfaces.Exception'
|
8
7
|
property :type, :required => true
|
9
8
|
property :value, :required => true
|
10
9
|
property :module
|
11
|
-
|
12
10
|
end
|
13
11
|
|
14
12
|
register_interface :exception => ExceptionInterface
|
15
|
-
|
16
13
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'raven/interfaces'
|
2
2
|
|
3
3
|
module Raven
|
4
|
-
|
5
4
|
class HttpInterface < Interface
|
6
5
|
|
7
6
|
name 'sentry.interfaces.Http'
|
@@ -29,7 +28,7 @@ module Raven
|
|
29
28
|
next unless key.upcase == key # Non-upper case stuff isn't either
|
30
29
|
if key.start_with?('HTTP_')
|
31
30
|
# Header
|
32
|
-
http_key = key[5..key.length-1].split('_').map{|s| s.capitalize}.join('-')
|
31
|
+
http_key = key[5..key.length - 1].split('_').map { |s| s.capitalize }.join('-')
|
33
32
|
self.headers[http_key] = value.to_s
|
34
33
|
elsif ['CONTENT_TYPE', 'CONTENT_LENGTH'].include? key
|
35
34
|
self.headers[key.capitalize] = value.to_s
|
@@ -38,17 +37,17 @@ module Raven
|
|
38
37
|
self.env[key] = value.to_s
|
39
38
|
end
|
40
39
|
end
|
41
|
-
self.data = if req.form_data?
|
42
|
-
req.POST
|
43
|
-
elsif req.body
|
44
|
-
data = req.body.read
|
45
|
-
req.body.rewind
|
46
|
-
data
|
47
|
-
end
|
48
|
-
end
|
49
40
|
|
41
|
+
self.data =
|
42
|
+
if req.form_data?
|
43
|
+
req.POST
|
44
|
+
elsif req.body
|
45
|
+
data = req.body.read
|
46
|
+
req.body.rewind
|
47
|
+
data
|
48
|
+
end
|
49
|
+
end
|
50
50
|
end
|
51
51
|
|
52
52
|
register_interface :http => HttpInterface
|
53
|
-
|
54
53
|
end
|
@@ -3,7 +3,6 @@ require 'hashie'
|
|
3
3
|
require 'raven/interfaces'
|
4
4
|
|
5
5
|
module Raven
|
6
|
-
|
7
6
|
class StacktraceInterface < Interface
|
8
7
|
|
9
8
|
name 'sentry.interfaces.Stacktrace'
|
@@ -14,13 +13,13 @@ module Raven
|
|
14
13
|
super(*arguments)
|
15
14
|
end
|
16
15
|
|
17
|
-
def to_hash
|
18
|
-
data = super
|
19
|
-
data['frames'] = data['frames'].map{|frame| frame.to_hash}
|
16
|
+
def to_hash(*args)
|
17
|
+
data = super(*args)
|
18
|
+
data['frames'] = data['frames'].map { |frame| frame.to_hash }
|
20
19
|
data
|
21
20
|
end
|
22
21
|
|
23
|
-
def frame(attributes=nil, &block)
|
22
|
+
def frame(attributes = nil, &block)
|
24
23
|
Frame.new(attributes, &block)
|
25
24
|
end
|
26
25
|
|
@@ -45,12 +44,12 @@ module Raven
|
|
45
44
|
def filename
|
46
45
|
return nil if self.abs_path.nil?
|
47
46
|
|
48
|
-
prefix =
|
47
|
+
prefix = $LOAD_PATH.select { |s| self.abs_path.start_with?(s.to_s) }.sort_by { |s| s.to_s.length }.last
|
49
48
|
prefix ? self.abs_path[prefix.chomp(File::SEPARATOR).length+1..-1] : self.abs_path
|
50
49
|
end
|
51
50
|
|
52
|
-
def to_hash
|
53
|
-
data = super
|
51
|
+
def to_hash(*args)
|
52
|
+
data = super(*args)
|
54
53
|
data['filename'] = self.filename
|
55
54
|
data.delete('vars') unless self.vars && !self.vars.empty?
|
56
55
|
data.delete('pre_context') unless self.pre_context && !self.pre_context.empty?
|
@@ -59,9 +58,7 @@ module Raven
|
|
59
58
|
data
|
60
59
|
end
|
61
60
|
end
|
62
|
-
|
63
61
|
end
|
64
62
|
|
65
63
|
register_interface :stack_trace => StacktraceInterface
|
66
|
-
|
67
64
|
end
|
data/lib/raven/linecache.rb
CHANGED
data/lib/raven/logger.rb
CHANGED
@@ -13,12 +13,10 @@ module Raven
|
|
13
13
|
msg = args[0] # Block-level default args is a 1.9 feature
|
14
14
|
msg ||= block.call if block
|
15
15
|
logger = Raven.configuration[:logger]
|
16
|
-
if logger.nil?
|
17
|
-
|
18
|
-
end
|
16
|
+
logger = ::Logger.new(STDOUT) if logger.nil?
|
17
|
+
|
19
18
|
logger.send(level, "#{LOG_PREFIX}#{msg}") if logger
|
20
19
|
end
|
21
20
|
end
|
22
|
-
|
23
21
|
end
|
24
22
|
end
|