lapsoss 0.4.11 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4370921854bb3be19bd9209a54da4a763833386b0ef917c6ec5a632a2941db9
4
- data.tar.gz: 7df3efd16d2b889561b94a76c2d8ed7b7e764ca6b2a5b45e3edf510b58bcf8bc
3
+ metadata.gz: 7c8f5f1fbdb514808ad6accd57f448a1d997f86f8c53224456421879e78ee40e
4
+ data.tar.gz: ee76c128c4b6f7b0f7d51ff81700258d6a8e1fbde522400009fa682b49658c7f
5
5
  SHA512:
6
- metadata.gz: 23f1efbcc3d5fb6cceb32f9d7794f1ce8943dfe51696b42c95c2bdc257acb0a6770c0470d2d72729f45e9beb7919948c46dea8db6bfb903381466c7dfd2ab771
7
- data.tar.gz: 3fd7dbd3eca37712e7eec4fa9908939b797805d779d62f242c6c6e30f1ca7baeeb49470f1a1f7a1cd97f5d3d0320ecd116048870a2bb4d530380bcfd716243e5
6
+ metadata.gz: '0591e240fabe7f68e179a09f55d61bc03f26374ca7abd28bc4f5a67789644670342ef43d7f56ebff6c3e409e7df18fd77ae11e82ae5d6fe44af582add4e20efb'
7
+ data.tar.gz: f85e9148f94abe28ff69693169fc600641c99cf1d2f0d0204b95c3c3582e039d5fab19cc9a7b8442e09dd72b2d2c2ce33f71339d0967b068a3c1363dab583bd5
data/README.md CHANGED
@@ -39,7 +39,7 @@ end
39
39
  ## Requirements
40
40
 
41
41
  - Ruby 3.3+
42
- - Rails 7.2+
42
+ - Rails 8.1+
43
43
 
44
44
  ## Installation
45
45
 
@@ -69,7 +69,7 @@ That's it. No 500-line examples needed.
69
69
 
70
70
  ## Built for Rails, Not Around It
71
71
 
72
- Lapsoss integrates with Rails' native error reporting API introduced in Rails 7. No monkey-patching, no global error handlers:
72
+ Lapsoss integrates with Rails' native error reporting API (`Rails.error`). No monkey-patching, no global error handlers:
73
73
 
74
74
  ```ruby
75
75
  # It just works with Rails.error:
@@ -116,6 +116,51 @@ end
116
116
 
117
117
  # Or use Rails.error directly with your configured services
118
118
  Rails.error.report(e, context: { user_id: current_user.id })
119
+
120
+ # For "should never happen" paths, Rails.error.unexpected raises in
121
+ # development/test and reports in production - and routes through Lapsoss too
122
+ Rails.error.unexpected("Reached unreachable branch")
123
+ ```
124
+
125
+ ### Structured Events as Breadcrumbs
126
+
127
+ Lapsoss automatically subscribes to the structured event reporter
128
+ (`Rails.event`) and records emitted events as breadcrumbs. When an error is
129
+ captured, the recent activity trail is attached to the report - no
130
+ monkey-patching, just Rails' native API:
131
+
132
+ ```ruby
133
+ Rails.event.notify("order.checkout_started", cart_id: cart.id)
134
+ # ... an exception here includes that breadcrumb in the error report
135
+
136
+ # Tags and context flow into breadcrumb metadata
137
+ Rails.event.tagged(section: "checkout") do
138
+ Rails.event.notify("payment.authorized", amount: 42_00)
139
+ end
140
+ ```
141
+
142
+ Tune or disable it:
143
+
144
+ ```ruby
145
+ Lapsoss.configure do |config|
146
+ config.capture_rails_events = false # opt out entirely
147
+ config.rails_event_filter = ->(event) { !event[:name].start_with?("noisy.") }
148
+ end
149
+ ```
150
+
151
+ Rails-side enrichment also composes: context added via `Rails.error.add_middleware`
152
+ flows into the `context:` Lapsoss receives for free.
153
+
154
+ ### Silencing Capture
155
+
156
+ Suppress delivery for a block (thread-local) - useful in tests or around
157
+ expected-failure paths. Breadcrumbs and scope still accumulate; only delivery
158
+ is skipped:
159
+
160
+ ```ruby
161
+ Lapsoss.silence do
162
+ retry_flaky_third_party_call
163
+ end
119
164
  ```
120
165
 
121
166
  ### No Global Patching Philosophy
@@ -329,7 +374,9 @@ end
329
374
 
330
375
  ### Filtering Errors
331
376
 
332
- You decide what errors to track. Lapsoss doesn't make assumptions:
377
+ You decide what errors to track. Lapsoss doesn't make assumptions.
378
+
379
+ **Execution order:** `exclusion_filter` runs first, then `before_send`.
333
380
 
