rollbar 2.19.1 → 2.27.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/.github/pull_request_template.md +25 -0
  3. data/.rubocop.yml +168 -0
  4. data/.travis.yml +63 -34
  5. data/Appraisals +10 -10
  6. data/Gemfile +35 -14
  7. data/README.md +5 -2
  8. data/Rakefile +0 -0
  9. data/data/rollbar.snippet.js +1 -1
  10. data/docs/configuration.md +17 -0
  11. data/gemfiles/rails30.gemfile +10 -10
  12. data/gemfiles/rails31.gemfile +10 -9
  13. data/gemfiles/rails32.gemfile +10 -9
  14. data/gemfiles/rails40.gemfile +10 -9
  15. data/gemfiles/rails41.gemfile +10 -9
  16. data/gemfiles/rails42.gemfile +12 -9
  17. data/gemfiles/rails50.gemfile +21 -14
  18. data/gemfiles/rails51.gemfile +21 -14
  19. data/gemfiles/rails52.gemfile +15 -12
  20. data/gemfiles/rails60.gemfile +67 -0
  21. data/lib/generators/rollbar/rollbar_generator.rb +1 -1
  22. data/lib/rails/rollbar_runner.rb +4 -2
  23. data/lib/rollbar/capistrano.rb +1 -1
  24. data/lib/rollbar/capistrano3.rb +6 -3
  25. data/lib/rollbar/capistrano_tasks.rb +29 -21
  26. data/lib/rollbar/configuration.rb +86 -16
  27. data/lib/rollbar/delay/girl_friday.rb +4 -8
  28. data/lib/rollbar/delay/resque.rb +3 -6
  29. data/lib/rollbar/delay/sidekiq.rb +4 -10
  30. data/lib/rollbar/delay/sucker_punch.rb +16 -19
  31. data/lib/rollbar/delay/thread.rb +16 -2
  32. data/lib/rollbar/deploy.rb +52 -29
  33. data/lib/rollbar/encoding/encoder.rb +17 -10
  34. data/lib/rollbar/exception_reporter.rb +19 -5
  35. data/lib/rollbar/item/backtrace.rb +13 -3
  36. data/lib/rollbar/item/frame.rb +9 -1
  37. data/lib/rollbar/item/locals.rb +100 -0
  38. data/lib/rollbar/item.rb +56 -17
  39. data/lib/rollbar/json.rb +6 -51
  40. data/lib/rollbar/language_support.rb +4 -20
  41. data/lib/rollbar/lazy_store.rb +5 -5
  42. data/lib/rollbar/logger.rb +1 -0
  43. data/lib/rollbar/logger_proxy.rb +6 -2
  44. data/lib/rollbar/middleware/js.rb +28 -18
  45. data/lib/rollbar/middleware/rack.rb +4 -1
  46. data/lib/rollbar/middleware/rails/rollbar.rb +10 -1
  47. data/lib/rollbar/notifier/trace_with_bindings.rb +65 -0
  48. data/lib/rollbar/notifier.rb +225 -89
  49. data/lib/rollbar/plugin.rb +54 -6
  50. data/lib/rollbar/plugins/active_job.rb +6 -2
  51. data/lib/rollbar/plugins/basic_socket.rb +21 -6
  52. data/lib/rollbar/plugins/delayed_job/job_data.rb +3 -3
  53. data/lib/rollbar/plugins/delayed_job/plugin.rb +13 -3
  54. data/lib/rollbar/plugins/error_context.rb +11 -0
  55. data/lib/rollbar/plugins/goalie.rb +11 -3
  56. data/lib/rollbar/plugins/rails/controller_methods.rb +15 -3
  57. data/lib/rollbar/plugins/rake.rb +2 -2
  58. data/lib/rollbar/plugins/sidekiq/plugin.rb +5 -4
  59. data/lib/rollbar/plugins.rb +7 -1
  60. data/lib/rollbar/rake_tasks.rb +4 -148
  61. data/lib/rollbar/request_data_extractor.rb +31 -21
  62. data/lib/rollbar/rollbar_test.rb +36 -0
  63. data/lib/rollbar/scrubbers/params.rb +19 -18
  64. data/lib/rollbar/scrubbers/url.rb +18 -9
  65. data/lib/rollbar/scrubbers.rb +3 -3
  66. data/lib/rollbar/truncation/frames_strategy.rb +1 -1
  67. data/lib/rollbar/truncation/min_body_strategy.rb +2 -3
  68. data/lib/rollbar/truncation/mixin.rb +1 -1
  69. data/lib/rollbar/truncation/remove_any_key_strategy.rb +123 -0
  70. data/lib/rollbar/truncation/remove_extra_strategy.rb +35 -0
  71. data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
  72. data/lib/rollbar/truncation/strings_strategy.rb +6 -5
  73. data/lib/rollbar/truncation.rb +9 -2
  74. data/lib/rollbar/util/hash.rb +15 -0
  75. data/lib/rollbar/util/ip_anonymizer.rb +8 -7
  76. data/lib/rollbar/util/ip_obfuscator.rb +1 -1
  77. data/lib/rollbar/util.rb +6 -2
  78. data/lib/rollbar/version.rb +1 -1
  79. data/lib/rollbar.rb +2 -3
  80. data/lib/tasks/benchmark.rake +103 -0
  81. data/rollbar.gemspec +13 -5
  82. data/spec/support/rollbar_api.rb +67 -0
  83. metadata +21 -23
  84. data/gemfiles/ruby_1_8_and_1_9_2.gemfile +0 -49
  85. data/lib/rollbar/json/default.rb +0 -11
  86. data/lib/rollbar/json/oj.rb +0 -16
