dead_bro 0.2.5 → 0.2.6

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: 95efdf7e1aadb84f27739eb59612c8ad3bf0c6a5315d12497322140fdd0ca676
4
- data.tar.gz: c9285dd8f024f10d974b04b76e98a79f365bb6e07ab1fa665a8340cc34bc69e7
3
+ metadata.gz: 7e977f41766dfbcf7ca52cf14aafb217595f35860746a553bd9386b1ddfe7797
4
+ data.tar.gz: 24858e179f45181d6d144352347ed3f760a19abe53cead83c80eb4644e281f39
5
5
  SHA512:
6
- metadata.gz: 7b12f73db0672c45f624b0a3916b65c95c8d0929e491ef173832b5f960cfb073b2cf0b337a2071908f5a4bbe768551e851747c56e5a90a704c76719e13449773
7
- data.tar.gz: b99e770dae2b68d773eee279b02c78821244bf9c0322e91776301611d0204a0ebdd3c3b5e0c4bf62aec9e5a403bdb4c66ee35f29907fb7d5e68ae978eca33c4d
6
+ metadata.gz: 7310571657927f6404088b2605d710cb9e107d5e63231cddcf785ffc9cc22a78ff634d5bc5969e34d08e634ed0cdc46f85f8f2d6937bc05ebe9af14b00c4968c
7
+ data.tar.gz: eaaec05db2cdf1d2da03cfa873c333286d891e33cb2e37d6b347b319a3ae8481f142182d87c3ce20bd2990829075aa236e52c9f52388d2799fc862b1511ceabd
@@ -6,6 +6,7 @@ module DeadBro
6
6
  class MemoryTrackingSubscriber
7
7
  # Object allocation events
8
8
  ALLOCATION_EVENT = "object_allocations.active_support"
9
+ PROCESS_ACTION_EVENT = "process_action.action_controller"
9
10
 
10
11
  THREAD_LOCAL_KEY = :dead_bro_memory_events
11
12
  # Consider objects larger than this many bytes as "large"
@@ -28,6 +29,23 @@ module DeadBro
28
29
  next unless rand < ALLOCATION_SAMPLING_RATE
29
30
  track_allocation(data, started, finished)
30
31
  end
32
+
33
+ # Subscribe to process_action to capture request-level allocation counters
34
+ ActiveSupport::Notifications.subscribe(PROCESS_ACTION_EVENT) do |*args|
35
+ event = if args.length == 1 && args.first.is_a?(ActiveSupport::Notifications::Event)
36
+ args.first
37
+ else
38
+ ActiveSupport::Notifications::Event.new(*args)
39
+ end
40
+ allocations = event.respond_to?(:allocations) ? event.allocations : event.payload[:allocations]
41
+ allocated_bytes = event.respond_to?(:allocated_bytes) ? event.allocated_bytes : event.payload[:allocated_bytes]
42
+ next unless allocations || allocated_bytes
43
+
44
+ record_request_allocations(
45
+ allocations: allocations,
46
+ allocated_bytes: allocated_bytes
47
+ )
48
+ end
31
49
  rescue
32
50
  # Allocation tracking might not be available in all Ruby versions
33
51
  end
@@ -44,9 +62,10 @@ module DeadBro
44
62
  allocations: [],
45
63
  memory_snapshots: [],
46
64
  large_objects: [],
65
+ request_allocations: nil,
47
66
  gc_before: gc_stats,
48
67
  memory_before: memory_usage_mb,
49
- start_time: Time.now.utc.to_i,
68
+ start_time: Time.now.to_f,
50
69
  object_counts_before: count_objects_snapshot
51
70
  }
52
71
  end
@@ -58,7 +77,7 @@ module DeadBro
58
77
  if events
59
78
  events[:gc_after] = gc_stats
60
79
  events[:memory_after] = memory_usage_mb
61
- events[:end_time] = Time.now.utc.to_i
80
+ events[:end_time] = Time.now.to_f
62
81
  events[:duration_seconds] = events[:end_time] - events[:start_time]
63
82
  events[:object_counts_after] = count_objects_snapshot
64
83
 
@@ -71,6 +90,16 @@ module DeadBro
71
90
  events || {}
72
91
  end
73
92
 
93
+ # Record request-level allocation counters from Rails instrumentation.
94
+ def self.record_request_allocations(allocations:, allocated_bytes:)
95
+ return unless Thread.current[THREAD_LOCAL_KEY]
96
+
97
+ Thread.current[THREAD_LOCAL_KEY][:request_allocations] = {
98
+ allocations: allocations,
99
+ allocated_bytes: allocated_bytes
100
+ }
101
+ end
102
+
74
103
  def self.track_allocation(data, started, finished)
75
104
  return unless Thread.current[THREAD_LOCAL_KEY]
76
105
 
@@ -122,6 +151,7 @@ module DeadBro
122
151
  allocations = memory_events[:allocations] || []
123
152
  large_objects = memory_events[:large_objects] || []
124
153
  snapshots = memory_events[:memory_snapshots] || []
154
+ request_allocations = memory_events[:request_allocations]
125
155
 
126
156
  # Calculate memory growth
127
157
  memory_growth = 0
@@ -132,6 +162,19 @@ module DeadBro
132
162
  # Calculate allocation totals
133
163
  total_allocations = allocations.sum { |a| a[:count] }
134
164
  total_allocated_size = allocations.sum { |a| a[:size] }
165
+ if request_allocations
166
+ total_allocated_size = request_allocations[:allocated_bytes].to_i if total_allocated_size.zero?
167
+ end
168
+ gc_allocations = nil
169
+ if memory_events[:gc_before] && memory_events[:gc_after]
170
+ gc_allocations = (memory_events[:gc_after][:total_allocated_objects] || 0) -
171
+ (memory_events[:gc_before][:total_allocated_objects] || 0)
172
+ end
173
+ if gc_allocations.to_i > 0
174
+ total_allocations = gc_allocations
175
+ elsif total_allocations.zero? && request_allocations
176
+ total_allocations = request_allocations[:allocations].to_i
177
+ end
135
178
 
136
179
  # Group allocations by class
137
180
  allocations_by_class = allocations.group_by { |a| a[:class_name] }
@@ -174,7 +217,8 @@ module DeadBro
174
217
  (total_allocations.to_f / memory_events[:duration_seconds]).round(2) : 0,
175
218
  top_allocating_classes: top_allocating_classes.map { |class_name, data|
176
219
  {
177
- class_name: class_name,
220
+ class: class_name,
221
+ name: class_name,
178
222
  count: data[:count],
179
223
  size: data[:size],
180
224
  size_mb: (data[:size] / 1_000_000.0).round(2)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeadBro
4
- VERSION = "0.2.5"
4
+ VERSION = "0.2.6"
5
5
  end
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.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emanuel Comsa