brainzlab 0.1.2 → 0.1.3

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +6 -21
  3. data/README.md +16 -2
  4. data/lib/brainzlab/beacon/client.rb +38 -40
  5. data/lib/brainzlab/beacon/provisioner.rb +1 -1
  6. data/lib/brainzlab/beacon.rb +15 -15
  7. data/lib/brainzlab/configuration.rb +92 -90
  8. data/lib/brainzlab/context.rb +2 -3
  9. data/lib/brainzlab/cortex/client.rb +29 -31
  10. data/lib/brainzlab/cortex/provisioner.rb +1 -1
  11. data/lib/brainzlab/cortex.rb +7 -11
  12. data/lib/brainzlab/dendrite/client.rb +42 -44
  13. data/lib/brainzlab/dendrite/provisioner.rb +1 -1
  14. data/lib/brainzlab/dendrite.rb +4 -4
  15. data/lib/brainzlab/devtools/data/collector.rb +22 -22
  16. data/lib/brainzlab/devtools/middleware/asset_server.rb +14 -14
  17. data/lib/brainzlab/devtools/middleware/database_handler.rb +52 -55
  18. data/lib/brainzlab/devtools/middleware/debug_panel.rb +19 -19
  19. data/lib/brainzlab/devtools/middleware/error_page.rb +45 -44
  20. data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +39 -35
  21. data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +13 -9
  22. data/lib/brainzlab/devtools.rb +11 -11
  23. data/lib/brainzlab/flux/buffer.rb +3 -3
  24. data/lib/brainzlab/flux/client.rb +14 -16
  25. data/lib/brainzlab/flux/provisioner.rb +13 -13
  26. data/lib/brainzlab/flux.rb +8 -8
  27. data/lib/brainzlab/instrumentation/action_mailer.rb +14 -13
  28. data/lib/brainzlab/instrumentation/active_record.rb +13 -15
  29. data/lib/brainzlab/instrumentation/aws.rb +43 -39
  30. data/lib/brainzlab/instrumentation/dalli.rb +20 -20
  31. data/lib/brainzlab/instrumentation/delayed_job.rb +27 -29
  32. data/lib/brainzlab/instrumentation/elasticsearch.rb +23 -24
  33. data/lib/brainzlab/instrumentation/excon.rb +27 -27
  34. data/lib/brainzlab/instrumentation/faraday.rb +3 -4
  35. data/lib/brainzlab/instrumentation/good_job.rb +28 -28
  36. data/lib/brainzlab/instrumentation/grape.rb +24 -24
  37. data/lib/brainzlab/instrumentation/graphql.rb +24 -23
  38. data/lib/brainzlab/instrumentation/httparty.rb +13 -14
  39. data/lib/brainzlab/instrumentation/mongodb.rb +7 -7
  40. data/lib/brainzlab/instrumentation/net_http.rb +6 -6
  41. data/lib/brainzlab/instrumentation/redis.rb +14 -21
  42. data/lib/brainzlab/instrumentation/resque.rb +23 -24
  43. data/lib/brainzlab/instrumentation/sidekiq.rb +29 -28
  44. data/lib/brainzlab/instrumentation/solid_queue.rb +37 -41
  45. data/lib/brainzlab/instrumentation/stripe.rb +36 -37
  46. data/lib/brainzlab/instrumentation/typhoeus.rb +19 -17
  47. data/lib/brainzlab/instrumentation.rb +20 -20
  48. data/lib/brainzlab/nerve/client.rb +38 -40
  49. data/lib/brainzlab/nerve/provisioner.rb +1 -1
  50. data/lib/brainzlab/nerve.rb +6 -6
  51. data/lib/brainzlab/pulse/client.rb +15 -11
  52. data/lib/brainzlab/pulse/instrumentation.rb +61 -57
  53. data/lib/brainzlab/pulse/propagation.rb +28 -28
  54. data/lib/brainzlab/pulse/provisioner.rb +12 -12
  55. data/lib/brainzlab/pulse/tracer.rb +3 -3
  56. data/lib/brainzlab/pulse.rb +13 -13
  57. data/lib/brainzlab/rails/log_formatter.rb +127 -121
  58. data/lib/brainzlab/rails/log_subscriber.rb +70 -76
  59. data/lib/brainzlab/rails/railtie.rb +66 -89
  60. data/lib/brainzlab/recall/buffer.rb +1 -1
  61. data/lib/brainzlab/recall/client.rb +14 -10
  62. data/lib/brainzlab/recall/logger.rb +16 -18
  63. data/lib/brainzlab/recall/provisioner.rb +16 -16
  64. data/lib/brainzlab/recall.rb +11 -13
  65. data/lib/brainzlab/reflex/breadcrumbs.rb +2 -2
  66. data/lib/brainzlab/reflex/client.rb +14 -10
  67. data/lib/brainzlab/reflex/provisioner.rb +12 -12
  68. data/lib/brainzlab/reflex.rb +29 -29
  69. data/lib/brainzlab/sentinel/client.rb +40 -42
  70. data/lib/brainzlab/sentinel/provisioner.rb +1 -1
  71. data/lib/brainzlab/sentinel.rb +5 -5
  72. data/lib/brainzlab/signal/client.rb +12 -14
  73. data/lib/brainzlab/signal/provisioner.rb +12 -12
  74. data/lib/brainzlab/signal.rb +7 -7
  75. data/lib/brainzlab/synapse/client.rb +42 -44
  76. data/lib/brainzlab/synapse/provisioner.rb +1 -1
  77. data/lib/brainzlab/synapse.rb +6 -6
  78. data/lib/brainzlab/utilities/circuit_breaker.rb +37 -41
  79. data/lib/brainzlab/utilities/health_check.rb +53 -55
  80. data/lib/brainzlab/utilities/log_formatter.rb +38 -40
  81. data/lib/brainzlab/utilities/rate_limiter.rb +5 -5
  82. data/lib/brainzlab/utilities.rb +4 -4
  83. data/lib/brainzlab/vault/cache.rb +1 -1
  84. data/lib/brainzlab/vault/client.rb +39 -41
  85. data/lib/brainzlab/vault/provisioner.rb +1 -1
  86. data/lib/brainzlab/vault.rb +19 -25
  87. data/lib/brainzlab/version.rb +1 -1
  88. data/lib/brainzlab/vision/client.rb +20 -20
  89. data/lib/brainzlab/vision/provisioner.rb +21 -21
  90. data/lib/brainzlab/vision.rb +17 -19
  91. data/lib/brainzlab-sdk.rb +1 -1
  92. data/lib/brainzlab.rb +22 -24
  93. data/lib/generators/brainzlab/install/install_generator.rb +29 -27
  94. metadata +1 -1
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/log_subscriber"
3
+ require 'active_support/log_subscriber'
4
4
 