@@ -14,7 +14,6 @@ module Rollbar
14
14
 
15
15
  def call(options = {})
16
16
  url = options[:url]
17
- return url unless Rollbar::LanguageSupport.can_scrub_url?
18
17
 
19
18
  filter(url,
20
19
  build_regex(options[:scrub_fields]),
@@ -23,7 +22,7 @@ module Rollbar
23
22
  options.fetch(:randomize_scrub_length, true),
24
23
  options[:scrub_fields].include?(SCRUB_ALL),
25
24
  build_whitelist_regex(options[:whitelist] || []))
26
- rescue => e
25
+ rescue StandardError => e
27
26
  Rollbar.logger.error("[Rollbar] There was an error scrubbing the url: #{e}, options: #{options.inspect}")
28
27
  url
29
28
  end
@@ -33,6 +32,7 @@ module Rollbar
33
32
  def build_whitelist_regex(whitelist)
34
33
  fields = whitelist.find_all { |f| f.is_a?(String) || f.is_a?(Symbol) }
35
34
  return unless fields.any?
35
+
36
36
  Regexp.new(fields.map { |val| /\A#{Regexp.escape(val.to_s)}\z/ }.join('|'))
37
37
  end
38
38
 
@@ -67,10 +67,7 @@ module Rollbar
67
67
 
68
68
  params = decode_www_form(query)
69
69
 
70
- encoded_query = encode_www_form(filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist))
71
-
72
- # We want this to rebuild array params like foo[]=1&foo[]=2
73
- URI.escape(CGI.unescape(encoded_query))
70
+ encode_www_form(filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist))
74
71
  end
75
72
 
76
73
  def decode_www_form(query)
@@ -78,7 +75,15 @@ module Rollbar
78
75
  end
79
76
 
80
77
  def encode_www_form(params)
81
- URI.encode_www_form(params)
78
+ restore_square_brackets(URI.encode_www_form(params))
79
+ end
80
+
81
+ def restore_square_brackets(query)
82
+ # We want this to rebuild array params like foo[]=1&foo[]=2
83
+ #
84
+ # URI.encode_www_form follows the spec at https://url.spec.whatwg.org/#concept-urlencoded-serializer
85
+ # and percent encodes square brackets. Here we change them back.
86
+ query.gsub('%5B', '[').gsub('%5D', ']')
82
87
  end
83
88
 
84
89
  def filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist)
@@ -95,12 +100,16 @@ module Rollbar
95
100
  if randomize_scrub_length
96
101
  random_filtered_value
97
102
  else
