brainzlab 0.1.34 → 0.1.35

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/brainzlab/beacon/client.rb +4 -6
  3. data/lib/brainzlab/configuration.rb +301 -272
  4. data/lib/brainzlab/cortex/client.rb +4 -6
  5. data/lib/brainzlab/debug.rb +6 -6
  6. data/lib/brainzlab/dendrite/client.rb +4 -6
  7. data/lib/brainzlab/development/logger.rb +2 -2
  8. data/lib/brainzlab/development/store.rb +2 -4
  9. data/lib/brainzlab/devtools/middleware/error_page.rb +1 -1
  10. data/lib/brainzlab/errors.rb +5 -12
  11. data/lib/brainzlab/instrumentation/action_cable.rb +4 -4
  12. data/lib/brainzlab/instrumentation/action_controller.rb +12 -12
  13. data/lib/brainzlab/instrumentation/action_dispatch.rb +1 -1
  14. data/lib/brainzlab/instrumentation/action_mailbox.rb +7 -13
  15. data/lib/brainzlab/instrumentation/action_view.rb +29 -33
  16. data/lib/brainzlab/instrumentation/active_job.rb +6 -10
  17. data/lib/brainzlab/instrumentation/active_record.rb +21 -24
  18. data/lib/brainzlab/instrumentation/active_storage.rb +4 -4
  19. data/lib/brainzlab/instrumentation/active_support_cache.rb +6 -8
  20. data/lib/brainzlab/instrumentation/aws.rb +10 -7
  21. data/lib/brainzlab/instrumentation/grape.rb +3 -1
  22. data/lib/brainzlab/instrumentation/rails_deprecation.rb +1 -1
  23. data/lib/brainzlab/instrumentation/railties.rb +2 -2
  24. data/lib/brainzlab/nerve/client.rb +4 -6
  25. data/lib/brainzlab/pulse/client.rb +1 -1
  26. data/lib/brainzlab/pulse.rb +5 -1
  27. data/lib/brainzlab/rails/railtie.rb +1 -3
  28. data/lib/brainzlab/reflex/client.rb +1 -1
  29. data/lib/brainzlab/sentinel/client.rb +4 -6
  30. data/lib/brainzlab/synapse/client.rb +4 -6
  31. data/lib/brainzlab/testing/event_store.rb +3 -3
  32. data/lib/brainzlab/testing/matchers.rb +4 -4
  33. data/lib/brainzlab/testing.rb +5 -3
  34. data/lib/brainzlab/vault/client.rb +4 -6
  35. data/lib/brainzlab/version.rb +1 -1
  36. data/lib/brainzlab/vision/client.rb +3 -3
  37. data/lib/fluyenta-ruby.rb +1 -1
  38. metadata +1 -1
@@ -184,9 +184,9 @@ module BrainzLab
184
184
  BrainzLab.debug_log("[Cortex::Client] #{operation} failed: #{structured_error.message}")
185
185
 
186
186
  # Call on_error callback if configured
187
- if @config.on_error
188
- @config.on_error.call(structured_error, { service: 'Cortex', operation: operation })
189
- end
187
+ return unless @config.on_error
188
+
189
+ @config.on_error.call(structured_error, { service: 'Cortex', operation: operation })
190
190
  end
191
191
 
192
192
  def handle_response_error(response, operation)
@@ -196,9 +196,7 @@ module BrainzLab
196
196
  BrainzLab.debug_log("[Cortex::Client] #{operation} failed: #{structured_error.message}")
197
197
 
198
198
  # Call on_error callback if configured
199
- if @config.on_error
200
- @config.on_error.call(structured_error, { service: 'Cortex', operation: operation })
201
- end
199
+ @config.on_error&.call(structured_error, { service: 'Cortex', operation: operation })
202
200
 
203
201
  structured_error
204
202
  end
@@ -172,7 +172,7 @@ module BrainzLab
172
172
 
173
173
  def format_message(message, level:, **data)
174
174
  timestamp = format_timestamp
