airbrake-ruby 3.1.0 → 3.2.0
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 +4 -4
- data/lib/airbrake-ruby.rb +197 -43
- data/lib/airbrake-ruby/config.rb +43 -11
- data/lib/airbrake-ruby/deploy_notifier.rb +47 -0
- data/lib/airbrake-ruby/filter_chain.rb +32 -50
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +9 -1
- data/lib/airbrake-ruby/filters/sql_filter.rb +104 -0
- data/lib/airbrake-ruby/hash_keyable.rb +37 -0
- data/lib/airbrake-ruby/ignorable.rb +44 -0
- data/lib/airbrake-ruby/notice.rb +2 -22
- data/lib/airbrake-ruby/{notifier.rb → notice_notifier.rb} +66 -46
- data/lib/airbrake-ruby/performance_notifier.rb +161 -0
- data/lib/airbrake-ruby/stat.rb +56 -0
- data/lib/airbrake-ruby/tdigest.rb +393 -0
- data/lib/airbrake-ruby/time_truncate.rb +17 -0
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/airbrake_spec.rb +57 -13
- data/spec/async_sender_spec.rb +0 -2
- data/spec/backtrace_spec.rb +0 -2
- data/spec/code_hunk_spec.rb +0 -2
- data/spec/config/validator_spec.rb +0 -2
- data/spec/config_spec.rb +16 -4
- data/spec/deploy_notifier_spec.rb +41 -0
- data/spec/file_cache.rb +0 -2
- data/spec/filter_chain_spec.rb +1 -7
- data/spec/filters/context_filter_spec.rb +0 -2
- data/spec/filters/dependency_filter_spec.rb +0 -2
- data/spec/filters/exception_attributes_filter_spec.rb +0 -2
- data/spec/filters/gem_root_filter_spec.rb +0 -2
- data/spec/filters/git_last_checkout_filter_spec.rb +0 -2
- data/spec/filters/git_repository_filter.rb +0 -2
- data/spec/filters/git_revision_filter_spec.rb +0 -2
- data/spec/filters/keys_blacklist_spec.rb +0 -2
- data/spec/filters/keys_whitelist_spec.rb +0 -2
- data/spec/filters/root_directory_filter_spec.rb +0 -2
- data/spec/filters/sql_filter_spec.rb +219 -0
- data/spec/filters/system_exit_filter_spec.rb +0 -2
- data/spec/filters/thread_filter_spec.rb +0 -2
- data/spec/ignorable_spec.rb +14 -0
- data/spec/nested_exception_spec.rb +0 -2
- data/spec/{notifier_spec.rb → notice_notifier_spec.rb} +24 -114
- data/spec/{notifier_spec → notice_notifier_spec}/options_spec.rb +40 -39
- data/spec/notice_spec.rb +2 -4
- data/spec/performance_notifier_spec.rb +287 -0
- data/spec/promise_spec.rb +0 -2
- data/spec/response_spec.rb +0 -2
- data/spec/stat_spec.rb +35 -0
- data/spec/sync_sender_spec.rb +0 -2
- data/spec/tdigest_spec.rb +230 -0
- data/spec/time_truncate_spec.rb +13 -0
- data/spec/truncator_spec.rb +0 -2
- metadata +34 -15
- data/lib/airbrake-ruby/route_sender.rb +0 -175
- data/spec/route_sender_spec.rb +0 -130
@@ -0,0 +1,47 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# DeployNotifier sends deploy information to Airbrake. The information
|
3
|
+
# consists of:
|
4
|
+
# - environment
|
5
|
+
# - username
|
6
|
+
# - repository
|
7
|
+
# - revision
|
8
|
+
# - version
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
# @since v3.2.0
|
12
|
+
class DeployNotifier
|
13
|
+
# @param [Airbrake::Config] config
|
14
|
+
def initialize(config)
|
15
|
+
@config =
|
16
|
+
if config.is_a?(Config)
|
17
|
+
config
|
18
|
+
else
|
19
|
+
loc = caller_locations(1..1).first
|
20
|
+
signature = "#{self.class.name}##{__method__}"
|
21
|
+
warn(
|
22
|
+
"#{loc.path}:#{loc.lineno}: warning: passing a Hash to #{signature} " \
|
23
|
+
'is deprecated. Pass `Airbrake::Config` instead'
|
24
|
+
)
|
25
|
+
Config.new(config)
|
26
|
+
end
|
27
|
+
|
28
|
+
@sender = SyncSender.new(@config)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @see Airbrake.create_deploy
|
32
|
+
def notify(deploy_info, promise = Airbrake::Promise.new)
|
33
|
+
if @config.ignored_environment?
|
34
|
+
return promise.reject("The '#{@config.environment}' environment is ignored")
|
35
|
+
end
|
36
|
+
|
37
|
+
deploy_info[:environment] ||= @config.environment
|
38
|
+
@sender.send(
|
39
|
+
deploy_info,
|
40
|
+
promise,
|
41
|
+
URI.join(@config.host, "api/v4/projects/#{@config.project_id}/deploys")
|
42
|
+
)
|
43
|
+
|
44
|
+
promise
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,29 +1,44 @@
|
|
1
1
|
module Airbrake
|
2
|
-
#
|
3
|
-
#
|
2
|
+
# FilterChain represents an ordered array of filters.
|
3
|
+
#
|
4
|
+
# A filter is an object that responds to <b>#call</b> (typically a Proc or a
|
5
|
+
# class that implements the call method). The <b>#call</b> method must accept
|
6
|
+
# exactly one argument: an object to be filtered.
|
7
|
+
#
|
8
|
+
# When you add a new filter to the chain, it gets inserted according to its
|
9
|
+
# <b>weight</b>. Smaller weight means the filter will be somewhere in the
|
10
|
+
# beginning of the array. Larger - in the end. If a filter doesn't implement
|
11
|
+
# weight, the chain assumes it's equal to 0.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# class MyFilter
|
15
|
+
# attr_reader :weight
|
16
|
+
#
|
17
|
+
# def initialize
|
18
|
+
# @weight = 1
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def call(obj)
|
22
|
+
# puts 'Filtering...'
|
23
|
+
# obj[:data] = '[Filtered]'
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# filter_chain = FilterChain.new
|
28
|
+
# filter_chain.add_filter(MyFilter)
|
29
|
+
#
|
30
|
+
# filter_chain.refine(obj)
|
31
|
+
# #=> Filtering...
|
4
32
|
#
|
5
33
|
# @see Airbrake.add_filter
|
6
34
|
# @api private
|
7
35
|
# @since v1.0.0
|
8
36
|
class FilterChain
|
9
|
-
# @return [Array<Class>] filters to be executed first
|
10
|
-
DEFAULT_FILTERS = [
|
11
|
-
Airbrake::Filters::SystemExitFilter,
|
12
|
-
Airbrake::Filters::GemRootFilter
|
13
|
-
|
14
|
-
# Optional filters (must be included by users):
|
15
|
-
# Airbrake::Filters::ThreadFilter
|
16
|
-
].freeze
|
17
|
-
|
18
37
|
# @return [Integer]
|
19
38
|
DEFAULT_WEIGHT = 0
|
20
39
|
|
21
|
-
def initialize
|
22
|
-
@config = config
|
23
|
-
@context = context
|
40
|
+
def initialize
|
24
41
|
@filters = []
|
25
|
-
DEFAULT_FILTERS.each { |f| add_filter(f.new) }
|
26
|
-
add_default_filters
|
27
42
|
end
|
28
43
|
|
29
44
|
# Adds a filter to the filter chain. Sorts filters by weight.
|
@@ -51,6 +66,7 @@ module Airbrake
|
|
51
66
|
#
|
52
67
|
# @param [Airbrake::Notice] notice The notice to be filtered
|
53
68
|
# @return [void]
|
69
|
+
# @todo Make it work with anything, not only notices
|
54
70
|
def refine(notice)
|
55
71
|
@filters.each do |filter|
|
56
72
|
break if notice.ignored?
|
@@ -75,39 +91,5 @@ module Airbrake
|
|
75
91
|
end
|
76
92
|
q.text(']')
|
77
93
|
end
|
78
|
-
|
79
|
-
private
|
80
|
-
|
81
|
-
# rubocop:disable Metrics/AbcSize
|
82
|
-
def add_default_filters
|
83
|
-
if (whitelist_keys = @config.whitelist_keys).any?
|
84
|
-
add_filter(
|
85
|
-
Airbrake::Filters::KeysWhitelist.new(@config.logger, whitelist_keys)
|
86
|
-
)
|
87
|
-
end
|
88
|
-
|
89
|
-
if (blacklist_keys = @config.blacklist_keys).any?
|
90
|
-
add_filter(
|
91
|
-
Airbrake::Filters::KeysBlacklist.new(@config.logger, blacklist_keys)
|
92
|
-
)
|
93
|
-
end
|
94
|
-
|
95
|
-
add_filter(Airbrake::Filters::ContextFilter.new(@context))
|
96
|
-
add_filter(Airbrake::Filters::ExceptionAttributesFilter.new(@config.logger))
|
97
|
-
|
98
|
-
return unless (root_directory = @config.root_directory)
|
99
|
-
[
|
100
|
-
Airbrake::Filters::RootDirectoryFilter,
|
101
|
-
Airbrake::Filters::GitRevisionFilter,
|
102
|
-
Airbrake::Filters::GitRepositoryFilter
|
103
|
-
].each do |filter|
|
104
|
-
add_filter(filter.new(root_directory))
|
105
|
-
end
|
106
|
-
|
107
|
-
add_filter(
|
108
|
-
Airbrake::Filters::GitLastCheckoutFilter.new(@config.logger, root_directory)
|
109
|
-
)
|
110
|
-
end
|
111
|
-
# rubocop:enable Metrics/AbcSize
|
112
94
|
end
|
113
95
|
end
|
@@ -11,6 +11,7 @@ module Airbrake
|
|
11
11
|
def initialize(root_directory)
|
12
12
|
@git_path = File.join(root_directory, '.git')
|
13
13
|
@repository = nil
|
14
|
+
@git_version = Gem::Version.new(`git --version`.split.last)
|
14
15
|
@weight = 116
|
15
16
|
end
|
16
17
|
|
@@ -25,7 +26,14 @@ module Airbrake
|
|
25
26
|
|
26
27
|
return unless File.exist?(@git_path)
|
27
28
|
|
28
|
-
@repository =
|
29
|
+
@repository =
|
30
|
+
if @git_version >= Gem::Version.new('2.7.0')
|
31
|
+
`cd #{@git_path} && git config --get remote.origin.url`.chomp
|
32
|
+
else
|
33
|
+
"`git remote get-url` is unsupported in git #{@git_version}. " \
|
34
|
+
'Consider an upgrade to 2.7+'
|
35
|
+
end
|
36
|
+
|
29
37
|
return unless @repository
|
30
38
|
notice[:context][:repository] = @repository
|
31
39
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Airbrake
|
2
|
+
module Filters
|
3
|
+
# SqlFilter filters out sensitive data from {Airbrake::Query}. Sensitive
|
4
|
+
# data is everything that is not table names or fields (e.g. column values
|
5
|
+
# and such).
|
6
|
+
#
|
7
|
+
# Supports the following SQL dialects:
|
8
|
+
# * PostgreSQL
|
9
|
+
# * MySQL
|
10
|
+
# * SQLite
|
11
|
+
# * Cassandra
|
12
|
+
# * Oracle
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since v3.2.0
|
16
|
+
class SqlFilter
|
17
|
+
# @return [String] the label to replace real values of filtered query
|
18
|
+
FILTERED = '?'.freeze
|
19
|
+
|
20
|
+
# @return [String] the string that will replace the query in case we
|
21
|
+
# cannot filter it
|
22
|
+
ERROR_MSG = 'Error: Airbrake::Query was not filtered'.freeze
|
23
|
+
|
24
|
+
# @return [Hash{Symbol=>Regexp}] matchers for certain features of SQL
|
25
|
+
ALL_FEATURES = {
|
26
|
+
# rubocop:disable Metrics/LineLength
|
27
|
+
single_quotes: /'(?:[^']|'')*?(?:\\'.*|'(?!'))/,
|
28
|
+
double_quotes: /"(?:[^"]|"")*?(?:\\".*|"(?!"))/,
|
29
|
+
dollar_quotes: /(\$(?!\d)[^$]*?\$).*?(?:\1|$)/,
|
30
|
+
uuids: /\{?(?:[0-9a-fA-F]\-*){32}\}?/,
|
31
|
+
numeric_literals: /\b-?(?:[0-9]+\.)?[0-9]+([eE][+-]?[0-9]+)?\b/,
|
32
|
+
boolean_literals: /\b(?:true|false|null)\b/i,
|
33
|
+
hexadecimal_literals: /0x[0-9a-fA-F]+/,
|
34
|
+
comments: /(?:#|--).*?(?=\r|\n|$)/i,
|
35
|
+
multi_line_comments: %r{/\*(?:[^/]|/[^*])*?(?:\*/|/\*.*)},
|
36
|
+
oracle_quoted_strings: /q'\[.*?(?:\]'|$)|q'\{.*?(?:\}'|$)|q'\<.*?(?:\>'|$)|q'\(.*?(?:\)'|$)/
|
37
|
+
# rubocop:enable Metrics/LineLength
|
38
|
+
}.freeze
|
39
|
+
|
40
|
+
# @return [Hash{Symbol=>Array<Symbol>}] a set of features that corresponds
|
41
|
+
# to a certain dialect
|
42
|
+
DIALECT_FEATURES = {
|
43
|
+
default: ALL_FEATURES.keys,
|
44
|
+
mysql: %i[
|
45
|
+
single_quotes double_quotes numeric_literals boolean_literals
|
46
|
+
hexadecimal_literals comments multi_line_comments
|
47
|
+
].freeze,
|
48
|
+
postgres: %i[
|
49
|
+
single_quotes dollar_quotes uuids numeric_literals boolean_literals
|
50
|
+
comments multi_line_comments
|
51
|
+
].freeze,
|
52
|
+
sqlite: %i[
|
53
|
+
single_quotes numeric_literals boolean_literals hexadecimal_literals
|
54
|
+
comments multi_line_comments
|
55
|
+
].freeze,
|
56
|
+
oracle: %i[
|
57
|
+
single_quotes oracle_quoted_strings numeric_literals comments
|
58
|
+
multi_line_comments
|
59
|
+
].freeze,
|
60
|
+
cassandra: %i[
|
61
|
+
single_quotes uuids numeric_literals boolean_literals
|
62
|
+
hexadecimal_literals comments multi_line_comments
|
63
|
+
].freeze
|
64
|
+
}.freeze
|
65
|
+
|
66
|
+
# @return [Hash{Symbol=>Regexp}] a set of regexps to check for unmatches
|
67
|
+
# quotes after filtering (should be none)
|
68
|
+
UNMATCHED_PAIR = {
|
69
|
+
mysql: %r{'|"|/\*|\*/},
|
70
|
+
mysql2: %r{'|"|/\*|\*/},
|
71
|
+
postgres: %r{'|/\*|\*/|\$(?!\?)},
|
72
|
+
sqlite: %r{'|/\*|\*/},
|
73
|
+
cassandra: %r{'|/\*|\*/},
|
74
|
+
oracle: %r{'|/\*|\*/},
|
75
|
+
oracle_enhanced: %r{'|/\*|\*/}
|
76
|
+
}.freeze
|
77
|
+
|
78
|
+
def initialize(dialect)
|
79
|
+
@dialect =
|
80
|
+
case dialect
|
81
|
+
when /mysql/i then :mysql
|
82
|
+
when /postgres/i then :postgres
|
83
|
+
when /sqlite/i then :sqlite
|
84
|
+
when /oracle/i then :oracle
|
85
|
+
when /cassandra/i then :cassandra
|
86
|
+
else
|
87
|
+
:default
|
88
|
+
end
|
89
|
+
|
90
|
+
features = DIALECT_FEATURES[@dialect].map { |f| ALL_FEATURES[f] }
|
91
|
+
@regexp = Regexp.union(features)
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param [Airbrake::Query] resource
|
95
|
+
def call(resource)
|
96
|
+
return unless resource.respond_to?(:query)
|
97
|
+
|
98
|
+
q = resource.query.gsub(@regexp, FILTERED)
|
99
|
+
q = ERROR_MSG if UNMATCHED_PAIR[@dialect] =~ q
|
100
|
+
resource.query = q
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# HashKeyable allows instances of the class to be used as a Hash key in a
|
3
|
+
# consistent manner.
|
4
|
+
#
|
5
|
+
# The class that includes it must implement *to_h*, which defines properties
|
6
|
+
# that all of the instances must share in order to produce the same {#hash}.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# class C
|
10
|
+
# include Airbrake::HashKeyable
|
11
|
+
#
|
12
|
+
# def initialize(key)
|
13
|
+
# @key = key
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def to_h
|
17
|
+
# { 'key' => @key }
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# h = {}
|
22
|
+
# h[C.new('key1')] = 1
|
23
|
+
# h[C.new('key1')] #=> 1
|
24
|
+
# h[C.new('key2')] #=> nil
|
25
|
+
module HashKeyable
|
26
|
+
# @param [Object] other
|
27
|
+
# @return [Boolean]
|
28
|
+
def eql?(other)
|
29
|
+
other.is_a?(self.class) && other.hash == hash
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Integer]
|
33
|
+
def hash
|
34
|
+
to_h.hash
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# Ignorable contains methods that allow the includee to be ignored.
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# class A
|
6
|
+
# include Airbrake::Ignorable
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# a = A.new
|
10
|
+
# a.ignore!
|
11
|
+
# a.ignored? #=> true
|
12
|
+
#
|
13
|
+
# @since v3.2.0
|
14
|
+
# @api private
|
15
|
+
module Ignorable
|
16
|
+
attr_accessor :ignored
|
17
|
+
|
18
|
+
# Checks whether the instance was ignored.
|
19
|
+
# @return [Boolean]
|
20
|
+
# @see #ignore!
|
21
|
+
# rubocop:disable Style/DoubleNegation
|
22
|
+
def ignored?
|
23
|
+
!!ignored
|
24
|
+
end
|
25
|
+
# rubocop:enable Style/DoubleNegation
|
26
|
+
|
27
|
+
# Ignores an instance. Ignored instances must never reach the Airbrake
|
28
|
+
# dashboard.
|
29
|
+
# @return [void]
|
30
|
+
# @see #ignored?
|
31
|
+
def ignore!
|
32
|
+
self.ignored = true
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# A method that is meant to be used as a guard.
|
38
|
+
# @raise [Airbrake::Error] when instance is ignored
|
39
|
+
def raise_if_ignored
|
40
|
+
return unless ignored?
|
41
|
+
raise Airbrake::Error, "cannot access ignored #{self.class}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/airbrake-ruby/notice.rb
CHANGED
@@ -49,6 +49,8 @@ module Airbrake
|
|
49
49
|
# @return [String]
|
50
50
|
DEFAULT_SEVERITY = 'error'.freeze
|
51
51
|
|
52
|
+
include Ignorable
|
53
|
+
|
52
54
|
# @since v1.7.0
|
53
55
|
# @return [Hash{Symbol=>Object}] the hash with arbitrary objects to be used
|
54
56
|
# in filters
|
@@ -91,23 +93,6 @@ module Airbrake
|
|
91
93
|
end
|
92
94
|
end
|
93
95
|
|
94
|
-
# Ignores a notice. Ignored notices never reach the Airbrake dashboard.
|
95
|
-
#
|
96
|
-
# @return [void]
|
97
|
-
# @see #ignored?
|
98
|
-
# @note Ignored noticed can't be unignored
|
99
|
-
def ignore!
|
100
|
-
@payload = nil
|
101
|
-
end
|
102
|
-
|
103
|
-
# Checks whether the notice was ignored.
|
104
|
-
#
|
105
|
-
# @return [Boolean]
|
106
|
-
# @see #ignore!
|
107
|
-
def ignored?
|
108
|
-
@payload.nil?
|
109
|
-
end
|
110
|
-
|
111
96
|
# Reads a value from notice's payload.
|
112
97
|
#
|
113
98
|
# @return [Object]
|
@@ -160,11 +145,6 @@ module Airbrake
|
|
160
145
|
}.merge(CONTEXT).delete_if { |_key, val| val.nil? || val.empty? }
|
161
146
|
end
|
162
147
|
|
163
|
-
def raise_if_ignored
|
164
|
-
return unless ignored?
|
165
|
-
raise Airbrake::Error, 'cannot access ignored notice'
|
166
|
-
end
|
167
|
-
|
168
148
|
def truncate
|
169
149
|
TRUNCATABLE_KEYS.each do |key|
|
170
150
|
@payload[key] = @truncator.truncate(@payload[key])
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Airbrake
|
2
|
-
#
|
2
|
+
# NoticeNotifier is reponsible for sending notices to Airbrake. It supports
|
3
3
|
# synchronous and asynchronous delivery.
|
4
4
|
#
|
5
5
|
# @see Airbrake::Config The list of options
|
6
6
|
# @since v1.0.0
|
7
|
-
# @api
|
7
|
+
# @api public
|
8
8
|
# rubocop:disable Metrics/ClassLength
|
9
|
-
class
|
9
|
+
class NoticeNotifier
|
10
10
|
# @return [String] the label to be prepended to the log output
|
11
11
|
LOG_LABEL = '**Airbrake:'.freeze
|
12
12
|
|
@@ -16,31 +16,44 @@ module Airbrake
|
|
16
16
|
"project_key=\"%<project_key>s\" " \
|
17
17
|
"host=\"%<host>s\" filter_chain=%<filter_chain>s>".freeze
|
18
18
|
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
# @return [Array<Class>] filters to be executed first
|
20
|
+
DEFAULT_FILTERS = [
|
21
|
+
Airbrake::Filters::SystemExitFilter,
|
22
|
+
Airbrake::Filters::GemRootFilter
|
23
|
+
|
24
|
+
# Optional filters (must be included by users):
|
25
|
+
# Airbrake::Filters::ThreadFilter
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
# Creates a new notice notifier with the given config options.
|
23
29
|
#
|
24
|
-
# @example
|
30
|
+
# @example
|
25
31
|
# config = Airbrake::Config.new
|
26
32
|
# config.project_id = 123
|
27
33
|
# config.project_key = '321'
|
28
|
-
#
|
34
|
+
# notice_notifier = Airbrake::NoticeNotifier.new(config)
|
29
35
|
#
|
30
|
-
# @param [
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
# @param [Airbrake::Config] config
|
37
|
+
def initialize(config)
|
38
|
+
@config =
|
39
|
+
if config.is_a?(Config)
|
40
|
+
config
|
41
|
+
else
|
42
|
+
loc = caller_locations(1..1).first
|
43
|
+
signature = "#{self.class.name}##{__method__}"
|
44
|
+
warn(
|
45
|
+
"#{loc.path}:#{loc.lineno}: warning: passing a Hash to #{signature} " \
|
46
|
+
'is deprecated. Pass `Airbrake::Config` instead'
|
47
|
+
)
|
48
|
+
Config.new(config)
|
49
|
+
end
|
38
50
|
|
39
51
|
@context = {}
|
40
|
-
@filter_chain = FilterChain.new
|
52
|
+
@filter_chain = FilterChain.new
|
41
53
|
@async_sender = AsyncSender.new(@config)
|
42
54
|
@sync_sender = SyncSender.new(@config)
|
43
|
-
|
55
|
+
|
56
|
+
add_default_filters
|
44
57
|
end
|
45
58
|
|
46
59
|
# @macro see_public_api_method
|
@@ -83,18 +96,6 @@ module Airbrake
|
|
83
96
|
@async_sender.close
|
84
97
|
end
|
85
98
|
|
86
|
-
# @macro see_public_api_method
|
87
|
-
def create_deploy(deploy_params)
|
88
|
-
deploy_params[:environment] ||= @config.environment
|
89
|
-
promise = Airbrake::Promise.new
|
90
|
-
@sync_sender.send(
|
91
|
-
deploy_params,
|
92
|
-
promise,
|
93
|
-
URI.join(@config.host, "api/v4/projects/#{@config.project_id}/deploys")
|
94
|
-
)
|
95
|
-
promise
|
96
|
-
end
|
97
|
-
|
98
99
|
# @macro see_public_api_method
|
99
100
|
def configured?
|
100
101
|
@config.valid?
|
@@ -105,21 +106,6 @@ module Airbrake
|
|
105
106
|
@context.merge!(context)
|
106
107
|
end
|
107
108
|
|
108
|
-
# @macro see_public_api_method
|
109
|
-
def notify_request(request_info)
|
110
|
-
promise = Airbrake::Promise.new
|
111
|
-
|
112
|
-
if @config.ignored_environment?
|
113
|
-
return promise.reject("The '#{@config.environment}' environment is ignored")
|
114
|
-
end
|
115
|
-
|
116
|
-
unless @config.route_stats
|
117
|
-
return promise.reject("The Route Stats feature is disabled")
|
118
|
-
end
|
119
|
-
|
120
|
-
@route_sender.notify_request(request_info, promise)
|
121
|
-
end
|
122
|
-
|
123
109
|
# @return [String] customized inspect to lessen the amount of clutter
|
124
110
|
def inspect
|
125
111
|
format(
|
@@ -193,6 +179,40 @@ module Airbrake
|
|
193
179
|
return caller_copy if clean_bt.empty?
|
194
180
|
clean_bt
|
195
181
|
end
|
182
|
+
|
183
|
+
# rubocop:disable Metrics/AbcSize
|
184
|
+
def add_default_filters
|
185
|
+
DEFAULT_FILTERS.each { |f| add_filter(f.new) }
|
186
|
+
|
187
|
+
if (whitelist_keys = @config.whitelist_keys).any?
|
188
|
+
add_filter(
|
189
|
+
Airbrake::Filters::KeysWhitelist.new(@config.logger, whitelist_keys)
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
if (blacklist_keys = @config.blacklist_keys).any?
|
194
|
+
add_filter(
|
195
|
+
Airbrake::Filters::KeysBlacklist.new(@config.logger, blacklist_keys)
|
196
|
+
)
|
197
|
+
end
|
198
|
+
|
199
|
+
add_filter(Airbrake::Filters::ContextFilter.new(@context))
|
200
|
+
add_filter(Airbrake::Filters::ExceptionAttributesFilter.new(@config.logger))
|
201
|
+
|
202
|
+
return unless (root_directory = @config.root_directory)
|
203
|
+
[
|
204
|
+
Airbrake::Filters::RootDirectoryFilter,
|
205
|
+
Airbrake::Filters::GitRevisionFilter,
|
206
|
+
Airbrake::Filters::GitRepositoryFilter
|
207
|
+
].each do |filter|
|
208
|
+
add_filter(filter.new(root_directory))
|
209
|
+
end
|
210
|
+
|
211
|
+
add_filter(
|
212
|
+
Airbrake::Filters::GitLastCheckoutFilter.new(@config.logger, root_directory)
|
213
|
+
)
|
214
|
+
end
|
215
|
+
# rubocop:enable Metrics/AbcSize
|
196
216
|
end
|
197
217
|
# rubocop:enable Metrics/ClassLength
|
198
218
|
end
|