dead_bro 0.2.15 → 0.2.16

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: 2251b88befeee4d2b7668bc504cc99d94cd154dd4539258545c1084e7a388709
4
- data.tar.gz: 10141477e9697b91d95290ccfc695abb304e8dfbdfb526f95646269be03be0ef
3
+ metadata.gz: 0bfea7b6292743b5e6a0f7226c1bd8877ebfbe1131f95d5c1679f07377768ed2
4
+ data.tar.gz: '08ab07422afbd9d2d340e5195f47ceda9a184faa9a870e5464d6169dfc86ee6b'
5
5
  SHA512:
6
- metadata.gz: 39ec9243a8792016f7cf9bf5f8d81856c121365b5cebef91ef7d318f642e7480a66b32a92b63ec944ee3aebb9e92ffdfc27c9e284e41da7daa081661e893b38a
7
- data.tar.gz: 519f6df31fb8dc567a6974052e58787098021078514eaa2877a2f582651c5a5fec316f4da58a625a4b6d00eed7fae614fe5dd79f1da17ae2d4d7227ce8f7061b
6
+ metadata.gz: 76822c848e35d76f6cb54d7953e9ad7bb68de09b706be6f7586c4c67a3e430074fcd33515394965aeeb1d41c74577295ce56942badb05d96fd390e1daefeb410
7
+ data.tar.gz: 2cd76061aa3f443723dfc3e934b1cd36e7e7576257f6637a4a1deab4e05c3154d309c9d4b59d084b46e89521774e47475a84fdc711db42d03b1dab496682d532
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.16] - 2026-05-24
4
+
5
+ ### Added
6
+ - `ArObjectTracker`: subscribes to Rails' built-in `instantiation.active_record` notification to count the total number of ActiveRecord model instances hydrated during each request or background job. The count is reported as `ar_instantiation_count` in every payload. Uses a thread-local counter with an idempotent `subscribe!` guard, matching the same start/stop lifecycle as `GcTracker`. No monkey-patching required — Rails emits this event natively with a `record_count` field that accumulates correctly across batch loads.
7
+
3
8
  ## [0.2.14] - 2026-05-23
4
9
 
5
10
  ### Added
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/notifications"
4
+
5
+ module DeadBro
6
+ module ArObjectTracker
7
+ THREAD_KEY = :dead_bro_ar_objects
8
+
9
+ def self.subscribe!
10
+ return if @subscribed
11
+ @subscribed = true
12
+ ActiveSupport::Notifications.subscribe("instantiation.active_record") do |_name, _started, _finished, _id, data|
13
+ count = Thread.current[THREAD_KEY]
14
+ next unless count
15
+ Thread.current[THREAD_KEY] = count + (data[:record_count] || 1).to_i
16
+ end
17
+ rescue StandardError
18
+ # Never raise from instrumentation install
19
+ end
20
+
21
+ def self.start_request_tracking
22
+ Thread.current[THREAD_KEY] = 0
23
+ end
24
+
25
+ def self.stop_request_tracking
26
+ Thread.current[THREAD_KEY]
27
+ ensure
28
+ Thread.current[THREAD_KEY] = nil
29
+ end
30
+ end
31
+ end
@@ -15,6 +15,7 @@ module DeadBro
15
15
  # Snap GC state before the job runs so stop_request_tracking gets a valid diff
16
16
  ActiveSupport::Notifications.subscribe("perform_start.active_job") do |_name, _started, _finished, _unique_id, _data|
17
17
  DeadBro::GcTracker.start_request_tracking if defined?(DeadBro::GcTracker)
18
+ DeadBro::ArObjectTracker.start_request_tracking if defined?(DeadBro::ArObjectTracker)
18
19
  rescue
19
20
  end
20
21
 
@@ -69,6 +70,7 @@ module DeadBro
69
70
  sql_queries = DeadBro::SqlSubscriber.stop_request_tracking
70
71
  db_connection_stats = defined?(DeadBro::DbConnectionSubscriber) ? DeadBro::DbConnectionSubscriber.stop_request_tracking : {}