98
- '*' * (value.length rescue 8)
103
+ '*' * (begin
104
+ value.length
105
+ rescue StandardError
106
+ 8
107
+ end)
99
108
  end
100
109
  end
101
110
 
102
111
  def random_filtered_value
103
- '*' * (rand(5) + 3)
112
+ '*' * rand(3..7)
104
113
  end
105
114
  end
106
115
  end
@@ -1,17 +1,17 @@
1
1
  module Rollbar
2
2
  module Scrubbers
3
- extend self
3
+ module_function
4
4
 
5
5
  def scrub_value(value)
6
6
  if Rollbar.configuration.randomize_scrub_length
7
7
  random_filtered_value
8
8
  else
9
- '*' * (value.length rescue 8)
9
+ '*' * 6
10
10
  end
11
11
  end
12
12
 
13
13
  def random_filtered_value
14
- '*' * (rand(5) + 3)
14
+ '*' * rand(3..7)
15
15
  end
16
16
  end
17
17
  end
@@ -11,7 +11,7 @@ module Rollbar
11
11
  end
12
12
 
13
13
  def call(payload)
14
- new_payload = Rollbar::Util.deep_copy(payload)
14
+ new_payload = payload
15
15
  body = new_payload['data']['body']
16
16
 
17
17
  if body['trace_chain']
@@ -11,8 +11,7 @@ module Rollbar
11
11
  end
12
12
 
13
13
  def call(payload)
14
- new_payload = Rollbar::Util.deep_copy(payload)
15
- body = new_payload['data']['body']
14
+ body = payload['data']['body']
16
15
 
17
16
  if body['trace_chain']
18
17
  body['trace_chain'] = body['trace_chain'].map do |trace_data|
@@ -22,7 +21,7 @@ module Rollbar
22
21
  body['trace'] = truncate_trace_data(body['trace'])
23
22
  end
24
23
 
25
- dump(new_payload)
24
+ dump(payload)
26
25
  end
27
26
 
28
27
  def truncate_trace_data(trace_data)
@@ -9,7 +9,7 @@ module Rollbar
9
9
  result.bytesize > MAX_PAYLOAD_SIZE
10
10
  end
11
11
 
12
- def select_frames(frames, range = 150)
12
+ def select_frames(frames, range = 50)
13
13
  return frames unless frames.count > range * 2
14
14
 
15
15
  frames[0, range] + frames[-range, range]
