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 CHANGED
@@ -1,10 +1,11 @@
1
1
  require 'openssl'
2
- require 'uri'
3
2
  require 'multi_json'
4
- require 'faraday'
3
+ require 'zlib'
4
+ require 'base64'
5
5
 
6
6
  require 'raven/version'
7
- require 'raven/error'
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
- AUTH_HEADER_KEY = 'X-Sentry-Auth'
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 conn
24
- # Error checking
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
- Raven.logger.debug "Raven client connecting to #{self.configuration[:server]}"
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
- @conn ||= Faraday.new(
33
- :url => self.configuration[:server],
34
- :ssl => {:verify => self.configuration.ssl_verification}
35
- ) do |builder|
36
- builder.adapter Faraday.default_adapter
37
- builder.options[:timeout] = self.configuration.timeout if self.configuration.timeout
38
- builder.options[:open_timeout] = self.configuration.open_timeout if self.configuration.open_timeout
39
- end
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[:secret_key], "#{timestamp} #{data}")
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[:public_key],
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
@@ -1,8 +1,8 @@
1
1
  module Raven
2
2
  class Configuration
3
3
 
4
- # Base URL of the Sentry server
5
- attr_accessor :server
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 do |line|
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
- end
132
+ }.select{ |f| f.filename }
130
133
  evt.culprit = evt.get_culprit(int.frames)
131
134
  end
132
135
  end
@@ -43,6 +43,8 @@ module Raven
43
43
  end
44
44
 
45
45
  def filename
46
+ return nil if self.abs_path.nil?
47
+
46
48
  prefix = $:.select {|s| self.abs_path.start_with?(s)}.sort_by {|s| s.length}.last
47
49
  prefix ? self.abs_path[prefix.chomp(File::SEPARATOR).length+1..-1] : self.abs_path
48
50
  end
data/lib/raven/rack.rb CHANGED
@@ -33,8 +33,10 @@ module Raven
33
33
  raise
34
34
  end
35
35
 
36
- if env['rack.exception']
37
- evt = Event.capture_rack_exception(env['rack.exception'], env)
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
@@ -1,3 +1,3 @@
1
1
  module Raven
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
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
- prerelease: false
5
- segments:
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
- date: 2013-01-04 00:00:00 -08:00
19
- default_executable:
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
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
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
- requirement: &id002 !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- segments:
43
- - 0
44
- version: "0"
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
- requirement: &id003 !ruby/object:Gem::Requirement
51
- requirements:
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
- segments:
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
- requirement: &id004 !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- segments:
68
- - 0
69
- version: "0"
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
- version_requirements: *id004
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
- has_rdoc: true
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
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- segments:
119
- - 0
120
- version: "0"
121
- required_rubygems_version: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- segments:
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.3.6
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
-