5
5
  module BrainzLab
6
6
  module Rails
@@ -21,12 +21,11 @@ module BrainzLab
21
21
  params = payload[:params]&.except(*INTERNAL_PARAMS) || {}
22
22
 
23
23
  formatter.start_request(request_id,
24
- method: payload[:method],
25
- path: payload[:path],
26
- params: filter_params(params),
27
- controller: payload[:controller],
28
- action: payload[:action]
29
- )
24
+ method: payload[:method],
25
+ path: payload[:path],
26
+ params: filter_params(params),
27
+ controller: payload[:controller],
28
+ action: payload[:action])
30
29
  end
31
30
 
32
31
  def process_action(event)
@@ -38,18 +37,15 @@ module BrainzLab
38
37
  payload = event.payload
39
38
 
40
39
  formatter.process_action(request_id,
41
- controller: payload[:controller],
42
- action: payload[:action],
43
- status: payload[:status],
44
- duration: event.duration,
45
- view_runtime: payload[:view_runtime],
46
- db_runtime: payload[:db_runtime]
47
- )
40
+ controller: payload[:controller],
41
+ action: payload[:action],
42
+ status: payload[:status],
43
+ duration: event.duration,
44
+ view_runtime: payload[:view_runtime],
45
+ db_runtime: payload[:db_runtime])
48
46
 
49
47
  # Handle exception if present
50
- if payload[:exception_object]
51
- formatter.error(request_id, payload[:exception_object])
52
- end
48
+ formatter.error(request_id, payload[:exception_object]) if payload[:exception_object]
53
49
 
