lapsoss 0.3.1 → 0.4.2

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +71 -7
  3. data/lib/lapsoss/adapters/appsignal_adapter.rb +18 -12
  4. data/lib/lapsoss/adapters/base.rb +19 -0
  5. data/lib/lapsoss/adapters/concerns/envelope_builder.rb +127 -0
  6. data/lib/lapsoss/adapters/concerns/http_delivery.rb +130 -0
  7. data/lib/lapsoss/adapters/concerns/level_mapping.rb +65 -0
  8. data/lib/lapsoss/adapters/insight_hub_adapter.rb +21 -21
  9. data/lib/lapsoss/adapters/rollbar_adapter.rb +64 -122
  10. data/lib/lapsoss/adapters/sentry_adapter.rb +77 -143
  11. data/lib/lapsoss/backtrace_processor.rb +1 -1
  12. data/lib/lapsoss/breadcrumb.rb +59 -0
  13. data/lib/lapsoss/client.rb +3 -5
  14. data/lib/lapsoss/configuration.rb +26 -31
  15. data/lib/lapsoss/event.rb +90 -96
  16. data/lib/lapsoss/fingerprinter.rb +57 -49
  17. data/lib/lapsoss/merged_scope.rb +1 -6
  18. data/lib/lapsoss/middleware/release_tracker.rb +11 -98
  19. data/lib/lapsoss/pipeline_builder.rb +2 -2
  20. data/lib/lapsoss/rails_error_subscriber.rb +3 -4
  21. data/lib/lapsoss/rails_middleware.rb +2 -2
  22. data/lib/lapsoss/railtie.rb +13 -2
  23. data/lib/lapsoss/registry.rb +7 -7
  24. data/lib/lapsoss/router.rb +1 -3
  25. data/lib/lapsoss/scope.rb +1 -6
  26. data/lib/lapsoss/scrubber.rb +15 -148
  27. data/lib/lapsoss/validators.rb +63 -92
  28. data/lib/lapsoss/version.rb +1 -1
  29. metadata +8 -24
  30. data/CHANGELOG.md +0 -5
  31. data/lib/lapsoss/exclusion_configuration.rb +0 -30
  32. data/lib/lapsoss/exclusion_presets.rb +0 -249
  33. data/lib/lapsoss/middleware/sample_filter.rb +0 -23
  34. data/lib/lapsoss/middleware/sampling_middleware.rb +0 -18
  35. data/lib/lapsoss/middleware/user_context_enhancer.rb +0 -46
  36. data/lib/lapsoss/release_providers.rb +0 -110
  37. data/lib/lapsoss/sampling/adaptive_sampler.rb +0 -46
  38. data/lib/lapsoss/sampling/composite_sampler.rb +0 -26
  39. data/lib/lapsoss/sampling/consistent_hash_sampler.rb +0 -30
  40. data/lib/lapsoss/sampling/exception_type_sampler.rb +0 -44
  41. data/lib/lapsoss/sampling/health_based_sampler.rb +0 -19
  42. data/lib/lapsoss/sampling/sampling_factory.rb +0 -69
  43. data/lib/lapsoss/sampling/time_based_sampler.rb +0 -44
  44. data/lib/lapsoss/sampling/user_based_sampler.rb +0 -42
  45. data/lib/lapsoss/user_context.rb +0 -175
  46. data/lib/lapsoss/user_context_integrations.rb +0 -39
  47. data/lib/lapsoss/user_context_middleware.rb +0 -50
  48. data/lib/lapsoss/user_context_provider.rb +0 -93
  49. data/lib/lapsoss/utils.rb +0 -13
@@ -2,7 +2,13 @@
2
2
 
3
3
  module Lapsoss
4
4
  class Railtie < Rails::Railtie
