rollbar 2.19.1 → 2.27.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|