175
- prefix = colorize("[BrainzLab]", :bold, :blue)
175
+ prefix = colorize('[BrainzLab]', :bold, :blue)
176
176
  level_badge = format_level(level)
177
177
  data_str = data.empty? ? '' : " #{format_data(data)}"
178
178
 
@@ -181,8 +181,8 @@ module BrainzLab
181
181
 
182
182
  def format_arrow_message(direction, service, message, level: :info)
183
183
  timestamp = format_timestamp
184
- prefix = colorize("[BrainzLab]", :bold, :blue)
185
- arrow = direction == :out ? colorize("->", :cyan) : colorize("<-", :green)
184
+ prefix = colorize('[BrainzLab]', :bold, :blue)
185
+ arrow = direction == :out ? colorize('->', :cyan) : colorize('<-', :green)
186
186
  service_name = colorize(service.to_s.capitalize, :magenta)
187
187
 
188
188
  "#{prefix} #{timestamp} #{arrow} #{service_name} #{message}"
@@ -242,7 +242,7 @@ module BrainzLab
242
242
  other_keys = data.keys.reject { |k| %i[message timestamp level].include?(k.to_sym) }
243
243
  if other_keys.any?
244
244
  key_summary = other_keys.take(3).map { |k| "#{k}: #{format_value(data[k])}" }.join(', ')
245
- key_summary += ", ..." if other_keys.length > 3
245
+ key_summary += ', ...' if other_keys.length > 3
246
246
  summary_parts << "(#{key_summary})"
247
247
  end
248
248
 
@@ -253,7 +253,7 @@ module BrainzLab
253
253
  return '' unless str
254
254
 
255
255
  str = str.to_s
256
- str.length > length ? "#{str[0..length - 4]}..." : str
256
+ str.length > length ? "#{str[0..(length - 4)]}..." : str
257
257
  end
258
258
 
259
259
  def status_message(status)
@@ -293,7 +293,7 @@ module BrainzLab
293
293
  else config.logger.info(strip_colors(output))
294
294
  end
295
295
  else
296
- $stderr.puts output
296
+ warn output
297
297
  end
298
298
  end
299
299
 
@@ -227,9 +227,9 @@ module BrainzLab
227
227
  BrainzLab.debug_log("[Dendrite::Client] #{operation} failed: #{structured_error.message}")
228
228
 
229
229
  # Call on_error callback if configured
230
- if @config.on_error
231
- @config.on_error.call(structured_error, { service: 'Dendrite', operation: operation })
232
- end
230
+ return unless @config.on_error
231
+
232
+ @config.on_error.call(structured_error, { service: 'Dendrite', operation: operation })
233
233
  end
234
234
 
235
235
  def handle_response_error(response, operation)
@@ -239,9 +239,7 @@ module BrainzLab
239
239
  BrainzLab.debug_log("[Dendrite::Client] #{operation} failed: #{structured_error.message}")
240
240
 
241
241
  # Call on_error callback if configured
242
- if @config.on_error
243
- @config.on_error.call(structured_error, { service: 'Dendrite', operation: operation })
244
- end
242
+ @config.on_error&.call(structured_error, { service: 'Dendrite', operation: operation })
245
243
 
246
244
  structured_error
247
245
  end
@@ -82,8 +82,8 @@ module BrainzLab
82
82
  when 'log'
83
83
  level = payload[:level]&.to_sym
84
84
  level_color = COLORS[level] || COLORS[:info]
