airbrake-ruby 4.15.0-java → 5.0.2-java

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby.rb +22 -33
  3. data/lib/airbrake-ruby/async_sender.rb +1 -1
  4. data/lib/airbrake-ruby/backtrace.rb +6 -5
  5. data/lib/airbrake-ruby/config.rb +30 -30
  6. data/lib/airbrake-ruby/config/processor.rb +69 -0
  7. data/lib/airbrake-ruby/config/validator.rb +6 -0
  8. data/lib/airbrake-ruby/file_cache.rb +1 -1
  9. data/lib/airbrake-ruby/filter_chain.rb +1 -0
  10. data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
  11. data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
  12. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -2
  13. data/lib/airbrake-ruby/filters/git_repository_filter.rb +3 -0
  14. data/lib/airbrake-ruby/filters/git_revision_filter.rb +2 -0
  15. data/lib/airbrake-ruby/filters/keys_filter.rb +21 -13
  16. data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
  17. data/lib/airbrake-ruby/filters/sql_filter.rb +4 -4
  18. data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
  19. data/lib/airbrake-ruby/filters/thread_filter.rb +2 -0
  20. data/lib/airbrake-ruby/ignorable.rb +1 -0
  21. data/lib/airbrake-ruby/notice.rb +1 -8
  22. data/lib/airbrake-ruby/notice_notifier.rb +1 -0
  23. data/lib/airbrake-ruby/performance_breakdown.rb +1 -6
  24. data/lib/airbrake-ruby/performance_notifier.rb +2 -15
  25. data/lib/airbrake-ruby/promise.rb +1 -0
  26. data/lib/airbrake-ruby/query.rb +1 -6
  27. data/lib/airbrake-ruby/queue.rb +1 -8
  28. data/lib/airbrake-ruby/remote_settings.rb +145 -0
  29. data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
  30. data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
  31. data/lib/airbrake-ruby/request.rb +1 -8
  32. data/lib/airbrake-ruby/stat.rb +1 -12
  33. data/lib/airbrake-ruby/sync_sender.rb +3 -2
  34. data/lib/airbrake-ruby/tdigest.rb +2 -0
  35. data/lib/airbrake-ruby/thread_pool.rb +1 -0
  36. data/lib/airbrake-ruby/truncator.rb +8 -2
  37. data/lib/airbrake-ruby/version.rb +11 -1
  38. data/spec/airbrake_spec.rb +45 -22
  39. data/spec/backtrace_spec.rb +26 -26
  40. data/spec/code_hunk_spec.rb +2 -2
  41. data/spec/config/processor_spec.rb +125 -0
  42. data/spec/config/validator_spec.rb +18 -1
  43. data/spec/config_spec.rb +11 -32
  44. data/spec/filters/gem_root_filter_spec.rb +4 -4
  45. data/spec/filters/keys_allowlist_spec.rb +1 -0
  46. data/spec/filters/keys_blocklist_spec.rb +10 -0
  47. data/spec/filters/root_directory_filter_spec.rb +4 -4
  48. data/spec/filters/sql_filter_spec.rb +2 -2
  49. data/spec/notice_notifier/options_spec.rb +2 -2
  50. data/spec/notice_notifier_spec.rb +2 -2
  51. data/spec/notice_spec.rb +1 -1
  52. data/spec/performance_breakdown_spec.rb +0 -12
  53. data/spec/performance_notifier_spec.rb +0 -25
  54. data/spec/query_spec.rb +1 -11
  55. data/spec/queue_spec.rb +1 -13
  56. data/spec/remote_settings/callback_spec.rb +141 -0
  57. data/spec/remote_settings/settings_data_spec.rb +348 -0
  58. data/spec/remote_settings_spec.rb +230 -0
  59. data/spec/request_spec.rb +1 -13
  60. data/spec/spec_helper.rb +4 -4
  61. data/spec/stat_spec.rb +0 -9
  62. data/spec/sync_sender_spec.rb +3 -1
  63. metadata +18 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae5dd62f478034e980ccfbc26b0eb53c7696a81f784a0b50643693b7f0d55548
4
- data.tar.gz: 653ff8929bc7199a77c59ead004167a38d214741157282d93e947c3d5ca8ecd6
3
+ metadata.gz: e7353bd2b22422a376f862a0af218a5fd67bd1a5074a759ee233b74bb5986c19
4
+ data.tar.gz: 9f0debfc7e2eb97bd2dd0e263d1e40f81e3c8132d009dfc18a9cfcabf66fe31f
5
5
  SHA512:
6
- metadata.gz: 4f264aa26bed243459d9f5c9eb8827d24ae05d1f9d5cd03416b4e10612e4df1782b2e6ef3cc170db523798e594e1d7d1765a3e9d59fbf81b7955729db9f16cf5
7
- data.tar.gz: 3c3b2312b7945685c6199ecd21f23601b752e1d4234d35461db2f4c7cf0318c24ee263df2536e9cffb7e107002a5a5be10af1cf7eecc16ac65e07cd948f2c68e
6
+ metadata.gz: 07ae0b29054ee4bf1a28d5aea1bc364e675290998dcad5a96ef9a218fa01173abc7577bba534bd10baf5786694aa86a3a2266ba42440947125c7a2dab4e6da5f
7
+ data.tar.gz: dc8eacdeda076da7adffa1a469ed2ffe65e3d78a810cbf38b2e5a55ba584144f343a9cfa9a3c2b1cc036eabe79198045c4dc5e8239dd948c7292f3fba1a3e3fc
@@ -12,6 +12,10 @@ require 'airbrake-ruby/mergeable'
12
12
  require 'airbrake-ruby/grouppable'
13
13
  require 'airbrake-ruby/config'
14
14
  require 'airbrake-ruby/config/validator'
15
+ require 'airbrake-ruby/config/processor'
16
+ require 'airbrake-ruby/remote_settings/callback'
17
+ require 'airbrake-ruby/remote_settings/settings_data'
18
+ require 'airbrake-ruby/remote_settings'
15
19
  require 'airbrake-ruby/promise'
16
20
  require 'airbrake-ruby/thread_pool'
17
21
  require 'airbrake-ruby/sync_sender'
@@ -117,7 +121,15 @@ module Airbrake
117
121
  def configure
118
122
  yield config = Airbrake::Config.instance
119
123
  Airbrake::Loggable.instance = config.logger
120
- process_config_options(config)
124
+
125
+ config_processor = Airbrake::Config::Processor.new(config)
126
+
127
+ config_processor.process_blocklist(notice_notifier)
128
+ config_processor.process_allowlist(notice_notifier)
129
+
130
+ @remote_settings ||= config_processor.process_remote_configuration
131
+
132
+ config_processor.add_filters(notice_notifier)
121
133
  end
122
134
 
123
135
  # @since v4.2.3
@@ -260,8 +272,8 @@ module Airbrake
260
272
  # Airbrake.close
261
273
  # Airbrake.notify('App crashed!') #=> raises Airbrake::Error
262
274
  #
263
- # @return [void]
264
- # rubocop:disable Style/GuardClause, Style/IfUnlessModifier
275
+ # @return [nil]
276
+ # rubocop:disable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
265
277
  def close
266
278
  if defined?(@notice_notifier) && @notice_notifier
267
279
  @notice_notifier.close
@@ -270,8 +282,14 @@ module Airbrake
270
282
  if defined?(@performance_notifier) && @performance_notifier
271
283
  @performance_notifier.close
272
284
  end
285
+
286
+ if defined?(@remote_settings) && @remote_settings
287
+ @remote_settings.stop_polling
288
+ end
289
+
290
+ nil
273
291
  end
274
- # rubocop:enable Style/GuardClause, Style/IfUnlessModifier
292
+ # rubocop:enable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
275
293
 
276
294
  # Pings the Airbrake Deploy API endpoint about the occurred deploy.
277
295
  #
@@ -567,35 +585,6 @@ module Airbrake
567
585
  self.notice_notifier = NoticeNotifier.new
568
586
  self.deploy_notifier = DeployNotifier.new
569
587
  end
570
-
571
- private
572
-
573
- # rubocop:disable Metrics/AbcSize
574
- def process_config_options(config)
575
- if config.blocklist_keys.any?
576
- blocklist = Airbrake::Filters::KeysBlocklist.new(config.blocklist_keys)
577
- notice_notifier.add_filter(blocklist)
578
- end
579
-
580
- if config.allowlist_keys.any?
581
- allowlist = Airbrake::Filters::KeysAllowlist.new(config.allowlist_keys)
582
- notice_notifier.add_filter(allowlist)
583
- end
584
-
585
- return unless config.root_directory
586
-
587
- [
588
- Airbrake::Filters::RootDirectoryFilter,
589
- Airbrake::Filters::GitRevisionFilter,
590
- Airbrake::Filters::GitRepositoryFilter,
591
- Airbrake::Filters::GitLastCheckoutFilter,
592
- ].each do |filter|
593
- next if notice_notifier.has_filter?(filter)
594
-
595
- notice_notifier.add_filter(filter.new(config.root_directory))
596
- end
597
- end
598
- # rubocop:enable Metrics/AbcSize
599
588
  end
