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.
- checksums.yaml +5 -5
- data/.github/pull_request_template.md +25 -0
- data/.rubocop.yml +168 -0
- data/.travis.yml +63 -34
- data/Appraisals +10 -10
- data/Gemfile +35 -14
- data/README.md +5 -2
- data/Rakefile +0 -0
- data/data/rollbar.snippet.js +1 -1
- data/docs/configuration.md +17 -0
- data/gemfiles/rails30.gemfile +10 -10
- data/gemfiles/rails31.gemfile +10 -9
- data/gemfiles/rails32.gemfile +10 -9
- data/gemfiles/rails40.gemfile +10 -9
- data/gemfiles/rails41.gemfile +10 -9
- data/gemfiles/rails42.gemfile +12 -9
- data/gemfiles/rails50.gemfile +21 -14
- data/gemfiles/rails51.gemfile +21 -14
- data/gemfiles/rails52.gemfile +15 -12
- data/gemfiles/rails60.gemfile +67 -0
- data/lib/generators/rollbar/rollbar_generator.rb +1 -1
- data/lib/rails/rollbar_runner.rb +4 -2
- data/lib/rollbar/capistrano.rb +1 -1
- data/lib/rollbar/capistrano3.rb +6 -3
- data/lib/rollbar/capistrano_tasks.rb +29 -21
- data/lib/rollbar/configuration.rb +86 -16
- data/lib/rollbar/delay/girl_friday.rb +4 -8
- data/lib/rollbar/delay/resque.rb +3 -6
- data/lib/rollbar/delay/sidekiq.rb +4 -10
- data/lib/rollbar/delay/sucker_punch.rb +16 -19
- data/lib/rollbar/delay/thread.rb +16 -2
- data/lib/rollbar/deploy.rb +52 -29
- data/lib/rollbar/encoding/encoder.rb +17 -10
- data/lib/rollbar/exception_reporter.rb +19 -5
- data/lib/rollbar/item/backtrace.rb +13 -3
- data/lib/rollbar/item/frame.rb +9 -1
- data/lib/rollbar/item/locals.rb +100 -0
- data/lib/rollbar/item.rb +56 -17
- data/lib/rollbar/json.rb +6 -51
- data/lib/rollbar/language_support.rb +4 -20
- data/lib/rollbar/lazy_store.rb +5 -5
- data/lib/rollbar/logger.rb +1 -0
- data/lib/rollbar/logger_proxy.rb +6 -2
- data/lib/rollbar/middleware/js.rb +28 -18
- data/lib/rollbar/middleware/rack.rb +4 -1
- data/lib/rollbar/middleware/rails/rollbar.rb +10 -1
- data/lib/rollbar/notifier/trace_with_bindings.rb +65 -0
- data/lib/rollbar/notifier.rb +225 -89
- data/lib/rollbar/plugin.rb +54 -6
- data/lib/rollbar/plugins/active_job.rb +6 -2
- data/lib/rollbar/plugins/basic_socket.rb +21 -6
- data/lib/rollbar/plugins/delayed_job/job_data.rb +3 -3
- data/lib/rollbar/plugins/delayed_job/plugin.rb +13 -3
- data/lib/rollbar/plugins/error_context.rb +11 -0
- data/lib/rollbar/plugins/goalie.rb +11 -3
- data/lib/rollbar/plugins/rails/controller_methods.rb +15 -3
- data/lib/rollbar/plugins/rake.rb +2 -2
- data/lib/rollbar/plugins/sidekiq/plugin.rb +5 -4
- data/lib/rollbar/plugins.rb +7 -1
- data/lib/rollbar/rake_tasks.rb +4 -148
- data/lib/rollbar/request_data_extractor.rb +31 -21
- data/lib/rollbar/rollbar_test.rb +36 -0
- data/lib/rollbar/scrubbers/params.rb +19 -18
- data/lib/rollbar/scrubbers/url.rb +18 -9
- data/lib/rollbar/scrubbers.rb +3 -3
- data/lib/rollbar/truncation/frames_strategy.rb +1 -1
- data/lib/rollbar/truncation/min_body_strategy.rb +2 -3
- data/lib/rollbar/truncation/mixin.rb +1 -1
- data/lib/rollbar/truncation/remove_any_key_strategy.rb +123 -0
- data/lib/rollbar/truncation/remove_extra_strategy.rb +35 -0
- data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
- data/lib/rollbar/truncation/strings_strategy.rb +6 -5
- data/lib/rollbar/truncation.rb +9 -2
- data/lib/rollbar/util/hash.rb +15 -0
- data/lib/rollbar/util/ip_anonymizer.rb +8 -7
- data/lib/rollbar/util/ip_obfuscator.rb +1 -1
- data/lib/rollbar/util.rb +6 -2
- data/lib/rollbar/version.rb +1 -1
- data/lib/rollbar.rb +2 -3
- data/lib/tasks/benchmark.rake +103 -0
- data/rollbar.gemspec +13 -5
- data/spec/support/rollbar_api.rb +67 -0
- metadata +21 -23
- data/gemfiles/ruby_1_8_and_1_9_2.gemfile +0 -49
- data/lib/rollbar/json/default.rb +0 -11
- 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
|
-
|
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
|
-
'*' * (
|
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
|
-
'*' *
|
112
|
+
'*' * rand(3..7)
|
104
113
|
end
|
105
114
|
end
|
106
115
|
end
|
data/lib/rollbar/scrubbers.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module Rollbar
|
2
2
|
module Scrubbers
|
3
|
-
|
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
|
-
'*' *
|
9
|
+
'*' * 6
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
def random_filtered_value
|
14
|
-
'*' *
|
14
|
+
'*' * rand(3..7)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -11,8 +11,7 @@ module Rollbar
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(payload)
|
14
|
-
|
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(
|
24
|
+
dump(payload)
|
26
25
|
end
|
27
26
|
|
28
27
|
def truncate_trace_data(trace_data)
|
@@ -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(
|
23
|
-
result = dump(
|
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
|
-
|
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
|
data/lib/rollbar/truncation.rb
CHANGED
@@ -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
|
|
data/lib/rollbar/util/hash.rb
CHANGED
@@ -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
|
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.
|
70
|
+
obj.dup
|
67
71
|
elsif obj.is_a?(Array)
|
68
|
-
obj.
|
72
|
+
obj.dup.clear
|
69
73
|
else
|
70
74
|
obj
|
71
75
|
end
|
data/lib/rollbar/version.rb
CHANGED
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
|
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
|
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
|
-
|
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 =
|
10
|
+
gem.description = 'Easy and powerful exception tracking for Ruby'
|
10
11
|
gem.executables = ['rollbar-rails-runner']
|
11
|
-
gem.summary =
|
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
|
20
|
+
gem.version = Rollbar::VERSION
|
19
21
|
|
20
|
-
gem.
|
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
|