dead_bro 0.2.36 → 0.2.38

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.
@@ -13,6 +13,10 @@ module DeadBro
13
13
  # drop with an excluded request) — ErrorMiddleware must not send it again.
14
14
  mark_reported(data)
15
15
 
16
+ # Closes the action span opened at start_processing, whether or not
17
+ # this request is sent.
18
+ DeadBro::SpanTracker.finish_action(started, finished)
19
+
16
20
  # When disabled remotely, fire a heartbeat at most once per minute so the gem
17
21
  # can detect when tracking has been re-enabled, then skip all tracking.
18
22
  unless DeadBro.configuration.enabled
@@ -166,7 +170,8 @@ module DeadBro
166
170
  db_runtime_ms: data[:db_runtime],
167
171
  memory_usage: memory_usage_mb,
168
172
  gc_stats: end_gc_stats,
169
- sql_count: sql_count(data),
173
+ sql_count: sql_count(sql_queries),
174
+ sql_cached_count: sql_cached_count(sql_queries),
170
175
  sql_queries: sql_queries,
171
176
  transaction_events: transaction_events,
172
177
  http_outgoing: Thread.current[:dead_bro_http_events] || [],
@@ -190,6 +195,14 @@ module DeadBro
190
195
  watch_events: watch_events,
191
196
  logs: DeadBro.logger.logs
192
197
  }
198
+ # The span tree (see SpanTracker); the middleware spans are added when
199
+ # the payload is sent.
200
+ spans = DeadBro::SpanTracker.payload_spans
201
+ if spans
202
+ detail_fields[:spans] = spans
203
+ spans_dropped = DeadBro::SpanTracker.payload_spans_dropped
204
+ detail_fields[:spans_dropped] = spans_dropped if spans_dropped
205
+ end
193
206
 
194
207
  # Report exceptions attached to this action (e.g. controller/view errors)
195
208
  if data[:exception] || data[:exception_object]
@@ -222,7 +235,7 @@ module DeadBro
222
235
  )
223
236
 
224
237
  event_name = (exception_class || exception_obj&.class&.name || "exception").to_s
225
- client.post_metric(event_name: event_name, payload: error_payload, force: true)
238
+ DeadBro::SpanTracker.post(client, event_name, error_payload, request_type_key)
226
239
  rescue
227
240
  ensure
228
241
  next
@@ -246,10 +259,12 @@ module DeadBro
246
259
  user_agent: safe_user_agent(data),
247
260
  user_id: extract_user_id(data)
248
261
  )
249
- # force: true — the sampling decision (global or per-request-type) was
250
- # already made above; client#post_metric must not re-roll it with the
251
- # global-only rate, which would silently override a per-type sample rate.
252
- client.post_metric(event_name: name, payload: payload, force: true)
262
+ # Sent with force: true — the sampling decision (global or
263
+ # per-request-type) was already made above; client#post_metric must not
264
+ # re-roll it with the global-only rate, which would silently override a
265
+ # per-type sample rate. Held until the middleware chain returns when the
266
+ # request runs inside one (see SpanTracker.post).
267
+ DeadBro::SpanTracker.post(client, name, payload, request_type_key)
253
268
  rescue *DeadBro::CONTAINED_ERRORS
254
269
  # Anything raised here would fail the host's request (see
255
270
  # DeadBro::CONTAINED_ERRORS) — drop this request's metrics instead.
@@ -472,20 +487,24 @@ module DeadBro
472
487
  {}
473
488
  end
474
489
 