@@ -0,0 +1,123 @@
1
+ require 'rollbar/util'
2
+
3
+ module Rollbar
4
+ module Truncation
5
+ class RemoveAnyKeyStrategy
6
+ include ::Rollbar::Truncation::Mixin
7
+
8
+ attr_accessor :payload, :data, :sizes, :extracted_title
9
+
10
+ def self.call(payload)
11
+ new(payload).call
12
+ end
13
+
14
+ def initialize(payload)
15
+ @payload = payload
16
+ @data = payload['data']
17
+ @extracted_title = extract_title(data['body']) if data['body']
18
+ end
19
+
20
+ def call
21
+ remove_unknown_root_keys
22
+
23
+ json_payload = remove_oversized_data_keys
24
+
25
+ return json_payload if json_payload
26
+
27
+ dump(payload)
28
+ end
29
+
30
+ def remove_unknown_root_keys
31
+ payload.keys.reject { |key| root_keys.include?(key) }.each do |key|
32
+ truncation_key['root'] ||= {}
33
+ size = dump(payload.delete(key)).bytesize
34
+ truncation_key['root'][key] = "unknown root key removed, size: #{size} bytes"
35
+ end
36
+ end
37
+
38
+ def remove_oversized_data_keys
39
+ data_keys.keys.sort { |a, b| data_keys[b] <=> data_keys[a] }.each do |key|
40
+ json_payload = remove_key_and_return_payload(key)
41
+
42
+ return json_payload unless truncate?(json_payload)
43
+ end
44
+
45
+ false
46
+ end
47
+
48
+ def remove_key_and_return_payload(key)
49
+ size = data_keys[key]
50
+
51
+ data.delete(key)
52
+
53
+ replace_message_body if key == 'body'
54
+
55
+ truncation_key[key] = "key removed, size: #{size} bytes"
56
+
57
+ dump(payload)
58
+ end
59
+
60
+ def replace_message_body
61
+ data['body'] = message_key
62
+ data['title'] ||= extracted_title if extracted_title
63
+ end
64
+
65
+ def truncation_key
66
+ @truncation_key ||=
67
+ # initialize the diagnostic key for truncation
68
+ (data['notifier']['diagnostic'] ||= {}) &&
69
+ (data['notifier']['diagnostic']['truncation'] ||= {})
70
+ end
71
+
72
+ def root_keys
73
+ # Valid keys in root of payload
74
+ %w[access_token data]
75
+ end
76
+
77
+ def skip_keys
78
+ # Don't try to truncate these data keys
79
+ %w[notifier uuid title platform language framework level]
80
+ end
81
+
82
+ def message_key
83
+ # use this message if data.body gets removed
84
+ {
85
+ 'message' => {
86
+ 'body' => 'Payload keys removed due to oversized payload. See diagnostic key'
87
+ }
88
+ }
89
+ end
90
+
91
+ def extract_title(body)
92
+ return body['message']['body'] if body['message'] && body['message']['body']
93
+ return extract_title_from_trace(body['trace']) if body['trace']
94
+ return extract_title_from_trace(body['trace_chain'][0]) if body['trace_chain'] && body['trace_chain'][0]
95
+ end
96
+
97
+ def extract_title_from_trace(trace)
98
+ exception = trace['exception']
99
+
100
+ "#{exception['class']}: #{exception['message']}"
101
+ end
102
+
103
+ def data_keys
104
+ @data_keys ||= {}.tap do |hash|
105
+ data.keys.reject { |key| skip_keys.include?(key) }.each do |key|
106
+ set_key_size(key, hash)
107
+ end
108
+ end
109
+ end
110
+
111
+ def set_key_size(key, hash)
112
+ size = dump(data[key]).bytesize
113
+ hash[key] = size
114
+ rescue ::JSON::GeneratorError
115
+ hash[key] = 0 # don't try to truncate non JSON object
116
+
117
+ # Log it
118
+ truncation_key['non_json_keys'] ||= {}
119
+ truncation_key['non_json_keys'][key] = data[key].class
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,35 @@
1
+ require 'rollbar/util'
2
+
3
+ module Rollbar
4
+ module Truncation
5
+ class RemoveExtraStrategy
6
+ include ::Rollbar::Truncation::Mixin
7
+
8
+ def self.call(payload)
9
+ new.call(payload)
10
+ end
11
+
12
+ def call(payload)
13
+ body = payload['data']['body']
14
+
15
+ delete_message_extra(body)
16
+ delete_trace_chain_extra(body)
17
+ delete_trace_extra(body)
18
+
19
+ dump(payload)
20
+ end
21
+
22
+ def delete_message_extra(body)
23
+ body['message'].delete('extra') if body['message'] && body['message']['extra']
24
+ end
25
+
26
+ def delete_trace_chain_extra(body)
27
+ body['trace_chain'][0].delete('extra') if body['trace_chain'] && body['trace_chain'][0]['extra']
28
+ end
29
+
30
+ def delete_trace_extra(body)
31
+ body['trace'].delete('extra') if body['trace'] && body['trace']['extra']
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ require 'rollbar/util'
2
+
3
+ module Rollbar
4
+ module Truncation
5
+ class RemoveRequestStrategy
6
+ include ::Rollbar::Truncation::Mixin
7
+
8
+ def self.call(payload)
9
+ new.call(payload)
10
+ end
11
+
12
+ def call(payload)
13
+ data = payload['data']
14
+
15
+ data.delete('request') if data['request']
16
+
17
+ dump(payload)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -6,7 +6,7 @@ module Rollbar
6
6
  class StringsStrategy
7
7
  include ::Rollbar::Truncation::Mixin
8
8
 
9
- STRING_THRESHOLDS = [1024, 512, 256]
9
+ STRING_THRESHOLDS = [1024, 512, 256, 128].freeze
10
10
 
11
11
  def self.call(payload)
12
12
  new.call(payload)
@@ -14,13 +14,12 @@ module Rollbar
14
14
 
