rails_event_viewer 0.1.2 → 0.2.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: ef30fa1ce21c1dc5c6eaa4634707801f2d32b67ab561231865cc67c0eb2c557f
4
- data.tar.gz: 9a423c1745dfb3a088137fbe4c912c069a1e65ca68afc0e4d1dac2961819baac
3
+ metadata.gz: 26f6b1798d95bf71759a16da1fd092f8d8296a4118378a8c5ce84e12848efe28
4
+ data.tar.gz: b290b0d5803b71aa2f8fda06ee160870672a4073c175c2bb6a0e0856f19b2dbc
5
5
  SHA512:
6
- metadata.gz: 3b25d996bb14c0bada11737d07a98f93fbd10b8f4781ea3163b79185e31a2b6fe30a99b74e69f63e1d6e768a1fa137124bab9f3a47da07f5940466de1933e2ff
7
- data.tar.gz: 828ddff25e0930d10bc34c75ee58e789f361f6dc14c3bf24c56b463e8b1327b454cf15ce7536f7d32969716f4c6db82bd9640c3bfcada4a8c9aed072132bc158
6
+ metadata.gz: ef7fc01c18016ff1f9d48de98fcc1f42b248ac1fea588806c6dc3a409b12f75291e4165ee59ff45220b93a024f6b816d7cb2dba4395c2b5c441dd6f323a8a17a
7
+ data.tar.gz: 896dd1e41a71c0c0bd25dbdd0a376ffd7c5c0c68b8d7d6cf445521127560d95ba0d351e1d9f9f4c6c5d73ed00ae6472dbd9096ceddf2d79cd8b1dbf4e3edb37f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 (2026-10-01)
4
+
5
+ - Pluggable buffers: `config.buffer` accepts any object implementing `RailsEventViewer::Buffer` (`push`, `drain`, `commit`, `revert`, `dead`, `size`, `after_fork`). `push` returns the new size. The in-memory buffer remains the default.
6
+ - A failed batch is reverted and retried with exponential backoff. After three failures it is written one event at a time.
7
+ - Events the adapter keeps rejecting, and events dropped by the buffer cap, are passed to `dead` instead of being lost silently.
8
+ - A failed sync write, or a failed `push` to the buffer in async mode, is now logged and re-raised to `Rails.event`, which reports it to `Rails.error` (or raises, with `raise_on_error`), instead of being swallowed.
9
+ - A banner warns when `sample_rate` is below 1.0, since timelines can have gaps.
10
+ - README now marks the gem as experimental and not yet recommended for production.
11
+
12
+ ## 0.1.3 (2026-10-01)
13
+
14
+ - The flusher thread starts on the first buffered event, not at boot, so consoles and rake tasks no longer run an idle thread.
15
+ - Flusher start/stop messages log at debug level.
16
+ - Events emitted after shutdown are written immediately instead of lost.
17
+ - Web requests never write to storage. A full buffer wakes the flusher thread instead.
18
+ - The buffer is capped at 10 times `buffer_size`. Overflow drops the oldest events and logs a warning.
19
+ - Removed the unused ActionCable broadcast.
20
+
3
21
  ## 0.1.2 (2026-09-30)
4
22
 
5
23
  - 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
@@ -2,6 +2,8 @@
2
2
 
3
3
  A Rails engine that captures events emitted with `Rails.event` and gives you a dashboard to browse, search, and chart them.
4
4
 
5
+ > **Experimental.** This gem is in early development and not recommended for production yet. APIs, the database schema, and behavior may change between minor versions.
6
+
5
7
  ## Requirements
6
8
 
7
9
  - Rails 8.1+
@@ -61,8 +63,15 @@ RailsEventViewer.configure do |config|
61
63
  end
