airbrake-ruby 5.0.0.rc.2 → 5.0.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby/backtrace.rb +6 -5
  3. data/lib/airbrake-ruby/config.rb +8 -36
  4. data/lib/airbrake-ruby/config/processor.rb +7 -3
  5. data/lib/airbrake-ruby/config/validator.rb +2 -0
  6. data/lib/airbrake-ruby/file_cache.rb +1 -1
  7. data/lib/airbrake-ruby/filter_chain.rb +1 -0
  8. data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
  9. data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
  10. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -2
  11. data/lib/airbrake-ruby/filters/git_repository_filter.rb +3 -0
  12. data/lib/airbrake-ruby/filters/git_revision_filter.rb +2 -0
  13. data/lib/airbrake-ruby/filters/keys_filter.rb +21 -13
  14. data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
  15. data/lib/airbrake-ruby/filters/sql_filter.rb +4 -4
  16. data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
  17. data/lib/airbrake-ruby/filters/thread_filter.rb +2 -0
  18. data/lib/airbrake-ruby/ignorable.rb +1 -0
  19. data/lib/airbrake-ruby/notice_notifier.rb +1 -0
  20. data/lib/airbrake-ruby/performance_breakdown.rb +1 -6
  21. data/lib/airbrake-ruby/performance_notifier.rb +1 -14
  22. data/lib/airbrake-ruby/promise.rb +1 -0
  23. data/lib/airbrake-ruby/query.rb +1 -6
  24. data/lib/airbrake-ruby/queue.rb +1 -8
  25. data/lib/airbrake-ruby/remote_settings.rb +7 -5
  26. data/lib/airbrake-ruby/remote_settings/settings_data.rb +13 -9
  27. data/lib/airbrake-ruby/request.rb +1 -8
  28. data/lib/airbrake-ruby/stat.rb +1 -12
  29. data/lib/airbrake-ruby/sync_sender.rb +1 -0
  30. data/lib/airbrake-ruby/tdigest.rb +2 -0
  31. data/lib/airbrake-ruby/thread_pool.rb +1 -0
  32. data/lib/airbrake-ruby/truncator.rb +8 -2
  33. data/lib/airbrake-ruby/version.rb +2 -2
  34. data/spec/backtrace_spec.rb +26 -26
  35. data/spec/code_hunk_spec.rb +2 -2
  36. data/spec/config/processor_spec.rb +5 -19
  37. data/spec/config_spec.rb +4 -29
  38. data/spec/filters/gem_root_filter_spec.rb +4 -4
  39. data/spec/filters/keys_allowlist_spec.rb +1 -0
  40. data/spec/filters/keys_blocklist_spec.rb +10 -0
  41. data/spec/filters/root_directory_filter_spec.rb +4 -4
  42. data/spec/filters/sql_filter_spec.rb +2 -2
  43. data/spec/notice_notifier/options_spec.rb +2 -2
  44. data/spec/notice_notifier_spec.rb +2 -2
  45. data/spec/notice_spec.rb +1 -1
  46. data/spec/performance_breakdown_spec.rb +0 -12
  47. data/spec/performance_notifier_spec.rb +0 -25
  48. data/spec/query_spec.rb +1 -11
  49. data/spec/queue_spec.rb +1 -13
  50. data/spec/remote_settings/settings_data_spec.rb +51 -13
  51. data/spec/remote_settings_spec.rb +14 -14
  52. data/spec/request_spec.rb +1 -13
  53. data/spec/spec_helper.rb +4 -4
  54. data/spec/stat_spec.rb +0 -9
  55. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36bf29e9b0f7ccd10afe2fdc47ec434c02941e8ad0f82e7806280b731db96bcf
4
- data.tar.gz: bcc5563ebce4151570184bf9ed9248eb21684fbc4cf5911fbea687f47e4587e4
3
+ metadata.gz: e98183a856071ce3d105c36adc9aa22a8ee7071b93958fd70fb673d2735b3977
4
+ data.tar.gz: 80464931a1362c4d845ffee737ed7aa1e46693136023b1f08006c49de98e62eb
5
5
  SHA512:
6
- metadata.gz: edf639bcf65ab8686114b93c920498605f6cfabce2ef6a6d4c364bd507076c0da80bd26358ce2414dfcf65c24b13f6665e0718a453d0e0e50f483077c2237e77
7
- data.tar.gz: 9967e9fa9ddef2d7a3be67aa0fc1cc44eca5a0c89945b0fa69bf4510733e827f164a70c7a12e36426d4a5b6f239fdd072a64de886aca42d93355ad18b5d96b66
6
+ metadata.gz: 8c32fc631e3af6348a871094dde31452d4a6fdef834596933e179d2acdbbd4935751715007fa7c4dcfce3639ebbd55f61b15f06428015647e4cbcac590ef7aaf
7
+ data.tar.gz: 23968940c6f1dfb500be5ab479c1d524cdc9f80e40808b4ff08d7f4b03c97baad603d97504c58a5300ddfa7ec9b1a4b5bd44a24a6a4a15776a82778ef2a0c324
@@ -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
 
@@ -4,7 +4,6 @@ module Airbrake
4
4
  #
5
5
  # @api public
6
6
  # @since v1.0.0
7
- # rubocop:disable Metrics/ClassLength
8
7
  class Config
9
8
  # @return [Integer] the project identificator. This value *must* be set.
10
9
  # @api public
@@ -47,15 +46,15 @@ module Airbrake
47
46
  # @api public
48
47
  attr_accessor :host
49
48
 
50
- # @since v?.?.?
49
+ # @since v5.0.0
51
50
  alias error_host host
52
- # @since v?.?.?
51
+ # @since v5.0.0
53
52
  alias error_host= host=
54
53
 
55
54
  # @return [String] the host, which provides the API endpoint to which
56
55
  # APM data should be sent
57
56
  # @api public
58
- # @since v?.?.?
57
+ # @since v5.0.0
59
58
  attr_accessor :apm_host
60
59
 
61
60
  # @return [String, Pathname] the working directory of your project
@@ -83,18 +82,12 @@ module Airbrake
83
82
  # @since v4.15.0
84
83
  attr_accessor :allowlist_keys
85
84
 
86
- # @deprecated Use allowlist_keys instead
87
- alias whitelist_keys allowlist_keys
88
-
89
85
  # @return [Array<String, Symbol, Regexp>] the keys, which should be
90
86
  # filtered
91
87
  # @api public
92
88
  # @since v4.15.0
93
89
  attr_accessor :blocklist_keys
94
90
 
95
- # @deprecated Use blocklist_keys instead
96
- alias blacklist_keys blocklist_keys
97
-
98
91
  # @return [Boolean] true if the library should attach code hunks to each
99
92
  # frame in a backtrace, false otherwise
100
93
  # @api public
@@ -128,14 +121,12 @@ module Airbrake
128
121
  # @return [Boolean] true if the library should send error reports to
129
122
  # Airbrake, false otherwise
130
123
  # @api public
131
- # @since ?.?.?
124
+ # @since 5.0.0
132
125
  attr_accessor :error_notifications
133
126
 
134
- # @note Not for public use!
135
- # @return [Boolean]
136
- # @api private
137
- # @since ?.?.?
138
- attr_accessor :__remote_configuration
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
139
130
 
140
131
  class << self
141
132
  # @return [Config]
@@ -160,6 +151,7 @@ module Airbrake
160
151
  self.project_key = user_config[:project_key]
161
152
  self.error_host = 'https://api.airbrake.io'
162
153
  self.apm_host = 'https://api.airbrake.io'
154
+ self.remote_config_host = 'https://v1-production-notifier-configs.s3.amazonaws.com'
163
155
 
164
156
  self.ignore_environments = []
165
157
 
@@ -179,30 +171,11 @@ module Airbrake
179
171
  self.query_stats = true
180
172
  self.job_stats = true
