rails_trace_viewer 0.1.2 → 0.1.4

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: 5ff338c196864dc973331301d6fbdbbc50de7ab3940ae012458f73bdfe5b0183
4
- data.tar.gz: b9b535f0575a9972380c9fca35faa82305298b23c64b524182c2ed01df92bc51
3
+ metadata.gz: abac85cedd4d86a997eea9b60f1b449e88ff3799cd13926fa83c143c3d3d1abb
4
+ data.tar.gz: 5fc903e2e18a93e94acb048a6b3350c06346840e285119f9e9221d9dc3f76b68
5
5
  SHA512:
6
- metadata.gz: 824699687247af12dc1abf2fd5be2c5bc45e12896606042c531fec5a6d6918a9b4ae06b7c8990b32ce3cbdb1cf77d5e7a6769e34261c633eef3eec8fb413ce22
7
- data.tar.gz: b140ba6bc597e257e286ed3c1d092660041ca5003b5b278dee51d962436ab54a566e01b4d5d331c4c7a5d444024e66691833800b3589a0d6e861297fcdabc4c6
6
+ metadata.gz: 20aa8961b4ce0797d78614075b8cb100f30b28a1a98e9286d839da5ef04c852f7fcc519b97a3228c8ad1bb2642341726048f5a6bae10337f92e0dc23c75d03ed
7
+ data.tar.gz: 9769095c141f0bf4024fea8a6e74da56600e4299eaf2b7d98cfb53139e442856e08ae7dad0a26f30f1fadb244b5a57c5e32cf5b5244b2e0b9cef28a8d0723a01
data/README.md CHANGED
@@ -2,7 +2,11 @@
2
2
 
3
3
  An educational and debugging tool for Ruby on Rails to visualize the request lifecycle in real-time.
4
4
 