54
50
  # Output the formatted log
55
51
  output = formatter.end_request(request_id)
@@ -81,11 +77,11 @@ module BrainzLab
81
77
  case obj
82
78
  when Hash
83
79
  obj.each_with_object({}) do |(k, v), h|
84
- if filter_keys.include?(k.to_s.downcase)
85
- h[k] = "[FILTERED]"
86
- else
87
- h[k] = deep_filter(v, filter_keys)
88
- end
80
+ h[k] = if filter_keys.include?(k.to_s.downcase)
81
+ '[FILTERED]'
82
+ else
83
+ deep_filter(v, filter_keys)
84
+ end
89
85
  end
90
86
  when Array
91
87
  obj.map { |v| deep_filter(v, filter_keys) }
@@ -121,13 +117,12 @@ module BrainzLab
121
117
  sql_pattern = normalize_sql(payload[:sql])
122
118
 
123
119
  LogSubscriber.formatter.sql_query(request_id,
124
- name: payload[:name],
125
- duration: event.duration,
126
- sql: payload[:sql],
127
- sql_pattern: sql_pattern,
128
- cached: payload[:cached] || payload[:name] == "CACHE",
129
- source: source
130
- )
120
+ name: payload[:name],
121
+ duration: event.duration,
122
+ sql: payload[:sql],
123
+ sql_pattern: sql_pattern,
124
+ cached: payload[:cached] || payload[:name] == 'CACHE',
125
+ source: source)
131
126
  end
132
127
 
133
128
  private
@@ -135,11 +130,11 @@ module BrainzLab
135
130
  def extract_source_location(backtrace)
136
131
  # Find the first line that's in app/ directory
137
132
  backtrace.each do |line|
138
- if line.include?("/app/") && !line.include?("/brainzlab")
139
- # Extract just the relevant part: app/models/user.rb:42
140
- match = line.match(%r{(app/[^:]+:\d+)})
141
- return match[1] if match
142
- end
133
+ next unless line.include?('/app/') && !line.include?('/brainzlab')
134
+
135
+ # Extract just the relevant part: app/models/user.rb:42
136
+ match = line.match(%r{(app/[^:]+:\d+)})
137
+ return match[1] if match
143
138
  end
144
139
  nil
145
140
  end
@@ -148,11 +143,11 @@ module BrainzLab
148
143
  return nil unless sql
149
144
 
150
145
  sql
