sentry-raven 0.12.2 → 0.12.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa170cbdab1ee92ed1a5b471c2edd146e9d3f3c5
4
- data.tar.gz: 4ca87cca729a05fbd1564a0e404b6bac57c47267
3
+ metadata.gz: f4d1ff44aab9878c7070e85ac6bac6a2573e5332
4
+ data.tar.gz: 7668ff7bdc645dc3d77305f0be63bd028696eee5
5
5
  SHA512:
6
- metadata.gz: e5f7bef20983567b7b622b119587524a3423f623683b39b2224203fa3df4335ec9aaf3bdde122220e86ca01aa96201d12b34ca62f77381a6c0d3fe923633a506
7
- data.tar.gz: ffb038d8c1a843c4458b0d7b21befacad00b14e43b32052db4054a4655e55fdde225482764b233adb8c93ae9d49f1b09b0a2f0d02b7bde654498204541847205
6
+ metadata.gz: ba3fb97a2c6a77adf1e8d5afcf00d7d94f14b3d5bf3851db165e0624afc1aa702efd61d2c3f24cf9195b8b9e2bedf72244219f7bd61a698e8d443732e227efec
7
+ data.tar.gz: e96788e536488bed998d179c9c752157044c5a703de5c479c9265966bde529f6d37dcba908478e9a292e4c149256f1ecb67ab748c2e89829ae73c8496c8d7e4a
data/README.md CHANGED
@@ -13,7 +13,7 @@ We test on Ruby MRI 1.8.7/REE, 1.9.3, 2.0 and 2.1. JRuby support is experimental
13
13
  ## Getting Started
14
14
  ### Install
15
15
  ```ruby
16
- gem "sentry-raven", :require => 'raven' #, :github => "getsentry/raven-ruby"
16
+ gem "sentry-raven" #, :github => "getsentry/raven-ruby"
17
17
  ```
18
18
  ### Set SENTRY_DSN