181
173
  self.error_notifications = true
182
- self.__remote_configuration = false
183
174
 
184
175
  merge(user_config)
185
176
  end
186
177
  # rubocop:enable Metrics/AbcSize
187
178
 
188
- def blacklist_keys=(keys)
189
- loc = caller_locations(1..1).first
190
- Kernel.warn(
191
- "#{loc.path}:#{loc.lineno}: warning: blacklist_keys= is deprecated " \
192
- "use blocklist_keys= instead",
193
- )
194
- self.blocklist_keys = keys
195
- end
196
-
197
- def whitelist_keys=(keys)
198
- loc = caller_locations(1..1).first
199
- Kernel.warn(
200
- "#{loc.path}:#{loc.lineno}: warning: whitelist_keys= is deprecated " \
201
- "use allowlist_keys= instead",
202
- )
203
- self.allowlist_keys = keys
204
- end
205
-
206
179
  # The full URL to the Airbrake Notice API. Based on the +:error_host+ option.
207
180
  # @return [URI] the endpoint address
208
181
  def error_endpoint
@@ -288,5 +261,4 @@ module Airbrake
288
261
  raise Airbrake::Error, "unknown option '#{option}'"
289
262
  end
290
263
  end
291
- # rubocop:enable Metrics/ClassLength
292
264
  end
@@ -3,7 +3,7 @@ module Airbrake
3
3
  # Processor is a helper class, which is responsible for setting default
4
4
  # config values, default notifier filters and remote configuration changes.
5
5
  #
6
- # @since v?.?.?
6
+ # @since 5.0.0
7
7
  # @api private
8
8
  class Processor
9
9
  # @param [Airbrake::Config] config
@@ -40,9 +40,13 @@ module Airbrake
40
40
 
41
41
  # @return [Airbrake::RemoteSettings]
42
42
  def process_remote_configuration
43
- return if !@project_id || !@config.__remote_configuration
43
+ return unless @project_id
44
44
 
45
- RemoteSettings.poll(@project_id, &method(:poll_callback))
45
+ RemoteSettings.poll(
46
+ @project_id,
47
+ @config.remote_config_host,
48
+ &method(:poll_callback)
49
+ )
46
50
  end
47
51
 
48
52
  # @param [Airbrake::NoticeNotifier] notifier
@@ -61,12 +61,14 @@ module Airbrake
61
61
 
62
62
  def valid_project_id?(config)
63
63
  return true if config.project_id.to_i > 0
64
+
64
65
  false
65
66
  end
66
67
 
67
68
  def valid_project_key?(config)
68
69
  return false unless config.project_key.is_a?(String)
69
70
  return false if config.project_key.empty?
71
+
70
72
  true
71
73
  end
72
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
 
@@ -30,6 +30,7 @@ module Airbrake
30
30
 
31
31
  @revision = find_revision
32
32
  return unless @revision
33
+
33
34
  notice[:context][:revision] = @revision
34
35
  end
35
36
 
@@ -41,6 +42,7 @@ module Airbrake
41
42
 
42
43
  head = File.read(head_path)
43
44
  return head unless head.start_with?(PREFIX)
45
+
44
46
  head = head.chomp[PREFIX.size..-1]
45
47
 
46
48
  ref_path = File.join(@git_path, head)
@@ -64,10 +64,14 @@ module Airbrake
64
64
  validate_patterns
65
65
  end
66
66
 
67
- FILTERABLE_KEYS.each { |key| filter_hash(notice[key]) }
67
+ FILTERABLE_KEYS.each do |key|
68
+ notice[key] = filter_hash(notice[key])
69
+ end
70
+
68
71
  FILTERABLE_CONTEXT_KEYS.each { |key| filter_context_key(notice, key) }
69
72
 
70
73
  return unless notice[:context][:url]
74
+
71
75
  filter_url(notice)
72
76
  end
73
77
 
@@ -81,26 +85,26 @@ module Airbrake
81
85
  def filter_hash(hash)