600
589
  end
601
590
  # rubocop:enable Metrics/ModuleLength
@@ -16,7 +16,7 @@ module Airbrake
16
16
  #
17
17
  # @param [Hash] payload Whatever needs to be sent
18
18
  # @return [Airbrake::Promise]
19
- def send(payload, promise, endpoint = @config.endpoint)
19
+ def send(payload, promise, endpoint = @config.error_endpoint)
20
20
  unless thread_pool << [payload, promise, endpoint]
21
21
  return promise.reject(
22
22
  "AsyncSender has reached its capacity of #{@config.queue_size}",
@@ -22,7 +22,7 @@ module Airbrake
22
22
  (?<line>\d+) # Matches '43'
23
23
  :in\s
24
24
  `(?<function>.*)' # Matches "`block (3 levels) in <top (required)>'"
25
- \z}x
25
+ \z}x.freeze
26
26
 
27
27
  # @return [Regexp] the pattern that matches JRuby Java stack frames, such
28
28
  # as org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
@@ -39,7 +39,7 @@ module Airbrake
39
39
  :?
40
40
  (?<line>\d+)? # Matches '105'
41
41
  \)
42
- \z}x
42
+ \z}x.freeze
43
43
 
44
44
  # @return [Regexp] the pattern that tries to assume what a generic stack
45
45
  # frame might look like, when exception's backtrace is set manually.
@@ -53,7 +53,7 @@ module Airbrake
53
53
  |
54
54
  :in\s(?<function>.+) # Matches ":in func"
55
55
  )? # ... or nothing
56
- \z}x
56
+ \z}x.freeze
57
57
 
58
58
  # @return [Regexp] the pattern that matches exceptions from PL/SQL such as
59
59
  # ORA-06512: at "STORE.LI_LICENSES_PACK", line 1945
@@ -67,7 +67,7 @@ module Airbrake
67
67
  |
68
68
  #{GENERIC}
69
69
  )
70
- \z/x
70
+ \z/x.freeze
71
71
 
72
72
  # @return [Regexp] the pattern that matches CoffeeScript backtraces
73
73
  # usually coming from Rails & ExecJS
@@ -82,7 +82,7 @@ module Airbrake
82
82
  # Matches the Ruby part of the backtrace
83
83
  #{RUBY}
84
84
  )
85
- \z/x
85
+ \z/x.freeze
86
86
  end
87
87
 
88
88
  # @return [Integer] how many first frames should include code hunks
@@ -95,6 +95,7 @@ module Airbrake
95
95
  # @return [Array<Hash{Symbol=>String,Integer}>] the parsed backtrace
96
96
  def self.parse(exception)
97
97
  return [] if exception.backtrace.nil? || exception.backtrace.none?
98
+
98
99
  parse_backtrace(exception)
99
100
  end
100
101
 
@@ -46,6 +46,17 @@ module Airbrake
46
46
  # @api public
47
47
  attr_accessor :host
48
48
 
49
+ # @since v5.0.0
50
+ alias error_host host
51
+ # @since v5.0.0
52
+ alias error_host= host=
53
+
54
+ # @return [String] the host, which provides the API endpoint to which
55
+ # APM data should be sent
56
+ # @api public
57
+ # @since v5.0.0
58
+ attr_accessor :apm_host
59
+
49
60
  # @return [String, Pathname] the working directory of your project
50
61
  # @api public
51
62
  attr_accessor :root_directory
@@ -71,18 +82,12 @@ module Airbrake
71
82
  # @since v4.15.0
72
83
  attr_accessor :allowlist_keys
73
84
 
74
- # @deprecated Use allowlist_keys instead
75
- alias whitelist_keys allowlist_keys
76
-
77
85
  # @return [Array<String, Symbol, Regexp>] the keys, which should be
78
86
  # filtered
79
87
  # @api public
80
88
  # @since v4.15.0
81
89
  attr_accessor :blocklist_keys
82
90
 
83
- # @deprecated Use blocklist_keys instead
84
- alias blacklist_keys blocklist_keys
85
-
86
91
  # @return [Boolean] true if the library should attach code hunks to each
87
92
  # frame in a backtrace, false otherwise
88
93
  # @api public
@@ -113,6 +118,16 @@ module Airbrake
113
118
  # @since v4.12.0