334
381
  ```ruby
335
382
  Lapsoss.configure do |config|
@@ -80,6 +80,11 @@ module Lapsoss
80
80
  private
81
81
 
82
82
  def capture_event(event)
83
+ if Current.silenced
84
+ @configuration.logger.debug("[LAPSOSS] Event dropped: capture silenced via Lapsoss.silence")
85
+ return nil
86
+ end
87
+
83
88
  @configuration.logger.debug("[LAPSOSS] capture_event called, async: #{@configuration.async}, executor: #{@executor.inspect}")
84
89
 
85
90
  # Apply pipeline processing if enabled
@@ -14,7 +14,7 @@ module Lapsoss
14
14
  :backtrace_strip_load_path, :backtrace_max_frames, :backtrace_enable_code_context,
15
15
  :enable_pipeline, :pipeline_builder, :sampling_strategy,
16
16
  :skip_rails_cache_errors, :force_sync_http, :capture_request_context,
17
- :exclusion_filter
17
+ :exclusion_filter, :capture_rails_events, :rails_event_filter
18
18
  attr_reader :fingerprint_callback, :environment, :before_send, :sample_rate, :error_handler, :transport_timeout,
19
19
  :transport_max_retries, :transport_initial_backoff, :transport_max_backoff, :transport_backoff_multiplier, :transport_ssl_verify, :default_context, :adapter_configs
20
20
 
@@ -62,6 +62,9 @@ module Lapsoss
62
62
  @sampling_strategy = nil
63
63
  # Rails error filtering
64
64
  @skip_rails_cache_errors = true
65
+ # Rails.event structured events as breadcrumbs (Rails 8.1+)
66
+ @capture_rails_events = true
67
+ @rails_event_filter = nil
65
68
  # HTTP client settings
66
69
  @force_sync_http = false
67
70
  # Capture request context in middleware
@@ -5,6 +5,7 @@ require "active_support/all"
5
5
  module Lapsoss
6
6
  class Current < ActiveSupport::CurrentAttributes
7
7
  attribute :scope, default: -> { Scope.new }
8
+ attribute :silenced, default: false
8
9
 
9
10
  def self.with_clean_scope
10
11
  previous_scope = scope
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lapsoss
4
+ # Subscribes to Rails' structured event reporter (Rails.event, Rails 8.1+)
5
+ # and records emitted events as Lapsoss breadcrumbs, giving error reports an
6
+ # automatic activity trail without any monkey-patching.
7
+ class RailsEventSubscriber
8
+ def emit(event)
9
+ return unless Lapsoss.client
10
+
11
+ Lapsoss.add_breadcrumb(event[:name], type: :event, **breadcrumb_metadata(event))
12
+ end
13
+
14
+ private
15
+
16
+ def breadcrumb_metadata(event)
17
+ metadata = {}
18
+ payload = serialize_payload(event[:payload])
19
+ metadata[:payload] = payload if payload
20
+ metadata[:tags] = event[:tags] if event[:tags].present?
21
+ metadata[:context] = event[:context] if event[:context].present?
22
+
23
+ if (location = event[:source_location])
24
+ metadata[:source] = "#{location[:filepath]}:#{location[:lineno]}"
25
+ end
26
+
27
+ metadata
28
+ end
29
+
30
+ # Payloads are either hashes or arbitrary event objects, which Rails passes
31
+ # through as-is and expects subscribers to serialize.
32
+ def serialize_payload(payload)
33
+ case payload
34
+ when nil, Hash
35
+ payload
36
+ else
37
+ payload.respond_to?(:serialize) ? payload.serialize : payload.inspect
38
+ end
39
+ end
40
+ end
41
+ end
@@ -39,6 +39,19 @@ module Lapsoss
39
39
  Rails.error.subscribe(Lapsoss::RailsErrorSubscriber.new)
40
40
  end
41
41
 
42
+ initializer "lapsoss.rails_event_subscriber" do
43
+ Rails.event.subscribe(Lapsoss::RailsEventSubscriber.new) do |event|
44
+ config = Lapsoss.configuration
45
+ if !config.capture_rails_events
46
+ false
47
+ elsif (filter = config.rails_event_filter)
48
+ !!filter.call(event)
49
+ else
50
+ true
51
+ end
52
+ end
53
+ end
54
+
42
55
  initializer "lapsoss.controller_transaction" do
43
56
  ActiveSupport.on_load(:action_controller) do
44
57
  require "lapsoss/rails_controller_transaction"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lapsoss
4
- VERSION = "0.4.11"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/lapsoss.rb CHANGED
@@ -69,6 +69,20 @@ module Lapsoss
69
69
  capture_exception(exception, **context.merge(handled: handled))
70
70
  end
71
71
 
72
+ # Suppress all event capture for the duration of the block (thread-local).
73
+ # Breadcrumbs and scope still accumulate; only delivery is skipped.
74
+ def silence
75
+ previous = Current.silenced
76
+ Current.silenced = true
77
+ yield
78
+ ensure
79
+ Current.silenced = previous
80
+ end
81
+
82
+ def silenced?
83
+ Current.silenced
84
+ end
85
+
72
86
  def add_breadcrumb(message, type: :default, **metadata)
73
87
  client.add_breadcrumb(message, type: type, **metadata)
74
88
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lapsoss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.11
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -15,7 +15,7 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '7.2'
18
+ version: '8.1'
19
19
  - - "<"
20
20
  - !ruby/object:Gem::Version
21
21
  version: '9.0'
@@ -25,7 +25,7 @@ dependencies:
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '7.2'
28
+ version: '8.1'
29
29
  - - "<"
30
30
  - !ruby/object:Gem::Version
31
31
  version: '9.0'
@@ -258,6 +258,7 @@ files:
258
258
  - lib/lapsoss/rails_controller_context.rb
259
259
  - lib/lapsoss/rails_controller_transaction.rb
260
260
  - lib/lapsoss/rails_error_subscriber.rb
261
+ - lib/lapsoss/rails_event_subscriber.rb
261
262
  - lib/lapsoss/railtie.rb
262
263
  - lib/lapsoss/registry.rb
263
264
  - lib/lapsoss/release_tracker.rb
@@ -293,7 +294,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
293
294
  - !ruby/object:Gem::Version
294
295
  version: '0'
295
296
  requirements: []
296
- rubygems_version: 3.6.9
297
+ rubygems_version: 4.0.10
297
298
  specification_version: 4
298
299
  summary: Modern error reporting with pluggable adapters for Rails applications
299
300
  test_files: []