5
- [![Watch the Demo](https://img.youtube.com/vi/Zwg3rROyaH0/maxresdefault.jpg)](https://youtu.be/Zwg3rROyaH0)
5
+ <div align="center">
6
+ <a href="https://youtu.be/duSncwziSwE">
7
+ <img src="https://markdown-videos-api.jorgenkh.no/url?url=https%3A%2F%2Fyoutu.be%2FduSncwziSwE" alt="Watch the Demo" style="width:100%; max-width:800px; border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,0.15);">
8
+ </a>
9
+ </div>
6
10
 
7
11
  Rails Trace Viewer provides a beautiful, interactive Call Stack Tree that visualizes how your Rails application processes requests. It traces the flow from the Controller through Models, Views, SQL Queries, and even across process boundaries into Sidekiq Background Jobs.
8
12
 
@@ -2,6 +2,9 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>Rails Trace Viewer</title>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+
5
8
  <script src="https://cdn.tailwindcss.com"></script>
6
9
  <script src="https://d3js.org/d3.v7.min.js"></script>
7
10
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dagre/0.8.5/dagre.min.js"></script>
@@ -144,7 +147,6 @@ document.addEventListener("DOMContentLoaded", () => {
144
147
  const emptyState = document.getElementById("empty-state");
145
148
  let graphs = {};
146
149
  let nodeBuffer = {};
147
- let verticalOffset = 60;
148
150
  const DAG_SPACING = 200;
149
151
 
150
152
  // Node Dimensions
@@ -167,24 +169,34 @@ document.addEventListener("DOMContentLoaded", () => {
167
169
  let subscription = null;
168
170
 
169
171
  function setupSubscription() {
170
- if (cable) cable.disconnect();
171
- cable = ActionCable.createConsumer();
172
-
173
- subscription = cable.subscriptions.create({ channel: "RailsTraceViewer::TraceChannel" }, {
174
- connected() { console.log("✅ TraceViewer: Connected"); },
175
- disconnected() { console.log("❌ TraceViewer: Disconnected"); },
176
- received(data) {
177
- if (!data || !data.node) return;
178
- if ((data.node.name || "").includes("RailsTraceViewer")) return;
179
-
180
- emptyState.classList.add("hidden");
181
-
182
- addNodeToGraph(data.trace_id, data.node);
183
-
184
- if (this.redrawTimer) clearTimeout(this.redrawTimer);
185
- this.redrawTimer = setTimeout(redrawAllGraphs, 100);
186
- }
187
- });
172
+ try {
173
+ if (cable) cable.disconnect();
174
+ } catch (err) {
175
+ console.warn("Error disconnecting previous cable:", err);
176
+ }
177
+
178
+ try {
179
+ cable = ActionCable.createConsumer();
180
+ subscription = cable.subscriptions.create({ channel: "RailsTraceViewer::TraceChannel" }, {
181
+ connected() { console.log("✅ TraceViewer: Connected"); },
182
+ disconnected() { console.log("❌ TraceViewer: Disconnected"); },
183
+ received(data) {
184
+ try {
185
+ if (!data || !data.node) return;
186
+ if ((data.node.name || "").includes("RailsTraceViewer")) return;
187
+
188
+ emptyState.classList.add("hidden");
189
+ addNodeToGraph(data.trace_id, data.node);
190
+ if (this.redrawTimer) clearTimeout(this.redrawTimer);
191
+ this.redrawTimer = setTimeout(redrawAllGraphs, 100);
192
+ } catch (err) {
193
+ console.error("Error processing trace message:", err);
194
+ }
195
+ }
196
+ });
197
+ } catch (err) {
198
+ console.error("Failed to create ActionCable consumer. Is ActionCable mounted at /cable?", err);
199
+ }
188
200
  }
189
201
 
190
202
  setupSubscription();
@@ -195,6 +207,7 @@ document.addEventListener("DOMContentLoaded", () => {
195
207
  let changed = false;
196
208
  Object.keys(nodeBuffer).forEach(pid => {
197
209
  const list = nodeBuffer[pid];
210
+ if (!list) return;
198
211
  const kept = [];
199
212
  list.forEach(item => {
200
213
  if (now - item.receivedAt > 3000) {
@@ -234,7 +247,7 @@ document.addEventListener("DOMContentLoaded", () => {
234
247
  // --- Rendering ---
235
248
  function redrawAllGraphs() {
236
249
  g.selectAll("*").remove();
237
- verticalOffset = 60;
250
+ let verticalOffset = 60;
238
251
 
239
252
  Object.keys(graphs).forEach(tid => {
240
253
  renderSingleDAG(graphs[tid], verticalOffset);
@@ -259,7 +272,7 @@ document.addEventListener("DOMContentLoaded", () => {
259
272
 
260
273
  Object.values(G.nodes).forEach(n => {
261
274
  let lbl = n.name || "Unknown";
262
- if (lbl.length > 38) lbl = lbl.substring(0, 35) + "...";
275
+ if (lbl.length > 29) lbl = lbl.substring(0, 27) + "...";
263
276
  dag.setNode(n.id, { label: lbl, width: NODE_WIDTH, height: NODE_HEIGHT, type: n.type, fullData: n });
264
277
  });
265
278
 
@@ -0,0 +1,45 @@
1
+ module RailsTraceViewer
2
+ module ActiveJobExtension
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attr_accessor :rtv_trace_id, :rtv_parent_id
7
+
8
+ around_enqueue do |job, block|
9
+ if defined?(RailsTraceViewer) && RailsTraceViewer.enabled
10
+ if RailsTraceViewer::TraceContext.active?
11
+ job.rtv_trace_id = RailsTraceViewer::TraceContext.trace_id
12
+ job.rtv_parent_id = RailsTraceViewer::TraceContext.parent_id
13
+ else
14
+ job.rtv_trace_id ||= SecureRandom.uuid
15
+ job.rtv_parent_id ||= nil
16
+ end
17
+ end
18
+
19
+ block.call
20
+ end
21
+ end
22
+
23
+ def serialize
24
+ data = super
25
+
26
+ if defined?(RailsTraceViewer) && RailsTraceViewer.enabled
27
+ data["rtv_trace_id"] = rtv_trace_id if respond_to?(:rtv_trace_id) && rtv_trace_id
28
+ data["rtv_parent_id"] = rtv_parent_id if respond_to?(:rtv_parent_id) && rtv_parent_id
29
+ end
30
+
31
+ data
32
+ end
33
+
34
+ def deserialize(job_data)
35
+ super(job_data)
36
+
37
+ if defined?(RailsTraceViewer) && RailsTraceViewer.enabled
38
+ self.rtv_trace_id = job_data["rtv_trace_id"] if job_data.key?("rtv_trace_id") && respond_to?(:rtv_trace_id=)
39
+ self.rtv_parent_id = job_data["rtv_parent_id"] if job_data.key?("rtv_parent_id") && respond_to?(:rtv_parent_id=)
40
+ end
41
+
42
+ self
43
+ end
44
+ end
45
+ end
@@ -129,23 +129,6 @@ module RailsTraceViewer
129
129
 
130
130
  after.each(&:call)
131
131
  end
132
-
133
- def finalize_trace(trace_id)
134
- trace = nil
135
-
136
- @mutex.synchronize do
137
- tree = TRACE_TREES[trace_id]
138
- return unless tree
139
- trace = tree[:root]
140
- TRACE_TREES.delete(trace_id)
141
- end
142
-
143
- ActionCable.server.broadcast(
144
- "rails_trace_viewer",
145
- event: "trace_completed",
146
- trace: trace
147
- )
148
- end
149
132
  end
150
133
  end
151
134
  end
@@ -2,48 +2,71 @@ module RailsTraceViewer
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace RailsTraceViewer
4
4
 
5
- config.to_prepare do
6
- if Rails.application.routes.routes.empty?
7
- Rails.application.reload_routes!
5
+ initializer "rails_trace_viewer.active_job_extension" do
6
+ ActiveSupport.on_load(:active_job) do
7
+ include RailsTraceViewer::ActiveJobExtension
8
8
  end
9
+ end
9
10
 
10
- is_mounted = Rails.application.routes.routes.any? do |route|
11
- app = route.app
12
- while app.respond_to?(:app) && app != app.app
13
- app = app.app
11
+ class << self
12
+ def enable_tracing!
13
+ return if @tracing_initialized
14
+
15
+ if Rails.application.routes.routes.empty?
16
+ Rails.application.reload_routes!
14
17
  end
15
- match_class = (app == RailsTraceViewer::Engine) || (app.to_s.include?("RailsTraceViewer::Engine"))
16
18
 
17
- path_match = (route.path.spec.to_s rescue "").include?("/rails_trace_viewer")
19
+ is_mounted = Rails.application.routes.routes.any? do |route|
20
+ app = route.app
21
+ while app.respond_to?(:app) && app != app.app
22
+ app = app.app
23
+ end
18
24
 
19
- match_class || path_match
20
- end
25
+ match_class = (app == RailsTraceViewer::Engine) ||
26
+ app.to_s.include?("RailsTraceViewer::Engine")
21
27
 
22
- if is_mounted
23
- RailsTraceViewer.enabled = true
24
-
25
- unless @booted_message_shown
26
- puts "✅ [RailsTraceViewer] Engine mounted. Tracing is ACTIVE."
27
- @booted_message_shown = true
28
+ path_match = (route.path.spec.to_s rescue "")
29
+ .include?("/rails_trace_viewer")
30
+
31
+ match_class || path_match
28
32
  end
29
33
 
30
- RailsTraceViewer::Subscribers::ControllerSubscriber.attach
31
- RailsTraceViewer::Subscribers::SqlSubscriber.attach
32
- RailsTraceViewer::Subscribers::ViewSubscriber.attach
33
- RailsTraceViewer::Subscribers::ActiveJobSubscriber.attach
34
- RailsTraceViewer::Subscribers::SidekiqSubscriber.attach if defined?(Sidekiq)
35
- RailsTraceViewer::Subscribers::MethodSubscriber.attach
36
-
37
- RailsTraceViewer::Collector.start_sweeper!
38
-
39
- else
40
- RailsTraceViewer.enabled = false
41
-
42
- unless @booted_message_shown
43
- puts "🚫 [RailsTraceViewer] Engine route not found. Tracing DISABLED (Zero Overhead)."
44
- @booted_message_shown = true
34
+ if is_mounted
35
+ RailsTraceViewer.enabled = true
36
+
37
+ unless @booted_message_shown
38
+ puts "✅ [RailsTraceViewer] Engine mounted. Tracing is ACTIVE."
39
+ @booted_message_shown = true
40
+ end
41
+
42
+ RailsTraceViewer::Subscribers::ControllerSubscriber.attach
43
+ RailsTraceViewer::Subscribers::SqlSubscriber.attach
44
+ RailsTraceViewer::Subscribers::ViewSubscriber.attach
45
+ RailsTraceViewer::Subscribers::ActiveJobSubscriber.attach
46
+ RailsTraceViewer::Subscribers::SidekiqSubscriber.attach if defined?(Sidekiq)
47
+ RailsTraceViewer::Subscribers::MethodSubscriber.attach
48
+
49
+ RailsTraceViewer::Collector.start_sweeper!
50
+
51
+ else
52
+ RailsTraceViewer.enabled = false
53
+
54
+ unless @booted_message_shown
55
+ puts "🚫 [RailsTraceViewer] Engine route not found. Tracing DISABLED (Zero Overhead)."
56
+ @booted_message_shown = true
57
+ end
45
58
  end
59
+
60
+ @tracing_initialized = true
46
61
  end
47
62
  end
63
+
64
+ config.to_prepare do
65
+ RailsTraceViewer::Engine.enable_tracing!
66
+ end
67
+
68
+ console do
69
+ RailsTraceViewer::Engine.enable_tracing!
70
+ end
48
71
  end
49
72
  end
@@ -9,19 +9,15 @@ module RailsTraceViewer
9
9
 
10
10
  ActiveSupport::Notifications.subscribe("enqueue.active_job") do |*_args, payload|
11
11
  job = payload[:job]
12
- next if job.class.include?(Sidekiq::Worker)
12
+ next if job.class.include?(Sidekiq::Worker) rescue false
13
13
 
14
- if RailsTraceViewer::TraceContext.active?
15
- trace_id = RailsTraceViewer::TraceContext.trace_id
16
- parent_id = RailsTraceViewer::TraceContext.parent_id
17
- else
18
- trace_id = SecureRandom.uuid
19
- parent_id = nil
20
- RailsTraceViewer::TraceContext.start!(trace_id)
21
- RailsTraceViewer::Collector.start_trace(trace_id)
22
- end
14
+ trace_id = job.respond_to?(:rtv_trace_id) ? job.rtv_trace_id : nil
15
+ parent_id = job.respond_to?(:rtv_parent_id) ? job.rtv_parent_id : nil
23
16
 
24
- enqueue_node_id = SecureRandom.uuid
17
+ trace_id ||= SecureRandom.uuid
18
+ parent_id ||= nil
19
+
20
+ enqueue_node_id = "rtv-enqueue-#{job.job_id}"
25
21
 
26
22
  node = {
27
23
  id: enqueue_node_id,
@@ -37,34 +33,35 @@ module RailsTraceViewer
37
33
  children: []
38
34
  }
39
35
 
40
- RailsTraceViewer::JobLinkRegistry.register(job, trace_id: trace_id, enqueue_node_id: enqueue_node_id)
41
36
  RailsTraceViewer::Collector.add_node(trace_id, node)
42
37
  end
43
38
 
44
39
  ActiveSupport::Notifications.subscribe("perform_start.active_job") do |*_args, payload|
45
40
  job = payload[:job]
46
41
 
47
- RailsTraceViewer::JobLinkRegistry.on_perform(job) do |trace_id, enqueue_node_id|
48
- RailsTraceViewer::TraceContext.start_job!(trace_id)
49
- RailsTraceViewer::Collector.start_trace(trace_id)
42
+ trace_id = job.respond_to?(:rtv_trace_id) ? job.rtv_trace_id : nil
43
+ trace_id ||= SecureRandom.uuid
44
+
45
+ enqueue_node_id = "rtv-enqueue-#{job.job_id}"
46
+
47
+ RailsTraceViewer::TraceContext.start_job!(trace_id)
48
+ RailsTraceViewer::Collector.start_trace(trace_id)
50
49
 
51
- node_id = SecureRandom.uuid
52
- node = {
53
- id: node_id,
54
- parent_id: enqueue_node_id,
55
- type: "job_perform",
56
- name: job.class.name,
57
- source: "ActiveJob Perform",
58
- job_id: job.job_id,
59
- arguments: safe_serialize.call(job.arguments),
60
- executions: job.executions,
61
- children: []
62
- }
50
+ node_id = SecureRandom.uuid
51
+ node = {
52
+ id: node_id,
53
+ parent_id: enqueue_node_id,
54
+ type: "job_perform",
55
+ name: job.class.name,
56
+ source: "ActiveJob Perform",
57
+ job_id: job.job_id,
58
+ arguments: safe_serialize.call(job.arguments),
59
+ executions: job.executions,
60
+ children: []
61
+ }
63
62
 
64
- RailsTraceViewer::Collector.add_node(trace_id, node)
65
- RailsTraceViewer::TraceContext.push(node_id)
66
- RailsTraceViewer::JobLinkRegistry.delete(job)
67
- end
63
+ RailsTraceViewer::Collector.add_node(trace_id, node)
64
+ RailsTraceViewer::TraceContext.push(node_id)
68
65
  end
69
66
  end
70
67
  end
@@ -40,6 +40,27 @@ module RailsTraceViewer
40
40
  is_singleton = tp.defined_class.singleton_class? rescue false
41
41
  method_sig = "#{class_name}#{is_singleton ? '.' : '#'}#{tp.method_id}"
42
42
 
43
+ arguments = {}
44
+ if tp.binding
45
+ tp.parameters.each do |type, name|
46
+ begin
47
+ val = tp.binding.local_variable_get(name)
48
+ if val.is_a?(String)
49
+ arguments[name] = val.length > 1000 ? val[0..1000] + "... (truncated)" : val
50
+ elsif val.is_a?(Numeric) || val == true || val == false || val.nil?
51
+ arguments[name] = val
52
+ elsif defined?(ActiveRecord::Base) && val.is_a?(ActiveRecord::Base)
53
+ arguments[name] = val.attributes
54
+ else
55
+ inspected = val.inspect
56
+ arguments[name] = inspected.length > 1000 ? inspected[0..1000] + "... (truncated)" : inspected
57
+ end
58
+ rescue => e
59
+ arguments[name] = "Error"
60
+ end
61
+ end
62
+ end
63
+
43
64
  node = {
44
65
  id: node_id,
45
66
  parent_id: parent_id,
@@ -50,6 +71,7 @@ module RailsTraceViewer
50
71
  line_number: tp.lineno,
51
72
  class_name: class_name,
52
73
  method_name: tp.method_id,
74
+ arguments: arguments,
53
75
  children: []
54
76
  }
55
77
  RailsTraceViewer::Collector.add_node(trace_id, node)
@@ -24,18 +24,13 @@ module RailsTraceViewer
24
24
 
25
25
  class ClientMiddleware
26
26
  def call(worker_class, job, queue, redis_pool)
27
- trace_id = nil
28
- parent_id = nil
29
- started_new_trace = false
30
27
 
31
28
  if RailsTraceViewer::TraceContext.active?
32
29
  trace_id = RailsTraceViewer::TraceContext.trace_id
33
30
  parent_id = RailsTraceViewer::TraceContext.parent_id
34
31
  else
35
32
  trace_id = SecureRandom.uuid
36
- RailsTraceViewer::TraceContext.start!(trace_id)
37
- RailsTraceViewer::Collector.start_trace(trace_id)
38
- started_new_trace = true
33
+ parent_id = nil
39
34
  end
40
35
 
41
36
  enqueue_node_id = SecureRandom.uuid
@@ -60,17 +55,13 @@ module RailsTraceViewer
60
55
  RailsTraceViewer::Collector.add_node(trace_id, node)
61
56
 
62
57
  yield
63
- ensure
64
- if started_new_trace
65
- RailsTraceViewer::TraceContext.stop!
66
- end
67
58
  end
68
59
  end
69
60
 
70
61
  class ServerMiddleware
71
62
  def call(worker, job, queue)
72
63
  trace_id = job["_trace_id"]
73
- parent_id = job["_enqueue_node_id"] || job["_parent_id"]
64
+ parent_id = job["_enqueue_node_id"]
74
65
  perform_node_id = nil
75
66
 
76
67
  if trace_id
@@ -1,31 +1,35 @@
1
1
  module RailsTraceViewer
2
2
  module Subscribers
3
3
  class SqlSubscriber
4
+
5
+ IGNORED_SQL_PATTERNS = /\A(?:BEGIN|COMMIT|ROLLBACK|SAVEPOINT|RELEASE SAVEPOINT)\b/i
6
+ IGNORED_PAYLOAD_NAMES = ["SCHEMA"].to_set
7
+
4
8
  def self.attach
5
9
  return if @attached
6
10
  @attached = true
7
11
 
8
12
  ActiveSupport::Notifications.subscribe("sql.active_record") do |*_args, payload|
9
13
  next unless RailsTraceViewer::TraceContext.active?
10
- next if payload[:name] == "SCHEMA"
14
+ next if IGNORED_PAYLOAD_NAMES.include?(payload[:name])
15
+
16
+ sql = (payload[:sql] || "").to_s
17
+ next if sql.match?(IGNORED_SQL_PATTERNS)
11
18
 
12
19
  source = extract_app_source(caller)
13
20
  next unless source
14
21
 
15
22
  raw_binds = payload[:type_casted_binds]
16
- if raw_binds.respond_to?(:call)
17
- raw_binds = raw_binds.call
18
- end
19
-
23
+ raw_binds = raw_binds.call if raw_binds.respond_to?(:call)
20
24
  binds = (raw_binds || []).map { |val| val.to_s }
21
25
 
22
26
  node = {
23
27
  id: SecureRandom.uuid,
24
28
  parent_id: RailsTraceViewer::TraceContext.parent_id,
25
29
  type: "sql",
26
- name: payload[:sql],
30
+ name: sql,
27
31
  source: source,
28
- full_sql: payload[:sql],
32
+ full_sql: sql,
29
33
  bind_values: binds,
30
34
  connection_id: payload[:connection_id],
31
35
  children: []
@@ -36,7 +40,14 @@ module RailsTraceViewer
36
40
  end
37
41
 
38
42
  def self.extract_app_source(bt)
39
- bt.find { |line| line.include?("/app/") }
43
+ app_root = Rails.root.to_s
44
+ bt.find { |line|
45
+ path = line.to_s
46
+ next false unless path.start_with?(app_root)
47
+ next false if path.include?("/vendor/") || path.include?("/node_modules/")
48
+ next false if path.include?("/rails_trace_viewer/")
49
+ true
50
+ }
40
51
  end
41
52
  end
42
53
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsTraceViewer
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.4"
5
5
  end
@@ -4,10 +4,10 @@ require "active_support"
4
4
  require "active_support/notifications"
5
5
 
6
6
  require "rails_trace_viewer/engine"
7
+ require "rails_trace_viewer/active_job_extension"
7
8
  require "rails_trace_viewer/collector"
8
9
  require "rails_trace_viewer/trace_context"
9
10
  require "rails_trace_viewer/broadcaster"
10
- require "rails_trace_viewer/job_link_registry"
11
11
  require "rails_trace_viewer/route_resolver"
12
12
 
13
13
  require "rails_trace_viewer/subscribers/controller_subscriber"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_trace_viewer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aditya-JOSH 
@@ -80,10 +80,10 @@ files:
80
80
  - app/views/rails_trace_viewer/traces/show.html.erb
81
81
  - config/routes.rb
82
82
  - lib/rails_trace_viewer.rb
83
+ - lib/rails_trace_viewer/active_job_extension.rb
83
84
  - lib/rails_trace_viewer/broadcaster.rb
84
85
  - lib/rails_trace_viewer/collector.rb
85
86
  - lib/rails_trace_viewer/engine.rb
86
- - lib/rails_trace_viewer/job_link_registry.rb
87
87
  - lib/rails_trace_viewer/route_resolver.rb
88
88
  - lib/rails_trace_viewer/subscribers/active_job_subscriber.rb
89
89
  - lib/rails_trace_viewer/subscribers/controller_subscriber.rb
@@ -1,42 +0,0 @@
1
- require "concurrent/map"
2
-
3
- module RailsTraceViewer
4
- class JobLinkRegistry
5
- @store = Concurrent::Map.new
6
- @pending = Concurrent::Map.new
7
-
8
- class << self
9
- def register(job, trace_id:, enqueue_node_id:)
10
- job_id = job.job_id
11
-
12
- @store[job_id] = {
13
- trace_id: trace_id,
14
- enqueue_node_id: enqueue_node_id
15
- }
16
-
17
- if @pending[job_id]
18
- @pending[job_id].each do |callback|
19
- callback.call(trace_id, enqueue_node_id)
20
- end
21
- @pending.delete(job_id)
22
- end
23
- end
24
-
25
- def on_perform(job, &block)
26
- job_id = job.job_id
27
-
28
- if @store[job_id]
29
- data = @store[job_id]
30
- block.call(data[:trace_id], data[:enqueue_node_id])
31
- else
32
- @pending[job_id] ||= []
33
- @pending[job_id] << block
34
- end
35
- end
36
-
37
- def delete(job)
38
- @store.delete(job.job_id)
39
- end
40
- end
41
- end
42
- end