rollbar 2.19.1 → 2.27.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.
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