85
- msg = "#{colorize("[#{level&.upcase}]", level_color)} #{payload[:message]}"
86
- msg
85
+ "#{colorize("[#{level&.upcase}]", level_color)} #{payload[:message]}"
86
+
87
87
  when 'error'
88
88
  "#{payload[:error_class]}: #{payload[:message]}"
89
89
  when 'trace'
@@ -89,10 +89,8 @@ module BrainzLab
89
89
  private
90
90
 
91
91
  def db
92
- @db ||= begin
93
- SQLite3::Database.new(@db_path).tap do |database|
94
- database.results_as_hash = false
95
- end
92
+ @db ||= SQLite3::Database.new(@db_path).tap do |database|
93
+ database.results_as_hash = false
96
94
  end
97
95
  end
98
96
 
@@ -93,7 +93,7 @@ module BrainzLab
93
93
  .gsub('&nbsp;', ' ')
94
94
  end
95
95
 
96
- def collect_debug_data_from_info(env, info, status = 500)
96
+ def collect_debug_data_from_info(env, info, _status = 500)
97
97
  context = defined?(BrainzLab::Context) ? BrainzLab::Context.current : nil
98
98
  collector_data = Data::Collector.get_request_data
99
99
 
@@ -53,13 +53,6 @@ module BrainzLab
53
53
  super(message)
54
54
  end
55
55
 
56
- # Format the error as a detailed string with hints and documentation links.
57
- #
58
- # @return [String] Formatted error message
59
- def to_s
60
- super
61
- end
62
-
63
56
  # Return a detailed formatted version of the error with hints and documentation links.
64
57
  # Use this method when you want the full structured output.
65
58
  #
@@ -70,12 +63,12 @@ module BrainzLab
70
63
 
71
64
  parts = ["#{self.class.name}: #{base_msg}"]
72
65
 
73
- parts << "" << "Hint: #{hint}" if hint
66
+ parts << '' << "Hint: #{hint}" if hint
74
67
  parts << "Docs: #{docs_url}" if docs_url
75
68
  parts << "Code: #{code}" if code
76
69
 
77
70
  if context && !context.empty?
78
- parts << "" << "Context:"
71
+ parts << '' << 'Context:'
79
72
  context.each do |key, value|
80
73
  parts << " #{key}: #{value}"
81
74
  end
@@ -124,7 +117,7 @@ module BrainzLab
124
117
  def initialize(message = nil, hint: nil, docs_url: nil, code: nil, context: nil)
125
118
  docs_url ||= "#{DOCS_BASE_URL}/sdk/ruby/configuration"
126
119
  code ||= 'configuration_error'
127
- super(message, hint: hint, docs_url: docs_url, code: code, context: context)
120
+ super
128
121
  end
129
122
  end
130
123
 
@@ -141,7 +134,7 @@ module BrainzLab
141
134
  def initialize(message = nil, hint: nil, docs_url: nil, code: nil, context: nil)
142
135
  docs_url ||= "#{DOCS_BASE_URL}/sdk/ruby/authentication"
143
136
  code ||= 'authentication_error'
144
- super(message, hint: hint, docs_url: docs_url, code: code, context: context)
137
+ super
145
138
  end
146
139
  end
147
140
 
@@ -158,7 +151,7 @@ module BrainzLab
158
151
  def initialize(message = nil, hint: nil, docs_url: nil, code: nil, context: nil)
159
152
  docs_url ||= "#{DOCS_BASE_URL}/sdk/ruby/troubleshooting#connection-issues"
160
153
  code ||= 'connection_error'
161
- super(message, hint: hint, docs_url: docs_url, code: code, context: context)
154
+ super
162
155
  end
163
156
  end
164
157
 
@@ -91,7 +91,7 @@ module BrainzLab
91
91
  duration = event.duration.round(2)
92
92
 
93
93
  channel_class = payload[:channel_class]
94
- data = payload[:data]
94
+ payload[:data]
95
95
  via = payload[:via]
96
96
 
97
97
  # Record breadcrumb
@@ -187,7 +187,7 @@ module BrainzLab
187
187
  # Log rejection to Recall
188
188
  if BrainzLab.configuration.recall_effectively_enabled?
189
189
  BrainzLab::Recall.warn(
190
- "ActionCable subscription rejected",
190
+ 'ActionCable subscription rejected',
191
191
  channel: channel_class
192
192
  )
193
193
  end
@@ -210,7 +210,7 @@ module BrainzLab
210
210
  duration = event.duration.round(2)
211
211
 
212
212
  broadcasting = payload[:broadcasting]
213
- message = payload[:message]
213
+ payload[:message]
214
214
  coder = payload[:coder]
215
215
 
216
216
  # Record breadcrumb
@@ -236,7 +236,7 @@ module BrainzLab
236
236
  # ============================================
237
237
  # Span Recording Helpers
238
238
  # ============================================
239
- def record_action_span(event, channel_class, action, duration, data)
239
+ def record_action_span(event, channel_class, action, duration, _data)
240
240
  return unless BrainzLab.configuration.pulse_effectively_enabled?
241
241
 
242
242
  tracer = BrainzLab::Pulse.tracer
@@ -58,7 +58,7 @@ module BrainzLab
58
58
  method = payload[:method]
59
59
  path = payload[:path]
60
60
  format = payload[:format]
61
- params = payload[:params]
61
+ payload[:params]
62
62
 
63
63
  # Skip health check endpoints
64
64
  return if excluded_path?(path)
@@ -99,12 +99,12 @@ module BrainzLab
99
99
  payload = event.payload
100
100
  duration = event.duration.round(2)
101
101
 
102
- controller = payload[:controller]
103
- action = payload[:action]
102
+ payload[:controller]
103
+ payload[:action]
104
104
  status = payload[:status]
105
- method = payload[:method]
105
+ payload[:method]
106
106
  path = payload[:path]
107
- format = payload[:format]
107
+ payload[:format]
108
108
 
109
109
  # Skip health check endpoints
110
110
  return if excluded_path?(path)
@@ -157,7 +157,7 @@ module BrainzLab
157
157
  )
158
158
  end
159
159
 
160
- def record_request_trace(event, payload, duration)
160
+ def record_request_trace(event, payload, _duration)
161
161
  # Only record if Pulse is enabled and no trace is already active
162
162
  # (middleware should handle this, but this is a fallback)
163
163
  return unless BrainzLab.configuration.pulse_effectively_enabled?
@@ -265,7 +265,7 @@ module BrainzLab
265
265
  # Also log to Recall - halted callbacks can indicate auth issues
266
266
  if BrainzLab.configuration.recall_effectively_enabled?
267
267
  BrainzLab::Recall.info(
268
- "Request halted by before_action filter",
268
+ 'Request halted by before_action filter',
269
269
  filter: filter.to_s
270
270
  )
271
271
  end
@@ -307,7 +307,7 @@ module BrainzLab
307
307
  # Log to Recall - this is a security-relevant event
308
308
  if BrainzLab.configuration.recall_effectively_enabled?
309
309
  BrainzLab::Recall.warn(
310
- "Unpermitted parameters rejected",
310
+ 'Unpermitted parameters rejected',
311
311
  unpermitted_keys: keys,
312
312
  controller: context[:controller],
313
313
  action: context[:action]
@@ -362,7 +362,7 @@ module BrainzLab
362
362
  filename = payload[:filename]
363
363
 
364
364
  BrainzLab::Reflex.add_breadcrumb(
365
- "Sending data#{filename ? ": #{filename}" : ''}",
365
+ "Sending data#{": #{filename}" if filename}",
366
366
  category: 'http.data',
367
367
  level: :info,
368
368
  data: {
@@ -391,7 +391,7 @@ module BrainzLab
391
391
  type = payload[:type]
392
392
 
393
393
  BrainzLab::Reflex.add_breadcrumb(
394
- "Streaming#{filename ? ": #{filename}" : ''}",
394
+ "Streaming#{": #{filename}" if filename}",
395
395
  category: 'http.stream',
396
396
  level: :info,
397
397
  data: {
@@ -597,7 +597,7 @@ module BrainzLab
597
597
  # Add breadcrumb
598
598
  if BrainzLab.configuration.reflex_effectively_enabled?
599
599
  BrainzLab::Reflex.add_breadcrumb(
600
- "Rate limit triggered",
600
+ 'Rate limit triggered',
601
601
  category: 'security.rate_limit',
602
602
  level: :warning,
603
603
  data: {
@@ -609,7 +609,7 @@ module BrainzLab
609
609
  # Log to Recall - rate limiting is security-relevant
610
610
  if BrainzLab.configuration.recall_effectively_enabled?
611
611
  BrainzLab::Recall.warn(
612
- "Rate limit triggered",
612
+ 'Rate limit triggered',
613
613
  path: payload[:request]&.path,
614
614
  ip: payload[:request]&.remote_ip
615
615
  )
@@ -100,7 +100,7 @@ module BrainzLab
100
100
 
101
101
  status = payload[:status]
102
102
  location = payload[:location]
103
- request = payload[:request]
103
+ payload[:request]
104
104
 
105
105
  # Record breadcrumb
106
106
  if BrainzLab.configuration.reflex_effectively_enabled?
@@ -4,8 +4,8 @@ module BrainzLab
4
4
  module Instrumentation
5
5
  class ActionMailbox
6
6
  # Thresholds for slow processing (in milliseconds)
7
- SLOW_PROCESSING_THRESHOLD = 1000 # 1 second
8
- VERY_SLOW_PROCESSING_THRESHOLD = 5000 # 5 seconds
7
+ SLOW_PROCESSING_THRESHOLD = 1000 # 1 second
8
+ VERY_SLOW_PROCESSING_THRESHOLD = 5000 # 5 seconds
9
9
 
10
10
  class << self
11
11
  def install!
@@ -102,7 +102,7 @@ module BrainzLab
102
102
  started_at: event.time,
103
103
  ended_at: event.end,
104
104
  duration_ms: duration,
105
- error: status == 'bounced' || status == 'failed',
105
+ error: %w[bounced failed].include?(status),
106
106
  data: {
107
107
  'mailbox.class' => mailbox_class,
108
108
  'mailbox.email_id' => email_id,
@@ -123,7 +123,7 @@ module BrainzLab
123
123
  return unless BrainzLab.configuration.recall_effectively_enabled?
124
124
 
125
125
  # Determine log level based on status and duration
126
- if status == 'bounced' || status == 'failed'
126
+ if %w[bounced failed].include?(status)
127
127
  BrainzLab::Recall.error(
128
128
  "Mailbox processing failed: #{mailbox_class}",
129
129
  mailbox: mailbox_class,
@@ -154,9 +154,7 @@ module BrainzLab
154
154
  def extract_from(inbound_email)
155
155
  return nil unless inbound_email
156
156
 
157
- if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:from)
158
- Array(inbound_email.mail.from).first
159
- end
157
+ Array(inbound_email.mail.from).first if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:from)
160
158
  rescue StandardError
161
159
  nil
162
160
  end
@@ -164,9 +162,7 @@ module BrainzLab
164
162
  def extract_to(inbound_email)
165
163
  return nil unless inbound_email
166
164
 
167
- if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:to)
168
- Array(inbound_email.mail.to).first
169
- end
165
+ Array(inbound_email.mail.to).first if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:to)
170
166
  rescue StandardError
171
167
  nil
172
168
  end
@@ -174,9 +170,7 @@ module BrainzLab
174
170
  def extract_subject(inbound_email)
175
171
  return nil unless inbound_email
176
172
 
177
- if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:subject)
178
- inbound_email.mail.subject
179
- end
173
+ inbound_email.mail.subject if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:subject)
180
174
  rescue StandardError
181
175
  nil
182
176
  end
@@ -115,17 +115,13 @@ module BrainzLab
115
115
  template_name = extract_template_name(identifier)
116
116
 
117
117
  # Add breadcrumb for significant collections
118
- if count >= COLLECTION_TRACKING_THRESHOLD || duration >= BrainzLab.configuration.slow_render_threshold
119
- record_collection_breadcrumb(template_name, duration, count, cache_hits)
120
- end
118
+ record_collection_breadcrumb(template_name, duration, count, cache_hits) if count >= COLLECTION_TRACKING_THRESHOLD || duration >= BrainzLab.configuration.slow_render_threshold
121
119
 
122
120
  # Add span to Pulse
123
121
  record_collection_span(event, template_name, duration, count, cache_hits)
124
122
 
125
123
  # Log slow collection renders to Recall
126
- if duration >= BrainzLab.configuration.slow_render_threshold
127
- log_slow_collection_render(template_name, duration, count, cache_hits)
128
- end
124
+ log_slow_collection_render(template_name, duration, count, cache_hits) if duration >= BrainzLab.configuration.slow_render_threshold
129
125
 
130
126
  # Track potential N+1 view pattern (many partials rendered)
131
127
  track_collection_performance(template_name, count, duration) if count >= 50
@@ -244,7 +240,7 @@ module BrainzLab
244
240
  else :error
245
241
  end
246
242
 
247
- cache_info = cache_hits > 0 ? " (#{cache_hits}/#{count} cached)" : ""
243
+ cache_info = cache_hits.positive? ? " (#{cache_hits}/#{count} cached)" : ''
248
244
 
249
245
  BrainzLab::Reflex.add_breadcrumb(
250
246
  "Render collection: #{template_name} x#{count}#{cache_info} (#{duration}ms)",
@@ -255,7 +251,7 @@ module BrainzLab
255
251
  count: count,
256
252
  cache_hits: cache_hits,
257
253
  duration_ms: duration,
258
- avg_per_item_ms: count > 0 ? (duration / count).round(2) : nil
254
+ avg_per_item_ms: count.positive? ? (duration / count).round(2) : nil
259
255
  }.compact
260
256
  )
261
257
  end
@@ -279,7 +275,7 @@ module BrainzLab
279
275
  'view.template' => template_name,
280
276
  'view.count' => count,
281
277
  'view.cache_hits' => cache_hits,
282
- 'view.avg_per_item_ms' => count > 0 ? (duration / count).round(2) : nil
278
+ 'view.avg_per_item_ms' => count.positive? ? (duration / count).round(2) : nil
283
279
  }.compact
284
280
  }
285
281
 
@@ -317,41 +313,41 @@ module BrainzLab
317
313
  count: count,
318
314
  cache_hits: cache_hits,
319
315
  duration_ms: duration,
320
- avg_per_item_ms: count > 0 ? (duration / count).round(2) : nil,
316
+ avg_per_item_ms: count.positive? ? (duration / count).round(2) : nil,
321
317
  threshold_exceeded: duration >= BrainzLab.configuration.very_slow_render_threshold ? 'critical' : 'warning'
322
318
  )
