lapsoss 0.1.0 → 0.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/lapsoss/adapters/appsignal_adapter.rb +25 -26
- data/lib/lapsoss/adapters/base.rb +2 -2
- data/lib/lapsoss/adapters/bugsnag_adapter.rb +12 -0
- data/lib/lapsoss/adapters/insight_hub_adapter.rb +29 -32
- data/lib/lapsoss/adapters/logger_adapter.rb +8 -8
- data/lib/lapsoss/adapters/rollbar_adapter.rb +27 -28
- data/lib/lapsoss/adapters/sentry_adapter.rb +23 -29
- data/lib/lapsoss/backtrace_frame.rb +21 -31
- data/lib/lapsoss/backtrace_processor.rb +28 -31
- data/lib/lapsoss/client.rb +4 -6
- data/lib/lapsoss/configuration.rb +48 -41
- data/lib/lapsoss/current.rb +1 -1
- data/lib/lapsoss/event.rb +6 -5
- data/lib/lapsoss/{exclusions.rb → exclusion_filter.rb} +56 -56
- data/lib/lapsoss/fingerprinter.rb +33 -37
- data/lib/lapsoss/http_client.rb +45 -11
- data/lib/lapsoss/middleware.rb +35 -43
- data/lib/lapsoss/pipeline.rb +6 -10
- data/lib/lapsoss/railtie.rb +9 -9
- data/lib/lapsoss/registry.rb +23 -22
- data/lib/lapsoss/release_tracker.rb +160 -182
- data/lib/lapsoss/router.rb +3 -5
- data/lib/lapsoss/sampling.rb +49 -53
- data/lib/lapsoss/scope.rb +6 -10
- data/lib/lapsoss/scrubber.rb +22 -24
- data/lib/lapsoss/user_context.rb +78 -85
- data/lib/lapsoss/validators.rb +13 -26
- data/lib/lapsoss/version.rb +1 -1
- data/lib/lapsoss.rb +12 -25
- metadata +59 -23
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
|
6
|
-
require_relative "backtrace_frame"
|
3
|
+
require 'active_support/cache'
|
4
|
+
require 'active_support/core_ext/numeric/time'
|
5
|
+
require_relative 'backtrace_frame'
|
7
6
|
|
8
7
|
module Lapsoss
|
9
8
|
class BacktraceProcessor
|
@@ -33,20 +32,20 @@ module Lapsoss
|
|
33
32
|
|
34
33
|
def initialize(config = {})
|
35
34
|
# Handle different config formats for backward compatibility
|
36
|
-
if config.respond_to?(:backtrace_context_lines)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
35
|
+
config_hash = if config.respond_to?(:backtrace_context_lines)
|
36
|
+
# Configuration object passed
|
37
|
+
{
|
38
|
+
context_lines: config.backtrace_context_lines,
|
39
|
+
max_frames: config.backtrace_max_frames,
|
40
|
+
enable_code_context: config.backtrace_enable_code_context,
|
41
|
+
in_app_patterns: config.backtrace_in_app_patterns,
|
42
|
+
exclude_patterns: config.backtrace_exclude_patterns,
|
43
|
+
strip_load_path: config.backtrace_strip_load_path
|
44
|
+
}
|
45
|
+
else
|
46
|
+
# Hash passed
|
47
|
+
config
|
48
|
+
end
|
50
49
|
|
51
50
|
@config = DEFAULT_CONFIG.merge(config_hash)
|
52
51
|
@file_cache = ActiveSupport::Cache::MemoryStore.new(
|
@@ -77,7 +76,7 @@ module Lapsoss
|
|
77
76
|
end
|
78
77
|
|
79
78
|
# Backward compatibility alias
|
80
|
-
|
79
|
+
alias process process_backtrace
|
81
80
|
|
82
81
|
def process_exception_backtrace(exception, follow_cause: false)
|
83
82
|
return [] unless exception&.backtrace
|
@@ -86,7 +85,7 @@ module Lapsoss
|
|
86
85
|
|
87
86
|
# Add exception-specific context
|
88
87
|
frames.each_with_index do |frame, index|
|
89
|
-
frame.define_singleton_method(:crash_frame?) { index
|
88
|
+
frame.define_singleton_method(:crash_frame?) { index.zero? }
|
90
89
|
frame.define_singleton_method(:exception_class) { exception.class.name }
|
91
90
|
end
|
92
91
|
|
@@ -100,7 +99,7 @@ module Lapsoss
|
|
100
99
|
end
|
101
100
|
|
102
101
|
# Backward compatibility aliases
|
103
|
-
|
102
|
+
alias process_exception process_exception_backtrace
|
104
103
|
|
105
104
|
def clear_cache!
|
106
105
|
@file_cache.clear
|
@@ -180,7 +179,7 @@ module Lapsoss
|
|
180
179
|
file_cache: {
|
181
180
|
# ActiveSupport::Cache::MemoryStore doesn't expose detailed stats
|
182
181
|
# but we can provide basic info
|
183
|
-
type:
|
182
|
+
type: 'ActiveSupport::Cache::MemoryStore',
|
184
183
|
configured_size: @file_cache.options[:size]
|
185
184
|
},
|
186
185
|
config: @config,
|
@@ -205,7 +204,7 @@ module Lapsoss
|
|
205
204
|
|
206
205
|
# Convert to 0-based index
|
207
206
|
line_index = line_number - 1
|
208
|
-
return nil if line_index
|
207
|
+
return nil if line_index.negative? || line_index >= lines.length
|
209
208
|
|
210
209
|
# Calculate context range
|
211
210
|
start_line = [0, line_index - context_lines].max
|
@@ -283,11 +282,11 @@ module Lapsoss
|
|
283
282
|
head_frames = frames.first(head_count)
|
284
283
|
|
285
284
|
# Get tail frames (original cause)
|
286
|
-
tail_frames = if tail_count
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
285
|
+
tail_frames = if tail_count.positive?
|
286
|
+
frames.last(tail_count)
|
287
|
+
else
|
288
|
+
[]
|
289
|
+
end
|
291
290
|
|
292
291
|
head_frames + tail_frames
|
293
292
|
end
|
@@ -335,9 +334,7 @@ module Lapsoss
|
|
335
334
|
paths << Dir.pwd
|
336
335
|
|
337
336
|
# Add gem paths
|
338
|
-
if defined?(Gem)
|
339
|
-
paths.concat(Gem.path.map { |p| File.join(p, 'gems') })
|
340
|
-
end
|
337
|
+
paths.concat(Gem.path.map { |p| File.join(p, 'gems') }) if defined?(Gem)
|
341
338
|
|
342
339
|
# Sort by length (longest first) for better matching
|
343
340
|
paths.uniq.sort_by(&:length).reverse
|
data/lib/lapsoss/client.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require 'concurrent'
|
4
|
+
require_relative 'scope'
|
5
|
+
require_relative 'current'
|
6
6
|
|
7
7
|
module Lapsoss
|
8
8
|
class Client
|
@@ -70,8 +70,6 @@ module Lapsoss
|
|
70
70
|
|
71
71
|
private
|
72
72
|
|
73
|
-
|
74
|
-
|
75
73
|
def capture_event(event)
|
76
74
|
# Apply pipeline processing if enabled
|
77
75
|
if @configuration.enable_pipeline && @configuration.pipeline
|
@@ -87,7 +85,7 @@ module Lapsoss
|
|
87
85
|
else
|
88
86
|
Router.process_event(event)
|
89
87
|
end
|
90
|
-
rescue => e
|
88
|
+
rescue StandardError => e
|
91
89
|
handle_capture_error(e)
|
92
90
|
end
|
93
91
|
|
@@ -1,26 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require
|
3
|
+
require_relative 'validators'
|
4
|
+
require 'active_support/configurable'
|
5
5
|
|
6
6
|
module Lapsoss
|
7
7
|
class Configuration
|
8
8
|
include Validators
|
9
9
|
include ActiveSupport::Configurable
|
10
10
|
|
11
|
-
attr_accessor :async, :logger, :enabled, :release,
|
11
|
+
attr_accessor :async, :logger, :enabled, :release, :debug,
|
12
12
|
:scrub_fields, :scrub_all, :whitelist_fields, :randomize_scrub_length,
|
13
13
|
:transport_jitter, :fingerprint_patterns,
|
14
14
|
:normalize_fingerprint_paths, :normalize_fingerprint_ids, :fingerprint_include_environment,
|
15
15
|
:backtrace_context_lines, :backtrace_in_app_patterns, :backtrace_exclude_patterns,
|
16
16
|
:backtrace_strip_load_path, :backtrace_max_frames, :backtrace_enable_code_context,
|
17
17
|
:enable_pipeline, :pipeline_builder, :sampling_strategy,
|
18
|
-
:skip_rails_cache_errors
|
19
|
-
attr_reader :fingerprint_callback
|
20
|
-
|
21
|
-
:transport_timeout, :transport_max_retries, :transport_initial_backoff,
|
22
|
-
:transport_max_backoff, :transport_backoff_multiplier, :transport_ssl_verify
|
23
|
-
attr_reader :default_context, :adapter_configs
|
18
|
+
:skip_rails_cache_errors, :force_sync_http
|
19
|
+
attr_reader :fingerprint_callback, :environment, :before_send, :sample_rate, :error_handler, :transport_timeout,
|
20
|
+
:transport_max_retries, :transport_initial_backoff, :transport_max_backoff, :transport_backoff_multiplier, :transport_ssl_verify, :default_context, :adapter_configs
|
24
21
|
|
25
22
|
def initialize
|
26
23
|
@adapter_configs = {}
|
@@ -29,11 +26,12 @@ module Lapsoss
|
|
29
26
|
@environment = nil
|
30
27
|
@enabled = true
|
31
28
|
@release = nil
|
29
|
+
@debug = false
|
32
30
|
@before_send = nil
|
33
31
|
@sample_rate = 1.0
|
34
32
|
@default_context = {}
|
35
33
|
@error_handler = nil
|
36
|
-
@scrub_fields = nil
|
34
|
+
@scrub_fields = nil # Will use defaults from Scrubber
|
37
35
|
@scrub_all = false
|
38
36
|
@whitelist_fields = []
|
39
37
|
@randomize_scrub_length = false
|
@@ -47,7 +45,7 @@ module Lapsoss
|
|
47
45
|
@transport_ssl_verify = true
|
48
46
|
# Fingerprinting settings
|
49
47
|
@fingerprint_callback = nil
|
50
|
-
@fingerprint_patterns = nil
|
48
|
+
@fingerprint_patterns = nil # Will use defaults from Fingerprinter
|
51
49
|
@normalize_fingerprint_paths = true
|
52
50
|
@normalize_fingerprint_ids = true
|
53
51
|
@fingerprint_include_environment = false
|
@@ -64,9 +62,10 @@ module Lapsoss
|
|
64
62
|
@sampling_strategy = nil
|
65
63
|
# Rails error filtering
|
66
64
|
@skip_rails_cache_errors = true
|
65
|
+
# HTTP client settings
|
66
|
+
@force_sync_http = false
|
67
67
|
end
|
68
68
|
|
69
|
-
|
70
69
|
# Register a named adapter configuration
|
71
70
|
#
|
72
71
|
# @param name [Symbol] Unique name for this adapter instance
|
@@ -99,7 +98,6 @@ module Lapsoss
|
|
99
98
|
register_adapter(name, :bugsnag, **settings)
|
100
99
|
end
|
101
100
|
|
102
|
-
|
103
101
|
# Convenience method for Rollbar
|
104
102
|
def use_rollbar(name: :rollbar, **settings)
|
105
103
|
register_adapter(name, :rollbar, **settings)
|
@@ -164,9 +162,17 @@ module Lapsoss
|
|
164
162
|
initialize
|
165
163
|
end
|
166
164
|
|
165
|
+
def debug?
|
166
|
+
@debug
|
167
|
+
end
|
168
|
+
|
169
|
+
def async?
|
170
|
+
@async
|
171
|
+
end
|
172
|
+
|
167
173
|
# Pipeline configuration
|
168
|
-
def configure_pipeline
|
169
|
-
require_relative
|
174
|
+
def configure_pipeline
|
175
|
+
require_relative 'pipeline'
|
170
176
|
@pipeline_builder = PipelineBuilder.new
|
171
177
|
yield(@pipeline_builder) if block_given?
|
172
178
|
@pipeline_builder
|
@@ -178,7 +184,7 @@ module Lapsoss
|
|
178
184
|
|
179
185
|
# Sampling configuration
|
180
186
|
def configure_sampling(strategy = nil, &block)
|
181
|
-
require_relative
|
187
|
+
require_relative 'sampling'
|
182
188
|
|
183
189
|
if strategy
|
184
190
|
@sampling_strategy = strategy
|
@@ -188,7 +194,7 @@ module Lapsoss
|
|
188
194
|
end
|
189
195
|
|
190
196
|
def create_sampling_strategy
|
191
|
-
require_relative
|
197
|
+
require_relative 'sampling'
|
192
198
|
|
193
199
|
case @sampling_strategy
|
194
200
|
when Symbol
|
@@ -213,85 +219,86 @@ module Lapsoss
|
|
213
219
|
|
214
220
|
# Validation and setter overrides
|
215
221
|
def sample_rate=(value)
|
216
|
-
validate_sample_rate!(value,
|
222
|
+
validate_sample_rate!(value, 'sample_rate') if value
|
217
223
|
@sample_rate = value
|
218
224
|
end
|
219
225
|
|
220
226
|
def before_send=(value)
|
221
|
-
validate_callable!(value,
|
227
|
+
validate_callable!(value, 'before_send')
|
222
228
|
@before_send = value
|
223
229
|
end
|
224
230
|
|
225
231
|
def error_handler=(value)
|
226
|
-
validate_callable!(value,
|
232
|
+
validate_callable!(value, 'error_handler')
|
227
233
|
@error_handler = value
|
228
234
|
end
|
229
235
|
|
230
236
|
def environment=(value)
|
231
|
-
validate_environment!(value,
|
237
|
+
validate_environment!(value, 'environment') if value
|
232
238
|
@environment = value&.to_s
|
233
239
|
end
|
234
240
|
|
235
241
|
def transport_timeout=(value)
|
236
|
-
validate_timeout!(value,
|
242
|
+
validate_timeout!(value, 'transport_timeout') if value
|
237
243
|
@transport_timeout = value
|
238
244
|
end
|
239
245
|
|
240
246
|
def transport_max_retries=(value)
|
241
|
-
validate_retries!(value,
|
247
|
+
validate_retries!(value, 'transport_max_retries') if value
|
242
248
|
@transport_max_retries = value
|
243
249
|
end
|
244
250
|
|
245
251
|
def transport_initial_backoff=(value)
|
246
|
-
validate_timeout!(value,
|
252
|
+
validate_timeout!(value, 'transport_initial_backoff') if value
|
247
253
|
@transport_initial_backoff = value
|
248
254
|
end
|
249
255
|
|
250
256
|
def transport_max_backoff=(value)
|
251
|
-
validate_timeout!(value,
|
257
|
+
validate_timeout!(value, 'transport_max_backoff') if value
|
252
258
|
@transport_max_backoff = value
|
253
259
|
end
|
254
260
|
|
255
261
|
def transport_backoff_multiplier=(value)
|
256
262
|
if value
|
257
|
-
validate_type!(value, [Numeric],
|
258
|
-
validate_numeric_range!(value, 1.0..10.0,
|
263
|
+
validate_type!(value, [Numeric], 'transport_backoff_multiplier')
|
264
|
+
validate_numeric_range!(value, 1.0..10.0, 'transport_backoff_multiplier')
|
259
265
|
end
|
260
266
|
@transport_backoff_multiplier = value
|
261
267
|
end
|
262
268
|
|
263
269
|
def transport_ssl_verify=(value)
|
264
|
-
validate_boolean!(value,
|
270
|
+
validate_boolean!(value, 'transport_ssl_verify') if value
|
265
271
|
@transport_ssl_verify = value
|
266
272
|
end
|
267
273
|
|
268
274
|
def fingerprint_callback=(value)
|
269
|
-
validate_callable!(value,
|
275
|
+
validate_callable!(value, 'fingerprint_callback')
|
270
276
|
@fingerprint_callback = value
|
271
277
|
end
|
272
278
|
|
273
279
|
# Configuration validation
|
274
280
|
def validate!
|
275
|
-
validate_sample_rate!(@sample_rate,
|
276
|
-
validate_callable!(@before_send,
|
277
|
-
validate_callable!(@error_handler,
|
278
|
-
validate_callable!(@fingerprint_callback,
|
279
|
-
validate_environment!(@environment,
|
281
|
+
validate_sample_rate!(@sample_rate, 'sample_rate') if @sample_rate
|
282
|
+
validate_callable!(@before_send, 'before_send')
|
283
|
+
validate_callable!(@error_handler, 'error_handler')
|
284
|
+
validate_callable!(@fingerprint_callback, 'fingerprint_callback')
|
285
|
+
validate_environment!(@environment, 'environment') if @environment
|
280
286
|
|
281
287
|
# Validate transport settings
|
282
|
-
validate_timeout!(@transport_timeout,
|
283
|
-
validate_retries!(@transport_max_retries,
|
284
|
-
validate_timeout!(@transport_initial_backoff,
|
285
|
-
validate_timeout!(@transport_max_backoff,
|
288
|
+
validate_timeout!(@transport_timeout, 'transport_timeout')
|
289
|
+
validate_retries!(@transport_max_retries, 'transport_max_retries')
|
290
|
+
validate_timeout!(@transport_initial_backoff, 'transport_initial_backoff')
|
291
|
+
validate_timeout!(@transport_max_backoff, 'transport_max_backoff')
|
286
292
|
|
287
293
|
if @transport_backoff_multiplier
|
288
|
-
validate_type!(@transport_backoff_multiplier, [Numeric],
|
289
|
-
validate_numeric_range!(@transport_backoff_multiplier, 1.0..10.0,
|
294
|
+
validate_type!(@transport_backoff_multiplier, [Numeric], 'transport_backoff_multiplier')
|
295
|
+
validate_numeric_range!(@transport_backoff_multiplier, 1.0..10.0, 'transport_backoff_multiplier')
|
290
296
|
end
|
291
297
|
|
292
298
|
# Validate that initial backoff is less than max backoff
|
293
299
|
if @transport_initial_backoff && @transport_max_backoff && @transport_initial_backoff > @transport_max_backoff
|
294
|
-
raise ValidationError,
|
300
|
+
raise ValidationError,
|
301
|
+
"transport_initial_backoff (#{@transport_initial_backoff}) must be less than transport_max_backoff (#{@transport_max_backoff})"
|
295
302
|
end
|
296
303
|
|
297
304
|
# Validate adapter configurations
|
data/lib/lapsoss/current.rb
CHANGED
data/lib/lapsoss/event.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative 'scrubber'
|
4
|
+
require_relative 'fingerprinter'
|
5
|
+
require_relative 'backtrace_processor'
|
6
6
|
|
7
7
|
module Lapsoss
|
8
8
|
class Event
|
9
|
-
attr_accessor :type, :timestamp, :level, :message, :exception, :context, :environment, :fingerprint,
|
9
|
+
attr_accessor :type, :timestamp, :level, :message, :exception, :context, :environment, :fingerprint,
|
10
|
+
:backtrace_frames
|
10
11
|
|
11
12
|
def initialize(type:, level: :info, **attributes)
|
12
13
|
@type = type
|
13
14
|
@level = level
|
14
|
-
@timestamp = Time.now
|
15
|
+
@timestamp = Time.zone.now
|
15
16
|
@context = {}
|
16
17
|
@environment = Lapsoss.configuration.environment
|
17
18
|
|
@@ -141,8 +141,8 @@ module Lapsoss
|
|
141
141
|
return false if @excluded_environments.empty?
|
142
142
|
|
143
143
|
environment = event.context[:environment] ||
|
144
|
-
|
145
|
-
|
144
|
+
event.context.dig(:tags, :environment) ||
|
145
|
+
Lapsoss.configuration.environment
|
146
146
|
|
147
147
|
return false unless environment
|
148
148
|
|
@@ -160,12 +160,12 @@ module Lapsoss
|
|
160
160
|
{
|
161
161
|
excluded_exceptions: [
|
162
162
|
# Test-related exceptions
|
163
|
-
|
164
|
-
|
163
|
+
'RSpec::Expectations::ExpectationNotMetError',
|
164
|
+
'Minitest::Assertion',
|
165
165
|
|
166
166
|
# Development tools
|
167
|
-
|
168
|
-
|
167
|
+
'Pry::CommandError',
|
168
|
+
'Byebug::CommandError'
|
169
169
|
],
|
170
170
|
excluded_patterns: [
|
171
171
|
/test/i,
|
@@ -181,19 +181,19 @@ module Lapsoss
|
|
181
181
|
{
|
182
182
|
excluded_exceptions: [
|
183
183
|
# Common Rails exceptions that are usually not actionable
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
184
|
+
'ActionController::RoutingError',
|
185
|
+
'ActionController::UnknownFormat',
|
186
|
+
'ActionController::BadRequest',
|
187
|
+
'ActionController::ParameterMissing',
|
188
188
|
|
189
189
|
# ActiveRecord exceptions for common user errors
|
190
|
-
|
191
|
-
|
190
|
+
'ActiveRecord::RecordNotFound',
|
191
|
+
'ActiveRecord::RecordInvalid',
|
192
192
|
|
193
193
|
# Network timeouts that are expected
|
194
|
-
|
195
|
-
|
196
|
-
|
194
|
+
'Net::ReadTimeout',
|
195
|
+
'Net::OpenTimeout',
|
196
|
+
'Timeout::Error'
|
197
197
|
],
|
198
198
|
excluded_patterns: [
|
199
199
|
# Bot and crawler patterns
|
@@ -215,10 +215,10 @@ module Lapsoss
|
|
215
215
|
],
|
216
216
|
excluded_messages: [
|
217
217
|
# Common spam/attack messages
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
218
|
+
'No route matches',
|
219
|
+
'Invalid authenticity token',
|
220
|
+
'Forbidden',
|
221
|
+
'Unauthorized'
|
222
222
|
]
|
223
223
|
}
|
224
224
|
end
|
@@ -227,8 +227,8 @@ module Lapsoss
|
|
227
227
|
{
|
228
228
|
excluded_exceptions: [
|
229
229
|
# Test data related errors
|
230
|
-
|
231
|
-
|
230
|
+
'ActiveRecord::RecordNotFound',
|
231
|
+
'ArgumentError'
|
232
232
|
],
|
233
233
|
excluded_patterns: [
|
234
234
|
/test/i,
|
@@ -267,15 +267,15 @@ module Lapsoss
|
|
267
267
|
/onerror=/i
|
268
268
|
],
|
269
269
|
excluded_messages: [
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
270
|
+
'Invalid authenticity token',
|
271
|
+
'Forbidden',
|
272
|
+
'Unauthorized',
|
273
|
+
'Access denied'
|
274
274
|
],
|
275
275
|
custom_filters: [
|
276
276
|
# Exclude requests from known bot user agents
|
277
277
|
lambda do |event|
|
278
|
-
user_agent = event.context.dig(:request, :headers,
|
278
|
+
user_agent = event.context.dig(:request, :headers, 'User-Agent')
|
279
279
|
return false unless user_agent
|
280
280
|
|
281
281
|
bot_patterns = [
|
@@ -297,14 +297,14 @@ module Lapsoss
|
|
297
297
|
{
|
298
298
|
excluded_exceptions: [
|
299
299
|
# Timeout exceptions that are expected under load
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
300
|
+
'Net::ReadTimeout',
|
301
|
+
'Net::OpenTimeout',
|
302
|
+
'Timeout::Error',
|
303
|
+
'Redis::TimeoutError',
|
304
304
|
|
305
305
|
# Memory and resource limits
|
306
|
-
|
307
|
-
|
306
|
+
'NoMemoryError',
|
307
|
+
'SystemStackError'
|
308
308
|
],
|
309
309
|
excluded_patterns: [
|
310
310
|
/timeout/i,
|
@@ -315,7 +315,7 @@ module Lapsoss
|
|
315
315
|
custom_filters: [
|
316
316
|
# Exclude high-frequency errors during peak times
|
317
317
|
lambda do |event|
|
318
|
-
now = Time.now
|
318
|
+
now = Time.zone.now
|
319
319
|
peak_hours = (9..17).cover?(now.hour) && (1..5).cover?(now.wday)
|
320
320
|
|
321
321
|
if peak_hours
|
@@ -334,11 +334,11 @@ module Lapsoss
|
|
334
334
|
{
|
335
335
|
excluded_exceptions: [
|
336
336
|
# User input validation errors
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
337
|
+
'ActiveModel::ValidationError',
|
338
|
+
'ActiveRecord::RecordInvalid',
|
339
|
+
'ActionController::ParameterMissing',
|
340
|
+
'ArgumentError',
|
341
|
+
'TypeError'
|
342
342
|
],
|
343
343
|
excluded_patterns: [
|
344
344
|
/validation/i,
|
@@ -373,15 +373,15 @@ module Lapsoss
|
|
373
373
|
|
374
374
|
presets.each do |preset|
|
375
375
|
config = case preset
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
376
|
+
when :development then development
|
377
|
+
when :production then production
|
378
|
+
when :staging then staging
|
379
|
+
when :security_focused then security_focused
|
380
|
+
when :performance_focused then performance_focused
|
381
|
+
when :user_error_focused then user_error_focused
|
382
|
+
when Hash then preset
|
383
|
+
else raise ArgumentError, "Unknown preset: #{preset}"
|
384
|
+
end
|
385
385
|
|
386
386
|
combined_config[:excluded_exceptions].concat(config[:excluded_exceptions] || [])
|
387
387
|
combined_config[:excluded_patterns].concat(config[:excluded_patterns] || [])
|
@@ -404,15 +404,15 @@ module Lapsoss
|
|
404
404
|
module ExclusionConfiguration
|
405
405
|
def self.configure_exclusions(config, preset: nil, **custom_config)
|
406
406
|
exclusion_config = if preset
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
407
|
+
case preset
|
408
|
+
when Array
|
409
|
+
ExclusionPresets.combined(preset)
|
410
|
+
else
|
411
|
+
ExclusionPresets.send(preset)
|
412
|
+
end
|
413
|
+
else
|
414
|
+
{}
|
415
|
+
end
|
416
416
|
|
417
417
|
# Merge custom configuration
|
418
418
|
exclusion_config.merge!(custom_config)
|