151
- .gsub(/\b\d+\b/, "?") # Replace numbers
152
- .gsub(/'[^']*'/, "?") # Replace single-quoted strings
153
- .gsub(/\$\d+/, "?") # Replace positional params
154
- .gsub(/\/\*.*?\*\//, "") # Remove comments
155
- .gsub(/\s+/, " ") # Normalize whitespace
146
+ .gsub(/\b\d+\b/, '?') # Replace numbers
147
+ .gsub(/'[^']*'/, '?') # Replace single-quoted strings
148
+ .gsub(/\$\d+/, '?') # Replace positional params
149
+ .gsub(%r{/\*.*?\*/}, '') # Remove comments
150
+ .gsub(/\s+/, ' ') # Normalize whitespace
156
151
  .strip
157
152
  end
158
153
  end
@@ -182,18 +177,18 @@ module BrainzLab
182
177
  return broadcasting unless broadcasting
183
178
 
184
179
  # Extract channel name from gid format: logs:Z2lkOi8vcmVjYWxsL1Byb2plY3QvNDhi...
185
- if broadcasting.start_with?("logs:")
186
- "LogsChannel"
187
- elsif broadcasting.include?(":")
180
+ if broadcasting.start_with?('logs:')
181
+ 'LogsChannel'
182
+ elsif broadcasting.include?(':')
188
183
  # Generic channel:id format
189
- broadcasting.split(":").first.capitalize + "Channel"
184
+ "#{broadcasting.split(':').first.capitalize}Channel"
190
185
  else
191
186
  broadcasting
192
187
  end
193
188
  end
194
189
 
195
190
  def format_message(message)
196
- return "{}" unless message
191
+ return '{}' unless message
197
192
 
198
193
  case message
199
194
  when Hash
@@ -214,58 +209,60 @@ module BrainzLab
214
209
  parts = []
215
210
 
216
211
  # Show key fields for log entries
217
- if hash["level"] || hash[:level]
218
- level = hash["level"] || hash[:level]
212
+ if hash['level'] || hash[:level]
213
+ level = hash['level'] || hash[:level]
219
214
  parts << colorize_level(level)
220
215
  end
221
216
 
222
- if hash["message"] || hash[:message]
223
- msg = hash["message"] || hash[:message]
217
+ if hash['message'] || hash[:message]
218
+ msg = hash['message'] || hash[:message]
224
219
  parts << truncate(msg.to_s, 50)
225
220
  end
226
221
 
227
- if hash["id"] || hash[:id]
228
- id = hash["id"] || hash[:id]
222
+ if hash['id'] || hash[:id]
223
+ id = hash['id'] || hash[:id]
229
224
  parts << colorize(id.to_s[0..7], :gray)
230
225
  end
231
226
 
232
- parts.any? ? parts.join(" ") : hash.keys.first(3).join(", ")
227
+ parts.any? ? parts.join(' ') : hash.keys.first(3).join(', ')
233
228
  end
234
229
 
235
230
  def build_output(channel, message, duration)
236
- time = Time.current.strftime("%H:%M:%S")
237
- duration_str = duration ? "#{duration.round(1)}ms" : ""
231
+ time = Time.current.strftime('%H:%M:%S')
232
+ duration_str = duration ? "#{duration.round(1)}ms" : ''
238
233
 
239
234
  parts = [
240
235
  colorize(time, :gray),
241
- colorize("", :magenta),
236
+ colorize('', :magenta),
242
237
  colorize(channel, :magenta),
243
- colorize("", :gray),
238
+ colorize('', :gray),
244
239
  message,
245
240
  colorize(duration_str, :gray)
246
241
  ]
247
242
 
248
- " " + parts.join(" ") + "\n"
243
+ " #{parts.join(' ')}\n"
249
244
  end
250
245
 
251
246
  def truncate(text, length)
252
247
  return text if text.nil? || text.length <= length
248
+
253
249
  "#{text[0..(length - 4)]}..."
254
250
  end
255
251
 
256
252
  def colorize(text, color)
257
253
  return text unless $stdout.tty?
258
254
  return text unless COLORS[color]
255
+
259
256
  "#{COLORS[color]}#{text}#{COLORS[:reset]}"
260
257
  end
261
258
 
262
259
  def colorize_level(level)
263
260
  color = case level.to_s.downcase
264
- when "debug" then :gray
265
- when "info" then :green
266
- when "warn", "warning" then :yellow
267
- when "error" then :red
268
- when "fatal" then :red
261
+ when 'debug' then :gray
262
+ when 'info' then :green
263
+ when 'warn', 'warning' then :yellow
264
+ when 'error' then :red
265
+ when 'fatal' then :red
269
266
  else :white
270
267
  end
271
268
  colorize(level.to_s.upcase.ljust(5), color)
@@ -284,10 +281,9 @@ module BrainzLab
284
281
  template = template_name(payload[:identifier])
285
282
 
286
283
  LogSubscriber.formatter.render_template(request_id,
287
- template: template,
288
- duration: event.duration,
289
- layout: payload[:layout]
290
- )
284
+ template: template,
285
+ duration: event.duration,
286
+ layout: payload[:layout])
291
287
  end
292
288
 
293
289
  def render_partial(event)
@@ -300,10 +296,9 @@ module BrainzLab
300
296
  template = template_name(payload[:identifier])
301
297
 
302
298
  LogSubscriber.formatter.render_partial(request_id,
303
- template: template,
304
- duration: event.duration,
305
- count: payload[:count]
306
- )
299
+ template: template,
300
+ duration: event.duration,
301
+ count: payload[:count])
307
302
  end
308
303
 
309
304
  def render_layout(event)
@@ -316,9 +311,8 @@ module BrainzLab
316
311
  layout = template_name(payload[:identifier])
317
312
 
318
313
  LogSubscriber.formatter.render_layout(request_id,
319
- layout: layout,
320
- duration: event.duration
321
- )
314
+ layout: layout,
315
+ duration: event.duration)
322
316
  end
323
317
 
324
318
  private
