airbrake-ruby 4.8.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +132 -57
- data/lib/airbrake-ruby/async_sender.rb +7 -30
- data/lib/airbrake-ruby/backtrace.rb +8 -7
- data/lib/airbrake-ruby/benchmark.rb +1 -1
- data/lib/airbrake-ruby/code_hunk.rb +1 -1
- data/lib/airbrake-ruby/config.rb +59 -15
- data/lib/airbrake-ruby/config/processor.rb +71 -0
- data/lib/airbrake-ruby/config/validator.rb +9 -3
- data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
- data/lib/airbrake-ruby/file_cache.rb +1 -1
- data/lib/airbrake-ruby/filter_chain.rb +16 -1
- data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +5 -5
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +3 -0
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +2 -0
- data/lib/airbrake-ruby/filters/{keys_whitelist.rb → keys_allowlist.rb} +3 -3
- data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
- data/lib/airbrake-ruby/filters/keys_filter.rb +39 -20
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +7 -7
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +5 -4
- data/lib/airbrake-ruby/grouppable.rb +12 -0
- data/lib/airbrake-ruby/ignorable.rb +1 -0
- data/lib/airbrake-ruby/inspectable.rb +2 -2
- data/lib/airbrake-ruby/loggable.rb +1 -1
- data/lib/airbrake-ruby/mergeable.rb +12 -0
- data/lib/airbrake-ruby/monotonic_time.rb +5 -0
- data/lib/airbrake-ruby/notice.rb +7 -14
- data/lib/airbrake-ruby/notice_notifier.rb +11 -3
- data/lib/airbrake-ruby/performance_breakdown.rb +16 -10
- data/lib/airbrake-ruby/performance_notifier.rb +80 -58
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +20 -15
- data/lib/airbrake-ruby/queue.rb +65 -0
- data/lib/airbrake-ruby/remote_settings.rb +105 -0
- data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
- data/lib/airbrake-ruby/request.rb +14 -12
- data/lib/airbrake-ruby/stat.rb +26 -33
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +43 -58
- data/lib/airbrake-ruby/thread_pool.rb +11 -1
- data/lib/airbrake-ruby/truncator.rb +10 -4
- data/lib/airbrake-ruby/version.rb +11 -1
- data/spec/airbrake_spec.rb +206 -71
- data/spec/async_sender_spec.rb +3 -12
- data/spec/backtrace_spec.rb +44 -44
- data/spec/code_hunk_spec.rb +11 -11
- data/spec/config/processor_spec.rb +143 -0
- data/spec/config/validator_spec.rb +23 -6
- data/spec/config_spec.rb +40 -14
- data/spec/deploy_notifier_spec.rb +2 -2
- data/spec/filter_chain_spec.rb +28 -1
- data/spec/filters/dependency_filter_spec.rb +1 -1
- data/spec/filters/gem_root_filter_spec.rb +9 -9
- data/spec/filters/git_last_checkout_filter_spec.rb +21 -4
- data/spec/filters/git_repository_filter.rb +1 -1
- data/spec/filters/git_revision_filter_spec.rb +10 -10
- data/spec/filters/{keys_whitelist_spec.rb → keys_allowlist_spec.rb} +29 -28
- data/spec/filters/{keys_blacklist_spec.rb → keys_blocklist_spec.rb} +39 -29
- data/spec/filters/root_directory_filter_spec.rb +9 -9
- data/spec/filters/sql_filter_spec.rb +58 -60
- data/spec/filters/system_exit_filter_spec.rb +1 -1
- data/spec/filters/thread_filter_spec.rb +32 -30
- data/spec/fixtures/project_root/code.rb +9 -9
- data/spec/loggable_spec.rb +17 -0
- data/spec/monotonic_time_spec.rb +11 -0
- data/spec/notice_notifier/options_spec.rb +17 -17
- data/spec/notice_notifier_spec.rb +20 -20
- data/spec/notice_spec.rb +6 -6
- data/spec/performance_breakdown_spec.rb +0 -1
- data/spec/performance_notifier_spec.rb +220 -73
- data/spec/query_spec.rb +1 -1
- data/spec/queue_spec.rb +18 -0
- data/spec/remote_settings/callback_spec.rb +143 -0
- data/spec/remote_settings/settings_data_spec.rb +348 -0
- data/spec/remote_settings_spec.rb +187 -0
- data/spec/request_spec.rb +1 -3
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +6 -6
- data/spec/stat_spec.rb +2 -12
- data/spec/sync_sender_spec.rb +14 -12
- data/spec/tdigest_spec.rb +7 -7
- data/spec/thread_pool_spec.rb +39 -10
- data/spec/timed_trace_spec.rb +1 -1
- data/spec/truncator_spec.rb +12 -12
- metadata +32 -14
@@ -4,7 +4,7 @@ module Airbrake
|
|
4
4
|
# notice, but specified keys.
|
5
5
|
#
|
6
6
|
# @example
|
7
|
-
# filter = Airbrake::Filters::
|
7
|
+
# filter = Airbrake::Filters::KeysAllowlist.new(
|
8
8
|
# [:email, /credit/i, 'password']
|
9
9
|
# )
|
10
10
|
# airbrake.add_filter(filter)
|
@@ -22,9 +22,9 @@ module Airbrake
|
|
22
22
|
# # email: 'john@example.com',
|
23
23
|
# # account_id: 42 }
|
24
24
|
#
|
25
|
-
# @see
|
25
|
+
# @see KeysBlocklist
|
26
26
|
# @see KeysFilter
|
27
|
-
class
|
27
|
+
class KeysAllowlist
|
28
28
|
include KeysFilter
|
29
29
|
|
30
30
|
def initialize(*)
|
@@ -4,7 +4,7 @@ module Airbrake
|
|
4
4
|
# list of parameters in the payload of a notice.
|
5
5
|
#
|
6
6
|
# @example
|
7
|
-
# filter = Airbrake::Filters::
|
7
|
+
# filter = Airbrake::Filters::KeysBlocklist.new(
|
8
8
|
# [:email, /credit/i, 'password']
|
9
9
|
# )
|
10
10
|
# airbrake.add_filter(filter)
|
@@ -22,10 +22,10 @@ module Airbrake
|
|
22
22
|
# # email: '[Filtered]',
|
23
23
|
# # credit_card: '[Filtered]' }
|
24
24
|
#
|
25
|
-
# @see
|
25
|
+
# @see KeysAllowlist
|
26
26
|
# @see KeysFilter
|
27
27
|
# @api private
|
28
|
-
class
|
28
|
+
class KeysBlocklist
|
29
29
|
include KeysFilter
|
30
30
|
|
31
31
|
def initialize(*)
|
@@ -7,8 +7,8 @@ module Airbrake
|
|
7
7
|
# class that includes this module must implement.
|
8
8
|
#
|
9
9
|
# @see Notice
|
10
|
-
# @see
|
11
|
-
# @see
|
10
|
+
# @see KeysAllowlist
|
11
|
+
# @see KeysBlocklist
|
12
12
|
# @api private
|
13
13
|
module KeysFilter
|
14
14
|
# @return [String] The label to replace real values of filtered payload
|
@@ -19,19 +19,30 @@ module Airbrake
|
|
19
19
|
VALID_PATTERN_CLASSES = [String, Symbol, Regexp].freeze
|
20
20
|
|
21
21
|
# @return [Array<Symbol>] parts of a Notice's payload that can be modified
|
22
|
-
# by
|
22
|
+
# by blocklist/allowlist filters
|
23
23
|
FILTERABLE_KEYS = %i[environment session params].freeze
|
24
24
|
|
25
25
|
# @return [Array<Symbol>] parts of a Notice's *context* payload that can
|
26
|
-
# be modified by
|
27
|
-
FILTERABLE_CONTEXT_KEYS = %i[
|
26
|
+
# be modified by blocklist/allowlist filters
|
27
|
+
FILTERABLE_CONTEXT_KEYS = %i[
|
28
|
+
user
|
29
|
+
|
30
|
+
# Provided by Airbrake::Rack::HttpHeadersFilter
|
31
|
+
headers
|
32
|
+
referer
|
33
|
+
httpMethod
|
34
|
+
|
35
|
+
# Provided by Airbrake::Rack::ContextFilter
|
36
|
+
userAddr
|
37
|
+
userAgent
|
38
|
+
].freeze
|
28
39
|
|
29
40
|
include Loggable
|
30
41
|
|
31
42
|
# @return [Integer]
|
32
43
|
attr_reader :weight
|
33
44
|
|
34
|
-
# Creates a new
|
45
|
+
# Creates a new KeysBlocklist or KeysAllowlist filter that uses the given
|
35
46
|
# +patterns+ for filtering a notice's payload.
|
36
47
|
#
|
37
48
|
# @param [Array<String,Regexp,Symbol>] patterns
|
@@ -53,10 +64,14 @@ module Airbrake
|
|
53
64
|
validate_patterns
|
54
65
|
end
|
55
66
|
|
56
|
-
FILTERABLE_KEYS.each
|
67
|
+
FILTERABLE_KEYS.each do |key|
|
68
|
+
notice[key] = filter_hash(notice[key])
|
69
|
+
end
|
70
|
+
|
57
71
|
FILTERABLE_CONTEXT_KEYS.each { |key| filter_context_key(notice, key) }
|
58
72
|
|
59
73
|
return unless notice[:context][:url]
|
74
|
+
|
60
75
|
filter_url(notice)
|
61
76
|
end
|
62
77
|
|
@@ -70,26 +85,26 @@ module Airbrake
|
|
70
85
|
def filter_hash(hash)
|
71
86
|
return hash unless hash.is_a?(Hash)
|
72
87
|
|
88
|
+
hash_copy = hash.dup
|
89
|
+
|
73
90
|
hash.each_key do |key|
|
74
91
|
if should_filter?(key.to_s)
|
75
|
-
|
76
|
-
elsif
|
77
|
-
filter_hash(
|
92
|
+
hash_copy[key] = FILTERED
|
93
|
+
elsif hash_copy[key].is_a?(Hash)
|
94
|
+
hash_copy[key] = filter_hash(hash_copy[key])
|
78
95
|
elsif hash[key].is_a?(Array)
|
79
|
-
|
96
|
+
hash_copy[key].each_with_index do |h, i|
|
97
|
+
hash_copy[key][i] = filter_hash(h)
|
98
|
+
end
|
80
99
|
end
|
81
100
|
end
|
101
|
+
|
102
|
+
hash_copy
|
82
103
|
end
|
83
104
|
|
84
105
|
def filter_url_params(url)
|
85
106
|
url.query = Hash[URI.decode_www_form(url.query)].map do |key, val|
|
86
|
-
|
87
|
-
# invalid characters, so be sure to escape individual components.
|
88
|
-
if should_filter?(key)
|
89
|
-
"#{URI.encode_www_form_component(key)}=[Filtered]"
|
90
|
-
else
|
91
|
-
"#{URI.encode_www_form_component(key)}=#{URI.encode_www_form_component(val)}"
|
92
|
-
end
|
107
|
+
should_filter?(key) ? "#{key}=[Filtered]" : "#{key}=#{val}"
|
93
108
|
end.join('&')
|
94
109
|
|
95
110
|
url.to_s
|
@@ -103,6 +118,7 @@ module Airbrake
|
|
103
118
|
end
|
104
119
|
|
105
120
|
return unless url.query
|
121
|
+
|
106
122
|
notice[:context][:url] = filter_url_params(url)
|
107
123
|
end
|
108
124
|
|
@@ -111,6 +127,7 @@ module Airbrake
|
|
111
127
|
|
112
128
|
@patterns = @patterns.flat_map do |pattern|
|
113
129
|
next(pattern) unless pattern.respond_to?(:call)
|
130
|
+
|
114
131
|
pattern.call
|
115
132
|
end
|
116
133
|
end
|
@@ -124,14 +141,16 @@ module Airbrake
|
|
124
141
|
|
125
142
|
logger.error(
|
126
143
|
"#{LOG_LABEL} one of the patterns in #{self.class} is invalid. " \
|
127
|
-
"Known patterns: #{@patterns}"
|
144
|
+
"Known patterns: #{@patterns}",
|
128
145
|
)
|
129
146
|
end
|
130
147
|
|
131
148
|
def filter_context_key(notice, key)
|
132
149
|
return unless notice[:context][key]
|
133
150
|
return if notice[:context][key] == FILTERED
|
134
|
-
|
151
|
+
unless should_filter?(key)
|
152
|
+
return notice[:context][key] = filter_hash(notice[:context][key])
|
153
|
+
end
|
135
154
|
|
136
155
|
notice[:context][key] = FILTERED
|
137
156
|
end
|
@@ -23,7 +23,7 @@ module Airbrake
|
|
23
23
|
|
24
24
|
# @return [Hash{Symbol=>Regexp}] matchers for certain features of SQL
|
25
25
|
ALL_FEATURES = {
|
26
|
-
# rubocop:disable
|
26
|
+
# rubocop:disable Layout/LineLength
|
27
27
|
single_quotes: /'(?:[^']|'')*?(?:\\'.*|'(?!'))/,
|
28
28
|
double_quotes: /"(?:[^"]|"")*?(?:\\".*|"(?!"))/,
|
29
29
|
dollar_quotes: /(\$(?!\d)[^$]*?\$).*?(?:\1|$)/,
|
@@ -33,13 +33,13 @@ module Airbrake
|
|
33
33
|
hexadecimal_literals: /0x[0-9a-fA-F]+/,
|
34
34
|
comments: /(?:#|--).*?(?=\r|\n|$)/i,
|
35
35
|
multi_line_comments: %r{/\*(?:[^/]|/[^*])*?(?:\*/|/\*.*)},
|
36
|
-
oracle_quoted_strings: /q'\[.*?(?:\]'|$)|q'\{.*?(?:\}'|$)|q'\<.*?(?:\>'|$)|q'\(.*?(?:\)'|$)
|
37
|
-
# rubocop:enable
|
36
|
+
oracle_quoted_strings: /q'\[.*?(?:\]'|$)|q'\{.*?(?:\}'|$)|q'\<.*?(?:\>'|$)|q'\(.*?(?:\)'|$)/,
|
37
|
+
# rubocop:enable Layout/LineLength
|
38
38
|
}.freeze
|
39
39
|
|
40
40
|
# @return [Regexp] the regexp that is applied after the feature regexps
|
41
41
|
# were used
|
42
|
-
POST_FILTER = /(?<=[values|in ]\().+(?=\))/i
|
42
|
+
POST_FILTER = /(?<=[values|in ]\().+(?=\))/i.freeze
|
43
43
|
|
44
44
|
# @return [Hash{Symbol=>Array<Symbol>}] a set of features that corresponds
|
45
45
|
# to a certain dialect
|
@@ -64,7 +64,7 @@ module Airbrake
|
|
64
64
|
cassandra: %i[
|
65
65
|
single_quotes uuids numeric_literals boolean_literals
|
66
66
|
hexadecimal_literals comments multi_line_comments
|
67
|
-
].freeze
|
67
|
+
].freeze,
|
68
68
|
}.freeze
|
69
69
|
|
70
70
|
# @return [Hash{Symbol=>Regexp}] a set of regexps to check for unmatches
|
@@ -76,7 +76,7 @@ module Airbrake
|
|
76
76
|
sqlite: %r{'|/\*|\*/},
|
77
77
|
cassandra: %r{'|/\*|\*/},
|
78
78
|
oracle: %r{'|/\*|\*/},
|
79
|
-
oracle_enhanced: %r{'|/\*|\*/}
|
79
|
+
oracle_enhanced: %r{'|/\*|\*/},
|
80
80
|
}.freeze
|
81
81
|
|
82
82
|
# @return [Array<Regexp>] the list of queries to be ignored
|
@@ -89,7 +89,7 @@ module Airbrake
|
|
89
89
|
/FROM pg_attribute/i,
|
90
90
|
/FROM pg_index/i,
|
91
91
|
/FROM pg_class/i,
|
92
|
-
/FROM pg_type/i
|
92
|
+
/FROM pg_type/i,
|
93
93
|
].freeze
|
94
94
|
|
95
95
|
def initialize(dialect)
|
@@ -16,7 +16,7 @@ module Airbrake
|
|
16
16
|
String,
|
17
17
|
Symbol,
|
18
18
|
Regexp,
|
19
|
-
Numeric
|
19
|
+
Numeric,
|
20
20
|
].freeze
|
21
21
|
|
22
22
|
# Variables starting with this prefix are not attached to a notice.
|
@@ -41,8 +41,7 @@ module Airbrake
|
|
41
41
|
thread_info[:fiber_variables] = vars
|
42
42
|
end
|
43
43
|
|
44
|
-
|
45
|
-
if th.respond_to?(:name) && (name = th.name)
|
44
|
+
if (name = th.name)
|
46
45
|
thread_info[:name] = name
|
47
46
|
end
|
48
47
|
|
@@ -56,6 +55,7 @@ module Airbrake
|
|
56
55
|
def thread_variables(th)
|
57
56
|
th.thread_variables.map.with_object({}) do |var, h|
|
58
57
|
next if var.to_s.start_with?(IGNORE_PREFIX)
|
58
|
+
|
59
59
|
h[var] = sanitize_value(th.thread_variable_get(var))
|
60
60
|
end
|
61
61
|
end
|
@@ -63,6 +63,7 @@ module Airbrake
|
|
63
63
|
def fiber_variables(th)
|
64
64
|
th.keys.map.with_object({}) do |key, h|
|
65
65
|
next if key.to_s.start_with?(IGNORE_PREFIX)
|
66
|
+
|
66
67
|
h[key] = sanitize_value(th[key])
|
67
68
|
end
|
68
69
|
end
|
@@ -72,7 +73,7 @@ module Airbrake
|
|
72
73
|
thread_info[:group] = th.group.list.map(&:inspect)
|
73
74
|
thread_info[:priority] = th.priority
|
74
75
|
|
75
|
-
thread_info[:safe_level] = th.safe_level
|
76
|
+
thread_info[:safe_level] = th.safe_level if Airbrake::HAS_SAFE_LEVEL
|
76
77
|
end
|
77
78
|
|
78
79
|
def sanitize_value(value)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# Grouppable adds the `#groups` method, so that we don't need to define it in
|
3
|
+
# all of performance models every time we add a model without groups.
|
4
|
+
#
|
5
|
+
# @since v4.9.0
|
6
|
+
# @api private
|
7
|
+
module Grouppable
|
8
|
+
def groups
|
9
|
+
{}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -21,7 +21,7 @@ module Airbrake
|
|
21
21
|
project_id: @config.project_id,
|
22
22
|
project_key: @config.project_key,
|
23
23
|
host: @config.host,
|
24
|
-
filter_chain: @filter_chain.inspect
|
24
|
+
filter_chain: @filter_chain.inspect,
|
25
25
|
)
|
26
26
|
end
|
27
27
|
|
@@ -30,7 +30,7 @@ module Airbrake
|
|
30
30
|
q.text("#<#{self.class}:0x#{(object_id << 1).to_s(16).rjust(16, '0')} ")
|
31
31
|
q.text(
|
32
32
|
"project_id=\"#{@config.project_id}\" project_key=\"#{@config.project_key}\" " \
|
33
|
-
"host=\"#{@config.host}\" filter_chain="
|
33
|
+
"host=\"#{@config.host}\" filter_chain=",
|
34
34
|
)
|
35
35
|
q.pp(@filter_chain)
|
36
36
|
q.text('>')
|
data/lib/airbrake-ruby/notice.rb
CHANGED
@@ -4,19 +4,12 @@ module Airbrake
|
|
4
4
|
#
|
5
5
|
# @since v1.0.0
|
6
6
|
class Notice
|
7
|
-
# @return [Hash{Symbol=>String}] the information about the notifier library
|
8
|
-
NOTIFIER = {
|
9
|
-
name: 'airbrake-ruby'.freeze,
|
10
|
-
version: Airbrake::AIRBRAKE_RUBY_VERSION,
|
11
|
-
url: 'https://github.com/airbrake/airbrake-ruby'.freeze
|
12
|
-
}.freeze
|
13
|
-
|
14
7
|
# @return [Hash{Symbol=>String,Hash}] the information to be displayed in the
|
15
8
|
# Context tab in the dashboard
|
16
9
|
CONTEXT = {
|
17
10
|
os: RUBY_PLATFORM,
|
18
11
|
language: "#{RUBY_ENGINE}/#{RUBY_VERSION}".freeze,
|
19
|
-
notifier:
|
12
|
+
notifier: Airbrake::NOTIFIER_INFO,
|
20
13
|
}.freeze
|
21
14
|
|
22
15
|
# @return [Integer] the maxium size of the JSON payload in bytes
|
@@ -32,7 +25,7 @@ module Airbrake
|
|
32
25
|
IOError,
|
33
26
|
NotImplementedError,
|
34
27
|
JSON::GeneratorError,
|
35
|
-
Encoding::UndefinedConversionError
|
28
|
+
Encoding::UndefinedConversionError,
|
36
29
|
].freeze
|
37
30
|
|
38
31
|
# @return [Array<Symbol>] the list of keys that can be be overwritten with
|
@@ -60,10 +53,10 @@ module Airbrake
|
|
60
53
|
errors: NestedException.new(exception).as_json,
|
61
54
|
context: context,
|
62
55
|
environment: {
|
63
|
-
program_name: $PROGRAM_NAME
|
56
|
+
program_name: $PROGRAM_NAME,
|
64
57
|
},
|
65
58
|
session: {},
|
66
|
-
params: params
|
59
|
+
params: params,
|
67
60
|
}
|
68
61
|
@truncator = Airbrake::Truncator.new(PAYLOAD_MAX_SIZE)
|
69
62
|
|
@@ -76,7 +69,7 @@ module Airbrake
|
|
76
69
|
#
|
77
70
|
# @return [Hash{String=>String}, nil]
|
78
71
|
# @api private
|
79
|
-
def to_json
|
72
|
+
def to_json(*_args)
|
80
73
|
loop do
|
81
74
|
begin
|
82
75
|
json = @payload.to_json
|
@@ -138,7 +131,7 @@ module Airbrake
|
|
138
131
|
# Make sure we always send hostname.
|
139
132
|
hostname: HOSTNAME,
|
140
133
|
|
141
|
-
severity: DEFAULT_SEVERITY
|
134
|
+
severity: DEFAULT_SEVERITY,
|
142
135
|
}.merge(CONTEXT).delete_if { |_key, val| val.nil? || val.empty? }
|
143
136
|
end
|
144
137
|
|
@@ -152,7 +145,7 @@ module Airbrake
|
|
152
145
|
logger.error(
|
153
146
|
"#{LOG_LABEL} truncation failed. File an issue at " \
|
154
147
|
"https://github.com/airbrake/airbrake-ruby " \
|
155
|
-
"and attach the following payload: #{@payload}"
|
148
|
+
"and attach the following payload: #{@payload}",
|
156
149
|
)
|
157
150
|
end
|
158
151
|
|
@@ -9,7 +9,7 @@ module Airbrake
|
|
9
9
|
# @return [Array<Class>] filters to be executed first
|
10
10
|
DEFAULT_FILTERS = [
|
11
11
|
Airbrake::Filters::SystemExitFilter,
|
12
|
-
Airbrake::Filters::GemRootFilter
|
12
|
+
Airbrake::Filters::GemRootFilter,
|
13
13
|
|
14
14
|
# Optional filters (must be included by users):
|
15
15
|
# Airbrake::Filters::ThreadFilter
|
@@ -55,7 +55,8 @@ module Airbrake
|
|
55
55
|
def build_notice(exception, params = {})
|
56
56
|
if @async_sender.closed?
|
57
57
|
raise Airbrake::Error,
|
58
|
-
"
|
58
|
+
"Airbrake is closed; can't build exception: " \
|
59
|
+
"#{exception.class}: #{exception}"
|
59
60
|
end
|
60
61
|
|
61
62
|
if exception.is_a?(Airbrake::Notice)
|
@@ -81,6 +82,12 @@ module Airbrake
|
|
81
82
|
@context.merge!(context)
|
82
83
|
end
|
83
84
|
|
85
|
+
# @return [Boolean]
|
86
|
+
# @since v4.14.0
|
87
|
+
def has_filter?(filter_class) # rubocop:disable Naming/PredicateName
|
88
|
+
@filter_chain.includes?(filter_class)
|
89
|
+
end
|
90
|
+
|
84
91
|
private
|
85
92
|
|
86
93
|
def convert_to_exception(ex)
|
@@ -116,7 +123,7 @@ module Airbrake
|
|
116
123
|
|
117
124
|
logger.warn(
|
118
125
|
"#{LOG_LABEL} falling back to sync delivery because there are no " \
|
119
|
-
"running async workers"
|
126
|
+
"running async workers",
|
120
127
|
)
|
121
128
|
@sync_sender
|
122
129
|
end
|
@@ -128,6 +135,7 @@ module Airbrake
|
|
128
135
|
# If true, then it's likely an internal library error. In this case return
|
129
136
|
# at least some backtrace to simplify debugging.
|
130
137
|
return caller_copy if clean_bt.empty?
|
138
|
+
|
131
139
|
clean_bt
|
132
140
|
end
|
133
141
|
end
|