sentry-raven 2.0.2 → 2.1.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.
- checksums.yaml +4 -4
- data/lib/raven/base.rb +8 -0
- data/lib/raven/configuration.rb +12 -3
- data/lib/raven/context.rb +27 -6
- data/lib/raven/event.rb +42 -24
- data/lib/raven/integrations/sidekiq.rb +47 -41
- data/lib/raven/{interfaces.rb → interface.rb} +8 -15
- data/lib/raven/interfaces/exception.rb +5 -4
- data/lib/raven/interfaces/http.rb +6 -11
- data/lib/raven/interfaces/message.rb +10 -6
- data/lib/raven/interfaces/single_exception.rb +1 -1
- data/lib/raven/interfaces/stack_trace.rb +5 -4
- data/lib/raven/transports/http.rb +2 -0
- data/lib/raven/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca26b5db2081fdbbdc2d2de7bbd580f1efcbd3f2
|
4
|
+
data.tar.gz: b95c0447aa43feb90d16585803a8815e218390c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49d734c72e306caf5e6a760ee9e76e787eb865f33542929b43ee244b7596607b7f9a13b1d77f531d25de4d09a04d15ca87fab96438379a4fc621b17f8e9c0959
|
7
|
+
data.tar.gz: 9c299e76d4f1081225fd7950a09434564bc4a805bc77673efe2a501af4446297c876bc68edd88267d429d35fa1ac20f24903c0193393b7ec0e85e07f3c9b36c5
|
data/lib/raven/base.rb
CHANGED
@@ -90,5 +90,13 @@ module Raven
|
|
90
90
|
opts[:to].send(:include, opts[:from].const_get("Old" + module_name))
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
def sys_command(unix_command, win_command = nil)
|
95
|
+
unix_result = `#{unix_command} 2>&1` rescue nil # redirect stderr to stdout
|
96
|
+
return unix_result if unix_result != "" && unix_result
|
97
|
+
return if win_command.nil?
|
98
|
+
win_result = `#{win_command}` rescue nil
|
99
|
+
win_result != "" && win_result
|
100
|
+
end
|
93
101
|
end
|
94
102
|
end
|
data/lib/raven/configuration.rb
CHANGED
@@ -267,15 +267,24 @@ module Raven
|
|
267
267
|
end
|
268
268
|
|
269
269
|
def detect_release
|
270
|
-
|
270
|
+
detect_release_from_git ||
|
271
271
|
detect_release_from_capistrano ||
|
272
|
-
|
272
|
+
detect_release_from_heroku
|
273
273
|
end
|
274
274
|
|
275
275
|
private
|
276
276
|
|
277
277
|
def detect_release_from_heroku
|
278
|
-
|
278
|
+
sys_dyno_info = File.read("/etc/heroku/dyno").strip if File.directory?("/etc/heroku") rescue nil
|
279
|
+
return unless sys_dyno_info
|
280
|
+
|
281
|
+
# being overly cautious, because if we raise an error Raven won't start
|
282
|
+
begin
|
283
|
+
hash = JSON.parse(sys_dyno_info)
|
284
|
+
hash && hash["release"] && hash["release"]["commit"]
|
285
|
+
rescue JSON::JSONError
|
286
|
+
Raven.logger.error "Cannot parse Heroku JSON: #{sys_dyno_info}"
|
287
|
+
end
|
279
288
|
end
|
280
289
|
|
281
290
|
def detect_release_from_capistrano
|
data/lib/raven/context.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
1
3
|
module Raven
|
2
4
|
class Context
|
3
5
|
def self.current
|
@@ -8,14 +10,33 @@ module Raven
|
|
8
10
|
Thread.current[:sentry_context] = nil
|
9
11
|
end
|
10
12
|
|
11
|
-
|
12
|
-
attr_accessor :rack_env, :user
|
13
|
+
attr_accessor :extra, :os, :rack_env, :runtime, :tags, :user
|
13
14
|
|
14
15
|
def initialize
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
self.extra = {}
|
17
|
+
self.os = self.class.os_context
|
18
|
+
self.rack_env = nil
|
19
|
+
self.runtime = self.class.runtime_context
|
20
|
+
self.tags = {}
|
21
|
+
self.user = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
def os_context
|
26
|
+
@os_context ||= {
|
27
|
+
"name" => Raven.sys_command("uname -s") || RbConfig::CONFIG["host_os"],
|
28
|
+
"version" => Raven.sys_command("uname -v"),
|
29
|
+
"build" => Raven.sys_command("uname -r"),
|
30
|
+
"kernel_version" => Raven.sys_command("uname -a", "ver")
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def runtime_context
|
35
|
+
@runtime_context ||= {
|
36
|
+
"name" => RbConfig::CONFIG["ruby_install_name"],
|
37
|
+
"version" => Raven.sys_command("ruby -v")
|
38
|
+
}
|
39
|
+
end
|
19
40
|
end
|
20
41
|
end
|
21
42
|
end
|
data/lib/raven/event.rb
CHANGED
@@ -21,11 +21,12 @@ module Raven
|
|
21
21
|
BACKTRACE_RE = /^(.+?):(\d+)(?::in `(.+?)')?$/
|
22
22
|
|
23
23
|
PLATFORM = "ruby".freeze
|
24
|
+
SDK = { "name" => "sentry-raven", "version" => Raven::VERSION }.freeze
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
:
|
28
|
-
:
|
26
|
+
attr_accessor :id, :timestamp, :time_spent, :level, :logger,
|
27
|
+
:culprit, :server_name, :release, :modules, :extra, :tags,
|
28
|
+
:context, :configuration, :checksum, :fingerprint, :environment,
|
29
|
+
:os, :runtime, :breadcrumbs, :user, :backtrace
|
29
30
|
|
30
31
|
def initialize(init = {})
|
31
32
|
@configuration = Raven.configuration
|
@@ -33,8 +34,6 @@ module Raven
|
|
33
34
|
@breadcrumbs = Raven.breadcrumbs
|
34
35
|
@context = Raven.context
|
35
36
|
@id = SecureRandom.uuid.delete("-")
|
36
|
-
@project = nil
|
37
|
-
@message = nil
|
38
37
|
@timestamp = Time.now.utc
|
39
38
|
@time_spent = nil
|
40
39
|
@level = :error
|
@@ -43,9 +42,11 @@ module Raven
|
|
43
42
|
@server_name = @configuration.server_name
|
44
43
|
@release = @configuration.release
|
45
44
|
@modules = list_gem_specs if @configuration.send_modules
|
46
|
-
@user = {}
|
47
|
-
@extra = {}
|
48
|
-
@
|
45
|
+
@user = {} # TODO: contexts
|
46
|
+
@extra = {} # TODO: contexts
|
47
|
+
@os = {} # TODO: contexts
|
48
|
+
@runtime = {} # TODO: contexts
|
49
|
+
@tags = {} # TODO: contexts
|
49
50
|
@checksum = nil
|
50
51
|
@fingerprint = nil
|
51
52
|
@environment = @configuration.current_environment
|
@@ -58,15 +59,17 @@ module Raven
|
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
|
-
if @context.rack_env
|
62
|
+
if @context.rack_env # TODO: contexts
|
62
63
|
@context.user[:ip_address] = calculate_real_ip_from_rack
|
63
64
|
end
|
64
65
|
|
65
|
-
init.each_pair { |key, val|
|
66
|
+
init.each_pair { |key, val| public_send(key.to_s + "=", val) }
|
66
67
|
|
67
|
-
@user = @context.user.merge(@user)
|
68
|
-
@extra = @context.extra.merge(@extra)
|
69
|
-
@tags = @configuration.tags.merge(@context.tags).merge(@tags)
|
68
|
+
@user = @context.user.merge(@user) # TODO: contexts
|
69
|
+
@extra = @context.extra.merge(@extra) # TODO: contexts
|
70
|
+
@tags = @configuration.tags.merge(@context.tags).merge(@tags) # TODO: contexts
|
71
|
+
@os = @context.os # TODO: contexts
|
72
|
+
@runtime = @context.runtime # TODO: contexts
|
70
73
|
|
71
74
|
# Some type coercion
|
72
75
|
@timestamp = @timestamp.strftime('%Y-%m-%dT%H:%M:%S') if @timestamp.is_a?(Time)
|
@@ -74,6 +77,18 @@ module Raven
|
|
74
77
|
@level = LOG_LEVELS[@level.to_s.downcase] if @level.is_a?(String) || @level.is_a?(Symbol)
|
75
78
|
end
|
76
79
|
|
80
|
+
def message
|
81
|
+
@interfaces[:logentry] && @interfaces[:logentry].unformatted_message
|
82
|
+
end
|
83
|
+
|
84
|
+
def message=(args)
|
85
|
+
message, params = *args
|
86
|
+
interface(:message) do |int|
|
87
|
+
int.message = message
|
88
|
+
int.params = params
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
77
92
|
class << self
|
78
93
|
def from_exception(exc, options = {}, &block)
|
79
94
|
exception_context = get_exception_context(exc) || {}
|
@@ -107,11 +122,8 @@ module Raven
|
|
107
122
|
|
108
123
|
new(options) do |evt|
|
109
124
|
evt.configuration = configuration
|
110
|
-
evt.message = message
|
111
125
|
evt.level = options[:level] || :error
|
112
|
-
evt.
|
113
|
-
int.message = message
|
114
|
-
end
|
126
|
+
evt.message = message, options[:message_params] || []
|
115
127
|
if options[:backtrace]
|
116
128
|
evt.interface(:stacktrace) do |int|
|
117
129
|
stacktrace_interface_from(int, evt, options[:backtrace])
|
@@ -196,10 +208,10 @@ module Raven
|
|
196
208
|
end
|
197
209
|
|
198
210
|
def interface(name, value = nil, &block)
|
199
|
-
int =
|
211
|
+
int = Interface.registered[name]
|
200
212
|
raise(Error, "Unknown interface: #{name}") unless int
|
201
|
-
@interfaces[int.
|
202
|
-
@interfaces[int.
|
213
|
+
@interfaces[int.sentry_alias] = int.new(value, &block) if value || block
|
214
|
+
@interfaces[int.sentry_alias]
|
203
215
|
end
|
204
216
|
|
205
217
|
def [](key)
|
@@ -213,13 +225,17 @@ module Raven
|
|
213
225
|
def to_hash
|
214
226
|
data = {
|
215
227
|
:event_id => @id,
|
216
|
-
:message => @message,
|
217
228
|
:timestamp => @timestamp,
|
218
229
|
:time_spent => @time_spent,
|
219
230
|
:level => @level,
|
220
|
-
:
|
221
|
-
:
|
231
|
+
:platform => PLATFORM,
|
232
|
+
:sdk => SDK,
|
233
|
+
:contexts => {
|
234
|
+
:os => @os,
|
235
|
+
:runtime => @runtime
|
236
|
+
}
|
222
237
|
}
|
238
|
+
|
223
239
|
data[:logger] = @logger if @logger
|
224
240
|
data[:culprit] = @culprit if @culprit
|
225
241
|
data[:server_name] = @server_name if @server_name
|
@@ -232,9 +248,11 @@ module Raven
|
|
232
248
|
data[:user] = @user if @user
|
233
249
|
data[:breadcrumbs] = @breadcrumbs.to_hash unless @breadcrumbs.empty?
|
234
250
|
data[:checksum] = @checksum if @checksum
|
251
|
+
|
235
252
|
@interfaces.each_pair do |name, int_data|
|
236
253
|
data[name.to_sym] = int_data.to_hash
|
237
254
|
end
|
255
|
+
data[:message] = message
|
238
256
|
data
|
239
257
|
end
|
240
258
|
|
@@ -3,56 +3,62 @@ require 'sidekiq'
|
|
3
3
|
|
4
4
|
module Raven
|
5
5
|
class Sidekiq
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
Raven.capture_exception(
|
11
|
-
|
12
|
-
|
6
|
+
ACTIVEJOB_RESERVED_PREFIX = "_aj_".freeze
|
7
|
+
|
8
|
+
def call(ex, context)
|
9
|
+
context = filter_context(context)
|
10
|
+
Raven.capture_exception(
|
11
|
+
ex,
|
12
|
+
:message => ex.message,
|
13
|
+
:extra => { :sidekiq => context },
|
14
|
+
:culprit => culprit_from_context(context)
|
15
|
+
)
|
13
16
|
ensure
|
14
17
|
Context.clear!
|
15
18
|
BreadcrumbBuffer.clear!
|
16
19
|
end
|
17
|
-
end
|
18
|
-
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
private
|
22
|
+
|
23
|
+
# Once an ActiveJob is queued, ActiveRecord references get serialized into
|
24
|
+
# some internal reserved keys, such as _aj_globalid.
|
25
|
+
#
|
26
|
+
# The problem is, if this job in turn gets queued back into ActiveJob with
|
27
|
+
# these magic reserved keys, ActiveJob will throw up and error. We want to
|
28
|
+
# capture these and mutate the keys so we can sanely report it.
|
29
|
+
def filter_context(context)
|
30
|
+
case context
|
31
|
+
when Array
|
32
|
+
context.map { |arg| filter_context(arg) }
|
33
|
+
when Hash
|
34
|
+
Hash[context.map { |key, value| filter_context_hash(key, value) }]
|
35
|
+
else
|
36
|
+
context
|
37
|
+
end
|
25
38
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Raven.capture_exception(ex, :extra => {
|
31
|
-
:sidekiq => filter_context(context)
|
32
|
-
})
|
39
|
+
|
40
|
+
def filter_context_hash(key, value)
|
41
|
+
(key = key[3..-1]) if key [0..3] == ACTIVEJOB_RESERVED_PREFIX
|
42
|
+
[key, filter_context(value)]
|
33
43
|
end
|
34
|
-
end
|
35
|
-
end
|
36
44
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
# this will change in the future:
|
46
|
+
# https://github.com/mperham/sidekiq/pull/3161
|
47
|
+
def culprit_from_context(context)
|
48
|
+
classname = (context["class"] || (context["job"] && context["job"]["class"]))
|
49
|
+
if classname
|
50
|
+
"Sidekiq/#{classname}"
|
51
|
+
elsif context["event"]
|
52
|
+
"Sidekiq/#{context['event']}"
|
53
|
+
else
|
54
|
+
"Sidekiq"
|
55
|
+
end
|
56
|
+
end
|
45
57
|
end
|
46
58
|
end
|
47
59
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# these are declared as private, and I don't think it's wise
|
53
|
-
# to keep chasing what this list is. But they all use a common prefix, so
|
54
|
-
# we want to strip this becuase ActiveJob will complain.
|
55
|
-
# e.g.: _aj_globalid -> _globalid
|
56
|
-
(key = key[3..-1]) if key [0..3] == "_aj_"
|
57
|
-
[key, filter_context(value)]
|
60
|
+
if Sidekiq::VERSION > '3'
|
61
|
+
Sidekiq.configure_server do |config|
|
62
|
+
config.error_handlers << Raven::Sidekiq.new
|
63
|
+
end
|
58
64
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
module Raven
|
2
|
-
INTERFACES = {} # rubocop:disable Style/MutableConstant
|
3
|
-
|
4
2
|
class Interface
|
5
3
|
def initialize(attributes = nil)
|
6
4
|
attributes.each do |attr, value|
|
@@ -10,23 +8,18 @@ module Raven
|
|
10
8
|
yield self if block_given?
|
11
9
|
end
|
12
10
|
|
13
|
-
def self.
|
14
|
-
|
11
|
+
def self.inherited(klass)
|
12
|
+
name = klass.name.split("::").last.downcase.gsub("interface", "")
|
13
|
+
registered[name.to_sym] = klass
|
14
|
+
super
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
17
|
+
def self.registered
|
18
|
+
@@registered ||= {} # rubocop:disable Style/ClassVars
|
19
19
|
end
|
20
|
-
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
INTERFACES[key.to_s] = klass
|
25
|
-
INTERFACES[klass.name] = klass
|
21
|
+
def to_hash
|
22
|
+
Hash[instance_variables.map { |name| [name[1..-1].to_sym, instance_variable_get(name)] }]
|
26
23
|
end
|
27
24
|
end
|
28
|
-
|
29
|
-
def self.find_interface(name)
|
30
|
-
INTERFACES[name.to_s]
|
31
|
-
end
|
32
25
|
end
|
@@ -1,16 +1,17 @@
|
|
1
|
-
require 'raven/
|
1
|
+
require 'raven/interface'
|
2
2
|
|
3
3
|
module Raven
|
4
4
|
class ExceptionInterface < Interface
|
5
|
-
name 'exception'
|
6
5
|
attr_accessor :values
|
7
6
|
|
7
|
+
def self.sentry_alias
|
8
|
+
:exception
|
9
|
+
end
|
10
|
+
|
8
11
|
def to_hash(*args)
|
9
12
|
data = super(*args)
|
10
13
|
data[:values] = data[:values].map(&:to_hash) if data[:values]
|
11
14
|
data
|
12
15
|
end
|
13
16
|
end
|
14
|
-
|
15
|
-
register_interface :exception => ExceptionInterface
|
16
17
|
end
|
@@ -1,15 +1,8 @@
|
|
1
|
-
require 'raven/
|
1
|
+
require 'raven/interface'
|
2
2
|
|
3
3
|
module Raven
|
4
4
|
class HttpInterface < Interface
|
5
|
-
|
6
|
-
attr_accessor :url
|
7
|
-
attr_accessor :method
|
8
|
-
attr_accessor :data
|
9
|
-
attr_accessor :query_string
|
10
|
-
attr_accessor :cookies
|
11
|
-
attr_accessor :headers
|
12
|
-
attr_accessor :env
|
5
|
+
attr_accessor :url, :method, :data, :query_string, :cookies, :headers, :env
|
13
6
|
|
14
7
|
def initialize(*arguments)
|
15
8
|
self.headers = {}
|
@@ -17,7 +10,9 @@ module Raven
|
|
17
10
|
self.cookies = nil
|
18
11
|
super(*arguments)
|
19
12
|
end
|
20
|
-
end
|
21
13
|
|
22
|
-
|
14
|
+
def self.sentry_alias
|
15
|
+
:request
|
16
|
+
end
|
17
|
+
end
|
23
18
|
end
|
@@ -1,16 +1,20 @@
|
|
1
|
-
require 'raven/
|
1
|
+
require 'raven/interface'
|
2
2
|
|
3
3
|
module Raven
|
4
4
|
class MessageInterface < Interface
|
5
|
-
|
6
|
-
attr_accessor :message
|
7
|
-
attr_accessor :params
|
5
|
+
attr_accessor :message, :params
|
8
6
|
|
9
7
|
def initialize(*arguments)
|
10
8
|
self.params = []
|
11
9
|
super(*arguments)
|
12
10
|
end
|
13
|
-
end
|
14
11
|
|
15
|
-
|
12
|
+
def unformatted_message
|
13
|
+
message % params
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.sentry_alias
|
17
|
+
:logentry
|
18
|
+
end
|
19
|
+
end
|
16
20
|
end
|
@@ -1,8 +1,7 @@
|
|
1
|
-
require 'raven/
|
1
|
+
require 'raven/interface'
|
2
2
|
|
3
3
|
module Raven
|
4
4
|
class StacktraceInterface < Interface
|
5
|
-
name 'stacktrace'
|
6
5
|
attr_accessor :frames
|
7
6
|
|
8
7
|
def initialize(*arguments)
|
@@ -10,6 +9,10 @@ module Raven
|
|
10
9
|
super(*arguments)
|
11
10
|
end
|
12
11
|
|
12
|
+
def self.sentry_alias
|
13
|
+
:stacktrace
|
14
|
+
end
|
15
|
+
|
13
16
|
def to_hash(*args)
|
14
17
|
data = super(*args)
|
15
18
|
data[:frames] = data[:frames].map(&:to_hash)
|
@@ -71,6 +74,4 @@ module Raven
|
|
71
74
|
end
|
72
75
|
end
|
73
76
|
end
|
74
|
-
|
75
|
-
register_interface :stack_trace => StacktraceInterface
|
76
77
|
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: 2.0
|
4
|
+
version: 2.1.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-
|
11
|
+
date: 2016-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -149,7 +149,7 @@ files:
|
|
149
149
|
- lib/raven/integrations/rake.rb
|
150
150
|
- lib/raven/integrations/sidekiq.rb
|
151
151
|
- lib/raven/integrations/tasks.rb
|
152
|
-
- lib/raven/
|
152
|
+
- lib/raven/interface.rb
|
153
153
|
- lib/raven/interfaces/exception.rb
|
154
154
|
- lib/raven/interfaces/http.rb
|
155
155
|
- lib/raven/interfaces/message.rb
|