82
86
  return hash unless hash.is_a?(Hash)
83
87
 
88
+ hash_copy = hash.dup
89
+
84
90
  hash.each_key do |key|
85
91
  if should_filter?(key.to_s)
86
- hash[key] = FILTERED
87
- elsif hash[key].is_a?(Hash)
88
- filter_hash(hash[key])
92
+ hash_copy[key] = FILTERED
93
+ elsif hash_copy[key].is_a?(Hash)
94
+ hash_copy[key] = filter_hash(hash_copy[key])
89
95
  elsif hash[key].is_a?(Array)
90
- hash[key].each { |h| filter_hash(h) }
96
+ hash_copy[key].each_with_index do |h, i|
97
+ hash_copy[key][i] = filter_hash(h)
98
+ end
91
99
  end
92
100
  end
101
+
102
+ hash_copy
93
103
  end
94
104
 
95
105
  def filter_url_params(url)
96
106
  url.query = Hash[URI.decode_www_form(url.query)].map do |key, val|
97
- # Ruby < 2.2 raises InvalidComponentError if the query contains
98
- # invalid characters, so be sure to escape individual components.
99
- if should_filter?(key)
100
- "#{URI.encode_www_form_component(key)}=[Filtered]"
101
- else
102
- "#{URI.encode_www_form_component(key)}=#{URI.encode_www_form_component(val)}"
103
- end
107
+ should_filter?(key) ? "#{key}=[Filtered]" : "#{key}=#{val}"
104
108
  end.join('&')
105
109
 
106
110
  url.to_s
@@ -114,6 +118,7 @@ module Airbrake
114
118
  end
115
119
 
116
120
  return unless url.query
121
+
117
122
  notice[:context][:url] = filter_url_params(url)
118
123
  end
119
124
 
@@ -122,6 +127,7 @@ module Airbrake
122
127
 
123
128
  @patterns = @patterns.flat_map do |pattern|
124
129
  next(pattern) unless pattern.respond_to?(:call)
130
+
125
131
  pattern.call
126
132
  end
127
133
  end
@@ -142,7 +148,9 @@ module Airbrake
142
148
  def filter_context_key(notice, key)
143
149
  return unless notice[:context][key]
144
150
  return if notice[:context][key] == FILTERED
145
- return filter_hash(notice[:context][key]) unless should_filter?(key)
151
+ unless should_filter?(key)
152
+ return notice[:context][key] = filter_hash(notice[:context][key])
153
+ end
146
154
 
147
155
  notice[:context][key] = FILTERED
148
156
  end
@@ -19,6 +19,7 @@ module Airbrake
19
19
  notice[:errors].each do |error|
20
20
  error[:backtrace].each do |frame|
21
21
  next unless (file = frame[:file])
22
+
22
23
  file.sub!(/\A#{@root_directory}/, PROJECT_ROOT_LABEL)
23
24
  end
24
25
  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 Metrics/LineLength
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 Metrics/LineLength
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
@@ -16,6 +16,7 @@ module Airbrake
16
16
  # @macro call_filter
17
17
  def call(notice)
18
18
  return if notice[:errors].none? { |error| error[:type] == SYSTEM_EXIT_TYPE }
19
+
19
20
  notice.ignore!
20
21
  end
21
22
  end
@@ -56,6 +56,7 @@ module Airbrake
56
56
  def thread_variables(th)
57
57
  th.thread_variables.map.with_object({}) do |var, h|
58
58
  next if var.to_s.start_with?(IGNORE_PREFIX)
59
+
59
60
  h[var] = sanitize_value(th.thread_variable_get(var))
60
61
  end
61
62
  end
@@ -63,6 +64,7 @@ module Airbrake
63
64
  def fiber_variables(th)
64
65
  th.keys.map.with_object({}) do |key, h|
65
66
  next if key.to_s.start_with?(IGNORE_PREFIX)
67
+
66
68
  h[key] = sanitize_value(th[key])
67
69
  end
68
70
  end