62
64
  ```
63
65
 
66
+ 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.
67
+
64
68
  Internal Rails events such as `active_record.*` and `action_controller.*` are ignored by default. Remove a pattern from `ignored_events` to capture it.
65
69
 
70
+ ## Sync vs async
71
+
72
+ - With `async = false`, each event is written inside your transaction, and a failed write is reported to `Rails.error`. In development and test, where Rails sets `raise_on_error`, it raises instead.
73
+ - With `async = true`, events wait in an in-memory buffer and are lost if the process is killed. Set `config.buffer` to your own `RailsEventViewer::Buffer`, for example backed by Redis, to keep them.
74
+
66
75
  ## Authentication
67
76
 
68
77
  Without authentication, the dashboard is open in development and test, and returns `403` everywhere else.
@@ -83,27 +92,9 @@ Set `RAILS_ENV` on every server. Without it, Rails falls back to development and
83
92
 
84
93
  ## Storage adapters
85
94
 
86
- | Adapter | Use it for |
87
- |---|---|
88
- | `:active_record` | The default. Stores events in your database, with full analytics. |
89
- | `:redis` | High volume, short-lived storage. Keeps the newest `max_events`. |
90
- | `:memory` | Development and tests. Lost on restart. |
91
- | `:null` | Disables storage. |
92
-
93
- Redis needs the `redis` gem:
94
-
95
- ```ruby
96
- config.storage_adapter = :redis
97
- config.adapter_options = {
98
- redis_options: { url: ENV["REDIS_URL"] },
99
- pool_size: 5,
100
- max_events: 10_000
101
- }
102
- ```
103
-
104
- Filtered queries on Redis scan every stored event, so keep `max_events` modest.
95
+ Set `config.storage_adapter` to `:active_record` (default), `:redis`, `:memory`, or `:null`. Redis needs the `redis` gem and takes options through `config.adapter_options`.
105
96
 
106
- For a custom adapter, include `RailsEventViewer::Adapter` and implement the methods it lists.
97
+ Filtered queries on Redis scan every stored event, so keep `max_events` (how many events Redis keeps, set in `adapter_options`) modest. For your own storage, include `RailsEventViewer::Adapter`.
107
98
 
108
99
  ## Rake tasks
109
100
 
@@ -33,6 +33,14 @@
33
33
  </div>
34
34
  <% end %>
35
35
 
36
+ <% if RailsEventViewer.sample_rate.to_f < 1.0 %>
37
+ <div class="mb-4 rounded-md bg-yellow-50 border border-yellow-200 p-4">
38
+ <p class="text-sm font-medium text-yellow-800">
39
+ Sampling is on: only <%= number_to_percentage(RailsEventViewer.sample_rate.to_f * 100, precision: 3, significant: true, strip_insignificant_zeros: true) %> of events are recorded, so timelines can have gaps.
40
+ </p>
41
+ </div>
42
+ <% end %>
43
+
36
44
  <%= yield %>
37
45
  </div>
38
46
  </main>
@@ -40,6 +40,11 @@ RailsEventViewer.configure do |config|
40
40
  # Flush interval in seconds (flushes even if buffer isn't full)
41
41
  # config.flush_interval = 2
42
42
 
43
+ # Buffer used when async is true. The default is in memory, so buffered events
44
+ # are lost if the process is killed. You can write your own buffers (see RailsEventViewer::Buffer)
45
+ # to persist them, for example in Redis.
46
+ # config.buffer = MyRedisBuffer.new
47
+
43
48
  # Sample rate: 1.0 = capture all events, 0.1 = capture 10% of events
44
49
  # Useful for high-volume production environments
45
50
  # config.sample_rate = 1.0
@@ -0,0 +1,79 @@
1
+ module RailsEventViewer
2
+ class BatchWriter
3
+ include Logging
4
+
5
+ MAX_ATTEMPTS = 3
6
+ LOGGED_EVENTS = 10
7
+
8
+ attr_reader :failed_attempts
9
+
10
+ def initialize(buffer)
11
+ @buffer = buffer
12
+ reset
13
+ end
14
+
15
+ def reset
16
+ @failed_attempts = 0
17
+ @strikes = Hash.new(0)
18
+ end
19
+
20
+ def write(events)
21
+ RailsEventViewer.adapter.write_events(events)
22
+ @buffer.commit(events)
23
+ forget(events)
24
+ @failed_attempts = 0
25
+ true
26
+ rescue => e
27
+ log_error("[RailsEventViewer] Failed to write #{events.size} events: #{e.message}")
28
+ @failed_attempts += 1
29
+ return write_individually(events) if @failed_attempts >= MAX_ATTEMPTS
30
+
31
+ @buffer.revert(events)
32
+ false
33
+ end
34
+
35
+ def forget(events)
36
+ events.each { |event| @strikes.delete(event) } unless @strikes.empty?
37
+ end
38
+
39
+ private
40
+
41
+ def write_individually(events)
42
+ written = []
43
+ rejected = []
44
+ events.each do |event|
45
+ (write_one(event) ? written : rejected) << event
46
+ break if written.empty? && rejected.size >= MAX_ATTEMPTS
47
+ end
48
+
49
+ if written.empty?
50
+ @buffer.revert(events)
51
+ return false
52
+ end
53
+
54
+ rejected.each { |event| @strikes[event] += 1 }
55
+ dead, retry_later = rejected.partition { |event| @strikes[event] >= MAX_ATTEMPTS }
56
+ forget(written + dead)
57
+
58
+ @buffer.commit(written)
59
+ @buffer.revert(retry_later) if retry_later.any?
60
+ give_up(dead) if dead.any?
61
+ @failed_attempts = retry_later.any? ? MAX_ATTEMPTS - 1 : 0
62
+ true
63
+ end
64
+
65
+ def give_up(events)
66
+ names = events.first(LOGGED_EVENTS).map { |event| event[:name] }.join(", ")
67
+ log_error("[RailsEventViewer] Gave up on #{events.size} events the adapter rejected #{MAX_ATTEMPTS} times (#{@last_rejection}): #{names}")
68
+ @buffer.dead(events)
69
+ end
70
+
71
+ def write_one(event)
72
+ RailsEventViewer.adapter.write_events([event])
73
+ true
74
+ rescue => e
75
+ @last_rejection = e.message
76
+ false
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,28 @@
1
+ module RailsEventViewer
2
+ module Buffer
3
+ def push(entry)
4
+ raise NotImplementedError, "#{self.class} must implement #push"
5
+ end
6
+
7
+ def drain(limit)
8
+ raise NotImplementedError, "#{self.class} must implement #drain"
9
+ end
10
+
11
+ def commit(entries)
12
+ end
13
+
14
+ def revert(entries)
15
+ end
16
+
17
+ def dead(entries)
18
+ commit(entries)
19
+ end
20
+
21
+ def size
22
+ raise NotImplementedError, "#{self.class} must implement #size"
23
+ end
24
+
25
+ def after_fork
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ module RailsEventViewer
2
+ module Buffers
3
+ class Memory
4
+ include Buffer
5
+
6
+ def initialize
7
+ @queue = Queue.new
8
+ end
9
+
10
+ def push(entry)
11
+ @queue << entry
12
+ @queue.size
13
+ end
14
+
15
+ def drain(limit)
16
+ entries = []
17
+ limit.times { entries << @queue.pop(true) }
18
+ entries
19
+ rescue ThreadError
20
+ entries
21
+ end
22
+
23
+ def revert(entries)
24
+ entries.each { |entry| @queue << entry }
25
+ end
26
+
27
+ def size
28
+ @queue.size
29
+ end
30
+
31
+ def after_fork
32
+ @queue = Queue.new
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,150 @@
1
+ module RailsEventViewer
2
+ class Flusher
3
+ include Logging
4
+
5
+ SHUTDOWN_TIMEOUT_SECONDS = 5
6
+ MAX_BUFFER_MULTIPLIER = 10
7
+
8
+ def initialize(buffer)
9
+ @buffer = buffer
10
+ @writer = BatchWriter.new(buffer)
11
+ @flush_requests = Queue.new
12
+ @mutex = Mutex.new
13
+ @thread = nil
14
+ @shutdown_requested = false
15
+ @dropped_count = 0
16
+ @pid = Process.pid
17
+ end
18
+
19
+ def push(entry)
20
+ handle_fork_if_needed
21
+
22
+ size = @buffer.push(entry)
23
+ return flush! if shutdown_requested?
24
+
25
+ ensure_thread!
26
+ drop_oldest_events if size > max_buffer_size
27
+ request_flush if size >= RailsEventViewer.buffer_size
28
+ end
29
+
30
+ def flush!
31
+ events = @buffer.drain([@buffer.size, max_buffer_size].min)
32
+ return true if events.empty?
33
+
34
+ written = @writer.write(events)
35
+ report_dropped_events if written
36
+ written
37
+ rescue => e
38
+ log_error("[RailsEventViewer] Failed to flush: #{e.message}")
39
+ false
40
+ end
41
+
42
+ def stop!
43
+ @mutex.synchronize { @shutdown_requested = true }
44
+
45
+ if @thread&.alive?
46
+ @flush_requests << true
47
+ @thread.join(SHUTDOWN_TIMEOUT_SECONDS)
48
+ end
49
+
50
+ @mutex.synchronize { @thread = nil }
51
+
52
+ loop do
53
+ remaining = @buffer.size
54
+ break if remaining.zero?
55
+
56
+ flush!
57
+ break if @buffer.size >= remaining
58
+ end
59
+ end
60
+
61
+ def running?
62
+ @thread&.alive? || false
63
+ end
64
+
65
+ def size
66
+ @buffer.size
67
+ end
68
+
69
+ private
70
+
71
+ def handle_fork_if_needed
72
+ @mutex.synchronize do
73
+ if @pid != Process.pid
74
+ @pid = Process.pid
75
+ @buffer.after_fork
76
+ @writer.reset
77
+ @flush_requests = Queue.new
78
+ @thread = nil
79
+ @shutdown_requested = false
80
+ @dropped_count = 0
81
+ end
82
+ end
83
+ end
84
+
85
+ def max_buffer_size
86
+ RailsEventViewer.buffer_size * MAX_BUFFER_MULTIPLIER
87
+ end
88
+
89
+ def drop_oldest_events
90
+ while @buffer.size > max_buffer_size
91
+ dropped = @buffer.drain(1)
92
+ break if dropped.empty?
93
+
94
+ @buffer.dead(dropped)
95
+ @writer.forget(dropped)
96
+ @mutex.synchronize { @dropped_count += 1 }
97
+ end
98
+ end
99
+
100
+ def report_dropped_events
101
+ dropped = @mutex.synchronize { @dropped_count.tap { @dropped_count = 0 } }
102
+ return if dropped.zero?
103
+
104
+ effective_logger&.warn("[RailsEventViewer] Dropped #{dropped} events because the buffer was full")
105
+ end
106
+
107
+ def request_flush
108
+ @flush_requests << true if @flush_requests.empty? && @writer.failed_attempts.zero?
109
+ end
110
+
111
+ def ensure_thread!
112
+ @mutex.synchronize do
113
+ return if @thread&.alive?
114
+ return if @shutdown_requested
115
+
116
+ @thread = Thread.new { run_loop }
117
+ end
118
+ end
119
+
120
+ def run_loop
121
+ effective_logger&.debug("[RailsEventViewer] Flusher thread started (PID: #{Process.pid})")
122
+
123
+ until shutdown_requested?
124
+ begin
125
+ wait_for_flush
126
+ loop do
127
+ break unless flush!
128
+ break if @buffer.size < RailsEventViewer.buffer_size || shutdown_requested?
129
+ end
130
+ rescue => e
131
+ log_error("[RailsEventViewer] Flusher error: #{e.message}")
132
+ end
133
+ end
134
+
135
+ effective_logger&.debug("[RailsEventViewer] Flusher thread stopped (PID: #{Process.pid})")
136
+ end
137
+
138
+ def wait_for_flush
139
+ backoff = 2**[@writer.failed_attempts, BatchWriter::MAX_ATTEMPTS].min
140
+ @flush_requests.clear unless @writer.failed_attempts.zero?
141
+ return if shutdown_requested?
142
+
143
+ @flush_requests.pop(timeout: RailsEventViewer.flush_interval * backoff)
144
+ end
145
+
146
+ def shutdown_requested?
147
+ @mutex.synchronize { @shutdown_requested }
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,19 @@
1
+ module RailsEventViewer
2
+ module Logging
3
+ private
4
+
5
+ def log_error(message)
6
+ logger = effective_logger
7
+
8
+ if logger
9
+ logger.error(message)
10
+ else
11
+ warn message
12
+ end
13
+ end
14
+
15
+ def effective_logger
16
+ RailsEventViewer.logger || (defined?(Rails) && Rails.logger)
17
+ end
18
+ end
19
+ end
@@ -2,156 +2,35 @@
2
2
 
3
3
  module RailsEventViewer
4
4
  class Subscriber
5
+ include Logging
6
+
5
7
  NANOSECONDS_PER_SECOND = 1_000_000_000.0
6
- SHUTDOWN_TIMEOUT_SECONDS = 5
7
- ACTION_CABLE_CHANNEL = "rails_event_viewer:events"
8
8
 
9
- def initialize
10
- @buffer = Queue.new
11
- @mutex = Mutex.new
12
- @flusher_thread = nil
13
- @shutdown_requested = false
14
- @pid = Process.pid
9
+ delegate :flush!, :stop!, :running?, to: :@flusher
10
+ delegate :size, to: :@flusher, prefix: :buffer
15
11
 
16
- ensure_flusher_thread!
12
+ def initialize
13
+ @flusher = Flusher.new(RailsEventViewer.buffer)
17
14
  end
18
15
 
19
16
  def emit(event)
20
- handle_fork_if_needed
21
-
22
17
  return unless should_capture?(event)
23
18
  return if sampled_out?
24
19
 
25
20
  entry = build_entry(event)
26
21
 
27
22
  if RailsEventViewer.async
28
- buffer_event(entry)
23
+ @flusher.push(entry)
29
24
  else
30
- write_immediately([entry])
25
+ RailsEventViewer.adapter.write_events([entry])
31
26
  end
32
27
  rescue => e
33
28
  handle_error(e, event)
34
- end
35
-
36
- def flush!
37
- return if @buffer.empty?
38
-
39
- events_to_write = drain_buffer
40
-
41
- return if events_to_write.empty?
42
-
43
- write_immediately(events_to_write)
44
- broadcast_events(events_to_write)
45
- end
46
-
47
- def stop!
48
- @mutex.synchronize do
49
- @shutdown_requested = true
50
- end
51
-
52
- if @flusher_thread&.alive?
53
- @flusher_thread.wakeup rescue nil
54
- @flusher_thread.join(SHUTDOWN_TIMEOUT_SECONDS)
55
- end
56
-
57
- @mutex.synchronize do
58
- @flusher_thread = nil
59
- end
60
-
61
- flush!
62
- end
63
-
64
- def running?
65
- @flusher_thread&.alive? || false
66
- end
67
-
68
- def buffer_size
69
- @buffer.size
29
+ raise
70
30
  end
71
31
 
72
32
  private
73
33
 
74
- def handle_fork_if_needed
75
- # Threads don't survive forks, so we need to restart the flusher
76
- @mutex.synchronize do
77
- if @pid != Process.pid
78
- @pid = Process.pid
79
- @buffer = Queue.new
80
- @flusher_thread = nil
81
- @shutdown_requested = false
82
- end
83
- end
84
- ensure_flusher_thread!
85
- end
86
-
87
- def drain_buffer
88
- events = []
89
- loop { events << @buffer.pop(true) }
90
- rescue ThreadError
91
- events
92
- end
93
-
94
- def buffer_event(entry)
95
- @buffer << entry
96
- ensure_flusher_thread!
97
-
98
- flush! if @buffer.size >= RailsEventViewer.buffer_size
99
- end
100
-
101
- def ensure_flusher_thread!
102
- return unless RailsEventViewer.async
103
-
104
- @mutex.synchronize do
105
- return if @flusher_thread&.alive?
106
- return if @shutdown_requested
107
-
108
- @flusher_thread = Thread.new { run_flusher_loop }
109
- end
110
- end
111
-
112
- def run_flusher_loop
113
- log_info("[RailsEventViewer] Flusher thread started (PID: #{Process.pid})")
114
-
115
- until shutdown_requested?
116
- begin
117
- sleep(RailsEventViewer.flush_interval)
118
- flush! unless @buffer.empty?
119
- rescue => e
120
- log_error("[RailsEventViewer] Flusher error: #{e.message}")
121
- end
122
- end
123
-
124
- log_info("[RailsEventViewer] Flusher thread stopped (PID: #{Process.pid})")
125
- end
126
-
127
- def shutdown_requested?
128
- @mutex.synchronize { @shutdown_requested }
129
- end
130
-
131
- def write_immediately(events)
132
- return if events.blank?
133
-
134
- RailsEventViewer.adapter.write_events(events)
135
- rescue => e
136
- log_error("[RailsEventViewer] Failed to write #{events.size} events: #{e.message}")
137
- end
138
-
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
34
  def should_capture?(event)
156
35
  return false unless event.is_a?(Hash)
157
36
  return false if event[:name].blank?
@@ -233,23 +112,5 @@ module RailsEventViewer
233
112
  def handle_error(error, event)
234
113
  log_error("[RailsEventViewer] Failed to capture event '#{event[:name]}': #{error.message}")
235
114
  end
236
-
237
- def log_info(message)
238
- effective_logger&.info(message)
239
- end
240
-
241
- def log_error(message)
242
- logger = effective_logger
243
-
244
- if logger
245
- logger.error(message)
246
- else
247
- warn message
248
- end
249
- end
250
-
251
- def effective_logger
252
- RailsEventViewer.logger || (defined?(Rails) && Rails.logger)
253
- end
254
115
  end
255
116
  end
@@ -1,3 +1,3 @@
1
1
  module RailsEventViewer
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -3,6 +3,8 @@ require "groupdate"
3
3
 
4
4
  require "rails_event_viewer/version"
5
5
  require "rails_event_viewer/engine"
6
+ require "rails_event_viewer/buffer"
7
+ require "rails_event_viewer/buffers/memory"
6
8
 
7
9
  module RailsEventViewer
8
10
  mattr_accessor :storage_adapter, default: :active_record
@@ -12,6 +14,7 @@ module RailsEventViewer
12
14
  mattr_accessor :buffer_size, default: 100 # Flush after N events
13
15
  mattr_accessor :flush_interval, default: 2 # Flush every N seconds
14
16
  mattr_accessor :sample_rate, default: 1.0 # 1.0 = 100%, 0.1 = 10%
17
+ mattr_accessor :buffer, default: Buffers::Memory.new
15
18
 
16
19
  mattr_accessor :retention_period, default: 7.days
17
20
  mattr_accessor :captured_events, default: [] # Empty = capture all
@@ -115,6 +118,9 @@ end
115
118
 
116
119
  require "rails_event_viewer/adapter"
117
120
  require "rails_event_viewer/events_relation"
121
+ require "rails_event_viewer/logging"
122
+ require "rails_event_viewer/batch_writer"
123
+ require "rails_event_viewer/flusher"
118
124
  require "rails_event_viewer/subscriber"
119
125
  require "rails_event_viewer/json_query"
120
126
  require "rails_event_viewer/time_utils"
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.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keshav Biswa
@@ -107,9 +107,14 @@ files:
107
107
  - lib/rails_event_viewer/adapters/memory.rb
108
108
  - lib/rails_event_viewer/adapters/null.rb
109
109
  - lib/rails_event_viewer/adapters/redis.rb
110
+ - lib/rails_event_viewer/batch_writer.rb
111
+ - lib/rails_event_viewer/buffer.rb
112
+ - lib/rails_event_viewer/buffers/memory.rb
110
113
  - lib/rails_event_viewer/engine.rb
111
114
  - lib/rails_event_viewer/events_relation.rb
115
+ - lib/rails_event_viewer/flusher.rb
112
116
  - lib/rails_event_viewer/json_query.rb
117
+ - lib/rails_event_viewer/logging.rb
113
118
  - lib/rails_event_viewer/subscriber.rb
114
119
  - lib/rails_event_viewer/time_utils.rb
115
120
  - lib/rails_event_viewer/version.rb