114
119
  attr_accessor :job_stats
115
120
 
121
+ # @return [Boolean] true if the library should send error reports to
122
+ # Airbrake, false otherwise
123
+ # @api public
124
+ # @since 5.0.0
125
+ attr_accessor :error_notifications
126
+
127
+ # @return [String] the host such as which should be used for fetching remote
128
+ # configuration options (example: "https://bucket-name.s3.amazonaws.com")
129
+ attr_accessor :remote_config_host
130
+
116
131
  class << self
117
132
  # @return [Config]
118
133
  attr_writer :instance
@@ -134,7 +149,9 @@ module Airbrake
134
149
  self.logger = ::Logger.new(File::NULL).tap { |l| l.level = Logger::WARN }
135
150
  self.project_id = user_config[:project_id]
136
151
  self.project_key = user_config[:project_key]
137
- self.host = 'https://api.airbrake.io'
152
+ self.error_host = 'https://api.airbrake.io'
153
+ self.apm_host = 'https://api.airbrake.io'
154
+ self.remote_config_host = 'https://v1-production-notifier-configs.s3.amazonaws.com'
138
155
 
139
156
  self.ignore_environments = []
140
157
 
@@ -153,37 +170,20 @@ module Airbrake
153
170
  self.performance_stats_flush_period = 15
154
171
  self.query_stats = true
155
172
  self.job_stats = true
173
+ self.error_notifications = true
156
174
 
157
175
  merge(user_config)
158
176
  end
159
177
  # rubocop:enable Metrics/AbcSize
160
178
 
161
- def blacklist_keys=(keys)
162
- loc = caller_locations(1..1).first
163
- Kernel.warn(
164
- "#{loc.path}:#{loc.lineno}: warning: blacklist_keys= is deprecated " \
165
- "use blocklist_keys= instead",
166
- )
167
- self.blocklist_keys = keys
168
- end
169
-
170
- def whitelist_keys=(keys)
171
- loc = caller_locations(1..1).first
172
- Kernel.warn(
173
- "#{loc.path}:#{loc.lineno}: warning: whitelist_keys= is deprecated " \
174
- "use allowlist_keys= instead",
175
- )
176
- self.allowlist_keys = keys
177
- end
178
-
179
- # The full URL to the Airbrake Notice API. Based on the +:host+ option.
179
+ # The full URL to the Airbrake Notice API. Based on the +:error_host+ option.
180
180
  # @return [URI] the endpoint address
181
- def endpoint
182
- @endpoint ||=
181
+ def error_endpoint
182
+ @error_endpoint ||=
183
183
  begin
