rails_event_viewer 0.1.2 → 0.1.3

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: ef30fa1ce21c1dc5c6eaa4634707801f2d32b67ab561231865cc67c0eb2c557f
4
- data.tar.gz: 9a423c1745dfb3a088137fbe4c912c069a1e65ca68afc0e4d1dac2961819baac
3
+ metadata.gz: df70eeee67ca7c67116c852f98659be2d9ee3803a1bd4b949d3190f0aed1d40b
4
+ data.tar.gz: 0a83f0ce0b0504c7ba9823a1e2c3eaa1e9a4f79297aae5ff35e8f742c01b51ea
5
5
  SHA512:
6
- metadata.gz: 3b25d996bb14c0bada11737d07a98f93fbd10b8f4781ea3163b79185e31a2b6fe30a99b74e69f63e1d6e768a1fa137124bab9f3a47da07f5940466de1933e2ff
7
- data.tar.gz: 828ddff25e0930d10bc34c75ee58e789f361f6dc14c3bf24c56b463e8b1327b454cf15ce7536f7d32969716f4c6db82bd9640c3bfcada4a8c9aed072132bc158
6
+ metadata.gz: 23eaca12170699b79b5fd635204e24a25bfc6a8eb8bbef0605aeaea40fab2701dda65ca4101fb9d64fea1a5c57fc77a9f94d6362a90f91fea587b196b5d38667
7
+ data.tar.gz: 8d981f6fe1a2673e91453ddf400be91537bd8b3686217c471e783939f9814ecc0b6240c368689c45219011e6d19ccdfed2e98ea19b61f7dcfcd2e0b5095267a9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3 (2026-10-01)
4
+
5
+ - The flusher thread starts on the first buffered event, not at boot, so consoles and rake tasks no longer run an idle thread.
6
+ - Flusher start/stop messages log at debug level.
7
+ - Events emitted after shutdown are written immediately instead of lost.
8
+ - Web requests never write to storage. A full buffer wakes the flusher thread instead.
9
+ - The buffer is capped at 10 times `buffer_size`. Overflow drops the oldest events and logs a warning.
10
+ - Removed the unused ActionCable broadcast.
11
+
3
12
  ## 0.1.2 (2026-09-30)
4
13
 
5
14
  - Removed the `pagy` dependency. Pagination is handled by a small built-in class, so host apps on any Pagy version, or none, can install the gem.
data/README.md CHANGED
@@ -61,6 +61,8 @@ RailsEventViewer.configure do |config|
61
61
  end