323
319
  end
324
320
 
325
321
  def track_collection_performance(template_name, count, duration)
326
- avg_per_item = count > 0 ? (duration / count).round(2) : 0
322
+ avg_per_item = count.positive? ? (duration / count).round(2) : 0
327
323
 
328
324
  # If average time per item is high, this might indicate N+1 in the partial
329
- if avg_per_item > 5 # More than 5ms per item is suspicious
330
- if BrainzLab.configuration.reflex_effectively_enabled?
331
- BrainzLab::Reflex.add_breadcrumb(
332
- "Slow collection items: #{template_name} (#{avg_per_item}ms/item)",
333
- category: 'view.performance',
334
- level: :warning,
335
- data: {
336
- template: template_name,
337
- count: count,
338
- duration_ms: duration,
339
- avg_per_item_ms: avg_per_item,
340
- suggestion: 'Consider caching, eager loading, or optimizing the partial'
341
- }
342
- )
343
- end
344
-
345
- if BrainzLab.configuration.recall_effectively_enabled?
346
- BrainzLab::Recall.warn(
347
- "Collection partial may have N+1 or performance issue",
325
+ return unless avg_per_item > 5 # More than 5ms per item is suspicious
326
+
327
+ if BrainzLab.configuration.reflex_effectively_enabled?
328
+ BrainzLab::Reflex.add_breadcrumb(
329
+ "Slow collection items: #{template_name} (#{avg_per_item}ms/item)",
330
+ category: 'view.performance',
331
+ level: :warning,
332
+ data: {
348
333
  template: template_name,
349
334
  count: count,
350
335
  duration_ms: duration,
351
- avg_per_item_ms: avg_per_item
352
- )
353
- end
336
+ avg_per_item_ms: avg_per_item,
337
+ suggestion: 'Consider caching, eager loading, or optimizing the partial'
338
+ }
339
+ )
354
340
  end