15
15
  def call(payload)
16
16
  result = nil
17
- new_payload = Rollbar::Util.deep_copy(payload)
18
17
 
19
18
  STRING_THRESHOLDS.each do |threshold|
20
19
  truncate_proc = truncate_strings_proc(threshold)
21
20
 
22
- ::Rollbar::Util.iterate_and_update(new_payload, truncate_proc)
23
- result = dump(new_payload)
21
+ ::Rollbar::Util.iterate_and_update(payload, truncate_proc)
22
+ result = dump(payload)
24
23
 
25
24
  break unless truncate?(result)
26
25
  end
@@ -30,7 +29,9 @@ module Rollbar
30
29
 
31
30
  def truncate_strings_proc(threshold)
32
31
  proc do |value|
33
- if value.is_a?(String) && value.bytesize > threshold
32
+ # Rollbar::Util.truncate will operate on characters, not bytes,
33
+ # so use value.length, not bytesize.
34
+ if value.is_a?(String) && value.length > threshold
34
35
  Rollbar::Util.truncate(value, threshold)
35
36
  else
36
37
  value
@@ -4,6 +4,9 @@ require 'rollbar/truncation/raw_strategy'
4
4
  require 'rollbar/truncation/frames_strategy'
5
5
  require 'rollbar/truncation/strings_strategy'
6
6
  require 'rollbar/truncation/min_body_strategy'
7
+ require 'rollbar/truncation/remove_request_strategy'
8
+ require 'rollbar/truncation/remove_extra_strategy'
9
+ require 'rollbar/truncation/remove_any_key_strategy'
7
10
 
8
11
  module Rollbar
9
12
  module Truncation
@@ -13,13 +16,17 @@ module Rollbar
13
16
  STRATEGIES = [RawStrategy,
14
17
  FramesStrategy,
15
18
  StringsStrategy,
16
- MinBodyStrategy]
19
+ MinBodyStrategy,
20
+ RemoveRequestStrategy,
21
+ RemoveExtraStrategy,
22
+ RemoveAnyKeyStrategy].freeze
17
23
 
18
- def self.truncate(payload)
24
+ def self.truncate(payload, attempts = [])
19
25
  result = nil
20
26
 
21
27
  STRATEGIES.each do |strategy|
22
28
  result = strategy.call(payload)
29
+ attempts << result.bytesize
23
30
  break unless truncate?(result)
24
31
  end
25
32
 
@@ -5,6 +5,7 @@ module Rollbar
5
5
  return if seen[hash.object_id]
6
6
 
7
7
  seen[hash.object_id] = true
8
+ replace_seen_children(hash, seen)
8
9
 
9
10
  hash.reduce({}) do |h, (key, value)|
10
11
  h[key.to_s] = map_value(value, :deep_stringify_keys, seen)
@@ -22,12 +23,26 @@ module Rollbar
22
23
  thing
23
24
  else
24
25
  seen[thing.object_id] = true
26
+ replace_seen_children(thing, seen)
25
27
  thing.map { |v| map_value(v, meth, seen) }
26
28
  end
27
29
  else
28
30
  thing
29
31
  end
30
32
  end
33
+
34
+ def self.replace_seen_children(thing, seen)
35
+ case thing
36
+ when ::Hash
37
+ thing.keys.each do |key|
38
+ thing[key] = "removed circular reference: #{thing[key]}" if seen[thing[key].object_id]
39
+ end
40
+ when Array
41
+ thing.each_with_index do |_, i|
42
+ thing[i] = "removed circular reference: #{thing[i]}" if seen[thing[i].object_id]
43
+ end
44
+ end
45
+ end
31
46
  end
32
47
  end
33
48
  end
@@ -5,26 +5,27 @@ module Rollbar
5
5
 
6
6
  def self.anonymize_ip(ip_string)
7
7
  return ip_string unless Rollbar.configuration.anonymize_user_ip
8
+
8
9
  ip = IPAddr.new(ip_string)
9
10
  return anonymize_ipv6 ip if ip.ipv6?
10
11
  return anonymize_ipv4 ip if ip.ipv4?
11
- rescue
12
+ rescue StandardError
12
13
  nil