62
62
  ```
63
63
 
64
+ With `async`, events are written by a background thread, never by your web requests. The buffer holds at most 10 times `buffer_size` events. If storage can't keep up, the oldest are dropped and a warning is logged. Events still in the buffer are written on a normal shutdown but lost if the process is killed.
65
+
64
66
  Internal Rails events such as `active_record.*` and `action_controller.*` are ignored by default. Remove a pattern from `ignored_events` to capture it.
65
67
 
66
68
  ## Authentication
@@ -4,16 +4,16 @@ module RailsEventViewer
4
4
  class Subscriber
5
5
  NANOSECONDS_PER_SECOND = 1_000_000_000.0
6
6
  SHUTDOWN_TIMEOUT_SECONDS = 5
7
- ACTION_CABLE_CHANNEL = "rails_event_viewer:events"
7
+ MAX_BUFFER_MULTIPLIER = 10
8
8
 
9
9
  def initialize
10
10
  @buffer = Queue.new
11
+ @flush_requests = Queue.new
11
12
  @mutex = Mutex.new
12
13
  @flusher_thread = nil
13
14
  @shutdown_requested = false
15
+ @dropped_count = 0
14
16
  @pid = Process.pid
15
-
16
- ensure_flusher_thread!
17
17
  end
18
18
 
19
19
  def emit(event)
@@ -41,7 +41,7 @@ module RailsEventViewer
41
41
  return if events_to_write.empty?
42
42
 
43
43
  write_immediately(events_to_write)
44
- broadcast_events(events_to_write)
44
+ report_dropped_events
45
45
  end
46
46
 
47
47
  def stop!
@@ -50,7 +50,7 @@ module RailsEventViewer
50
50
  end
51
51
 
52
52
  if @flusher_thread&.alive?
53
- @flusher_thread.wakeup rescue nil
53
+ @flush_requests << true
54
54
  @flusher_thread.join(SHUTDOWN_TIMEOUT_SECONDS)
55
55
  end
56
56
 
@@ -58,7 +58,7 @@ module RailsEventViewer
58
58
  @flusher_thread = nil
59
59
  end
60
60
 
61
- flush!
61
+ flush! until @buffer.empty?
62
62
  end
63
63
 
64
64
  def running?
@@ -77,25 +77,56 @@ module RailsEventViewer
77
77
  if @pid != Process.pid
78
78
  @pid = Process.pid
79
79
  @buffer = Queue.new
80
+ @flush_requests = Queue.new
80
81
  @flusher_thread = nil
81
82
  @shutdown_requested = false
83
+ @dropped_count = 0
82
84
  end
83
85
  end
84
- ensure_flusher_thread!
85
86
  end
86
87
 
87
88
  def drain_buffer
88
89
  events = []
89
- loop { events << @buffer.pop(true) }
90
+ [@buffer.size, max_buffer_size].min.times { events << @buffer.pop(true) }
91
+ events
90
92
  rescue ThreadError
91
93
  events
92
94
  end
93
95
 
94
96
  def buffer_event(entry)
95
97
  @buffer << entry
98
+ return flush! if shutdown_requested?
99
+
96
100
  ensure_flusher_thread!
101
+ drop_oldest_events if @buffer.size > max_buffer_size
102
+ request_flush if @buffer.size >= RailsEventViewer.buffer_size
103
+ end
97
104
 
98
- flush! if @buffer.size >= RailsEventViewer.buffer_size
105
+ def max_buffer_size
106
+ RailsEventViewer.buffer_size * MAX_BUFFER_MULTIPLIER
107
+ end
108
+
109
+ def drop_oldest_events
110
+ dropped = 0
111
+ while @buffer.size > max_buffer_size
112
+ @buffer.pop(true)
113
+ dropped += 1
114
+ end
115
+ rescue ThreadError
116
+ nil
117
+ ensure
118
+ @mutex.synchronize { @dropped_count += dropped } if dropped.positive?
119
+ end
120
+
121
+ def report_dropped_events
122
+ dropped = @mutex.synchronize { @dropped_count.tap { @dropped_count = 0 } }
123
+ return if dropped.zero?
124
+
125
+ effective_logger&.warn("[RailsEventViewer] Dropped #{dropped} events because the buffer was full")
126
+ end
127
+
128
+ def request_flush
129
+ @flush_requests << true if @flush_requests.empty?
99
130
  end
100
131
 
101
132
  def ensure_flusher_thread!
@@ -110,18 +141,21 @@ module RailsEventViewer
110
141
  end
111
142
 
112
143
  def run_flusher_loop
113
- log_info("[RailsEventViewer] Flusher thread started (PID: #{Process.pid})")
144
+ effective_logger&.debug("[RailsEventViewer] Flusher thread started (PID: #{Process.pid})")
114
145
 
115
146
  until shutdown_requested?
116
147
  begin
117
- sleep(RailsEventViewer.flush_interval)
118
- flush! unless @buffer.empty?
148
+ @flush_requests.pop(timeout: RailsEventViewer.flush_interval)
149
+ loop do
150
+ flush!
151
+ break if @buffer.size < RailsEventViewer.buffer_size || shutdown_requested?
152
+ end
119
153
  rescue => e
120
154
  log_error("[RailsEventViewer] Flusher error: #{e.message}")
121
155
  end
122
156
  end
123
157
 
124
- log_info("[RailsEventViewer] Flusher thread stopped (PID: #{Process.pid})")
158
+ effective_logger&.debug("[RailsEventViewer] Flusher thread stopped (PID: #{Process.pid})")
125
159
  end
126
160
 
127
161
  def shutdown_requested?
@@ -136,22 +170,6 @@ module RailsEventViewer
136
170
  log_error("[RailsEventViewer] Failed to write #{events.size} events: #{e.message}")
137
171
  end
138
172
 
139
- def broadcast_events(events)
140
- return unless defined?(ActionCable)
141
- return unless events.any?
142
-
143
- ActionCable.server.broadcast(
144
- ACTION_CABLE_CHANNEL,
145
- {
146
- action: "new_events",
147
- count: events.size,
148
- events: events.map { |e| { name: e[:name], occurred_at: e[:occurred_at]&.iso8601 } }
149
- }
150
- )
151
- rescue => e
152
- log_error("[RailsEventViewer] Broadcast error: #{e.message}")
153
- end
154
-
155
173
  def should_capture?(event)
156
174
  return false unless event.is_a?(Hash)
157
175
  return false if event[:name].blank?
@@ -234,10 +252,6 @@ module RailsEventViewer
234
252
  log_error("[RailsEventViewer] Failed to capture event '#{event[:name]}': #{error.message}")
235
253
  end
236
254
 
237
- def log_info(message)
238
- effective_logger&.info(message)
239
- end
240
-
241
255
  def log_error(message)
242
256
  logger = effective_logger
243
257
 
@@ -1,3 +1,3 @@
1
1
  module RailsEventViewer
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_event_viewer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keshav Biswa