lapsoss 0.2.0 → 0.3.1
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 +27 -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/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/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 +60 -7
- data/lib/lapsoss/middleware.rb +0 -345
- data/lib/lapsoss/sampling.rb +0 -328
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
|
3
|
+
require "set"
|
4
|
+
require "active_support/cache"
|
5
|
+
require "active_support/core_ext/numeric/time"
|
6
6
|
|
7
7
|
module Lapsoss
|
8
8
|
class BacktraceProcessor
|
@@ -42,10 +42,10 @@ module Lapsoss
|
|
42
42
|
exclude_patterns: config.backtrace_exclude_patterns,
|
43
43
|
strip_load_path: config.backtrace_strip_load_path
|
44
44
|
}
|
45
|
-
|
45
|
+
else
|
46
46
|
# Hash passed
|
47
47
|
config
|
48
|
-
|
48
|
+
end
|
49
49
|
|
50
50
|
@config = DEFAULT_CONFIG.merge(config_hash)
|
51
51
|
@file_cache = ActiveSupport::Cache::MemoryStore.new(
|
@@ -83,10 +83,13 @@ module Lapsoss
|
|
83
83
|
|
84
84
|
frames = process_backtrace(exception.backtrace)
|
85
85
|
|
86
|
-
#
|
87
|
-
frames.
|
88
|
-
|
89
|
-
|
86
|
+
# Wrap frames with exception-specific context
|
87
|
+
frames = frames.map.with_index do |frame, index|
|
88
|
+
ExceptionBacktraceFrame.new(
|
89
|
+
frame,
|
90
|
+
exception_class: exception.class.name,
|
91
|
+
is_crash_frame: index.zero?
|
92
|
+
)
|
90
93
|
end
|
91
94
|
|
92
95
|
# Follow exception causes if requested
|
@@ -179,7 +182,7 @@ module Lapsoss
|
|
179
182
|
file_cache: {
|
180
183
|
# ActiveSupport::Cache::MemoryStore doesn't expose detailed stats
|
181
184
|
# but we can provide basic info
|
182
|
-
type:
|
185
|
+
type: "ActiveSupport::Cache::MemoryStore",
|
183
186
|
configured_size: @file_cache.options[:size]
|
184
187
|
},
|
185
188
|
config: @config,
|
@@ -207,8 +210,8 @@ module Lapsoss
|
|
207
210
|
return nil if line_index.negative? || line_index >= lines.length
|
208
211
|
|
209
212
|
# Calculate context range
|
210
|
-
start_line = [0, line_index - context_lines].max
|
211
|
-
end_line = [lines.length - 1, line_index + context_lines].min
|
213
|
+
start_line = [ 0, line_index - context_lines ].max
|
214
|
+
end_line = [ lines.length - 1, line_index + context_lines ].min
|
212
215
|
|
213
216
|
{
|
214
217
|
pre_context: lines[start_line...line_index],
|
@@ -234,7 +237,7 @@ module Lapsoss
|
|
234
237
|
def parse_frames(backtrace)
|
235
238
|
load_paths = determine_load_paths
|
236
239
|
frames = backtrace.map do |line|
|
237
|
-
|
240
|
+
BacktraceFrameFactory.from_raw_line(
|
238
241
|
line,
|
239
242
|
in_app_patterns: @config[:in_app_patterns],
|
240
243
|
exclude_patterns: @config[:exclude_patterns],
|
@@ -248,7 +251,7 @@ module Lapsoss
|
|
248
251
|
|
249
252
|
def filter_frames(frames)
|
250
253
|
# Remove excluded frames
|
251
|
-
frames = frames.reject
|
254
|
+
frames = frames.reject { |frame| frame.excluded?(@config[:exclude_patterns]) }
|
252
255
|
|
253
256
|
# Filter gems if configured
|
254
257
|
unless @config[:include_gems_in_context]
|
@@ -284,9 +287,9 @@ module Lapsoss
|
|
284
287
|
# Get tail frames (original cause)
|
285
288
|
tail_frames = if tail_count.positive?
|
286
289
|
frames.last(tail_count)
|
287
|
-
|
290
|
+
else
|
288
291
|
[]
|
289
|
-
|
292
|
+
end
|
290
293
|
|
291
294
|
head_frames + tail_frames
|
292
295
|
end
|
@@ -296,8 +299,9 @@ module Lapsoss
|
|
296
299
|
context_frames = frames.select(&:app_frame?)
|
297
300
|
context_frames += frames.select(&:library_frame?).first(3)
|
298
301
|
|
299
|
-
context_frames.
|
300
|
-
frame.add_code_context(self, @config[:context_lines])
|
302
|
+
context_frames.each_with_index do |frame, _index|
|
303
|
+
updated_frame = frame.add_code_context(self, @config[:context_lines])
|
304
|
+
frames[frames.index(frame)] = updated_frame if updated_frame
|
301
305
|
end
|
302
306
|
end
|
303
307
|
|
@@ -305,7 +309,7 @@ module Lapsoss
|
|
305
309
|
seen = Set.new
|
306
310
|
frames.select do |frame|
|
307
311
|
# Create a key based on filename, line, and method
|
308
|
-
key = [frame.filename, frame.line_number, frame.function].join(
|
312
|
+
key = [ frame.filename, frame.line_number, frame.function ].join(":")
|
309
313
|
|
310
314
|
if seen.include?(key)
|
311
315
|
false
|
@@ -325,16 +329,16 @@ module Lapsoss
|
|
325
329
|
# Add common Rails paths if in Rails
|
326
330
|
if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
|
327
331
|
paths << Rails.root.to_s
|
328
|
-
paths << Rails.root.join(
|
329
|
-
paths << Rails.root.join(
|
330
|
-
paths << Rails.root.join(
|
332
|
+
paths << Rails.root.join("app").to_s
|
333
|
+
paths << Rails.root.join("lib").to_s
|
334
|
+
paths << Rails.root.join("config").to_s
|
331
335
|
end
|
332
336
|
|
333
337
|
# Add current working directory
|
334
338
|
paths << Dir.pwd
|
335
339
|
|
336
340
|
# Add gem paths
|
337
|
-
paths.concat(Gem.path.map { |p| File.join(p,
|
341
|
+
paths.concat(Gem.path.map { |p| File.join(p, "gems") }) if defined?(Gem)
|
338
342
|
|
339
343
|
# Sort by length (longest first) for better matching
|
340
344
|
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
|