@@ -327,10 +321,10 @@ module BrainzLab
327
321
  return nil unless identifier
328
322
 
329
323
  # Extract relative path from full identifier
330
- if identifier.include?("/app/views/")
331
- identifier.split("/app/views/").last
332
- elsif identifier.include?("/views/")
333
- identifier.split("/views/").last
324
+ if identifier.include?('/app/views/')
325
+ identifier.split('/app/views/').last
326
+ elsif identifier.include?('/views/')
327
+ identifier.split('/views/').last
334
328
  else
335
329
  File.basename(identifier)
336
330
  end
@@ -1,24 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'English'
3
4
  module BrainzLab
4
5
  module Rails
5
6
  class Railtie < ::Rails::Railtie
6
7
  generators do
7
- require "generators/brainzlab/install/install_generator"
8
+ require 'generators/brainzlab/install/install_generator'
8
9
  end
9
10
 
10
11
  # Load Vault secrets early, before configuration
11
12
  # This allows secrets to be used in config files
12
- initializer "brainzlab.load_vault_secrets", before: :load_environment_config do
13
+ initializer 'brainzlab.load_vault_secrets', before: :load_environment_config do
13
14
  if BrainzLab.configuration.vault_enabled && BrainzLab.configuration.vault_auto_load
14
- BrainzLab.debug_log("[Vault] Auto-loading secrets into ENV...")
15
+ BrainzLab.debug_log('[Vault] Auto-loading secrets into ENV...')
15
16
  BrainzLab::Vault.load!(
16
17
  provider_keys: BrainzLab.configuration.vault_load_provider_keys
17
18
  )
18
19
  end
19
20
  end
20
21
 
21
- initializer "brainzlab.configure_rails_initialization" do |app|
22
+ initializer 'brainzlab.configure_rails_initialization' do |app|
22
23
  # Set defaults from Rails
23
24
  BrainzLab.configure do |config|
24
25
  config.environment ||= ::Rails.env.to_s
@@ -34,7 +35,7 @@ module BrainzLab
34
35
 
35
36
  # Add DevTools middlewares if enabled
36
37
  if BrainzLab.configuration.devtools_enabled
37
- require_relative "../devtools"
38
+ require_relative '../devtools'
38
39
 
39
40
  # Asset server (handles /__brainzlab__/* requests)
40
41
  app.middleware.insert_before ActionDispatch::Static, BrainzLab::DevTools::Middleware::AssetServer
@@ -46,9 +47,7 @@ module BrainzLab
46
47
  # Error page (catches exceptions and renders branded error page)
47
48
  # Insert BEFORE DebugExceptions so we can intercept the HTML error page
48
49
  # that DebugExceptions renders and replace it with our own
49
- if defined?(ActionDispatch::DebugExceptions)
50
- app.middleware.insert_before ActionDispatch::DebugExceptions, BrainzLab::DevTools::Middleware::ErrorPage
51
- end
50
+ app.middleware.insert_before ActionDispatch::DebugExceptions, BrainzLab::DevTools::Middleware::ErrorPage if defined?(ActionDispatch::DebugExceptions)
52
51
 
53
52
  # Debug panel (injects panel into HTML responses)
54
53
  app.middleware.use BrainzLab::DevTools::Middleware::DebugPanel
@@ -71,14 +70,10 @@ module BrainzLab
71
70
  end
72
71
 
73
72
  # Hook into ActiveJob
74
- if defined?(ActiveJob::Base)
75
- ActiveJob::Base.include(BrainzLab::Rails::ActiveJobExtension)
76
- end
73
+ ActiveJob::Base.include(BrainzLab::Rails::ActiveJobExtension) if defined?(ActiveJob::Base)
77
74
 
78
75
  # Hook into ActionController for rescue_from fallback
79
- if defined?(ActionController::Base)
80
- ActionController::Base.include(BrainzLab::Rails::ControllerExtension)
81
- end
76
+ ActionController::Base.include(BrainzLab::Rails::ControllerExtension) if defined?(ActionController::Base)
82
77
 
83
78
  # Hook into Sidekiq if available
84
79
  if defined?(Sidekiq)
@@ -91,8 +86,8 @@ module BrainzLab
91
86
  class << self