184
- self.host = ('https://' << host) if host !~ %r{\Ahttps?://}
184
+ self.error_host = ('https://' << error_host) if error_host !~ %r{\Ahttps?://}
185
185
  api = "api/v3/projects/#{project_id}/notices"
186
- URI.join(host, api)
186
+ URI.join(error_host, api)
187
187
  end
188
188
  end
189
189
 
@@ -0,0 +1,69 @@
1
+ module Airbrake
2
+ class Config
3
+ # Processor is a helper class, which is responsible for setting default
4
+ # config values, default notifier filters and remote configuration changes.
5
+ #
6
+ # @since 5.0.0
7
+ # @api private
8
+ class Processor
9
+ # @param [Airbrake::Config] config
10
+ # @return [Airbrake::Config::Processor]
11
+ def self.process(config)
12
+ new(config).process
13
+ end
14
+
15
+ # @param [Airbrake::Config] config
16
+ def initialize(config)
17
+ @config = config
18
+ @blocklist_keys = @config.blocklist_keys
19
+ @allowlist_keys = @config.allowlist_keys
20
+ @project_id = @config.project_id
21
+ @poll_callback = Airbrake::RemoteSettings::Callback.new(config)
22
+ end
23
+
24
+ # @param [Airbrake::NoticeNotifier] notifier
25
+ # @return [void]
26
+ def process_blocklist(notifier)
27
+ return if @blocklist_keys.none?
28
+
29
+ blocklist = Airbrake::Filters::KeysBlocklist.new(@blocklist_keys)
30
+ notifier.add_filter(blocklist)
31
+ end
32
+
33
+ # @param [Airbrake::NoticeNotifier] notifier
34
+ # @return [void]
35
+ def process_allowlist(notifier)
36
+ return if @allowlist_keys.none?
37
+
38
+ allowlist = Airbrake::Filters::KeysAllowlist.new(@allowlist_keys)
39
+ notifier.add_filter(allowlist)
40
+ end
41
+
42
+ # @return [Airbrake::RemoteSettings]
43
+ def process_remote_configuration
44
+ return unless @project_id
45
+
46
+ RemoteSettings.poll(@project_id, @config.remote_config_host) do |data|
47
+ @poll_callback.call(data)
48
+ end
49
+ end
50
+
51
+ # @param [Airbrake::NoticeNotifier] notifier
52
+ # @return [void]
53
+ def add_filters(notifier)
54
+ return unless @config.root_directory
55
+
56
+ [
57
+ Airbrake::Filters::RootDirectoryFilter,
58
+ Airbrake::Filters::GitRevisionFilter,
59
+ Airbrake::Filters::GitRepositoryFilter,
60
+ Airbrake::Filters::GitLastCheckoutFilter,
61
+ ].each do |filter|
62
+ next if notifier.has_filter?(filter)
63
+
64
+ notifier.add_filter(filter.new(@config.root_directory))
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -44,6 +44,10 @@ module Airbrake
44
44
  def check_notify_ability(config)
45
45
  promise = Airbrake::Promise.new
46
46
 
47
+ unless config.error_notifications
48
+ return promise.reject('error notifications are disabled')
49
+ end
50
+
47
51
  if ignored_environment?(config)
48
52
  return promise.reject(
49
53
  "current environment '#{config.environment}' is ignored",
@@ -57,12 +61,14 @@ module Airbrake
57
61
 
58
62
  def valid_project_id?(config)
59
63
  return true if config.project_id.to_i > 0
64
+
60
65
  false
61
66
  end
62
67
 
63
68
  def valid_project_key?(config)
64
69
  return false unless config.project_key.is_a?(String)
65
70
  return false if config.project_key.empty?
71
+
66
72
  true
67
73
  end
68
74
 
@@ -40,7 +40,7 @@ module Airbrake
40
40
  data.empty?
41
41
  end
42
42
 
43
- # @since ?.?.?
43
+ # @since 4.7.0
44
44
  # @return [void]
45
45
  def self.reset
46
46
  @data = {}
@@ -70,6 +70,7 @@ module Airbrake
70
70
  def refine(notice)
71
71
  @filters.each do |filter|
72
72
  break if notice.ignored?
73
+
73
74
  filter.call(notice)
74
75
  end
75
76
  end
@@ -24,6 +24,7 @@ module Airbrake
24
24
 
25
25
  def git_version(spec)
26
26
  return unless spec.respond_to?(:git_version) || spec.git_version
27
+
27
28
  spec.git_version.to_s
28
29
  end
29
30
  end
@@ -23,6 +23,7 @@ module Airbrake
23
23
  # If the frame is unparseable, then 'file' is nil, thus nothing to
24
24
  # filter (all frame's data is in 'function' instead).
25
25
  next unless (file = frame[:file])
26
+
26
27
  frame[:file] = file.sub(/\A#{gem_path}/, GEM_ROOT_LABEL)
27
28
  end
28
29
  end
@@ -41,12 +41,12 @@ module Airbrake
41
41
 
42
42
  return unless File.exist?(@git_path)
43
43
  return unless (checkout = last_checkout)
44
+
44
45
  notice[:context][:lastCheckout] = checkout
45
46
  end
46
47
 
47
48
  private
48
49
 
49
- # rubocop:disable Metrics/AbcSize
50
50
  def last_checkout
51
51
  return unless (line = last_checkout_line)
52
52
 
@@ -66,7 +66,6 @@ module Airbrake
66
66
  time: timestamp(parts[-2].to_i),
67
67
  }
68
68
  end
69
- # rubocop:enable Metrics/AbcSize
70
69
 
71
70
  def last_checkout_line
72
71
  head_path = File.join(@git_path, 'logs', 'HEAD')
@@ -18,6 +18,7 @@ module Airbrake
18
18
  # @macro call_filter
19
19
  def call(notice)
20
20
  return if notice[:context].key?(:repository)
21
+
21
22
  attach_repository(notice)
22
23
  end
23
24
 
@@ -39,6 +40,7 @@ module Airbrake
39
40
  end
40
41
 
41
42
  return unless @repository
43
+
42
44
  notice[:context][:repository] = @repository
43
45
  end
44
46
 
@@ -46,6 +48,7 @@ module Airbrake
46
48
 
47
49
  def detect_git_version
48
50
  return unless which('git')
51
+
49
52
  Gem::Version.new(`git --version`.split[2])
50
53
  end
51
54