71
72
  gc_pressure = defined?(DeadBro::GcTracker) ? DeadBro::GcTracker.stop_request_tracking : {}
73
+ ar_instantiation_count = defined?(DeadBro::ArObjectTracker) ? DeadBro::ArObjectTracker.stop_request_tracking : nil
72
74
 
73
75
  # Stop memory tracking and get collected memory data
74
76
  if DeadBro.configuration.allocation_tracking_enabled && defined?(DeadBro::MemoryTrackingSubscriber)
@@ -108,6 +110,7 @@ module DeadBro
108
110
  db_connection_wait_ms: db_connection_stats[:wait_ms],
109
111
  db_connection_checkouts: db_connection_stats[:checkouts],
110
112
  gc_pressure: gc_pressure,
113
+ ar_instantiation_count: ar_instantiation_count,
111
114
  status: "completed",
112
115
  sql_queries: sql_queries,
113
116
  rails_env: DeadBro.env,
@@ -162,6 +165,7 @@ module DeadBro
162
165
  sql_queries = DeadBro::SqlSubscriber.stop_request_tracking
163
166
  db_connection_stats = defined?(DeadBro::DbConnectionSubscriber) ? DeadBro::DbConnectionSubscriber.stop_request_tracking : {}
164
167
  gc_pressure = defined?(DeadBro::GcTracker) ? DeadBro::GcTracker.stop_request_tracking : {}
168
+ ar_instantiation_count = defined?(DeadBro::ArObjectTracker) ? DeadBro::ArObjectTracker.stop_request_tracking : nil
165
169
 
166
170
  # Stop memory tracking and get collected memory data
167
171
  if DeadBro.configuration.allocation_tracking_enabled && defined?(DeadBro::MemoryTrackingSubscriber)
@@ -201,6 +205,7 @@ module DeadBro
201
205
  db_connection_wait_ms: db_connection_stats[:wait_ms],
202
206
  db_connection_checkouts: db_connection_stats[:checkouts],
203
207
  gc_pressure: gc_pressure,
208
+ ar_instantiation_count: ar_instantiation_count,
204
209
  status: "failed",
205
210
  sql_queries: sql_queries,
206
211
  exception_class: exception&.class&.name,
@@ -228,6 +233,7 @@ module DeadBro
228
233
  DeadBro::SqlSubscriber.stop_request_tracking if defined?(DeadBro::SqlSubscriber)
229
234
  DeadBro::DbConnectionSubscriber.stop_request_tracking if defined?(DeadBro::DbConnectionSubscriber)
230
235
  DeadBro::GcTracker.stop_request_tracking if defined?(DeadBro::GcTracker)
236
+ DeadBro::ArObjectTracker.stop_request_tracking if defined?(DeadBro::ArObjectTracker)
231
237
  DeadBro::LightweightMemoryTracker.stop_request_tracking if defined?(DeadBro::LightweightMemoryTracker)
232
238
  if DeadBro.configuration.allocation_tracking_enabled && defined?(DeadBro::MemoryTrackingSubscriber)
233
239
  DeadBro::MemoryTrackingSubscriber.stop_request_tracking
@@ -40,6 +40,10 @@ if defined?(Rails) && defined?(Rails::Railtie)
40
40
  require "dead_bro/db_connection_subscriber"
41
41
  DeadBro::DbConnectionSubscriber.install!
42
42
 
43
+ # Install ActiveRecord object instantiation tracking
44
+ require "dead_bro/ar_object_tracker"
45
+ DeadBro::ArObjectTracker.subscribe!
46
+
43
47
  # Install view rendering tracking
44
48
  require "dead_bro/view_rendering_subscriber"
45
49
  DeadBro::ViewRenderingSubscriber.subscribe!(client: shared_client)
@@ -64,6 +64,9 @@ module DeadBro
64
64
  # Start GC pressure tracking — snapshot before any app code runs
65
65
  DeadBro::GcTracker.start_request_tracking if defined?(DeadBro::GcTracker)
66
66
 
67
+ # Start AR object instantiation counting for this request
68
+ DeadBro::ArObjectTracker.start_request_tracking if defined?(DeadBro::ArObjectTracker)
69
+
67
70
  # Start outgoing HTTP accumulation for this request