92
87
  def setup_log_formatter
93
88
  # Lazy require to ensure Rails is fully loaded
94
- require_relative "log_formatter"
95
- require_relative "log_subscriber"
89
+ require_relative 'log_formatter'
90
+ require_relative 'log_subscriber'
96
91
 
97
92
  config = BrainzLab.configuration
98
93
 
@@ -124,37 +119,23 @@ module BrainzLab
124
119
  null_logger.level = Logger::FATAL
125
120
 
126
121
  # Silence ActiveRecord SQL logging
127
- if defined?(ActiveRecord::Base)
128
- ActiveRecord::Base.logger = null_logger
129
- end
122
+ ActiveRecord::Base.logger = null_logger if defined?(ActiveRecord::Base)
130
123
 
131
124
  # Silence ActionController logging (the "Completed" message)
132
- if defined?(ActionController::Base)
133
- ActionController::Base.logger = null_logger
134
- end
125
+ ActionController::Base.logger = null_logger if defined?(ActionController::Base)
135
126
 
136
127
  # Silence ActionView logging
137
- if defined?(ActionView::Base)
138
- ActionView::Base.logger = null_logger
139
- end
128
+ ActionView::Base.logger = null_logger if defined?(ActionView::Base)
140
129
 
141
130
  # Silence the class-level loggers for specific subscribers
142
- if defined?(ActionController::LogSubscriber)
143
- ActionController::LogSubscriber.logger = null_logger
144
- end
131
+ ActionController::LogSubscriber.logger = null_logger if defined?(ActionController::LogSubscriber)
145
132
 
146
- if defined?(ActionView::LogSubscriber)
147
- ActionView::LogSubscriber.logger = null_logger
148
- end
133
+ ActionView::LogSubscriber.logger = null_logger if defined?(ActionView::LogSubscriber)
149
134
 
150
- if defined?(ActiveRecord::LogSubscriber)
151
- ActiveRecord::LogSubscriber.logger = null_logger
152
- end
135
+ ActiveRecord::LogSubscriber.logger = null_logger if defined?(ActiveRecord::LogSubscriber)
153
136
 
154
137
  # Silence ActionCable logging
155
- if defined?(ActionCable::Server::Base)
156
- ActionCable.server.config.logger = null_logger
157
- end
138
+ ActionCable.server.config.logger = null_logger if defined?(ActionCable::Server::Base)
158
139
 
159
140
  if defined?(ActionCable::Connection::TaggedLoggerProxy)
160
141
  # ActionCable uses a tagged logger proxy that we need to quiet
@@ -184,7 +165,7 @@ module BrainzLab
184
165
  /^Rendering/,
185
166
  /^Rendered/,
186
167
  /^\[ActionCable\] Broadcasting/,
187
- /^\s*$/ # Empty lines
168
+ /^\s*$/ # Empty lines
188
169
  ].freeze
189
170
 
190
171
  def call(severity, datetime, progname, msg)
@@ -215,7 +196,7 @@ module BrainzLab
215
196
 
216
197
  # Set request context
217
198
  context = BrainzLab::Context.current
218
- request_id = request.request_id || env["action_dispatch.request_id"]
199
+ request_id = request.request_id || env['action_dispatch.request_id']
219
200
  context.request_id = request_id
220
201
 
221
202
  # Store request_id in thread local for log subscriber
@@ -224,7 +205,11 @@ module BrainzLab
224
205
  # Capture session_id - access session to ensure it's loaded
225
206
  if request.session.respond_to?(:id)
226
207
  # Force session load by accessing it
227
- session_id = request.session.id rescue nil
208
+ session_id = begin
209
+ request.session.id
210
+ rescue StandardError
211
+ nil
212
+ end
228
213
  context.session_id = session_id.to_s if session_id.present?
229
214
  end
230
215
 
@@ -238,7 +223,7 @@ module BrainzLab
238
223
  # Add breadcrumb for request start
239
224
  BrainzLab::Reflex.add_breadcrumb(
240
225
  "#{request.request_method} #{request.path}",
241
- category: "http.request",
226
+ category: 'http.request',
242
227
  level: :info,
243
228
  data: { url: request.url }
244
229
  )