5
- Rails.logger.debug "[Lapsoss] Railtie loaded" if ENV["DEBUG_LAPSOSS"]
5
+ if ENV["DEBUG_LAPSOSS"]
6
+ if Rails.logger.respond_to?(:tagged)
7
+ Rails.logger.tagged("Lapsoss") { Rails.logger.debug "Railtie loaded" }
8
+ else
9
+ Rails.logger.debug "[Lapsoss] Railtie loaded"
10
+ end
11
+ end
6
12
  config.lapsoss = ActiveSupport::OrderedOptions.new
7
13
 
8
14
  initializer "lapsoss.configure" do |_app|
@@ -14,7 +20,12 @@ module Lapsoss
14
20
  Rails.env
15
21
  end
16
22
 
17
- config.logger ||= Rails.logger
23
+ # Use tagged logger for all Lapsoss logs
24
+ config.logger ||= if Rails.logger.respond_to?(:tagged)
25
+ Rails.logger.tagged("Lapsoss")
26
+ else
27
+ ActiveSupport::TaggedLogging.new(Rails.logger).tagged("Lapsoss")
28
+ end
18
29
 
19
30
  config.release ||= if Rails.application.respond_to?(:version)
20
31
  Rails.application.version.to_s
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "singleton"
4
4
  require "concurrent"
5
+ require "active_support/core_ext/string/inflections"
5
6
 
6
7
  module Lapsoss
7
8
  class Registry
@@ -42,7 +43,7 @@ module Lapsoss
42
43
  name = if adapter.respond_to?(:name) && adapter.name
43
44
  adapter.name.to_sym
44
45
  elsif adapter.class.name
45
- adapter.class.name.split("::").last.to_sym
46
+ adapter.class.name.demodulize.underscore.to_sym
46
47
  else
47
48
  # Generate a unique name if class name is nil (anonymous class)
48
49
  :"adapter_#{adapter.object_id}"
@@ -116,13 +117,12 @@ module Lapsoss
116
117
  # Resolve adapter type to class
117
118
  def resolve_adapter_class(type)
118
119
  # Try to get the class by convention: Adapters::{Type}Adapter
119
- class_name = "#{type.to_s.split('_').map(&:capitalize).join}Adapter"
120
+ class_name = "#{type.to_s.camelize}Adapter"
121
+ full_class_name = "Lapsoss::Adapters::#{class_name}"
120
122
 
121
- begin
122
- Adapters.const_get(class_name)
123
- rescue NameError
124
- raise AdapterNotFoundError, "Unknown adapter type: #{type}. Expected class: Lapsoss::Adapters::#{class_name}"
125
- end
123
+ full_class_name.constantize
124
+ rescue NameError
125
+ raise AdapterNotFoundError, "Unknown adapter type: #{type}. Expected class: #{full_class_name}"
126
126
  end
127
127
  end
128
128
  end
@@ -19,10 +19,8 @@ module Lapsoss
19
19
 
20
20
  # Handle adapter errors gracefully
21
21
  def handle_adapter_error(adapter, event, error)
22
- return unless Lapsoss.configuration.logger
23
-
24
22
  Lapsoss.configuration.logger.error(
25
- "[Lapsoss] Adapter '#{adapter.name}' failed to capture event (type: #{event.type}): #{error.message}"
23
+ "Adapter '#{adapter.name}' failed to capture event (type: #{event.type}): #{error.message}"
26
24
  )
27
25
 
28
26
  # Call error handler if configured
data/lib/lapsoss/scope.rb CHANGED
@@ -12,12 +12,7 @@ module Lapsoss
12
12
  end
13
13
 
14
14
  def add_breadcrumb(message, type: :default, **metadata)
15
- breadcrumb = {
16
- message: message,
17
- type: type,
18
- metadata: metadata,
19
- timestamp: Time.now.utc
20
- }
15
+ breadcrumb = Breadcrumb.build(message, type: type, metadata: metadata)
21
16
  @breadcrumbs << breadcrumb
22
17
  # Keep breadcrumbs to a reasonable limit
23
18
  @breadcrumbs.shift if @breadcrumbs.length > 20