13
14
  end
14
-
15
+
15
16
  def self.anonymize_ipv4(ip)
16
17
  ip_parts = ip.to_s.split '.'
17
-
18
+
18
19
  ip_parts[ip_parts.count - 1] = '0'
19
-
20
+
20
21
  IPAddr.new(ip_parts.join('.')).to_s
21
22
  end
22
-
23
+
23
24
  def self.anonymize_ipv6(ip)
24
25
  ip_parts = ip.to_s.split ':'
25
-
26
+
26
27
  ip_string = ip_parts[0..2].join(':') + ':0000:0000:0000:0000:0000'
27
-
28
+
28
29
  IPAddr.new(ip_string).to_s
29
30
  end
30
31
  end
@@ -13,7 +13,7 @@ module Rollbar
13
13
  obfuscated_ip_int32 = ip_int32 ^ secret_int32 % (2 << 31)
14
14
 
15
15
  IPAddr.new(obfuscated_ip_int32, Socket::AF_INET).to_s
16
- rescue
16
+ rescue StandardError
17
17
  nil
18
18
  end
19
19
  end
data/lib/rollbar/util.rb CHANGED
@@ -2,6 +2,10 @@ require 'rollbar/util/hash'
2
2
 
3
3
  module Rollbar
4
4
  module Util # :nodoc:
5
+ def self.iterate_and_update_with_block(obj, &block)
6
+ iterate_and_update(obj, block)
7
+ end
8
+
5
9
  def self.iterate_and_update(obj, block, seen = {})
6
10
  return if obj.frozen? || seen[obj.object_id]
7
11
 
@@ -63,9 +67,9 @@ module Rollbar
63
67
 
64
68
  def self.clone_obj(obj)
65
69
  if obj.is_a?(::Hash)
66
- obj.clone
70
+ obj.dup
67
71
  elsif obj.is_a?(Array)
68
- obj.clone.clear
72
+ obj.dup.clear
69
73
  else
70
74
  obj
71
75
  end
@@ -1,3 +1,3 @@
1
1
  module Rollbar
2
- VERSION = '2.19.1'
2
+ VERSION = '2.27.1'.freeze
3
3
  end
data/lib/rollbar.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'net/protocol'
2
2
  require 'net/https'
3
3
  require 'socket'
4
- require 'thread'
5
4
  require 'uri'
6
5
  require 'open-uri'
7
6
  require 'forwardable'
@@ -22,10 +21,10 @@ require 'rollbar/notifier'
22
21
  # The Rollbar module. It stores a Rollbar::Notifier per thread and
23
22
  # provides some module methods in order to use the current thread notifier.
24
23
  module Rollbar
25
- PUBLIC_NOTIFIER_METHODS = %w(debug info warn warning error critical log logger
24
+ PUBLIC_NOTIFIER_METHODS = %w[debug info warn warning error critical log logger
26
25
  process_item process_from_async_handler scope
27
26
  send_failsafe log_info log_debug log_warning
28
- log_error silenced scope_object).freeze
27
+ log_error silenced scope_object].freeze
29
28
 
30
29
  class << self
31
30
  extend Forwardable