475
- def self.sql_count(data)
476
- # Count SQL queries from the payload if available
477
- if data[:sql_count]
478
- data[:sql_count]
479
- elsif defined?(ActiveRecord) && ActiveRecord::Base.connection
480
- # Try to get from ActiveRecord connection
481
- begin
482
- ActiveRecord::Base.connection.query_cache.size
483
- rescue
484
- 0
485
- end
486
- else
487
- 0
488
- end
490
+ # Number of SQL statements run during the request, query-cache hits included
491
+ # (the same count as Rails' "ActiveRecord: …ms (N queries, M cached)" log
492
+ # line). Summed from SqlSubscriber.stop_request_tracking's per-statement
493
+ # aggregates, which count every query — the raw query list stops at
494
+ # MAX_TRACKED_QUERIES. This used to read
495
+ # ActiveRecord::Base.connection.query_cache.size: the number of distinct
496
+ # cached SELECTs, an LRU capped at 100 since Rails 7.1, so every N+1 page
497
+ # reported "100" — and it leased a DB connection on requests with no SQL.
498
+ def self.sql_count(sql_queries)
499
+ Array(sql_queries).sum { |agg| agg[:count].to_i }
500
+ rescue
501
+ 0
502
+ end
503
+
504
+ # How many of sql_count were answered by the query cache, sent separately so
505
+ # the dashboard can tell repeated cache hits from database round trips.
506
+ def self.sql_cached_count(sql_queries)
507
+ Array(sql_queries).sum { |agg| agg[:cached_count].to_i }
489
508
  rescue
490
509
  0
491
510
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeadBro
4
- VERSION = "0.2.36"
4
+ VERSION = "0.2.38"
5
5
  end
6
-
@@ -91,6 +91,8 @@ module DeadBro
91
91
  frame[:slot] = events.length
92
92
  events << nil
93
93
  active_stack << frame
94
+ # The block's span in the request's span tree (nil in a job).
95
+ span_frame = DeadBro::SpanTracker.enter_watch(sanitized_label)
94
96
 
95
97
  begin
96
98
  yield
@@ -104,6 +106,8 @@ module DeadBro
104
106
  raise
105
107
  ensure
106
108
  active_stack.pop if active_stack.last.equal?(frame)
109
+ DeadBro::SpanTracker.leave_watch(span_frame)
110
+ frame[:span_id] = span_frame[:id] if span_frame.is_a?(Hash)
107
111
  append_completed_span(events, frame)
108
112
  end
109
113
  end
@@ -178,6 +182,7 @@ module DeadBro
178
182
  error: frame[:error] == true
179
183
  }
180
184
  span[:exception_class] = frame[:exception_class] if frame[:exception_class]
185
+ span[:span_id] = frame[:span_id] if frame[:span_id]
181
186
  tags = frame[:tags]
182
187
  span[:tags] = tags if tags.is_a?(Hash) && tags.any?
183
188
 
data/lib/dead_bro.rb CHANGED
@@ -30,6 +30,8 @@ module DeadBro
30
30
  autoload :MemoryDetails, "dead_bro/memory_details"
31
31
  autoload :Logger, "dead_bro/logger"
32
32
  autoload :WatchTracker, "dead_bro/watch_tracker"
33
+ autoload :SpanTracker, "dead_bro/span_tracker"
34
+ autoload :MiddlewareProbe, "dead_bro/middleware_probe"
33
35
  autoload :Sanitizer, "dead_bro/sanitizer"
34
36
  begin
35
37
  require "dead_bro/railtie"
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.36
4
+ version: 0.2.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emanuel Comsa
@@ -51,10 +51,12 @@ files:
51
51
  - lib/dead_bro/memory_leak_detector.rb
52
52
  - lib/dead_bro/memory_phase_tracker.rb
53
53
  - lib/dead_bro/memory_tracking_subscriber.rb
54
+ - lib/dead_bro/middleware_probe.rb
54
55
  - lib/dead_bro/monitor.rb
55
56
  - lib/dead_bro/railtie.rb
56
57
  - lib/dead_bro/redis_subscriber.rb
57
58
  - lib/dead_bro/sanitizer.rb
59
+ - lib/dead_bro/span_tracker.rb
58
60
  - lib/dead_bro/sql_subscriber.rb
59
61
  - lib/dead_bro/sql_tracking_middleware.rb
60
62
  - lib/dead_bro/subscriber.rb