341
+
342
+ return unless BrainzLab.configuration.recall_effectively_enabled?
343
+
344
+ BrainzLab::Recall.warn(
345
+ 'Collection partial may have N+1 or performance issue',
346
+ template: template_name,
347
+ count: count,
348
+ duration_ms: duration,
349
+ avg_per_item_ms: avg_per_item
350
+ )
355
351
  end
356
352
 
357
353
  # ============================================
@@ -4,8 +4,8 @@ module BrainzLab
4
4
  module Instrumentation
5
5
  class ActiveJob
6
6
  # Thresholds for slow job detection (in milliseconds)
7
- SLOW_JOB_THRESHOLD = 5000 # 5 seconds
8
- VERY_SLOW_JOB_THRESHOLD = 30_000 # 30 seconds
7
+ SLOW_JOB_THRESHOLD = 5000 # 5 seconds
8
+ VERY_SLOW_JOB_THRESHOLD = 30_000 # 30 seconds
9
9
 
10
10
  class << self
11
11
  def install!
@@ -95,7 +95,7 @@ module BrainzLab
95
95
  scheduled_in = scheduled_at ? ((scheduled_at - Time.now) / 60).round(1) : nil
96
96
 
97
97
  BrainzLab::Reflex.add_breadcrumb(
98
- "Job scheduled: #{job_class}#{scheduled_in ? " (in #{scheduled_in}min)" : ''}",
98
+ "Job scheduled: #{job_class}#{" (in #{scheduled_in}min)" if scheduled_in}",
99
99
  category: 'job.schedule',
100
100
  level: :info,
101
101
  data: {
@@ -242,14 +242,12 @@ module BrainzLab
242
242
 
243
243
  # Calculate queue wait time if enqueued_at is available
244
244
  queue_wait_ms = nil
245
- if job.enqueued_at
246
- queue_wait_ms = ((event.time - job.enqueued_at) * 1000).round(2)
247
- end
245
+ queue_wait_ms = ((event.time - job.enqueued_at) * 1000).round(2) if job.enqueued_at
248
246
 
249
247
  # Record breadcrumb
250
248
  if BrainzLab.configuration.reflex_effectively_enabled?
251
249
  BrainzLab::Reflex.add_breadcrumb(
252
- "Job started: #{job_class}#{executions > 1 ? " (attempt #{executions})" : ''}",
250
+ "Job started: #{job_class}#{" (attempt #{executions})" if executions > 1}",
253
251
  category: 'job.start',
254
252
  level: :info,
255
253
  data: {
@@ -293,9 +291,7 @@ module BrainzLab
293
291
  job_starts = Thread.current[:brainzlab_job_starts] || {}
294
292
  start_info = job_starts.delete(job_id) || {}
295
293
  queue_wait_ms = nil
296
- if start_info[:enqueued_at]
297
- queue_wait_ms = ((start_info[:started_at] - start_info[:enqueued_at]) * 1000).round(2)
298
- end
294
+ queue_wait_ms = ((start_info[:started_at] - start_info[:enqueued_at]) * 1000).round(2) if start_info[:enqueued_at]
299
295
 
300
296
  # Determine level based on outcome and duration
301
297
  level = if exception
@@ -80,7 +80,6 @@ module BrainzLab
80
80
  end
81
81
 
82
82
  def handle_sql_event(event)
83
- payload = event.payload
84
83
  duration = event.duration.round(2)
85
84
 
86
85
  # Record breadcrumb for Reflex (enhanced)
@@ -218,14 +217,12 @@ module BrainzLab
218
217
  tracker[:count] += 1
219
218
 
220
219
  # Store sample queries (limited)
221
- if tracker[:queries].size < 3
222
- tracker[:queries] << truncate_sql(sql, 200)
223
- end
220
+ tracker[:queries] << truncate_sql(sql, 200) if tracker[:queries].size < 3
224
221
 
225
222
  # Detect N+1 pattern
226
- if tracker[:count] == BrainzLab.configuration.n_plus_one_threshold
227
- report_n_plus_one(table, tracker)
228
- end
223
+ return unless tracker[:count] == BrainzLab.configuration.n_plus_one_threshold
224
+
225
+ report_n_plus_one(table, tracker)
229
226
  end
230
227
 
231
228
  def report_n_plus_one(table, tracker)
@@ -240,14 +237,14 @@ module BrainzLab
240
237
  }
241
238
  )
242
239
 
243
- if BrainzLab.configuration.recall_effectively_enabled?
244
- BrainzLab::Recall.warn(
245
- "Potential N+1 query detected",
246
- table: table,
247
- query_count: tracker[:count],
248
- sample_queries: tracker[:queries]
249
- )
250
- end
240
+ return unless BrainzLab.configuration.recall_effectively_enabled?
241
+
242
+ BrainzLab::Recall.warn(
243
+ 'Potential N+1 query detected',
244
+ table: table,
245
+ query_count: tracker[:count],
246
+ sample_queries: tracker[:queries]
247
+ )
251
248
  end
252
249
 
253
250
  def clear_n_plus_one_tracker!
@@ -332,8 +329,8 @@ module BrainzLab
332
329
  transaction = event.payload[:transaction]
333
330
  return unless transaction
334
331
 
335
- Thread.current[:brainzlab_transaction_starts] ||= {}
336
- Thread.current[:brainzlab_transaction_starts][transaction.object_id] = event.time
332
+ Thread.current[:brainzlab_transaction_starts] ||= {}.compare_by_identity
333
+ Thread.current[:brainzlab_transaction_starts][transaction] = event.time
337
334
  rescue StandardError => e
338
335
  BrainzLab.debug_log("ActiveRecord transaction start instrumentation failed: #{e.message}")
339
336
  end
@@ -344,8 +341,8 @@ module BrainzLab
344
341
  outcome = payload[:outcome] # :commit, :rollback, :restart, :incomplete
345
342
 
346
343
  # Calculate duration from stored start time
347
- starts = Thread.current[:brainzlab_transaction_starts] || {}
348
- start_time = starts.delete(transaction&.object_id) || event.time
344
+ starts = Thread.current[:brainzlab_transaction_starts] || {}.compare_by_identity
345
+ start_time = starts.delete(transaction) || event.time
349
346
  duration = ((event.end - start_time) * 1000).round(2)
350
347
 
351
348
  connection_name = extract_connection_name(payload[:connection])
@@ -440,7 +437,7 @@ module BrainzLab
440
437
  # Log to Recall
441
438
  if BrainzLab.configuration.recall_effectively_enabled?
442
439
  BrainzLab::Recall.warn(
443
- "Strict loading violation detected",
440
+ 'Strict loading violation detected',
444
441
  owner_class: owner_class,
445
442
  association: association_name.to_s,
446
443
  message: "Attempted to lazily load #{association_name} on #{owner_class} with strict_loading enabled"
@@ -485,7 +482,7 @@ module BrainzLab
485
482
  # Log to Recall
486
483
  if BrainzLab.configuration.recall_effectively_enabled?
487
484
  BrainzLab::Recall.warn(
488
- "Deprecated association accessed",
485
+ 'Deprecated association accessed',
489
486
  owner_class: owner_class,
490
487
  association: association_name.to_s,
491
488
  message: message
@@ -521,9 +518,9 @@ module BrainzLab
521
518
  # Handles: SELECT ... FROM table_name, SELECT ... FROM "table_name", etc.
522
519
  return nil unless sql =~ /\ASELECT/i
523
520
 
524
- if sql =~ /FROM\s+["'`]?(\w+)["'`]?/i
525
- ::Regexp.last_match(1)
526
- end
521
+ return unless sql =~ /FROM\s+["'`]?(\w+)["'`]?/i
522
+
523
+ ::Regexp.last_match(1)
527
524
  end
528
525
 
529
526
  def skip_query?(payload)