@@ -262,7 +247,7 @@ module BrainzLab
262
247
  Thread.current[:brainzlab_pulse_breakdown] = nil
263
248
  BrainzLab::Pulse.start_trace(
264
249
  "#{request.request_method} #{request.path}",
265
- kind: "request",
250
+ kind: 'request',
266
251
  parent_context: parent_context
267
252
  )
268
253
  end
@@ -272,7 +257,7 @@ module BrainzLab
272
257
  # Add breadcrumb for response
273
258
  BrainzLab::Reflex.add_breadcrumb(
274
259
  "Response #{status}",
275
- category: "http.response",
260
+ category: 'http.response',
276
261
  level: status >= 400 ? :error : :info,
277
262
  data: { status: status }
278
263
  )
@@ -290,9 +275,7 @@ module BrainzLab
290
275
  raise
291
276
  ensure
292
277
  # Finish Pulse trace for successful requests
293
- if should_trace && !$!
294
- record_pulse_trace(request, started_at, status)
295
- end
278
+ record_pulse_trace(request, started_at, status) if should_trace && !$ERROR_INFO
296
279
 
297
280
  Thread.current[:brainzlab_request_id] = nil
298
281
  BrainzLab::Context.clear!
@@ -306,8 +289,8 @@ module BrainzLab
306
289
  path = request.path
307
290
 
308
291
  # Check if path matches any excluded pattern
309
- !excluded.any? do |pattern|
310
- if pattern.include?("*")
292
+ excluded.none? do |pattern|
293
+ if pattern.include?('*')
311
294
  File.fnmatch?(pattern, path)
312
295
  else
313
296
  path.start_with?(pattern)
@@ -323,7 +306,6 @@ module BrainzLab
323
306
  spans = Thread.current[:brainzlab_pulse_spans] || []
324
307
  breakdown = Thread.current[:brainzlab_pulse_breakdown] || {}
325
308
 
326
-
327
309
  # Format spans for API
328
310
  formatted_spans = spans.map do |span|