19
19
  ```bash
data/bin/raven CHANGED
@@ -4,8 +4,6 @@ require "raven"
4
4
  require "raven/cli"
5
5
  require "optparse"
6
6
 
7
- options = {}
8
-
9
7
  parser = OptionParser.new do |opt|
10
8
  opt.banner = "Usage: raven COMMAND [OPTIONS]"
11
9
  opt.separator ""
@@ -0,0 +1,104 @@
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
@@ -61,7 +61,7 @@ module Raven
61
61
  end
62
62
 
63
63
  def inspect
64
- "<Line:#{to_s}>"
64
+ "<Line:#{self}>"
65
65
  end
66
66
 
67
67
  private
@@ -77,8 +77,8 @@ module Raven
77
77
 
78
78
  filters = opts[:filters] || []
79
79
  filtered_lines = ruby_lines.to_a.map do |line|
80
- filters.reduce(line) do |line, proc|
81
- proc.call(line)
80
+ filters.reduce(line) do |nested_line, proc|
81
+ proc.call(nested_line)
82
82
  end
83
83
  end.compact
84
84
 
@@ -86,7 +86,7 @@ module Raven
86
86
  Line.parse(unparsed_line)
87
87
  end
88
88
 
89
- instance = new(lines)
89
+ new(lines)
90
90
  end
91
91
 
92
92
  def initialize(lines)
data/lib/raven/base.rb CHANGED
@@ -14,6 +14,11 @@ require 'raven/processor/sanitizedata'
14
14
  require 'raven/processor/removecircularreferences'
15
15
  require 'raven/processor/utf8conversion'
16
16
 
17
+ major, minor, patch = RUBY_VERSION.split('.').map(&:to_i)
18
+ if (major == 1 && minor < 9) || (major == 1 && minor == 9 && patch < 2)
19
+ require 'raven/backports/uri'
20
+ end
21
+
17
22
  module Raven
18
23
  class << self
19
24
  # The client object is responsible for delivering formatted data to the Sentry server.
@@ -101,7 +106,7 @@ module Raven
101
106
 
102
107
  def capture_exception(exception, options = {})
103
108
  send_or_skip(exception) do
104
- if evt = Event.from_exception(exception, options)
109
+ if (evt = Event.from_exception(exception, options))
105
110
  yield evt if block_given?
106
111
  if configuration.async?
107
112
  configuration.async.call(evt)
@@ -114,7 +119,7 @@ module Raven
114
119
 
115
120
  def capture_message(message, options = {})
116
121
  send_or_skip(message) do
117
- if evt = Event.from_message(message, options)
122
+ if (evt = Event.from_message(message, options))
118
123
  yield evt if block_given?
119
124
  if configuration.async?
120
125
  configuration.async.call(evt)
@@ -192,7 +197,7 @@ module Raven
192
197
  # Extra context shows up as Additional Data within Sentry, and is completely arbitrary.
193
198
  #
194
199
  # @example
195
- # Raven.tags_context('my_custom_data' => 'value')
200
+ # Raven.extra_context('my_custom_data' => 'value')
196
201
  def extra_context(options = {})
197
202
  self.context.extra.merge!(options)
198
203
  end
@@ -208,7 +213,17 @@ module Raven
208
213
  def inject
209
214
  available_integrations = %w[delayed_job rails sidekiq rack rake]
210
215
  integrations_to_load = available_integrations & Gem.loaded_specs.keys
211
- integrations_to_load.each { |integration| require "raven/integrations/#{integration}" }
216
+ # TODO(dcramer): integrations should have some additional checks baked-in
217
+ # or we should break them out into their own repos. Specifically both the
218
+ # rails and delayed_job checks are not always valid (i.e. Rails 2.3) and
219
+ # https://github.com/getsentry/raven-ruby/issues/180
220
+ integrations_to_load.each do |integration|
221
+ begin
222
+ require "raven/integrations/#{integration}"
223
+ rescue Exception => error
224
+ self.logger.warn "Unable to load raven/integrations/#{integration}: #{error}"
225
+ end
226
+ end
212
227
  end
213
228
 
214
229
  # For cross-language compat
data/lib/raven/cli.rb CHANGED
@@ -7,7 +7,7 @@ module Raven
7
7
 
8
8
  logger = ::Logger.new(STDOUT)
9
9
  logger.level = ::Logger::ERROR
10
- logger.formatter = proc do |severity, datetime, progname, msg|
10
+ logger.formatter = proc do |_severity, _datetime, _progname, msg|
11
11
  "-> #{msg}\n"
12
12
  end
13
13
 
data/lib/raven/client.rb CHANGED
@@ -19,6 +19,7 @@ module Raven
19
19
  def initialize(configuration)
20
20
  @configuration = configuration
21
21
  @processors = configuration.processors.map { |v| v.new(self) }
22
+ @state = ClientState.new
22
23
  end
23
24
 
24
25
  def send(event)
@@ -29,18 +30,25 @@ module Raven
29
30
 
30
31
  # Set the project ID correctly
31
32
  event.project = self.configuration.project_id
33
+
34
+ if !@state.should_try?
35
+ Raven.logger.error("Not sending event due to previous failure(s): #{get_log_message(event)}")
36
+ return
37
+ end
38
+
32
39
  Raven.logger.debug "Sending event #{event.id} to Sentry"
33
40
 
34
41
  content_type, encoded_data = encode(event)
35
42
  begin
36
- transport.send(generate_auth_header(encoded_data), encoded_data,
43
+ transport.send(generate_auth_header, encoded_data,
37
44
  :content_type => content_type)
38
45
  rescue => e
39
- Raven.logger.error "Unable to record event with remote Sentry server (#{e.class} - #{e.message})"
40
- e.backtrace[0..10].each { |line| Raven.logger.error(line) }
46
+ failed_send(e, event)
41
47
  return
42
48
  end
43
49
 
50
+ successful_send
51
+
44
52
  event
45
53
  end
46
54
 
@@ -66,6 +74,10 @@ module Raven
66
74
  end
67
75
  end
68
76
 
77
+ def get_log_message(event)
78
+ (event && event.message) || '<no message value>'
79
+ end
80
+
69
81
  def transport
70
82
  @transport ||=
71
83
  case self.configuration.scheme
@@ -78,7 +90,7 @@ module Raven
78
90
  end
79
91
  end
80
92
 
81
- def generate_auth_header(data)
93
+ def generate_auth_header
82
94
  now = Time.now.to_i.to_s
83
95
  fields = {
84
96
  'sentry_version' => PROTOCOL_VERSION,
@@ -100,5 +112,53 @@ module Raven
100
112
  end
101
113
  end
102
114
 
115
+ def successful_send
116
+ @state.success
117
+ end
118
+
119
+ def failed_send(e, event)
120
+ @state.failure
121
+ Raven.logger.error "Unable to record event with remote Sentry server (#{e.class} - #{e.message})"
122
+ e.backtrace[0..10].each { |line| Raven.logger.error(line) }
123
+ Raven.logger.error("Failed to submit event: #{get_log_message(event)}")
124
+ end
125
+
126
+ end
127
+
128
+ class ClientState
129
+ def initialize
130
+ reset
131
+ end
132
+
133
+ def should_try?
134
+ return true if @status == :online
135
+
136
+ interval = @retry_after || [@retry_number, 6].min ** 2
137
+ return true if Time.now - @last_check >= interval
138
+
139
+ false
140
+ end
141
+
142
+ def failure(retry_after = nil)
143
+ @status = :error
144
+ @retry_number += 1
145
+ @last_check = Time.now
146
+ @retry_after = retry_after
147
+ end
148
+
149
+ def success
150
+ reset
151
+ end
152
+
153
+ def reset
154
+ @status = :online
155
+ @retry_number = 0
156
+ @last_check = nil
157
+ @retry_after = nil
158
+ end
159
+
160
+ def failed?
161
+ @status == :error
162
+ end
103
163
  end
104
164
  end
@@ -55,9 +55,12 @@ module Raven
55
55
  # Should the SSL certificate of the server be verified?
56
56
  attr_accessor :ssl_verification
57
57
 
58
- # Ssl settings passed direactly to faraday's ssl option
58
+ # SSl settings passed direactly to faraday's ssl option
59
59
  attr_accessor :ssl
60
60
 
61
+ # Proxy information to pass to the HTTP adapter
62
+ attr_accessor :proxy
63
+
61
64
  attr_reader :current_environment
62
65
 
63
66
  # The Faraday adapter to be used. Will default to Net::HTTP when not set.
@@ -106,6 +109,7 @@ module Raven
106
109
  self.encoding = 'gzip'
107
110
  self.timeout = 1
108
111
  self.open_timeout = 1
112
+ self.proxy = nil
109
113
  self.tags = {}
110
114
  self.async = false
111
115
  self.catch_debugged_exceptions = true
@@ -160,11 +164,7 @@ module Raven
160
164
  end
161
165
 
162
166
  def send_in_current_environment?
163
- if environments
164
- environments.include?(current_environment)
165
- else
166
- true
167
- end
167
+ !!server && (!environments || environments.include?(current_environment))
168
168
  end
169
169
 
170
170
  def log_excluded_environment_message
data/lib/raven/event.rb CHANGED
@@ -59,11 +59,9 @@ module Raven
59
59
 
60
60
  block.call(self) if block
61
61
 
62
- if @configuration.send_in_current_environment?
63
- if !self[:http] && context.rack_env
64
- self.interface :http do |int|
65
- int.from_rack(context.rack_env)
66
- end
62
+ if !self[:http] && context.rack_env
63
+ self.interface :http do |int|
64
+ int.from_rack(context.rack_env)
67
65
  end
68
66
  end
69
67
 
@@ -76,7 +74,7 @@ module Raven
76
74
  def get_hostname
77
75
  # Try to resolve the hostname to an FQDN, but fall back to whatever the load name is
78
76
  hostname = Socket.gethostname
79
- hostname = Socket.gethostbyname(hostname).first rescue hostname
77
+ Socket.gethostbyname(hostname).first rescue hostname
80
78
  end
81
79
 
82
80
  def get_modules
@@ -140,7 +138,7 @@ module Raven
140
138
  context_lines = configuration[:context_lines]
141
139
 
142
140
  new(options) do |evt|
143
- evt.message = "#{exc.class.to_s}: #{exc.message}"
141
+ evt.message = "#{exc.class}: #{exc.message}"
144
142
  evt.level = options[:level] || :error
145
143
 
146
144
  evt.interface(:exception) do |int|
@@ -186,7 +184,7 @@ module Raven
186
184
  end
187
185
 
188
186
  # Because linecache can go to hell
189
- def self._source_lines(path, from, to)
187
+ def self._source_lines(_path, _from, _to)
190
188
  end
191
189
 
192
190
  def get_file_context(filename, lineno, context)
@@ -3,10 +3,10 @@ require 'sidekiq'
3
3
 
4
4
  module Raven
5
5
  class Sidekiq
6
- def call(worker, msg, queue)
6
+ def call(_worker, msg, _queue)
7
7
  started_at = Time.now
8
8
  yield
9
- rescue => ex
9
+ rescue Exception => ex
10
10
  Raven.capture_exception(ex, :extra => { :sidekiq => msg },
11
11
  :time_spent => Time.now-started_at)
12
12
  raise
@@ -4,7 +4,7 @@ require 'raven/cli'
4
4
 
5
5
  namespace :raven do
6
6
  desc "Send a test event to the remote Sentry server"
7
- task :test, [:dsn] do |t, args|
7
+ task :test, [:dsn] do |_t, args|
8
8
  Rake::Task["environment"].invoke if defined? Rails
9
9
 
10
10
  Raven::CLI.test(args.dsn)
data/lib/raven/okjson.rb CHANGED
@@ -81,7 +81,7 @@ module OkJson
81
81
  when false then "false"
82
82
  when nil then "null"
83
83
  else
84
- raise Error, "cannot encode #{x.class}: #{x.inspect}"
84
+ strenc((x.inspect rescue $!.to_s))
85
85
  end
86
86
  end
87
87
 
@@ -3,7 +3,7 @@ module Raven
3
3
  STRING_MASK = '********'
4
4
  INT_MASK = 0
5
5
  DEFAULT_FIELDS = %w(authorization password passwd secret ssn social(.*)?sec)
6
- VALUES_RE = /^\d{16}$/
6
+ CREDIT_CARD_RE = /^(?:\d[ -]*?){13,16}$/
7
7
 
8
8
  def process(value)
9
9
  value.inject(value) { |memo,(k,v)| memo[k] = sanitize(k,v); memo }
@@ -13,13 +13,15 @@ module Raven
13
13
  if v.is_a?(Hash)
14
14
  process(v)
15
15
  elsif v.is_a?(Array)
16
- v.map{|a| sanitize(nil, a)}
16
+ v.map{|a| sanitize(k, a)}
17
+ elsif k == 'query_string'
18
+ sanitize_query_string(v)
17
19
  elsif v.is_a?(String) && (json = parse_json_or_nil(v))
18
20
  #if this string is actually a json obj, convert and sanitize
19
21
  json.is_a?(Hash) ? process(json).to_json : v
20
- elsif v.is_a?(Integer) && (VALUES_RE.match(v.to_s) || fields_re.match(k.to_s))
22
+ elsif v.is_a?(Integer) && (CREDIT_CARD_RE.match(v.to_s) || fields_re.match(k.to_s))
21
23
  INT_MASK
22
- elsif v.is_a?(String) && (VALUES_RE.match(v.to_s) || fields_re.match(k.to_s))
24
+ elsif v.is_a?(String) && (CREDIT_CARD_RE.match(v.to_s) || fields_re.match(k.to_s))
23
25
  STRING_MASK
24
26
  else
25
27
  v
@@ -28,6 +30,12 @@ module Raven
28
30
 
29
31
  private
30
32
 
33
+ def sanitize_query_string(query_string)
34
+ query_hash = CGI::parse(query_string)
35
+ processed_query_hash = process(query_hash)
36
+ URI.encode_www_form(processed_query_hash)
37
+ end
38
+
31
39
  def fields_re
32
40
  @fields_re ||= /(#{(DEFAULT_FIELDS + @sanitize_fields).join("|")})/i
33
41
  end
@@ -3,9 +3,9 @@ module Raven
3
3
 
4
4
  def process(value)
5
5
  if value.is_a? Array
6
- value.map { |v_| process v_ }
6
+ value.map { |v| process v }
7
7
  elsif value.is_a? Hash
8
- value.merge(value) { |k, v_| process v_ }
8
+ value.merge(value) { |_, v| process v }
9
9
  else
10
10
  clean_invalid_utf8_bytes(value)
11
11
  end
@@ -10,8 +10,8 @@ module Raven
10
10
  @configuration = configuration
11
11
  end
12
12
 
13
- def send(auth_header, data, options = {})
14
- raise Error.new('Abstract method not implemented')
13
+ def send#(auth_header, data, options = {})
14
+ raise NotImplementedError.new('Abstract method not implemented')
15
15
  end
16
16
 
17
17
  protected
@@ -9,7 +9,7 @@ module Raven
9
9
 
10
10
  def send(auth_header, data, options = {})
11
11
  project_id = self.configuration[:project_id]
12
- path = self.configuration[:path].gsub('/sentry', '') + "/"
12
+ path = self.configuration[:path] + "/"
13
13
 
14
14
  response = conn.post "#{path}api/#{project_id}/store/" do |req|
15
15
  req.headers['Content-Type'] = options[:content_type]
@@ -37,6 +37,10 @@ module Raven
37
37
  builder.adapter(*adapter)
38
38
  end
39
39
 
40
+ if self.configuration.proxy
41
+ conn.options[:proxy] = self.configuration.proxy
42
+ end
43
+
40
44
  if self.configuration.timeout
41
45
  conn.options[:timeout] = self.configuration.timeout
42
46
  end
@@ -7,7 +7,7 @@ module Raven
7
7
  module Transports
8
8
  class UDP < Transport
9
9
 
10
- def send(auth_header, data, options = {})
10
+ def send(auth_header, data, _options = {})
11
11
  conn.send "#{auth_header}\n\n#{data}", 0
12
12
  end
13
13
 
data/lib/raven/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Raven
2
- VERSION = "0.12.2"
2
+ VERSION = "0.12.3"
3
3
  end
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.12.2
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-08 00:00:00.000000000 Z
11
+ date: 2015-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: timecop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  description: A gem that provides a client interface for the Sentry error logger
98
112
  email: getsentry@googlegroups.com
99
113
  executables:
@@ -107,6 +121,7 @@ files:
107
121
  - README.md
108
122
  - bin/raven
109
123
  - lib/raven.rb
124
+ - lib/raven/backports/uri.rb
110
125
  - lib/raven/backtrace.rb
111
126
  - lib/raven/base.rb
112
127
  - lib/raven/better_attr_accessor.rb