@@ -4,165 +4,32 @@ require "active_support/parameter_filter"
4
4
 
5
5
  module Lapsoss
6
6
  class Scrubber
7
- DEFAULT_SCRUB_FIELDS = %w[
8
- password passwd pwd secret token key api_key access_token
9
- authorization auth_token session_token csrf_token
10
- credit_card cc_number card_number ssn social_security_number
11
- phone mobile email_address
12
- ].freeze
13
-
14
- PROTECTED_EVENT_FIELDS = %w[
15
- type timestamp level message exception environment context
16
- ].freeze
17
-
18
- ATTACHMENT_CLASSES = %w[
19
- ActionDispatch::Http::UploadedFile
20
- Rack::Multipart::UploadedFile
21
- Tempfile
7
+ # Match Rails conventions - these are only used when Rails is not available
8
+ # Rails uses partial matching, so 'passw' matches 'password'
9
+ DEFAULT_SCRUB_FIELDS = %i[
10
+ passw email secret token _key crypt salt certificate otp ssn cvv cvc
22
11
  ].freeze
23
12
 
24
13
  def initialize(config = {})
25
- @rails_parameter_filter = rails_parameter_filter
26
-
27
- # Only use custom scrubbing if Rails parameter filter is not available
28
- return if @rails_parameter_filter
29
-
30
- @scrub_fields = Array(config[:scrub_fields] || DEFAULT_SCRUB_FIELDS)
31
- @scrub_all = config[:scrub_all] || false
32
- @whitelist_fields = Array(config[:whitelist_fields] || [])
33
- @randomize_scrub_length = config[:randomize_scrub_length] || false
34
- @scrub_value = config[:scrub_value] || "**SCRUBBED**"
35
- end
36
-
37
- def scrub(data)
38
- return data if data.nil?
39
-
40
- # If Rails parameter filter is available, use it exclusively
41
- return @rails_parameter_filter.filter(data) if @rails_parameter_filter
42
-
43
- # Fallback to custom scrubbing logic only if Rails filter is not available
44
- @scrubbed_objects = {}.compare_by_identity
45
- scrub_recursive(data)
46
- end
47
-
48
- private
49
-
50
- def scrub_recursive(data)
51
- return data if @scrubbed_objects.key?(data)
52
-
53
- @scrubbed_objects[data] = true
54
-
55
- case data
56
- when Hash
57
- scrub_hash(data)
58
- when Array
59
- scrub_array(data)
14
+ # Combine: Rails filter parameters + custom fields (if provided)
15
+ base_params = if defined?(Rails) && Rails.respond_to?(:application) && Rails.application
16
+ Rails.application.config.filter_parameters.presence || DEFAULT_SCRUB_FIELDS
60
17
  else
61
- scrub_value(data)
18
+ DEFAULT_SCRUB_FIELDS
62
19
  end
63
- end
64
20
 
65
- def scrub_hash(hash)
66
- hash.each_with_object({}) do |(key, value), result|
67
- key_string = key.to_s.downcase
68
-
69
- result[key] = if should_scrub_field?(key_string)
70
- generate_scrub_value(value)
71
- elsif value.is_a?(Hash)
72
- scrub_recursive(value)
73
- elsif value.is_a?(Array)
74
- scrub_array(value)
75
- else
76
- scrub_value(value)
77
- end
78
- end
79
- end
80
-
81
- def scrub_array(array)
82
- array.map do |item|
83
- scrub_recursive(item)
84
- end
85
- end
86
-
87
- def scrub_value(value)
88
- if attachment_value?(value)
89
- scrub_attachment(value)
21
+ filter_params = if config[:scrub_fields]
22
+ Array(base_params) + Array(config[:scrub_fields])
90
23
  else
91
- value
24
+ base_params
92
25
  end
93
- end
94
-
95
- def should_scrub_field?(field_name)
96
- return false if whitelisted_field?(field_name)
97
- return false if protected_event_field?(field_name)
98
- return true if @scrub_all
99
26
 
100
- @scrub_fields.any? { |pattern| field_matches_pattern?(field_name, pattern) }
27
+ @filter = ActiveSupport::ParameterFilter.new(filter_params)
101
28
  end
102
29
 
103
- def field_matches_pattern?(field_name, pattern)
104
- if pattern.is_a?(Regexp)
105
- pattern.match?(field_name)
106
- else
107
- field_name.include?(pattern.to_s.downcase)
108
- end
109
- end
110
-
111
- def whitelisted_field?(field_name)
112
- @whitelist_fields.any? { |pattern| field_matches_pattern?(field_name, pattern) }
113
- end
114
-
115
- def protected_event_field?(field_name)
116
- PROTECTED_EVENT_FIELDS.include?(field_name.to_s)
117
- end
118
-
119
- def whitelisted_value?(_value)
120
- # Basic implementation - could be extended
121
- false
122
- end
123
-
124
- def attachment_value?(value)
125
- return false unless value.respond_to?(:class)
126
-
127
- ATTACHMENT_CLASSES.include?(value.class.name)
128
- end
129
-
130
- def scrub_attachment(attachment)
131
- {
132
- __attachment__: true,
133
- content_type: safe_call(attachment, :content_type),
134
- original_filename: safe_call(attachment, :original_filename),
135
- size: safe_call(attachment, :size) || safe_call(attachment, :tempfile, :size)
136
- }
137
- rescue StandardError => e
138
- { __attachment__: true, error: "Failed to extract attachment info: #{e.message}" }
139
- end
140
-
141
- def safe_call(object, *methods)
142
- methods.reduce(object) do |obj, method|
143
- obj.respond_to?(method) ? obj.public_send(method) : nil
144
- end
145
- end
146
-
147
- def generate_scrub_value(_original_value)
148
- if @randomize_scrub_length
149
- "*" * rand(6..12)
150
- else
151
- @scrub_value
152
- end
153
- end
154
-
155
- def rails_parameter_filter
156
- return nil unless defined?(Rails) && Rails.respond_to?(:application) && Rails.application
157
- return nil unless defined?(ActiveSupport::ParameterFilter)
158
-
159
- filter_params = Rails.application.config.filter_parameters
160
- return nil if filter_params.empty?
161
-
162
- ActiveSupport::ParameterFilter.new(filter_params)
163
- rescue StandardError
164
- # Fallback silently if Rails config is not available
165
- nil
30
+ def scrub(data)
31
+ return data if data.nil?
32
+ @filter.filter(data)
166
33
  end
167
34
  end
168
35
  end
@@ -1,129 +1,100 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "uri"
3
+ require "active_support/core_ext/object/blank"
4
4
 
5
5
  module Lapsoss
6
6
  module Validators
7
- class ValidationError < StandardError; end
7
+ extend ActiveSupport::Concern
8
8
 
9
9
  module_function
10
10
 
11
- def validate_presence!(value, name)
12
- if value.nil? || (value.respond_to?(:empty?) && value.empty?)
13
- raise ValidationError, "#{name} is required and cannot be nil or empty"
14
- end
11
+ def logger
12
+ Lapsoss.configuration.logger
15
13
  end
16
14
 
17
- def validate_type!(value, types, name)
18
- types = Array(types)
19
- unless types.any? { |type| value.is_a?(type) }
20
- type_names = types.map(&:name).join(" or ")
21
- raise ValidationError, "#{name} must be a #{type_names}, got #{value.class} (#{value.inspect})"
22
- end
15
+ # Simple presence check using AS blank?
16
+ def validate_presence!(value, name)
17
+ return true if value.present?
18
+ logger.warn "#{name} is missing or blank"
19
+ false
23
20
  end
24
21
 
22
+ # Check if callable
25
23
  def validate_callable!(value, name)
26
- unless value.nil? || value.respond_to?(:call)
27
- raise ValidationError, "#{name} must be callable (respond_to? :call) or nil, got #{value.class}"
28
- end
24
+ return true if value.nil? || value.respond_to?(:call)
25
+ logger.warn "#{name} should be callable but got #{value.class}"
26
+ false
29
27
  end
30
28
 
31
- def validate_numeric_range!(value, range, name)
32
- validate_type!(value, [ Numeric ], name)
33
- unless range.cover?(value)
34
- raise ValidationError, "#{name} must be between #{range.min} and #{range.max}, got #{value}"
35
- end
29
+ # DSN validation - just log issues
30
+ def validate_dsn!(dsn_string, name = "DSN")
31
+ return true if dsn_string.blank?
32
+
33
+ uri = URI.parse(dsn_string)
34
+ logger.warn "#{name} appears to be missing public key" if uri.user.blank?
35
+ logger.warn "#{name} appears to be missing host" if uri.host.blank?
36
+ true
37
+ rescue URI::InvalidURIError => e
38
+ logger.error "#{name} couldn't be parsed: #{e.message}"
39
+ false
36
40
  end
37
41
 
38
- def validate_url!(value, name)
39
- return if value.nil?
40
-
41
- validate_type!(value, [ String ], name)
42
-
43
- begin
44
- uri = URI.parse(value)
45
- raise ValidationError, "#{name} must be a valid URL with scheme and host" unless uri.scheme && uri.host
46
- raise ValidationError, "#{name} must use http or https scheme" unless %w[http https].include?(uri.scheme)
47
- rescue URI::InvalidURIError => e
48
- raise ValidationError, "#{name} is not a valid URL: #{e.message}"
49
- end
42
+ # Validate numeric ranges using AS Range#cover?
43
+ def validate_sample_rate!(value, name)
44
+ return true if value.nil?
45
+ return true if (0..1).cover?(value)
46
+ logger.warn "#{name} should be between 0 and 1, got #{value}"
47
+ false
50
48
  end
51
49
 
52
- def validate_dsn!(dsn_string, name = "DSN")
53
- return if dsn_string.nil?
54
-
55
- validate_type!(dsn_string, [ String ], name)
56
-
57
- begin
58
- uri = URI.parse(dsn_string)
50
+ def validate_timeout!(value, name)
51
+ return true if value.nil?
52
+ return true if value.positive?
53
+ logger.warn "#{name} should be positive, got #{value}"
54
+ false
55
+ end
59
56
 
60
- # Check required components
61
- validate_presence!(uri.scheme, "#{name} scheme")
62
- validate_presence!(uri.host, "#{name} host")
63
- validate_presence!(uri.user, "#{name} public key")
57
+ def validate_retries!(value, name)
58
+ return true if value.nil?
59
+ return true if value >= 0
60
+ logger.warn "#{name} should be non-negative, got #{value}"
61
+ false
62
+ end
64
63
 
65
- # Validate scheme
66
- raise ValidationError, "#{name} must use http or https scheme" unless %w[http https].include?(uri.scheme)
64
+ # Environment validation using AS presence
65
+ def validate_environment!(value, name = "environment")
66
+ return true if value.blank?
67
67
 
68
- # Extract project ID from path
69
- path_parts = uri.path&.split("/") || []
70
- project_id = path_parts.last
71
- validate_presence!(project_id, "#{name} project ID")
68
+ value_str = value.to_s.strip
69
+ return true if value_str.present?
72
70
 
73
- # Validate project ID is numeric
74
- unless project_id.match?(/^\d+$/)
75
- raise ValidationError, "#{name} project ID must be numeric, got '#{project_id}'"
76
- end
77
- rescue URI::InvalidURIError => e
78
- raise ValidationError, "#{name} is not a valid URI: #{e.message}"
79
- end
71
+ logger.warn "#{name} should not be empty"
72
+ false
80
73
  end
81
74
 
75
+ # API key validation using AS blank?
82
76
  def validate_api_key!(value, name, format: nil)
83
- validate_presence!(value, name)
84
- validate_type!(value, [ String ], name)
77
+ return false if value.blank? && logger.warn("#{name} is missing")
85
78
 
79
+ # Optional format hints
86
80
  case format
87
81
  when :uuid
88
- unless value.match?(/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i)
89
- raise ValidationError, "#{name} must be a valid UUID format"
90
- end
91
- when :hex
92
- raise ValidationError, "#{name} must be a valid hexadecimal string" unless value.match?(/\A[0-9a-f]+\z/i)
82
+ logger.info "#{name} doesn't look like a UUID, but continuing anyway" unless value.match?(/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i)
93
83
  when :alphanumeric
94
- raise ValidationError, "#{name} must be alphanumeric" unless value.match?(/\A[a-z0-9]+\z/i)
84
+ logger.info "#{name} contains special characters, but continuing anyway" unless value.match?(/\A[a-z0-9]+\z/i)
95
85
  end
96
- end
97
-
98
- def validate_environment!(value, name = "environment")
99
- return if value.nil?
100
-
101
- validate_type!(value, [ String, Symbol ], name)
102
86
 
103
- env_string = value.to_s
104
- unless env_string.match?(/\A[a-z0-9_-]+\z/i)
105
- raise ValidationError, "#{name} must contain only alphanumeric characters, underscores, and hyphens"
106
- end
87
+ true
107
88
  end
108
89
 
109
- def validate_sample_rate!(value, name = "sample_rate")
110
- return if value.nil?
111
-
112
- validate_numeric_range!(value, 0.0..1.0, name)
113
- end
114
-
115
- def validate_timeout!(value, name = "timeout")
116
- return if value.nil?
117
-
118
- validate_type!(value, [ Numeric ], name)
119
- raise ValidationError, "#{name} must be positive, got #{value}" if value <= 0
120
- end
121
-
122
- def validate_retries!(value, name = "max_retries")
123
- return if value.nil?
124
-
125
- validate_type!(value, [ Integer ], name)
126
- validate_numeric_range!(value, 0..10, name)
90
+ # URL validation
91
+ def validate_url!(value, name)
92
+ return true if value.nil?
93
+ URI.parse(value)
94
+ true
95
+ rescue URI::InvalidURIError => e
96
+ logger.warn "#{name} couldn't be parsed as URL: #{e.message}"
97
+ false
127
98
  end
128
99
  end
129
100
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lapsoss
4
- VERSION = "0.3.1"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lapsoss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
8
- bindir: exe
8
+ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
@@ -212,13 +212,15 @@ executables: []
212
212
  extensions: []
213
213
  extra_rdoc_files: []
214
214
  files:
215
- - CHANGELOG.md
216
215
  - LICENSE.txt
217
216
  - README.md
218
217
  - lib/lapsoss.rb
219
218
  - lib/lapsoss/adapters/appsignal_adapter.rb
220
219
  - lib/lapsoss/adapters/base.rb
221
220
  - lib/lapsoss/adapters/bugsnag_adapter.rb
221
+ - lib/lapsoss/adapters/concerns/envelope_builder.rb
222
+ - lib/lapsoss/adapters/concerns/http_delivery.rb
223
+ - lib/lapsoss/adapters/concerns/level_mapping.rb
222
224
  - lib/lapsoss/adapters/insight_hub_adapter.rb
223
225
  - lib/lapsoss/adapters/logger_adapter.rb
224
226
  - lib/lapsoss/adapters/rollbar_adapter.rb
@@ -226,14 +228,13 @@ files:
226
228
  - lib/lapsoss/backtrace_frame.rb
227
229
  - lib/lapsoss/backtrace_frame_factory.rb
228
230
  - lib/lapsoss/backtrace_processor.rb
231
+ - lib/lapsoss/breadcrumb.rb
229
232
  - lib/lapsoss/client.rb
230
233
  - lib/lapsoss/configuration.rb
231
234
  - lib/lapsoss/current.rb
232
235
  - lib/lapsoss/event.rb
233
236
  - lib/lapsoss/exception_backtrace_frame.rb
234
- - lib/lapsoss/exclusion_configuration.rb
235
237
  - lib/lapsoss/exclusion_filter.rb
236
- - lib/lapsoss/exclusion_presets.rb
237
238
  - lib/lapsoss/fingerprinter.rb
238
239
  - lib/lapsoss/http_client.rb
239
240
  - lib/lapsoss/merged_scope.rb
@@ -245,36 +246,19 @@ files:
245
246
  - lib/lapsoss/middleware/metrics_collector.rb
246
247
  - lib/lapsoss/middleware/rate_limiter.rb
247
248
  - lib/lapsoss/middleware/release_tracker.rb
248
- - lib/lapsoss/middleware/sample_filter.rb
249
- - lib/lapsoss/middleware/sampling_middleware.rb
250
- - lib/lapsoss/middleware/user_context_enhancer.rb
251
249
  - lib/lapsoss/pipeline.rb
252
250
  - lib/lapsoss/pipeline_builder.rb
253
251
  - lib/lapsoss/rails_error_subscriber.rb
254
252
  - lib/lapsoss/rails_middleware.rb
255
253
  - lib/lapsoss/railtie.rb
256
254
  - lib/lapsoss/registry.rb
257
- - lib/lapsoss/release_providers.rb
258
255
  - lib/lapsoss/release_tracker.rb
259
256
  - lib/lapsoss/router.rb
260
- - lib/lapsoss/sampling/adaptive_sampler.rb
261
257
  - lib/lapsoss/sampling/base.rb
262
- - lib/lapsoss/sampling/composite_sampler.rb
263
- - lib/lapsoss/sampling/consistent_hash_sampler.rb
264
- - lib/lapsoss/sampling/exception_type_sampler.rb
265
- - lib/lapsoss/sampling/health_based_sampler.rb
266
258
  - lib/lapsoss/sampling/rate_limiter.rb
267
- - lib/lapsoss/sampling/sampling_factory.rb
268
- - lib/lapsoss/sampling/time_based_sampler.rb
269
259
  - lib/lapsoss/sampling/uniform_sampler.rb
270
- - lib/lapsoss/sampling/user_based_sampler.rb
271
260
  - lib/lapsoss/scope.rb
272
261
  - lib/lapsoss/scrubber.rb
273
- - lib/lapsoss/user_context.rb
274
- - lib/lapsoss/user_context_integrations.rb
275
- - lib/lapsoss/user_context_middleware.rb
276
- - lib/lapsoss/user_context_provider.rb
277
- - lib/lapsoss/utils.rb
278
262
  - lib/lapsoss/validators.rb
279
263
  - lib/lapsoss/version.rb
280
264
  homepage: https://github.com/seuros/lapsoss
@@ -284,7 +268,7 @@ metadata:
284
268
  allowed_push_host: https://rubygems.org
285
269
  homepage_uri: https://github.com/seuros/lapsoss
286
270
  source_code_uri: https://github.com/seuros/lapsoss
287
- changelog_uri: https://github.com/seuros/lapsoss/blob/main/CHANGELOG.md
271
+ changelog_uri: https://github.com/seuros/lapsoss/blob/master/CHANGELOG.md
288
272
  rubygems_mfa_required: 'true'
289
273
  rdoc_options: []
290
274
  require_paths:
@@ -293,7 +277,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
293
277
  requirements:
294
278
  - - ">="
295
279
  - !ruby/object:Gem::Version
296
- version: 3.2.0
280
+ version: 3.3.0
297
281
  required_rubygems_version: !ruby/object:Gem::Requirement
298
282
  requirements:
299
283
  - - ">="
data/CHANGELOG.md DELETED
@@ -1,5 +0,0 @@
1
- ## [Unreleased]
2
-
3
- ## [0.1.0] - 2025-07-06
4
-
5
- - Initial release
@@ -1,30 +0,0 @@
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