sentry-raven 0.4.0 → 0.4.1
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.
Potentially problematic release.
This version of sentry-raven might be problematic. Click here for more details.
- data/lib/raven/client.rb +38 -36
- data/lib/raven/configuration.rb +31 -8
- data/lib/raven/event.rb +6 -3
- data/lib/raven/interfaces/stack_trace.rb +2 -0
- data/lib/raven/rack.rb +4 -2
- data/lib/raven/transports.rb +32 -0
- data/lib/raven/transports/http.rb +44 -0
- data/lib/raven/transports/udp.rb +35 -0
- data/lib/raven/version.rb +1 -1
- metadata +82 -79
data/lib/raven/client.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'openssl'
|
2
|
-
require 'uri'
|
3
2
|
require 'multi_json'
|
4
|
-
require '
|
3
|
+
require 'zlib'
|
4
|
+
require 'base64'
|
5
5
|
|
6
6
|
require 'raven/version'
|
7
|
-
require 'raven/
|
7
|
+
require 'raven/transports/http'
|
8
|
+
require 'raven/transports/udp'
|
8
9
|
|
9
10
|
module Raven
|
10
11
|
|
@@ -12,7 +13,7 @@ module Raven
|
|
12
13
|
|
13
14
|
PROTOCOL_VERSION = '2.0'
|
14
15
|
USER_AGENT = "raven-ruby/#{Raven::VERSION}"
|
15
|
-
|
16
|
+
CONTENT_TYPE = 'application/json'
|
16
17
|
|
17
18
|
attr_accessor :configuration
|
18
19
|
|
@@ -20,28 +21,44 @@ module Raven
|
|
20
21
|
@configuration = configuration
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
|
25
|
-
raise Error.new('No server specified') unless self.configuration[:server]
|
26
|
-
raise Error.new('No public key specified') unless self.configuration[:public_key]
|
27
|
-
raise Error.new('No secret key specified') unless self.configuration[:secret_key]
|
28
|
-
raise Error.new('No project ID specified') unless self.configuration[:project_id]
|
24
|
+
def send(event)
|
25
|
+
return unless configuration.send_in_current_environment?
|
29
26
|
|
30
|
-
|
27
|
+
# Set the project ID correctly
|
28
|
+
event.project = self.configuration.project_id
|
29
|
+
Raven.logger.debug "Sending event #{event.id} to Sentry"
|
30
|
+
content_type, encoded_data = encode(event)
|
31
|
+
transport.send(generate_auth_header(encoded_data), encoded_data,
|
32
|
+
:content_type => content_type)
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
private
|
36
|
+
|
37
|
+
def encode(event)
|
38
|
+
encoded = MultiJson.encode(event.to_hash)
|
39
|
+
case self.configuration.encoding
|
40
|
+
when 'gzip'
|
41
|
+
gzipped = Zlib::Deflate.deflate(encoded)
|
42
|
+
b64_encoded = Base64.strict_encode64(gzipped)
|
43
|
+
return 'application/octet-stream', b64_encoded
|
44
|
+
else
|
45
|
+
return 'application/json', encoded
|
46
|
+
end
|
40
47
|
end
|
41
48
|
|
49
|
+
def transport
|
50
|
+
@transport ||= case self.configuration.scheme
|
51
|
+
when 'udp'
|
52
|
+
Transports::UDP.new self.configuration
|
53
|
+
when 'http', 'https'
|
54
|
+
Transports::HTTP.new self.configuration
|
55
|
+
else
|
56
|
+
raise Error.new("Unknown transport scheme '#{self.configuration.scheme}'")
|
57
|
+
end
|
58
|
+
end
|
42
59
|
|
43
60
|
def generate_signature(timestamp, data)
|
44
|
-
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), self.configuration
|
61
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), self.configuration.secret_key, "#{timestamp} #{data}")
|
45
62
|
end
|
46
63
|
|
47
64
|
def generate_auth_header(data)
|
@@ -50,27 +67,12 @@ module Raven
|
|
50
67
|
'sentry_version' => PROTOCOL_VERSION,
|
51
68
|
'sentry_client' => USER_AGENT,
|
52
69
|
'sentry_timestamp' => now,
|
53
|
-
'sentry_key' => self.configuration
|
70
|
+
'sentry_key' => self.configuration.public_key,
|
54
71
|
'sentry_signature' => generate_signature(now, data)
|
55
72
|
}
|
56
73
|
'Sentry ' + fields.map{|key, value| "#{key}=#{value}"}.join(', ')
|
57
74
|
end
|
58
75
|
|
59
|
-
def send(event)
|
60
|
-
return unless configuration.send_in_current_environment?
|
61
|
-
|
62
|
-
# Set the project ID correctly
|
63
|
-
event.project = self.configuration[:project_id]
|
64
|
-
Raven.logger.debug "Sending event #{event.id} to Sentry"
|
65
|
-
response = self.conn.post '/api/store/' do |req|
|
66
|
-
req.headers['Content-Type'] = 'application/json'
|
67
|
-
req.body = MultiJson.encode(event.to_hash)
|
68
|
-
req.headers[AUTH_HEADER_KEY] = self.generate_auth_header(req.body)
|
69
|
-
end
|
70
|
-
raise Error.new("Error from Sentry server (#{response.status}): #{response.body}") unless response.status == 200
|
71
|
-
response
|
72
|
-
end
|
73
|
-
|
74
76
|
end
|
75
77
|
|
76
78
|
end
|
data/lib/raven/configuration.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Raven
|
2
2
|
class Configuration
|
3
3
|
|
4
|
-
#
|
5
|
-
|
4
|
+
# Simple server string (setter provided below)
|
5
|
+
attr_reader :server
|
6
6
|
|
7
7
|
# Public key for authentication with the Sentry server
|
8
8
|
attr_accessor :public_key
|
@@ -10,9 +10,18 @@ module Raven
|
|
10
10
|
# Secret key for authentication with the Sentry server
|
11
11
|
attr_accessor :secret_key
|
12
12
|
|
13
|
+
# Accessors for the component parts of the DSN
|
14
|
+
attr_accessor :scheme
|
15
|
+
attr_accessor :host
|
16
|
+
attr_accessor :port
|
17
|
+
attr_accessor :path
|
18
|
+
|
13
19
|
# Project ID number to send to the Sentry server
|
14
20
|
attr_accessor :project_id
|
15
21
|
|
22
|
+
# Encoding type for event bodies
|
23
|
+
attr_reader :encoding
|
24
|
+
|
16
25
|
# Logger to use internally
|
17
26
|
attr_accessor :logger
|
18
27
|
|
@@ -59,22 +68,36 @@ module Raven
|
|
59
68
|
self.excluded_exceptions = IGNORE_DEFAULT
|
60
69
|
self.processors = [Raven::Processor::SanitizeData]
|
61
70
|
self.ssl_verification = true
|
71
|
+
self.encoding = 'json'
|
72
|
+
self.timeout = 1
|
73
|
+
self.open_timeout = 1
|
62
74
|
end
|
63
75
|
|
64
76
|
def server=(value)
|
65
77
|
uri = URI::parse(value)
|
78
|
+
uri_path = uri.path.split('/')
|
79
|
+
|
66
80
|
if uri.user
|
67
81
|
# DSN-style string
|
68
|
-
uri_path = uri.path.split('/')
|
69
82
|
@project_id = uri_path.pop
|
70
|
-
@server = "#{uri.scheme}://#{uri.host}"
|
71
|
-
@server << ":#{uri.port}" unless uri.port == {'http'=>80,'https'=>443}[uri.scheme]
|
72
|
-
@server << uri_path.join('/')
|
73
83
|
@public_key = uri.user
|
74
84
|
@secret_key = uri.password
|
75
|
-
else
|
76
|
-
@server = value
|
77
85
|
end
|
86
|
+
|
87
|
+
@scheme = uri.scheme
|
88
|
+
@host = uri.host
|
89
|
+
@port = uri.port if uri.port
|
90
|
+
@path = uri_path.join('/')
|
91
|
+
|
92
|
+
# For anyone who wants to read the base server string
|
93
|
+
@server = "#{@scheme}://#{@host}"
|
94
|
+
@server << ":#{@port}" unless @port == {'http'=>80,'https'=>443}[@scheme]
|
95
|
+
@server << @path
|
96
|
+
end
|
97
|
+
|
98
|
+
def encoding=(encoding)
|
99
|
+
raise Error.new('Unsupported encoding') unless ['gzip', 'json'].include? encoding
|
100
|
+
@encoding = encoding
|
78
101
|
end
|
79
102
|
|
80
103
|
alias_method :dsn=, :server=
|
data/lib/raven/event.rb
CHANGED
@@ -20,6 +20,8 @@ module Raven
|
|
20
20
|
|
21
21
|
BACKTRACE_RE = /^(.+?):(\d+)(?::in `(.+?)')?$/
|
22
22
|
|
23
|
+
PLATFORM = "ruby"
|
24
|
+
|
23
25
|
attr_reader :id
|
24
26
|
attr_accessor :project, :message, :timestamp, :level
|
25
27
|
attr_accessor :logger, :culprit, :server_name, :modules, :extra, :tags
|
@@ -82,6 +84,7 @@ module Raven
|
|
82
84
|
'level' => self.level,
|
83
85
|
'project' => self.project,
|
84
86
|
'logger' => self.logger,
|
87
|
+
'platform' => PLATFORM,
|
85
88
|
}
|
86
89
|
data['culprit'] = self.culprit if self.culprit
|
87
90
|
data['server_name'] = self.server_name if self.server_name
|
@@ -115,18 +118,18 @@ module Raven
|
|
115
118
|
if (exc.backtrace)
|
116
119
|
evt.interface :stack_trace do |int|
|
117
120
|
backtrace = Backtrace.parse(exc.backtrace)
|
118
|
-
int.frames = backtrace.lines.reverse.map
|
121
|
+
int.frames = backtrace.lines.reverse.map { |line|
|
119
122
|
int.frame do |frame|
|
120
123
|
frame.abs_path = line.file
|
121
124
|
frame.function = line.method
|
122
125
|
frame.lineno = line.number
|
123
126
|
frame.in_app = line.in_app
|
124
|
-
if context_lines
|
127
|
+
if context_lines and frame.abs_path
|
125
128
|
frame.pre_context, frame.context_line, frame.post_context = \
|
126
129
|
evt.get_context(frame.abs_path, frame.lineno, context_lines)
|
127
130
|
end
|
128
131
|
end
|
129
|
-
|
132
|
+
}.select{ |f| f.filename }
|
130
133
|
evt.culprit = evt.get_culprit(int.frames)
|
131
134
|
end
|
132
135
|
end
|
data/lib/raven/rack.rb
CHANGED
@@ -33,8 +33,10 @@ module Raven
|
|
33
33
|
raise
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
error = env['rack.exception'] || env['sinatra.error']
|
37
|
+
|
38
|
+
if error
|
39
|
+
evt = Event.capture_rack_exception(error, env)
|
38
40
|
Raven.send(evt) if evt
|
39
41
|
end
|
40
42
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'raven/error'
|
2
|
+
|
3
|
+
module Raven
|
4
|
+
|
5
|
+
module Transports
|
6
|
+
|
7
|
+
class Transport
|
8
|
+
|
9
|
+
attr_accessor :configuration
|
10
|
+
|
11
|
+
def initialize(configuration)
|
12
|
+
@configuration = configuration
|
13
|
+
end
|
14
|
+
|
15
|
+
def send(auth_header, data, options = {})
|
16
|
+
raise Error.new('Abstract method not implemented')
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def verify_configuration
|
22
|
+
raise Error.new('No server specified') unless self.configuration.server
|
23
|
+
raise Error.new('No public key specified') unless self.configuration.public_key
|
24
|
+
raise Error.new('No secret key specified') unless self.configuration.secret_key
|
25
|
+
raise Error.new('No project ID specified') unless self.configuration.project_id
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
require 'raven/transports'
|
4
|
+
require 'raven/error'
|
5
|
+
|
6
|
+
module Raven
|
7
|
+
|
8
|
+
module Transports
|
9
|
+
|
10
|
+
class HTTP < Transport
|
11
|
+
|
12
|
+
def send(auth_header, data, options = {})
|
13
|
+
response = conn.post '/api/store/' do |req|
|
14
|
+
req.headers['Content-Type'] = options[:content_type]
|
15
|
+
req.headers['X-Sentry-Auth'] = auth_header
|
16
|
+
req.body = data
|
17
|
+
end
|
18
|
+
raise Error.new("Error from Sentry server (#{response.status}): #{response.body}") unless response.status == 200
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def conn
|
24
|
+
@conn ||= begin
|
25
|
+
self.verify_configuration
|
26
|
+
|
27
|
+
Raven.logger.debug "Raven HTTP Transport connecting to #{self.configuration.server}"
|
28
|
+
|
29
|
+
Faraday.new(
|
30
|
+
:url => self.configuration[:server],
|
31
|
+
:ssl => {:verify => self.configuration.ssl_verification}
|
32
|
+
) do |builder|
|
33
|
+
builder.adapter Faraday.default_adapter
|
34
|
+
builder.options[:timeout] = self.configuration.timeout if self.configuration.timeout
|
35
|
+
builder.options[:open_timeout] = self.configuration.open_timeout if self.configuration.open_timeout
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
require 'raven/transports'
|
4
|
+
require 'raven/error'
|
5
|
+
|
6
|
+
module Raven
|
7
|
+
|
8
|
+
module Transports
|
9
|
+
|
10
|
+
class UDP < Transport
|
11
|
+
|
12
|
+
def send(auth_header, data, options = {})
|
13
|
+
conn.send "#{auth_header}\n\n#{data}", 0
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def conn
|
19
|
+
@conn ||= begin
|
20
|
+
sock = UDPSocket.new
|
21
|
+
sock.connect(self.configuration.host, self.configuration.port)
|
22
|
+
sock
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify_configuration
|
27
|
+
super
|
28
|
+
raise Error.new('No port specified') unless self.configuration.port
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/raven/version.rb
CHANGED
metadata
CHANGED
@@ -1,84 +1,90 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-raven
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 4
|
8
|
-
- 0
|
9
|
-
version: 0.4.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.1
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Noah Kantrowitz
|
13
9
|
- David Cramer
|
14
10
|
autorequire:
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2013-01-29 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
22
16
|
name: faraday
|
23
|
-
|
24
|
-
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
segments:
|
29
|
-
- 0
|
30
|
-
- 7
|
31
|
-
- 6
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
32
22
|
version: 0.7.6
|
33
23
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: uuidtools
|
37
24
|
prerelease: false
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 0.7.6
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: uuidtools
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
45
39
|
type: :runtime
|
46
|
-
version_requirements: *id002
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: multi_json
|
49
40
|
prerelease: false
|
50
|
-
|
51
|
-
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: multi_json
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
52
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
55
|
-
- 1
|
56
|
-
- 0
|
57
|
-
version: "1.0"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
58
55
|
type: :runtime
|
59
|
-
version_requirements: *id003
|
60
|
-
- !ruby/object:Gem::Dependency
|
61
|
-
name: hashie
|
62
56
|
prerelease: false
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: hashie
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
70
71
|
type: :runtime
|
71
|
-
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
72
79
|
description:
|
73
80
|
email: noah@coderanger.net
|
74
|
-
executables:
|
81
|
+
executables:
|
75
82
|
- raven
|
76
83
|
extensions: []
|
77
|
-
|
78
|
-
extra_rdoc_files:
|
84
|
+
extra_rdoc_files:
|
79
85
|
- README.md
|
80
86
|
- LICENSE
|
81
|
-
files:
|
87
|
+
files:
|
82
88
|
- lib/raven/backtrace.rb
|
83
89
|
- lib/raven/client.rb
|
84
90
|
- lib/raven/configuration.rb
|
@@ -97,40 +103,37 @@ files:
|
|
97
103
|
- lib/raven/rails/middleware/debug_exceptions_catcher.rb
|
98
104
|
- lib/raven/railtie.rb
|
99
105
|
- lib/raven/sidekiq.rb
|
106
|
+
- lib/raven/transports/http.rb
|
107
|
+
- lib/raven/transports/udp.rb
|
108
|
+
- lib/raven/transports.rb
|
100
109
|
- lib/raven/version.rb
|
101
110
|
- lib/raven.rb
|
102
111
|
- lib/sentry-raven.rb
|
103
112
|
- README.md
|
104
113
|
- LICENSE
|
105
|
-
|
114
|
+
- bin/raven
|
106
115
|
homepage: http://github.com/getsentry/raven-ruby
|
107
116
|
licenses: []
|
108
|
-
|
109
117
|
post_install_message:
|
110
118
|
rdoc_options: []
|
111
|
-
|
112
|
-
require_paths:
|
119
|
+
require_paths:
|
113
120
|
- lib
|
114
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
requirements:
|
123
|
-
- -
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
|
126
|
-
- 0
|
127
|
-
version: "0"
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ! '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
128
133
|
requirements: []
|
129
|
-
|
130
134
|
rubyforge_project:
|
131
|
-
rubygems_version: 1.
|
135
|
+
rubygems_version: 1.8.23
|
132
136
|
signing_key:
|
133
137
|
specification_version: 3
|
134
138
|
summary: A gem that provides a client interface for the Sentry error logger
|
135
139
|
test_files: []
|
136
|
-
|