68
71
  Thread.current[:dead_bro_http_events] = []
69
72
 
@@ -101,6 +104,8 @@ module DeadBro
101
104
  Thread.current[:dead_bro_queue_duration_ms] = nil
102
105
  DeadBro::DbConnectionSubscriber.stop_request_tracking if defined?(DeadBro::DbConnectionSubscriber)
103
106
  Thread.current[DeadBro::GcTracker::THREAD_KEY] = nil if defined?(DeadBro::GcTracker)
107
+ # Bypass stop_request_tracking intentionally — cleanup only, no return value needed here.
108
+ Thread.current[DeadBro::ArObjectTracker::THREAD_KEY] = nil if defined?(DeadBro::ArObjectTracker)
104
109
  Thread.current[DeadBro::TRACKING_START_TIME_KEY] = nil
105
110
  end
106
111
 
@@ -68,6 +68,9 @@ module DeadBro
68
68
  # Stop GC pressure tracking — diff minor/major runs, objects allocated, GC time
69
69
  gc_pressure = defined?(DeadBro::GcTracker) ? DeadBro::GcTracker.stop_request_tracking : {}
70
70
 
71
+ # Stop AR object instantiation tracking
72
+ ar_instantiation_count = defined?(DeadBro::ArObjectTracker) ? DeadBro::ArObjectTracker.stop_request_tracking : nil
73
+
71
74
  # Stop view rendering tracking and get collected view events
72
75
  view_events = DeadBro::ViewRenderingSubscriber.stop_request_tracking
73
76
  view_performance = DeadBro::ViewRenderingSubscriber.analyze_view_performance(view_events)
@@ -182,6 +185,7 @@ module DeadBro
182
185
  db_connection_wait_ms: db_connection_stats[:wait_ms],
183
186
  db_connection_checkouts: db_connection_stats[:checkouts],
184
187
  gc_pressure: gc_pressure,
188
+ ar_instantiation_count: ar_instantiation_count,
185
189
  logs: DeadBro.logger.logs
186
190
  }
187
191
  client.post_metric(event_name: name, payload: payload)
@@ -204,6 +208,7 @@ module DeadBro
204
208
  Thread.current[:dead_bro_http_events] = nil
205
209
  DeadBro::DbConnectionSubscriber.stop_request_tracking if defined?(DeadBro::DbConnectionSubscriber)
206
210
  DeadBro::GcTracker.stop_request_tracking if defined?(DeadBro::GcTracker)
211
+ DeadBro::ArObjectTracker.stop_request_tracking if defined?(DeadBro::ArObjectTracker)
207
212
  rescue
208
213
  # Best effort — draining must never raise from the notifications callback.
209
214
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeadBro
4
- VERSION = "0.2.15"
4
+ VERSION = "0.2.16"
5
5
  end
data/lib/dead_bro.rb CHANGED
@@ -19,6 +19,7 @@ module DeadBro
19
19
  autoload :MemoryLeakDetector, "dead_bro/memory_leak_detector"
20
20
  autoload :LightweightMemoryTracker, "dead_bro/lightweight_memory_tracker"
21
21
  autoload :GcTracker, "dead_bro/gc_tracker"
22
+ autoload :ArObjectTracker, "dead_bro/ar_object_tracker"
22
23
  autoload :MemoryHelpers, "dead_bro/memory_helpers"
23
24
  autoload :JobSubscriber, "dead_bro/job_subscriber"
24
25
  autoload :JobSqlTrackingMiddleware, "dead_bro/job_sql_tracking_middleware"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dead_bro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.15
4
+ version: 0.2.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emanuel Comsa
@@ -21,6 +21,7 @@ files:
21
21
  - FEATURES.md
22
22
  - README.md
23
23
  - lib/dead_bro.rb
24
+ - lib/dead_bro/ar_object_tracker.rb
24
25
  - lib/dead_bro/cache_subscriber.rb
25
26
  - lib/dead_bro/circuit_breaker.rb
26
27
  - lib/dead_bro/client.rb