lapsoss 0.2.0 → 0.3.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/README.md +153 -733
- data/lib/lapsoss/adapters/appsignal_adapter.rb +22 -22
- data/lib/lapsoss/adapters/base.rb +0 -3
- data/lib/lapsoss/adapters/insight_hub_adapter.rb +108 -104
- data/lib/lapsoss/adapters/logger_adapter.rb +1 -1
- data/lib/lapsoss/adapters/rollbar_adapter.rb +108 -68
- data/lib/lapsoss/adapters/sentry_adapter.rb +24 -24
- data/lib/lapsoss/backtrace_frame.rb +37 -206
- data/lib/lapsoss/backtrace_frame_factory.rb +228 -0
- data/lib/lapsoss/backtrace_processor.rb +26 -23
- data/lib/lapsoss/client.rb +2 -4
- data/lib/lapsoss/configuration.rb +28 -32
- data/lib/lapsoss/current.rb +10 -2
- data/lib/lapsoss/event.rb +28 -5
- data/lib/lapsoss/exception_backtrace_frame.rb +39 -0
- data/lib/lapsoss/exclusion_configuration.rb +30 -0
- data/lib/lapsoss/exclusion_filter.rb +0 -273
- data/lib/lapsoss/exclusion_presets.rb +249 -0
- data/lib/lapsoss/fingerprinter.rb +28 -28
- data/lib/lapsoss/http_client.rb +8 -8
- data/lib/lapsoss/merged_scope.rb +63 -0
- data/lib/lapsoss/middleware/base.rb +15 -0
- data/lib/lapsoss/middleware/conditional_filter.rb +18 -0
- data/lib/lapsoss/middleware/event_enricher.rb +19 -0
- data/lib/lapsoss/middleware/event_transformer.rb +19 -0
- data/lib/lapsoss/middleware/exception_filter.rb +43 -0
- data/lib/lapsoss/middleware/metrics_collector.rb +44 -0
- data/lib/lapsoss/middleware/rate_limiter.rb +31 -0
- data/lib/lapsoss/middleware/release_tracker.rb +117 -0
- data/lib/lapsoss/middleware/sample_filter.rb +23 -0
- data/lib/lapsoss/middleware/sampling_middleware.rb +18 -0
- data/lib/lapsoss/middleware/user_context_enhancer.rb +46 -0
- data/lib/lapsoss/middleware.rb +0 -339
- data/lib/lapsoss/pipeline.rb +0 -68
- data/lib/lapsoss/pipeline_builder.rb +69 -0
- data/lib/lapsoss/rails_error_subscriber.rb +42 -0
- data/lib/lapsoss/rails_middleware.rb +78 -0
- data/lib/lapsoss/railtie.rb +22 -50
- data/lib/lapsoss/registry.rb +18 -5
- data/lib/lapsoss/release_providers.rb +110 -0
- data/lib/lapsoss/release_tracker.rb +159 -232
- data/lib/lapsoss/sampling/adaptive_sampler.rb +46 -0
- data/lib/lapsoss/sampling/base.rb +11 -0
- data/lib/lapsoss/sampling/composite_sampler.rb +26 -0
- data/lib/lapsoss/sampling/consistent_hash_sampler.rb +30 -0
- data/lib/lapsoss/sampling/exception_type_sampler.rb +44 -0
- data/lib/lapsoss/sampling/health_based_sampler.rb +19 -0
- data/lib/lapsoss/sampling/rate_limiter.rb +32 -0
- data/lib/lapsoss/sampling/sampling_factory.rb +69 -0
- data/lib/lapsoss/sampling/time_based_sampler.rb +44 -0
- data/lib/lapsoss/sampling/uniform_sampler.rb +15 -0
- data/lib/lapsoss/sampling/user_based_sampler.rb +42 -0
- data/lib/lapsoss/sampling.rb +0 -322
- data/lib/lapsoss/scope.rb +12 -48
- data/lib/lapsoss/scrubber.rb +7 -7
- data/lib/lapsoss/user_context.rb +30 -203
- data/lib/lapsoss/user_context_integrations.rb +39 -0
- data/lib/lapsoss/user_context_middleware.rb +50 -0
- data/lib/lapsoss/user_context_provider.rb +93 -0
- data/lib/lapsoss/utils.rb +13 -0
- data/lib/lapsoss/validators.rb +15 -15
- data/lib/lapsoss/version.rb +1 -1
- data/lib/lapsoss.rb +3 -3
- metadata +54 -5
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require_relative 'backtrace_frame'
|
3
|
+
require "active_support/cache"
|
4
|
+
require "active_support/core_ext/numeric/time"
|
6
5
|
|
7
6
|
module Lapsoss
|
8
7
|
class BacktraceProcessor
|
@@ -42,10 +41,10 @@ module Lapsoss
|
|
42
41
|
exclude_patterns: config.backtrace_exclude_patterns,
|
43
42
|
strip_load_path: config.backtrace_strip_load_path
|
44
43
|
}
|
45
|
-
|
44
|
+
else
|
46
45
|
# Hash passed
|
47
46
|
config
|
48
|
-
|
47
|
+
end
|
49
48
|
|
50
49
|
@config = DEFAULT_CONFIG.merge(config_hash)
|
51
50
|
@file_cache = ActiveSupport::Cache::MemoryStore.new(
|
@@ -83,10 +82,13 @@ module Lapsoss
|
|
83
82
|
|
84
83
|
frames = process_backtrace(exception.backtrace)
|
85
84
|
|
86
|
-
#
|
87
|
-
frames.
|
88
|
-
|
89
|
-
|
85
|
+
# Wrap frames with exception-specific context
|
86
|
+
frames = frames.map.with_index do |frame, index|
|
87
|
+
ExceptionBacktraceFrame.new(
|
88
|
+
frame,
|
89
|
+
exception_class: exception.class.name,
|
90
|
+
is_crash_frame: index.zero?
|
91
|
+
)
|
90
92
|
end
|
91
93
|
|
92
94
|
# Follow exception causes if requested
|
@@ -179,7 +181,7 @@ module Lapsoss
|
|
179
181
|
file_cache: {
|
180
182
|
# ActiveSupport::Cache::MemoryStore doesn't expose detailed stats
|
181
183
|
# but we can provide basic info
|
182
|
-
type:
|
184
|
+
type: "ActiveSupport::Cache::MemoryStore",
|
183
185
|
configured_size: @file_cache.options[:size]
|
184
186
|
},
|
185
187
|
config: @config,
|
@@ -207,8 +209,8 @@ module Lapsoss
|
|
207
209
|
return nil if line_index.negative? || line_index >= lines.length
|
208
210
|
|
209
211
|
# Calculate context range
|
210
|
-
start_line = [0, line_index - context_lines].max
|
211
|
-
end_line = [lines.length - 1, line_index + context_lines].min
|
212
|
+
start_line = [ 0, line_index - context_lines ].max
|
213
|
+
end_line = [ lines.length - 1, line_index + context_lines ].min
|
212
214
|
|
213
215
|
{
|
214
216
|
pre_context: lines[start_line...line_index],
|
@@ -234,7 +236,7 @@ module Lapsoss
|
|
234
236
|
def parse_frames(backtrace)
|
235
237
|
load_paths = determine_load_paths
|
236
238
|
frames = backtrace.map do |line|
|
237
|
-
|
239
|
+
BacktraceFrameFactory.from_raw_line(
|
238
240
|
line,
|
239
241
|
in_app_patterns: @config[:in_app_patterns],
|
240
242
|
exclude_patterns: @config[:exclude_patterns],
|
@@ -248,7 +250,7 @@ module Lapsoss
|
|
248
250
|
|
249
251
|
def filter_frames(frames)
|
250
252
|
# Remove excluded frames
|
251
|
-
frames = frames.reject
|
253
|
+
frames = frames.reject { |frame| frame.excluded?(@config[:exclude_patterns]) }
|
252
254
|
|
253
255
|
# Filter gems if configured
|
254
256
|
unless @config[:include_gems_in_context]
|
@@ -284,9 +286,9 @@ module Lapsoss
|
|
284
286
|
# Get tail frames (original cause)
|
285
287
|
tail_frames = if tail_count.positive?
|
286
288
|
frames.last(tail_count)
|
287
|
-
|
289
|
+
else
|
288
290
|
[]
|
289
|
-
|
291
|
+
end
|
290
292
|
|
291
293
|
head_frames + tail_frames
|
292
294
|
end
|
@@ -296,8 +298,9 @@ module Lapsoss
|
|
296
298
|
context_frames = frames.select(&:app_frame?)
|
297
299
|
context_frames += frames.select(&:library_frame?).first(3)
|
298
300
|
|
299
|
-
context_frames.
|
300
|
-
frame.add_code_context(self, @config[:context_lines])
|
301
|
+
context_frames.each_with_index do |frame, _index|
|
302
|
+
updated_frame = frame.add_code_context(self, @config[:context_lines])
|
303
|
+
frames[frames.index(frame)] = updated_frame if updated_frame
|
301
304
|
end
|
302
305
|
end
|
303
306
|
|
@@ -305,7 +308,7 @@ module Lapsoss
|
|
305
308
|
seen = Set.new
|
306
309
|
frames.select do |frame|
|
307
310
|
# Create a key based on filename, line, and method
|
308
|
-
key = [frame.filename, frame.line_number, frame.function].join(
|
311
|
+
key = [ frame.filename, frame.line_number, frame.function ].join(":")
|
309
312
|
|
310
313
|
if seen.include?(key)
|
311
314
|
false
|
@@ -325,16 +328,16 @@ module Lapsoss
|
|
325
328
|
# Add common Rails paths if in Rails
|
326
329
|
if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
|
327
330
|
paths << Rails.root.to_s
|
328
|
-
paths << Rails.root.join(
|
329
|
-
paths << Rails.root.join(
|
330
|
-
paths << Rails.root.join(
|
331
|
+
paths << Rails.root.join("app").to_s
|
332
|
+
paths << Rails.root.join("lib").to_s
|
333
|
+
paths << Rails.root.join("config").to_s
|
331
334
|
end
|
332
335
|
|
333
336
|
# Add current working directory
|
334
337
|
paths << Dir.pwd
|
335
338
|
|
336
339
|
# Add gem paths
|
337
|
-
paths.concat(Gem.path.map { |p| File.join(p,
|
340
|
+
paths.concat(Gem.path.map { |p| File.join(p, "gems") }) if defined?(Gem)
|
338
341
|
|
339
342
|
# Sort by length (longest first) for better matching
|
340
343
|
paths.uniq.sort_by(&:length).reverse
|
data/lib/lapsoss/client.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require_relative 'scope'
|
5
|
-
require_relative 'current'
|
3
|
+
require "concurrent"
|
6
4
|
|
7
5
|
module Lapsoss
|
8
6
|
class Client
|
@@ -47,7 +45,7 @@ module Lapsoss
|
|
47
45
|
original_scope = current_scope
|
48
46
|
|
49
47
|
# Create a merged scope with the new context
|
50
|
-
merged_scope = MergedScope.new([context], original_scope)
|
48
|
+
merged_scope = MergedScope.new([ context ], original_scope)
|
51
49
|
Current.scope = merged_scope
|
52
50
|
|
53
51
|
yield(merged_scope)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require 'active_support/configurable'
|
3
|
+
require "active_support/configurable"
|
5
4
|
|
6
5
|
module Lapsoss
|
7
6
|
class Configuration
|
@@ -15,7 +14,7 @@ module Lapsoss
|
|
15
14
|
:backtrace_context_lines, :backtrace_in_app_patterns, :backtrace_exclude_patterns,
|
16
15
|
:backtrace_strip_load_path, :backtrace_max_frames, :backtrace_enable_code_context,
|
17
16
|
:enable_pipeline, :pipeline_builder, :sampling_strategy,
|
18
|
-
:skip_rails_cache_errors, :force_sync_http
|
17
|
+
:skip_rails_cache_errors, :force_sync_http, :capture_request_context
|
19
18
|
attr_reader :fingerprint_callback, :environment, :before_send, :sample_rate, :error_handler, :transport_timeout,
|
20
19
|
:transport_max_retries, :transport_initial_backoff, :transport_max_backoff, :transport_backoff_multiplier, :transport_ssl_verify, :default_context, :adapter_configs
|
21
20
|
|
@@ -64,6 +63,8 @@ module Lapsoss
|
|
64
63
|
@skip_rails_cache_errors = true
|
65
64
|
# HTTP client settings
|
66
65
|
@force_sync_http = false
|
66
|
+
# Capture request context in middleware
|
67
|
+
@capture_request_context = true
|
67
68
|
end
|
68
69
|
|
69
70
|
# Register a named adapter configuration
|
@@ -172,7 +173,6 @@ module Lapsoss
|
|
172
173
|
|
173
174
|
# Pipeline configuration
|
174
175
|
def configure_pipeline
|
175
|
-
require_relative 'pipeline'
|
176
176
|
@pipeline_builder = PipelineBuilder.new
|
177
177
|
yield(@pipeline_builder) if block_given?
|
178
178
|
@pipeline_builder
|
@@ -184,8 +184,6 @@ module Lapsoss
|
|
184
184
|
|
185
185
|
# Sampling configuration
|
186
186
|
def configure_sampling(strategy = nil, &block)
|
187
|
-
require_relative 'sampling'
|
188
|
-
|
189
187
|
if strategy
|
190
188
|
@sampling_strategy = strategy
|
191
189
|
elsif block_given?
|
@@ -194,8 +192,6 @@ module Lapsoss
|
|
194
192
|
end
|
195
193
|
|
196
194
|
def create_sampling_strategy
|
197
|
-
require_relative 'sampling'
|
198
|
-
|
199
195
|
case @sampling_strategy
|
200
196
|
when Symbol
|
201
197
|
case @sampling_strategy
|
@@ -219,80 +215,80 @@ module Lapsoss
|
|
219
215
|
|
220
216
|
# Validation and setter overrides
|
221
217
|
def sample_rate=(value)
|
222
|
-
validate_sample_rate!(value,
|
218
|
+
validate_sample_rate!(value, "sample_rate") if value
|
223
219
|
@sample_rate = value
|
224
220
|
end
|
225
221
|
|
226
222
|
def before_send=(value)
|
227
|
-
validate_callable!(value,
|
223
|
+
validate_callable!(value, "before_send")
|
228
224
|
@before_send = value
|
229
225
|
end
|
230
226
|
|
231
227
|
def error_handler=(value)
|
232
|
-
validate_callable!(value,
|
228
|
+
validate_callable!(value, "error_handler")
|
233
229
|
@error_handler = value
|
234
230
|
end
|
235
231
|
|
236
232
|
def environment=(value)
|
237
|
-
validate_environment!(value,
|
233
|
+
validate_environment!(value, "environment") if value
|
238
234
|
@environment = value&.to_s
|
239
235
|
end
|
240
236
|
|
241
237
|
def transport_timeout=(value)
|
242
|
-
validate_timeout!(value,
|
238
|
+
validate_timeout!(value, "transport_timeout") if value
|
243
239
|
@transport_timeout = value
|
244
240
|
end
|
245
241
|
|
246
242
|
def transport_max_retries=(value)
|
247
|
-
validate_retries!(value,
|
243
|
+
validate_retries!(value, "transport_max_retries") if value
|
248
244
|
@transport_max_retries = value
|
249
245
|
end
|
250
246
|
|
251
247
|
def transport_initial_backoff=(value)
|
252
|
-
validate_timeout!(value,
|
248
|
+
validate_timeout!(value, "transport_initial_backoff") if value
|
253
249
|
@transport_initial_backoff = value
|
254
250
|
end
|
255
251
|
|
256
252
|
def transport_max_backoff=(value)
|
257
|
-
validate_timeout!(value,
|
253
|
+
validate_timeout!(value, "transport_max_backoff") if value
|
258
254
|
@transport_max_backoff = value
|
259
255
|
end
|
260
256
|
|
261
257
|
def transport_backoff_multiplier=(value)
|
262
258
|
if value
|
263
|
-
validate_type!(value, [Numeric],
|
264
|
-
validate_numeric_range!(value, 1.0..10.0,
|
259
|
+
validate_type!(value, [ Numeric ], "transport_backoff_multiplier")
|
260
|
+
validate_numeric_range!(value, 1.0..10.0, "transport_backoff_multiplier")
|
265
261
|
end
|
266
262
|
@transport_backoff_multiplier = value
|
267
263
|
end
|
268
264
|
|
269
265
|
def transport_ssl_verify=(value)
|
270
|
-
validate_boolean!(value,
|
266
|
+
validate_boolean!(value, "transport_ssl_verify") if value
|
271
267
|
@transport_ssl_verify = value
|
272
268
|
end
|
273
269
|
|
274
270
|
def fingerprint_callback=(value)
|
275
|
-
validate_callable!(value,
|
271
|
+
validate_callable!(value, "fingerprint_callback")
|
276
272
|
@fingerprint_callback = value
|
277
273
|
end
|
278
274
|
|
279
275
|
# Configuration validation
|
280
276
|
def validate!
|
281
|
-
validate_sample_rate!(@sample_rate,
|
282
|
-
validate_callable!(@before_send,
|
283
|
-
validate_callable!(@error_handler,
|
284
|
-
validate_callable!(@fingerprint_callback,
|
285
|
-
validate_environment!(@environment,
|
277
|
+
validate_sample_rate!(@sample_rate, "sample_rate") if @sample_rate
|
278
|
+
validate_callable!(@before_send, "before_send")
|
279
|
+
validate_callable!(@error_handler, "error_handler")
|
280
|
+
validate_callable!(@fingerprint_callback, "fingerprint_callback")
|
281
|
+
validate_environment!(@environment, "environment") if @environment
|
286
282
|
|
287
283
|
# Validate transport settings
|
288
|
-
validate_timeout!(@transport_timeout,
|
289
|
-
validate_retries!(@transport_max_retries,
|
290
|
-
validate_timeout!(@transport_initial_backoff,
|
291
|
-
validate_timeout!(@transport_max_backoff,
|
284
|
+
validate_timeout!(@transport_timeout, "transport_timeout")
|
285
|
+
validate_retries!(@transport_max_retries, "transport_max_retries")
|
286
|
+
validate_timeout!(@transport_initial_backoff, "transport_initial_backoff")
|
287
|
+
validate_timeout!(@transport_max_backoff, "transport_max_backoff")
|
292
288
|
|
293
289
|
if @transport_backoff_multiplier
|
294
|
-
validate_type!(@transport_backoff_multiplier, [Numeric],
|
295
|
-
validate_numeric_range!(@transport_backoff_multiplier, 1.0..10.0,
|
290
|
+
validate_type!(@transport_backoff_multiplier, [ Numeric ], "transport_backoff_multiplier")
|
291
|
+
validate_numeric_range!(@transport_backoff_multiplier, 1.0..10.0, "transport_backoff_multiplier")
|
296
292
|
end
|
297
293
|
|
298
294
|
# Validate that initial backoff is less than max backoff
|
@@ -311,7 +307,7 @@ module Lapsoss
|
|
311
307
|
|
312
308
|
def validate_adapter_config!(name, config)
|
313
309
|
validate_presence!(config[:type], "adapter type for '#{name}'")
|
314
|
-
validate_type!(config[:settings], [Hash], "adapter settings for '#{name}'")
|
310
|
+
validate_type!(config[:settings], [ Hash ], "adapter settings for '#{name}'")
|
315
311
|
end
|
316
312
|
end
|
317
313
|
end
|
data/lib/lapsoss/current.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "active_support/all"
|
4
4
|
|
5
5
|
module Lapsoss
|
6
6
|
class Current < ActiveSupport::CurrentAttributes
|
7
|
-
attribute :scope
|
7
|
+
attribute :scope, default: -> { Scope.new }
|
8
|
+
|
9
|
+
def self.with_clean_scope
|
10
|
+
previous_scope = scope
|
11
|
+
self.scope = Scope.new
|
12
|
+
yield
|
13
|
+
ensure
|
14
|
+
self.scope = previous_scope
|
15
|
+
end
|
8
16
|
end
|
9
17
|
end
|
data/lib/lapsoss/event.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'scrubber'
|
4
|
-
require_relative 'fingerprinter'
|
5
|
-
require_relative 'backtrace_processor'
|
6
|
-
|
7
3
|
module Lapsoss
|
8
4
|
class Event
|
9
5
|
attr_accessor :type, :timestamp, :level, :message, :exception, :context, :environment, :fingerprint,
|
@@ -12,7 +8,7 @@ module Lapsoss
|
|
12
8
|
def initialize(type:, level: :info, **attributes)
|
13
9
|
@type = type
|
14
10
|
@level = level
|
15
|
-
@timestamp =
|
11
|
+
@timestamp = Utils.current_time
|
16
12
|
@context = {}
|
17
13
|
@environment = Lapsoss.configuration.environment
|
18
14
|
|
@@ -23,6 +19,9 @@ module Lapsoss
|
|
23
19
|
# Process backtrace if we have an exception
|
24
20
|
@backtrace_frames = process_backtrace if @exception
|
25
21
|
|
22
|
+
# Set message from exception if not provided
|
23
|
+
@message ||= @exception.message if @exception
|
24
|
+
|
26
25
|
# Generate fingerprint after all attributes are set (unless explicitly set to nil or a value)
|
27
26
|
@fingerprint = generate_fingerprint if @fingerprint.nil? && !attributes.key?(:fingerprint)
|
28
27
|
end
|
@@ -104,5 +103,29 @@ module Lapsoss
|
|
104
103
|
|
105
104
|
@backtrace_frames.map(&:to_h)
|
106
105
|
end
|
106
|
+
|
107
|
+
public
|
108
|
+
|
109
|
+
def exception_type
|
110
|
+
exception&.class&.name
|
111
|
+
end
|
112
|
+
|
113
|
+
def backtrace
|
114
|
+
if @backtrace_frames
|
115
|
+
@backtrace_frames.map(&:raw_line)
|
116
|
+
elsif exception
|
117
|
+
exception.backtrace
|
118
|
+
else
|
119
|
+
[]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def request_context
|
124
|
+
# Request context is stored in extra by the middleware
|
125
|
+
# Check both string and symbol keys for compatibility
|
126
|
+
return nil unless context[:extra]
|
127
|
+
|
128
|
+
context[:extra]["request"] || context[:extra][:request]
|
129
|
+
end
|
107
130
|
end
|
108
131
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lapsoss
|
4
|
+
# Wrapper for BacktraceFrame that adds exception-specific metadata
|
5
|
+
class ExceptionBacktraceFrame
|
6
|
+
attr_reader :frame, :exception_class, :is_crash_frame
|
7
|
+
|
8
|
+
def initialize(frame, exception_class: nil, is_crash_frame: false)
|
9
|
+
@frame = frame
|
10
|
+
@exception_class = exception_class
|
11
|
+
@is_crash_frame = is_crash_frame
|
12
|
+
end
|
13
|
+
|
14
|
+
def crash_frame?
|
15
|
+
@is_crash_frame
|
16
|
+
end
|
17
|
+
|
18
|
+
# Delegate all other methods to the wrapped frame
|
19
|
+
def method_missing(method, *, &)
|
20
|
+
if @frame.respond_to?(method)
|
21
|
+
@frame.send(method, *, &)
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def respond_to_missing?(method, include_private = false)
|
28
|
+
@frame.respond_to?(method, include_private) || super
|
29
|
+
end
|
30
|
+
|
31
|
+
# Override to_h to include exception metadata
|
32
|
+
def to_h
|
33
|
+
@frame.to_h.merge(
|
34
|
+
exception_class: @exception_class,
|
35
|
+
crash_frame: @is_crash_frame
|
36
|
+
).compact
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lapsoss
|
4
|
+
# Configuration helper for exclusions
|
5
|
+
module ExclusionConfiguration
|
6
|
+
def self.configure_exclusions(config, preset: nil, **custom_config)
|
7
|
+
exclusion_config = if preset
|
8
|
+
case preset
|
9
|
+
when Array
|
10
|
+
ExclusionPresets.combined(preset)
|
11
|
+
else
|
12
|
+
ExclusionPresets.send(preset)
|
13
|
+
end
|
14
|
+
else
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Merge custom configuration
|
19
|
+
exclusion_config.merge!(custom_config)
|
20
|
+
|
21
|
+
# Create exclusion filter
|
22
|
+
exclusion_filter = ExclusionFilter.new(exclusion_config)
|
23
|
+
|
24
|
+
# Add to configuration
|
25
|
+
config.exclusion_filter = exclusion_filter
|
26
|
+
|
27
|
+
exclusion_filter
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|