airbrake-ruby 4.1.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/airbrake-ruby/async_sender.rb +22 -96
- data/lib/airbrake-ruby/backtrace.rb +8 -7
- data/lib/airbrake-ruby/benchmark.rb +39 -0
- data/lib/airbrake-ruby/code_hunk.rb +1 -1
- data/lib/airbrake-ruby/config/processor.rb +84 -0
- data/lib/airbrake-ruby/config/validator.rb +9 -3
- data/lib/airbrake-ruby/config.rb +76 -20
- data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
- data/lib/airbrake-ruby/file_cache.rb +6 -0
- 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 +30 -6
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +4 -2
- 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 +2 -2
- data/lib/airbrake-ruby/mergeable.rb +12 -0
- data/lib/airbrake-ruby/monotonic_time.rb +48 -0
- data/lib/airbrake-ruby/notice.rb +10 -20
- data/lib/airbrake-ruby/notice_notifier.rb +23 -42
- data/lib/airbrake-ruby/performance_breakdown.rb +52 -0
- data/lib/airbrake-ruby/performance_notifier.rb +126 -49
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +26 -11
- data/lib/airbrake-ruby/queue.rb +65 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +120 -0
- data/lib/airbrake-ruby/remote_settings.rb +145 -0
- data/lib/airbrake-ruby/request.rb +20 -6
- data/lib/airbrake-ruby/stashable.rb +15 -0
- data/lib/airbrake-ruby/stat.rb +34 -24
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +43 -58
- data/lib/airbrake-ruby/thread_pool.rb +138 -0
- data/lib/airbrake-ruby/timed_trace.rb +58 -0
- data/lib/airbrake-ruby/truncator.rb +10 -4
- data/lib/airbrake-ruby/version.rb +11 -1
- data/lib/airbrake-ruby.rb +219 -53
- data/spec/airbrake_spec.rb +428 -9
- data/spec/async_sender_spec.rb +26 -110
- data/spec/backtrace_spec.rb +44 -44
- data/spec/benchmark_spec.rb +33 -0
- data/spec/code_hunk_spec.rb +11 -11
- data/spec/config/processor_spec.rb +209 -0
- data/spec/config/validator_spec.rb +23 -6
- data/spec/config_spec.rb +77 -7
- data/spec/deploy_notifier_spec.rb +2 -2
- data/spec/{file_cache.rb → file_cache_spec.rb} +2 -4
- 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 +13 -11
- 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 +110 -55
- data/spec/filters/system_exit_filter_spec.rb +1 -1
- data/spec/filters/thread_filter_spec.rb +33 -31
- data/spec/fixtures/project_root/code.rb +9 -9
- data/spec/loggable_spec.rb +17 -0
- data/spec/monotonic_time_spec.rb +23 -0
- data/spec/{notice_notifier_spec → notice_notifier}/options_spec.rb +19 -21
- data/spec/notice_notifier_spec.rb +20 -80
- data/spec/notice_spec.rb +9 -11
- data/spec/performance_breakdown_spec.rb +11 -0
- data/spec/performance_notifier_spec.rb +360 -85
- data/spec/query_spec.rb +11 -0
- data/spec/queue_spec.rb +18 -0
- data/spec/remote_settings/settings_data_spec.rb +365 -0
- data/spec/remote_settings_spec.rb +230 -0
- data/spec/request_spec.rb +9 -0
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +9 -13
- data/spec/stashable_spec.rb +23 -0
- data/spec/stat_spec.rb +17 -15
- data/spec/sync_sender_spec.rb +14 -12
- data/spec/tdigest_spec.rb +6 -6
- data/spec/thread_pool_spec.rb +187 -0
- data/spec/timed_trace_spec.rb +125 -0
- data/spec/truncator_spec.rb +12 -12
- metadata +55 -18
@@ -0,0 +1,58 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# TimedTrace represents a chunk of code performance of which was measured and
|
3
|
+
# stored under a label. The chunk is called a "span".
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# timed_trace = TimedTrace.new
|
7
|
+
# timed_trace.span('http request') do
|
8
|
+
# http.get('example.com')
|
9
|
+
# end
|
10
|
+
# timed_trace.spans #=> { 'http request' => 0.123 }
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
# @since v4.3.0
|
14
|
+
class TimedTrace
|
15
|
+
# @param [String] label
|
16
|
+
# @return [Airbrake::TimedTrace]
|
17
|
+
def self.span(label, &block)
|
18
|
+
new.tap { |timed_trace| timed_trace.span(label, &block) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@spans = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] label
|
26
|
+
# @return [Boolean]
|
27
|
+
def span(label)
|
28
|
+
start_span(label)
|
29
|
+
yield
|
30
|
+
stop_span(label)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [String] label
|
34
|
+
# @return [Boolean]
|
35
|
+
def start_span(label)
|
36
|
+
return false if @spans.key?(label)
|
37
|
+
|
38
|
+
@spans[label] = Airbrake::Benchmark.new
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [String] label
|
43
|
+
# @return [Boolean]
|
44
|
+
def stop_span(label)
|
45
|
+
return false unless @spans.key?(label)
|
46
|
+
|
47
|
+
@spans[label].stop
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Hash<String=>Float>]
|
52
|
+
def spans
|
53
|
+
@spans.each_with_object({}) do |(label, benchmark), new_spans|
|
54
|
+
new_spans[label] = benchmark.duration
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -12,6 +12,10 @@ module Airbrake
|
|
12
12
|
# strings with +ENCODING_OPTIONS+
|
13
13
|
TEMP_ENCODING = 'utf-16'.freeze
|
14
14
|
|
15
|
+
# @return [Array<Encoding>] encodings that are eligible for fixing invalid
|
16
|
+
# characters
|
17
|
+
SUPPORTED_ENCODINGS = [Encoding::UTF_8, Encoding::ASCII].freeze
|
18
|
+
|
15
19
|
# @return [String] what to append when something is a circular reference
|
16
20
|
CIRCULAR = '[Circular]'.freeze
|
17
21
|
|
@@ -35,6 +39,7 @@ module Airbrake
|
|
35
39
|
def truncate(object, seen = Set.new)
|
36
40
|
if seen.include?(object.object_id)
|
37
41
|
return CIRCULAR if CIRCULAR_TYPES.any? { |t| object.is_a?(t) }
|
42
|
+
|
38
43
|
return object
|
39
44
|
end
|
40
45
|
truncate_object(object, seen << object.object_id)
|
@@ -63,6 +68,7 @@ module Airbrake
|
|
63
68
|
def truncate_string(str)
|
64
69
|
fixed_str = replace_invalid_characters(str)
|
65
70
|
return fixed_str if fixed_str.length <= @max_size
|
71
|
+
|
66
72
|
(fixed_str.slice(0, @max_size) + TRUNCATED).freeze
|
67
73
|
end
|
68
74
|
|
@@ -76,6 +82,7 @@ module Airbrake
|
|
76
82
|
truncated_hash = {}
|
77
83
|
hash.each_with_index do |(key, val), idx|
|
78
84
|
break if idx + 1 > @max_size
|
85
|
+
|
79
86
|
truncated_hash[key] = truncate(val, seen)
|
80
87
|
end
|
81
88
|
|
@@ -103,13 +110,12 @@ module Airbrake
|
|
103
110
|
# @return [String] a UTF-8 encoded string
|
104
111
|
# @see https://github.com/flori/json/commit/3e158410e81f94dbbc3da6b7b35f4f64983aa4e3
|
105
112
|
def replace_invalid_characters(str)
|
106
|
-
|
107
|
-
utf8_string = (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII)
|
113
|
+
utf8_string = SUPPORTED_ENCODINGS.include?(str.encoding)
|
108
114
|
return str if utf8_string && str.valid_encoding?
|
109
115
|
|
110
116
|
temp_str = str.dup
|
111
|
-
temp_str.encode!(TEMP_ENCODING, ENCODING_OPTIONS) if utf8_string
|
112
|
-
temp_str.encode!('utf-8', ENCODING_OPTIONS)
|
117
|
+
temp_str.encode!(TEMP_ENCODING, **ENCODING_OPTIONS) if utf8_string
|
118
|
+
temp_str.encode!('utf-8', **ENCODING_OPTIONS)
|
113
119
|
end
|
114
120
|
end
|
115
121
|
end
|
@@ -2,5 +2,15 @@
|
|
2
2
|
# More information: http://semver.org/
|
3
3
|
module Airbrake
|
4
4
|
# @return [String] the library version
|
5
|
-
|
5
|
+
# @api public
|
6
|
+
AIRBRAKE_RUBY_VERSION = '5.0.0'.freeze
|
7
|
+
|
8
|
+
# @return [Hash{Symbol=>String}] the information about the notifier library
|
9
|
+
# @since 5.0.0
|
10
|
+
# @api public
|
11
|
+
NOTIFIER_INFO = {
|
12
|
+
name: 'airbrake-ruby'.freeze,
|
13
|
+
version: Airbrake::AIRBRAKE_RUBY_VERSION,
|
14
|
+
url: 'https://github.com/airbrake/airbrake-ruby'.freeze,
|
15
|
+
}.freeze
|
6
16
|
end
|
data/lib/airbrake-ruby.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
require 'net/https'
|
2
2
|
require 'logger'
|
3
3
|
require 'json'
|
4
|
-
require 'thread'
|
5
4
|
require 'set'
|
6
5
|
require 'socket'
|
7
6
|
require 'time'
|
8
7
|
|
9
8
|
require 'airbrake-ruby/version'
|
10
9
|
require 'airbrake-ruby/loggable'
|
10
|
+
require 'airbrake-ruby/stashable'
|
11
|
+
require 'airbrake-ruby/mergeable'
|
12
|
+
require 'airbrake-ruby/grouppable'
|
11
13
|
require 'airbrake-ruby/config'
|
12
14
|
require 'airbrake-ruby/config/validator'
|
15
|
+
require 'airbrake-ruby/config/processor'
|
16
|
+
require 'airbrake-ruby/remote_settings/settings_data'
|
17
|
+
require 'airbrake-ruby/remote_settings'
|
13
18
|
require 'airbrake-ruby/promise'
|
19
|
+
require 'airbrake-ruby/thread_pool'
|
14
20
|
require 'airbrake-ruby/sync_sender'
|
15
21
|
require 'airbrake-ruby/async_sender'
|
16
22
|
require 'airbrake-ruby/response'
|
@@ -21,8 +27,8 @@ require 'airbrake-ruby/notice'
|
|
21
27
|
require 'airbrake-ruby/backtrace'
|
22
28
|
require 'airbrake-ruby/truncator'
|
23
29
|
require 'airbrake-ruby/filters/keys_filter'
|
24
|
-
require 'airbrake-ruby/filters/
|
25
|
-
require 'airbrake-ruby/filters/
|
30
|
+
require 'airbrake-ruby/filters/keys_allowlist'
|
31
|
+
require 'airbrake-ruby/filters/keys_blocklist'
|
26
32
|
require 'airbrake-ruby/filters/gem_root_filter'
|
27
33
|
require 'airbrake-ruby/filters/system_exit_filter'
|
28
34
|
require 'airbrake-ruby/filters/root_directory_filter'
|
@@ -46,6 +52,11 @@ require 'airbrake-ruby/time_truncate'
|
|
46
52
|
require 'airbrake-ruby/tdigest'
|
47
53
|
require 'airbrake-ruby/query'
|
48
54
|
require 'airbrake-ruby/request'
|
55
|
+
require 'airbrake-ruby/performance_breakdown'
|
56
|
+
require 'airbrake-ruby/benchmark'
|
57
|
+
require 'airbrake-ruby/monotonic_time'
|
58
|
+
require 'airbrake-ruby/timed_trace'
|
59
|
+
require 'airbrake-ruby/queue'
|
49
60
|
|
50
61
|
# Airbrake is a thin wrapper around instances of the notifier classes (such as
|
51
62
|
# notice, performance & deploy notifiers). It creates a way to access them via a
|
@@ -63,6 +74,7 @@ require 'airbrake-ruby/request'
|
|
63
74
|
#
|
64
75
|
# @since v1.0.0
|
65
76
|
# @api public
|
77
|
+
# rubocop:disable Metrics/ModuleLength
|
66
78
|
module Airbrake
|
67
79
|
# The general error that this library uses when it wants to raise.
|
68
80
|
Error = Class.new(StandardError)
|
@@ -74,14 +86,26 @@ module Airbrake
|
|
74
86
|
# special cases where we need to work around older implementations
|
75
87
|
JRUBY = (RUBY_ENGINE == 'jruby')
|
76
88
|
|
77
|
-
#
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
89
|
+
# @return [Boolean] true if this Ruby supports safe levels and tainting,
|
90
|
+
# to guard against using deprecated or unsupported features.
|
91
|
+
HAS_SAFE_LEVEL = (
|
92
|
+
RUBY_ENGINE == 'ruby' &&
|
93
|
+
Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7')
|
94
|
+
)
|
83
95
|
|
84
96
|
class << self
|
97
|
+
# @since v4.2.3
|
98
|
+
# @api private
|
99
|
+
attr_writer :performance_notifier
|
100
|
+
|
101
|
+
# @since v4.2.3
|
102
|
+
# @api private
|
103
|
+
attr_writer :notice_notifier
|
104
|
+
|
105
|
+
# @since v4.2.3
|
106
|
+
# @api private
|
107
|
+
attr_writer :deploy_notifier
|
108
|
+
|
85
109
|
# Configures the Airbrake notifier.
|
86
110
|
#
|
87
111
|
# @example
|
@@ -90,28 +114,45 @@ module Airbrake
|
|
90
114
|
# c.project_key = 'fd04e13d806a90f96614ad8e529b2822'
|
91
115
|
# end
|
92
116
|
#
|
93
|
-
# @yield [config]
|
117
|
+
# @yield [config]
|
94
118
|
# @yieldparam config [Airbrake::Config]
|
95
119
|
# @return [void]
|
96
|
-
# @raise [Airbrake::Error] when trying to reconfigure already
|
97
|
-
# existing notifier
|
98
|
-
# @raise [Airbrake::Error] when either +project_id+ or +project_key+
|
99
|
-
# is missing (or both)
|
100
|
-
# @note There's no way to read config values outside of this library
|
101
120
|
def configure
|
102
121
|
yield config = Airbrake::Config.instance
|
122
|
+
Airbrake::Loggable.instance = config.logger
|
103
123
|
|
104
|
-
|
105
|
-
raise Airbrake::Error, result.value['error']
|
106
|
-
end
|
124
|
+
config_processor = Airbrake::Config::Processor.new(config)
|
107
125
|
|
108
|
-
|
126
|
+
config_processor.process_blocklist(notice_notifier)
|
127
|
+
config_processor.process_allowlist(notice_notifier)
|
128
|
+
|
129
|
+
@remote_settings ||= config_processor.process_remote_configuration
|
130
|
+
|
131
|
+
config_processor.add_filters(notice_notifier)
|
132
|
+
end
|
133
|
+
|
134
|
+
# @since v4.2.3
|
135
|
+
# @api private
|
136
|
+
def performance_notifier
|
137
|
+
@performance_notifier ||= PerformanceNotifier.new
|
138
|
+
end
|
139
|
+
|
140
|
+
# @since v4.2.3
|
141
|
+
# @api private
|
142
|
+
def notice_notifier
|
143
|
+
@notice_notifier ||= NoticeNotifier.new
|
144
|
+
end
|
145
|
+
|
146
|
+
# @since v4.2.3
|
147
|
+
# @api private
|
148
|
+
def deploy_notifier
|
149
|
+
@deploy_notifier ||= DeployNotifier.new
|
109
150
|
end
|
110
151
|
|
111
152
|
# @return [Boolean] true if the notifier was configured, false otherwise
|
112
153
|
# @since v2.3.0
|
113
154
|
def configured?
|
114
|
-
@notice_notifier.configured?
|
155
|
+
@notice_notifier && @notice_notifier.configured?
|
115
156
|
end
|
116
157
|
|
117
158
|
# Sends an exception to Airbrake asynchronously.
|
@@ -136,7 +177,7 @@ module Airbrake
|
|
136
177
|
# @return [Airbrake::Promise]
|
137
178
|
# @see .notify_sync
|
138
179
|
def notify(exception, params = {}, &block)
|
139
|
-
|
180
|
+
notice_notifier.notify(exception, params, &block)
|
140
181
|
end
|
141
182
|
|
142
183
|
# Sends an exception to Airbrake synchronously.
|
@@ -156,7 +197,7 @@ module Airbrake
|
|
156
197
|
# @return [Airbrake::Promise] the reponse from the server
|
157
198
|
# @see .notify
|
158
199
|
def notify_sync(exception, params = {}, &block)
|
159
|
-
|
200
|
+
notice_notifier.notify_sync(exception, params, &block)
|
160
201
|
end
|
161
202
|
|
162
203
|
# Runs a callback before {.notify} or {.notify_sync} kicks in. This is
|
@@ -184,7 +225,7 @@ module Airbrake
|
|
184
225
|
# @yieldreturn [void]
|
185
226
|
# @return [void]
|
186
227
|
def add_filter(filter = nil, &block)
|
187
|
-
|
228
|
+
notice_notifier.add_filter(filter, &block)
|
188
229
|
end
|
189
230
|
|
190
231
|
# Deletes a filter added via {Airbrake#add_filter}.
|
@@ -201,7 +242,7 @@ module Airbrake
|
|
201
242
|
# @since v3.1.0
|
202
243
|
# @note This method cannot delete filters assigned via the Proc form.
|
203
244
|
def delete_filter(filter_class)
|
204
|
-
|
245
|
+
notice_notifier.delete_filter(filter_class)
|
205
246
|
end
|
206
247
|
|
207
248
|
# Builds an Airbrake notice. This is useful, if you want to add or modify a
|
@@ -219,7 +260,7 @@ module Airbrake
|
|
219
260
|
# @return [Airbrake::Notice] the notice built with help of the given
|
220
261
|
# arguments
|
221
262
|
def build_notice(exception, params = {})
|
222
|
-
|
263
|
+
notice_notifier.build_notice(exception, params)
|
223
264
|
end
|
224
265
|
|
225
266
|
# Makes the notice notifier a no-op, which means you cannot use the
|
@@ -230,10 +271,24 @@ module Airbrake
|
|
230
271
|
# Airbrake.close
|
231
272
|
# Airbrake.notify('App crashed!') #=> raises Airbrake::Error
|
232
273
|
#
|
233
|
-
# @return [
|
274
|
+
# @return [nil]
|
275
|
+
# rubocop:disable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
|
234
276
|
def close
|
235
|
-
@notice_notifier
|
277
|
+
if defined?(@notice_notifier) && @notice_notifier
|
278
|
+
@notice_notifier.close
|
279
|
+
end
|
280
|
+
|
281
|
+
if defined?(@performance_notifier) && @performance_notifier
|
282
|
+
@performance_notifier.close
|
283
|
+
end
|
284
|
+
|
285
|
+
if defined?(@remote_settings) && @remote_settings
|
286
|
+
@remote_settings.stop_polling
|
287
|
+
end
|
288
|
+
|
289
|
+
nil
|
236
290
|
end
|
291
|
+
# rubocop:enable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
|
237
292
|
|
238
293
|
# Pings the Airbrake Deploy API endpoint about the occurred deploy.
|
239
294
|
#
|
@@ -245,7 +300,7 @@ module Airbrake
|
|
245
300
|
# @option deploy_info [Symbol] :version
|
246
301
|
# @return [void]
|
247
302
|
def notify_deploy(deploy_info)
|
248
|
-
|
303
|
+
deploy_notifier.notify(deploy_info)
|
249
304
|
end
|
250
305
|
|
251
306
|
# Merges +context+ with the current context.
|
@@ -293,12 +348,11 @@ module Airbrake
|
|
293
348
|
# @param [Hash{Symbol=>Object}] context
|
294
349
|
# @return [void]
|
295
350
|
def merge_context(context)
|
296
|
-
|
351
|
+
notice_notifier.merge_context(context)
|
297
352
|
end
|
298
353
|
|
299
|
-
# Increments request statistics of a certain +route+
|
300
|
-
#
|
301
|
-
# +status_code+.
|
354
|
+
# Increments request statistics of a certain +route+ invoked with +method+,
|
355
|
+
# which returned +status_code+.
|
302
356
|
#
|
303
357
|
# After a certain amount of time (n seconds) the aggregated route
|
304
358
|
# information will be sent to Airbrake.
|
@@ -311,8 +365,7 @@ module Airbrake
|
|
311
365
|
# func: 'do_stuff',
|
312
366
|
# file: 'app/models/foo.rb',
|
313
367
|
# line: 452,
|
314
|
-
#
|
315
|
-
# end_time: Time.now
|
368
|
+
# timing: 123.45 # ms
|
316
369
|
# )
|
317
370
|
#
|
318
371
|
# @param [Hash{Symbol=>Object}] request_info
|
@@ -326,18 +379,31 @@ module Airbrake
|
|
326
379
|
# called the query (optional)
|
327
380
|
# @option request_info [Integer] :line The line that executes the query
|
328
381
|
# (optional)
|
329
|
-
# @option request_info [
|
330
|
-
#
|
382
|
+
# @option request_info [Float] :timing How much time it took to process the
|
383
|
+
# request (in ms)
|
384
|
+
# @param [Hash] stash What needs to be appeneded to the stash, so it's
|
385
|
+
# available in filters
|
331
386
|
# @return [void]
|
332
387
|
# @since v3.0.0
|
333
388
|
# @see Airbrake::PerformanceNotifier#notify
|
334
|
-
def notify_request(request_info)
|
335
|
-
|
389
|
+
def notify_request(request_info, stash = {})
|
390
|
+
request = Request.new(**request_info)
|
391
|
+
request.stash.merge!(stash)
|
392
|
+
performance_notifier.notify(request)
|
393
|
+
end
|
394
|
+
|
395
|
+
# Synchronously increments request statistics of a certain +route+ invoked
|
396
|
+
# with +method+, which returned +status_code+.
|
397
|
+
# @since v4.10.0
|
398
|
+
# @see .notify_request
|
399
|
+
def notify_request_sync(request_info, stash = {})
|
400
|
+
request = Request.new(**request_info)
|
401
|
+
request.stash.merge!(stash)
|
402
|
+
performance_notifier.notify_sync(request)
|
336
403
|
end
|
337
404
|
|
338
|
-
# Increments SQL statistics of a certain +query
|
339
|
-
#
|
340
|
-
# provided, the query is grouped by these parameters.
|
405
|
+
# Increments SQL statistics of a certain +query+. When +method+ and +route+
|
406
|
+
# are provided, the query is grouped by these parameters.
|
341
407
|
#
|
342
408
|
# After a certain amount of time (n seconds) the aggregated query
|
343
409
|
# information will be sent to Airbrake.
|
@@ -347,24 +413,112 @@ module Airbrake
|
|
347
413
|
# method: 'GET',
|
348
414
|
# route: '/things',
|
349
415
|
# query: 'SELECT * FROM things',
|
350
|
-
#
|
351
|
-
# end_time: Time.now
|
416
|
+
# timing: 123.45 # ms
|
352
417
|
# )
|
353
418
|
#
|
354
419
|
# @param [Hash{Symbol=>Object}] query_info
|
355
|
-
# @option
|
356
|
-
# @option request_info [String] :method The HTTP method that triggered this
|
420
|
+
# @option query_info [String] :method The HTTP method that triggered this
|
357
421
|
# SQL query (optional)
|
358
|
-
# @option
|
422
|
+
# @option query_info [String] :route The route that triggered this SQL
|
359
423
|
# query (optional)
|
360
|
-
# @option
|
361
|
-
# @option
|
362
|
-
#
|
424
|
+
# @option query_info [String] :query The query that was executed
|
425
|
+
# @option query_info [Float] :timing How much time it took to process the
|
426
|
+
# query (in ms)
|
427
|
+
# @param [Hash] stash What needs to be appeneded to the stash, so it's
|
428
|
+
# available in filters
|
363
429
|
# @return [void]
|
364
430
|
# @since v3.2.0
|
365
431
|
# @see Airbrake::PerformanceNotifier#notify
|
366
|
-
def notify_query(query_info)
|
367
|
-
|
432
|
+
def notify_query(query_info, stash = {})
|
433
|
+
query = Query.new(**query_info)
|
434
|
+
query.stash.merge!(stash)
|
435
|
+
performance_notifier.notify(query)
|
436
|
+
end
|
437
|
+
|
438
|
+
# Synchronously increments SQL statistics of a certain +query+. When
|
439
|
+
# +method+ and +route+ are provided, the query is grouped by these
|
440
|
+
# parameters.
|
441
|
+
# @since v4.10.0
|
442
|
+
# @see .notify_query
|
443
|
+
def notify_query_sync(query_info, stash = {})
|
444
|
+
query = Query.new(**query_info)
|
445
|
+
query.stash.merge!(stash)
|
446
|
+
performance_notifier.notify_sync(query)
|
447
|
+
end
|
448
|
+
|
449
|
+
# Increments performance breakdown statistics of a certain route.
|
450
|
+
#
|
451
|
+
# @example
|
452
|
+
# Airbrake.notify_request(
|
453
|
+
# method: 'POST',
|
454
|
+
# route: '/thing/:id/create',
|
455
|
+
# response_type: 'json',
|
456
|
+
# groups: { db: 24.0, view: 0.4 }, # ms
|
457
|
+
# timing: 123.45 # ms
|
458
|
+
# )
|
459
|
+
#
|
460
|
+
# @param [Hash{Symbol=>Object}] breakdown_info
|
461
|
+
# @option breakdown_info [String] :method HTTP method
|
462
|
+
# @option breakdown_info [String] :route
|
463
|
+
# @option breakdown_info [String] :response_type
|
464
|
+
# @option breakdown_info [Array<Hash{Symbol=>Float}>] :groups
|
465
|
+
# @option breakdown_info [Float] :timing How much time it took to process
|
466
|
+
# the performance breakdown (in ms)
|
467
|
+
# @param [Hash] stash What needs to be appeneded to the stash, so it's
|
468
|
+
# available in filters
|
469
|
+
# @return [void]
|
470
|
+
# @since v4.2.0
|
471
|
+
def notify_performance_breakdown(breakdown_info, stash = {})
|
472
|
+
performance_breakdown = PerformanceBreakdown.new(**breakdown_info)
|
473
|
+
performance_breakdown.stash.merge!(stash)
|
474
|
+
performance_notifier.notify(performance_breakdown)
|
475
|
+
end
|
476
|
+
|
477
|
+
# Increments performance breakdown statistics of a certain route
|
478
|
+
# synchronously.
|
479
|
+
# @since v4.10.0
|
480
|
+
# @see .notify_performance_breakdown
|
481
|
+
def notify_performance_breakdown_sync(breakdown_info, stash = {})
|
482
|
+
performance_breakdown = PerformanceBreakdown.new(**breakdown_info)
|
483
|
+
performance_breakdown.stash.merge!(stash)
|
484
|
+
performance_notifier.notify_sync(performance_breakdown)
|
485
|
+
end
|
486
|
+
|
487
|
+
# Increments statistics of a certain queue (worker).
|
488
|
+
#
|
489
|
+
# @example
|
490
|
+
# Airbrake.notify_queue(
|
491
|
+
# queue: 'emails',
|
492
|
+
# error_count: 1,
|
493
|
+
# groups: { redis: 24.0, sql: 0.4 } # ms
|
494
|
+
# )
|
495
|
+
#
|
496
|
+
# @param [Hash{Symbol=>Object}] queue_info
|
497
|
+
# @option queue_info [String] :queue The name of the queue/worker
|
498
|
+
# @option queue_info [Integer] :error_count How many times this worker
|
499
|
+
# failed
|
500
|
+
# @option queue_info [Array<Hash{Symbol=>Float}>] :groups Where the job
|
501
|
+
# spent its time
|
502
|
+
# @option breakdown_info [Float] :timing How much time it took to process
|
503
|
+
# the queue (in ms)
|
504
|
+
# @param [Hash] stash What needs to be appended to the stash, so it's
|
505
|
+
# available in filters
|
506
|
+
# @return [void]
|
507
|
+
# @since v4.9.0
|
508
|
+
# @see .notify_queue_sync
|
509
|
+
def notify_queue(queue_info, stash = {})
|
510
|
+
queue = Queue.new(**queue_info)
|
511
|
+
queue.stash.merge!(stash)
|
512
|
+
performance_notifier.notify(queue)
|
513
|
+
end
|
514
|
+
|
515
|
+
# Increments statistics of a certain queue (worker) synchronously.
|
516
|
+
# @since v4.10.0
|
517
|
+
# @see .notify_queue
|
518
|
+
def notify_queue_sync(queue_info, stash = {})
|
519
|
+
queue = Queue.new(**queue_info)
|
520
|
+
queue.stash.merge!(stash)
|
521
|
+
performance_notifier.notify_sync(queue)
|
368
522
|
end
|
369
523
|
|
370
524
|
# Runs a callback before {.notify_request} or {.notify_query} kicks in. This
|
@@ -399,7 +553,7 @@ module Airbrake
|
|
399
553
|
# @since v3.2.0
|
400
554
|
# @see Airbrake::PerformanceNotifier#add_filter
|
401
555
|
def add_performance_filter(filter = nil, &block)
|
402
|
-
|
556
|
+
performance_notifier.add_filter(filter, &block)
|
403
557
|
end
|
404
558
|
|
405
559
|
# Deletes a filter added via {Airbrake#add_performance_filter}.
|
@@ -417,7 +571,19 @@ module Airbrake
|
|
417
571
|
# @note This method cannot delete filters assigned via the Proc form.
|
418
572
|
# @see Airbrake::PerformanceNotifier#delete_filter
|
419
573
|
def delete_performance_filter(filter_class)
|
420
|
-
|
574
|
+
performance_notifier.delete_filter(filter_class)
|
575
|
+
end
|
576
|
+
|
577
|
+
# Resets all notifiers, including its filters
|
578
|
+
# @return [void]
|
579
|
+
# @since v4.2.2
|
580
|
+
def reset
|
581
|
+
close
|
582
|
+
|
583
|
+
self.performance_notifier = PerformanceNotifier.new
|
584
|
+
self.notice_notifier = NoticeNotifier.new
|
585
|
+
self.deploy_notifier = DeployNotifier.new
|
421
586
|
end
|
422
587
|
end
|
423
588
|
end
|
589
|
+
# rubocop:enable Metrics/ModuleLength
|