@@ -0,0 +1,103 @@
1
+ require 'benchmark'
2
+
3
+ namespace :benchmark do
4
+ desc 'Measure TracePoint perf for current Ruby'
5
+ task :trace_point do
6
+ ARGV.each { |a| task(a.to_sym { ; }) } # Keep rake from treating these ask task names.
7
+
8
+ options = {}.tap do |hash|
9
+ ARGV.each { |arg| hash[arg] = true }
10
+ end
11
+
12
+ puts "options: #{options}"
13
+
14
+ trace_with_bindings = BenchmarkTraceWithBindings.new(options)
15
+
16
+ trace_with_bindings.enable
17
+ puts(Benchmark.measure do
18
+ TraceTest.benchmark_with_locals
19
+ end)
20
+ trace_with_bindings.disable
21
+
22
+ puts "counts: #{trace_with_bindings.counts}" if options['counts']
23
+ end
24
+ end
25
+
26
+ class TraceTest # :nodoc:
27
+ class << self
28
+ def benchmark_with_locals
29
+ foo = false
30
+
31
+ (0..20_000).each do |index|
32
+ foo = TraceTest
33
+
34
+ change_frame_with_locals(foo, index)
35
+ end
36
+ end
37
+
38
+ def change_frame_with_locals(foo, _index)
39
+ foo.tap do |obj|
40
+ bar = 'bar'
41
+ hash = { :foo => obj, :bar => bar } # rubocop:disable Lint/UselessAssignment
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ class BenchmarkTraceWithBindings # :nodoc:
48
+ attr_reader :frames, :exception_frames, :options, :counts
49
+
50
+ def initialize(options = {})
51
+ @options = options
52
+ @frames = []
53
+ @exception_frames = []
54
+ @exception_signature = nil
55
+ @counts = init_counts({})
56
+ end
57
+
58
+ def init_counts(counts)
59
+ [:call, :b_call, :c_call, :class].each do |event|
60
+ counts[event] = 0
61
+ end
62
+ counts
63
+ end
64
+
65
+ def enable
66
+ return if options['disable']
67
+
68
+ trace_point.enable if defined?(TracePoint)
69
+ end
70
+
71
+ def disable
72
+ return if options['disable']
73
+
74
+ trace_point.disable if defined?(TracePoint)
75
+ end
76
+
77
+ def trace_point # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
78
+ return unless defined?(TracePoint)
79
+
80
+ @trace_point ||= TracePoint.new(:call, :return, :b_call, :b_return, :c_call, :c_return, :raise) do |tp|
81
+ next if options['hook_only']
82
+
83
+ case tp.event
84
+ when :call, :b_call, :c_call, :class
85
+ @counts[tp.event] += 1 if options['counts']
86
+ frame = options['frame'] ? frame(tp) : {}
87
+ frames.push frame if options['stack']
88
+ when :return, :b_return, :c_return, :end
89
+ frames.pop if options['stack']
90
+ end
91
+ end
92
+ end
93
+
94
+ def frame(trace)
95
+ {
96
+ :binding => trace.binding,
97
+ :defined_class => trace.defined_class,
98
+ :method_id => trace.method_id,
99
+ :path => trace.path,
100
+ :lineno => trace.lineno
101
+ }
102
+ end
103
+ end
data/rollbar.gemspec CHANGED
@@ -1,21 +1,29 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
2
3
  require File.expand_path('../lib/rollbar/version', __FILE__)
3
4
 
4
5
  Gem::Specification.new do |gem|
5
- is_jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE)
6
+ _is_jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby')
6
7
 
7
8
  gem.authors = ['Rollbar, Inc.']
8
9
  gem.email = ['support@rollbar.com']
9
- gem.description = %q{Easy and powerful exception tracking for Ruby}
10
+ gem.description = 'Easy and powerful exception tracking for Ruby'
10
11
  gem.executables = ['rollbar-rails-runner']
11
- gem.summary = %q{Reports exceptions to Rollbar}
12
+ gem.summary = 'Reports exceptions to Rollbar'
12
13
  gem.homepage = 'https://rollbar.com'
13
14
  gem.license = 'MIT'
14
15
  gem.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ gem.files += ['spec/support/rollbar_api.rb'] # useful helper for app spec/tests.
15
17
  gem.name = 'rollbar'
16
18
  gem.require_paths = ['lib']
17
19
  gem.required_ruby_version = '>= 1.9.3'
18
- gem.version = Rollbar::VERSION
20
+ gem.version = Rollbar::VERSION
19
21
 
20
- gem.add_runtime_dependency 'multi_json'
22
+ if gem.respond_to?(:metadata)
23
+ gem.metadata['changelog_uri'] = 'https://github.com/rollbar/rollbar-gem/releases'
24
+ gem.metadata['source_code_uri'] = 'https://github.com/rollbar/rollbar-gem'
25
+ gem.metadata['bug_tracker_uri'] = 'https://github.com/rollbar/rollbar-gem/issues'
26
+ gem.metadata['homepage_uri'] = 'https://rollbar.com/'
27
+ gem.metadata['documentation_uri'] = 'https://docs.rollbar.com/docs/ruby'
28
+ end
21
29
  end