329
311
  {
@@ -339,7 +321,7 @@ module BrainzLab
339
321
 
340
322
  BrainzLab::Pulse.record_trace(
341
323
  "#{request.request_method} #{request.path}",
342
- kind: "request",
324
+ kind: 'request',
343
325
  started_at: started_at,
344
326
  ended_at: ended_at,
345
327
  request_id: context.request_id,
@@ -377,11 +359,11 @@ module BrainzLab
377
359
  case obj
378
360
  when Hash
379
361
  obj.each_with_object({}) do |(k, v), h|
380
- if BrainzLab::Reflex::FILTERED_PARAMS.include?(k.to_s)
381
- h[k] = "[FILTERED]"
382
- else
383
- h[k] = deep_filter(v)
384
- end
362
+ h[k] = if BrainzLab::Reflex::FILTERED_PARAMS.include?(k.to_s)
363
+ '[FILTERED]'
364
+ else
365
+ deep_filter(v)
366
+ end
385
367
  end
386
368
  when Array
387
369
  obj.map { |v| deep_filter(v) }
@@ -408,11 +390,11 @@ module BrainzLab
408
390
  def extract_headers(env)
409
391
  headers = {}
410
392
  env.each do |key, value|
411
- next unless key.start_with?("HTTP_")
412
- next if key == "HTTP_COOKIE"
413
- next if key == "HTTP_AUTHORIZATION"
393
+ next unless key.start_with?('HTTP_')
394
+ next if key == 'HTTP_COOKIE'
395
+ next if key == 'HTTP_AUTHORIZATION'
414
396
 
415
- header_name = key.sub("HTTP_", "").split("_").map(&:capitalize).join("-")
397
+ header_name = key.sub('HTTP_', '').split('_').map(&:capitalize).join('-')
416
398
  headers[header_name] = value
417
399
  end
418
400
  headers
@@ -424,11 +406,10 @@ module BrainzLab
424
406
  def report(error, handled:, severity:, context: {}, source: nil)
425
407
  # Capture both handled and unhandled, but mark them
426
408
  BrainzLab::Reflex.capture(error,
427
- handled: handled,
428
- severity: severity.to_s,
429
- source: source,
430
- extra: context
431
- )
409
+ handled: handled,
410
+ severity: severity.to_s,
411
+ source: source,
412
+ extra: context)
432
413
  rescue StandardError => e
433
414
  BrainzLab.configuration.logger&.error("[BrainzLab] ErrorSubscriber failed: #{e.message}")
434
415
  end
@@ -454,7 +435,7 @@ module BrainzLab
454
435
  # Add breadcrumb
455
436
  BrainzLab::Reflex.add_breadcrumb(
456
437
  "#{self.class.name}##{action_name}",
457
- category: "controller",
438
+ category: 'controller',
458
439
  level: :info
459
440
  )
460
441
 
@@ -491,7 +472,7 @@ module BrainzLab
491
472
 
492
473
  BrainzLab::Reflex.add_breadcrumb(
493
474
  "Job #{self.class.name}",
494
- category: "job",
475
+ category: 'job',
495
476
  level: :info,
496
477
  data: { job_id: job_id, queue: queue_name }
497
478
  )
@@ -501,7 +482,7 @@ module BrainzLab
501
482
  if should_trace
502
483
  Thread.current[:brainzlab_pulse_spans] = []
503
484
  Thread.current[:brainzlab_pulse_breakdown] = nil
504
- BrainzLab::Pulse.start_trace(self.class.name, kind: "job")
485
+ BrainzLab::Pulse.start_trace(self.class.name, kind: 'job')
505
486
  end
506
487
 
507
488
  error_occurred = nil
@@ -513,9 +494,7 @@ module BrainzLab
513
494
  end
514
495
  ensure
515
496
  # Record Pulse trace for job
516
- if should_trace
517
- record_pulse_job_trace(started_at, error_occurred)
518
- end
497
+ record_pulse_job_trace(started_at, error_occurred) if should_trace
519
498
 
520
499
  BrainzLab::Context.clear!
521
500
  end
@@ -550,7 +529,7 @@ module BrainzLab
550
529
 
551
530
  BrainzLab::Pulse.record_trace(
552
531
  self.class.name,
553
- kind: "job",
532
+ kind: 'job',
554
533
  started_at: started_at,
555
534
  ended_at: ended_at,
556
535
  job_class: self.class.name,
@@ -589,15 +568,14 @@ module BrainzLab
589
568
 
590
569
  def brainzlab_rescue_job(exception)
591
570
  BrainzLab::Reflex.capture(exception,
592
- tags: { type: "background_job" },
593
- extra: {
594
- job_class: self.class.name,
595
- job_id: job_id,
596
- queue_name: queue_name,
597
- executions: executions,
598
- arguments: arguments.map(&:to_s).first(5)
599
- }
600
- )
571
+ tags: { type: 'background_job' },
572
+ extra: {
573
+ job_class: self.class.name,
574
+ job_id: job_id,
575
+ queue_name: queue_name,
576
+ executions: executions,
577
+ arguments: arguments.map(&:to_s).first(5)
578
+ })
601
579
  raise exception # Re-raise to let ActiveJob handle retries
602
580
  end
603
581
  end
@@ -606,15 +584,14 @@ module BrainzLab
606
584
  class SidekiqErrorHandler
607
585
  def call(exception, context, _config = nil)
608
586
  BrainzLab::Reflex.capture(exception,
609
- tags: { type: "sidekiq" },
610
- extra: {
611
- job_class: context[:job]["class"],
612
- job_id: context[:job]["jid"],
613
- queue: context[:job]["queue"],
614
- args: context[:job]["args"]&.map(&:to_s)&.first(5),
615
- retry_count: context[:job]["retry_count"]
616
- }
617
- )
587
+ tags: { type: 'sidekiq' },
588
+ extra: {
589
+ job_class: context[:job]['class'],
590
+ job_id: context[:job]['jid'],
591
+ queue: context[:job]['queue'],
592
+ args: context[:job]['args']&.map(&:to_s)&.first(5),
593
+ retry_count: context[:job]['retry_count']
594
+ })
618
595
  rescue StandardError => e
619
596
  BrainzLab.configuration.logger&.error("[BrainzLab] Sidekiq handler failed: #{e.message}")
620
597
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "concurrent"
3
+ require 'concurrent'
4
4
 
5
5
  module BrainzLab
6
6
  module Recall