activerabbit-ai 0.4.8 → 0.5.0

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: 954a33d564508a6af9e73defded58f6b4ea9f0b359da045d7566a91f7bfc846d
4
- data.tar.gz: 4123b66a3933827a2bca1a78e2a235aa3a76abac2db5e209d60e6626edbdbc2f
3
+ metadata.gz: 915dd514027b844f4959d32085c1c26dfb69924b911fe31472c9f89eeaba0fd5
4
+ data.tar.gz: 128a2fe0aaaf197b72ee457c1f240df1057d63c029fd65dba5a92f890ff18de5
5
5
  SHA512:
6
- metadata.gz: 4a4d4f10428dc2e7bf4b96606b1d0ddf809244f046bf5c4ec880a043d9a9436777851146b03e1882c8e306f512e9e83bef09148377e237348ee43246f35399a0
7
- data.tar.gz: ca02b6426b33d2117455ae68d99fd20e47bb9ba792f8b18bd02b55caf09de6227a5442da53b4baa29221d81f3148dc19d34c67a578eced741f6f1c75629dc7af
6
+ metadata.gz: 382c8d0304b2048f8fa26c481530f1bfe19abac6ec8ec21c9fed57aebac84c2e40750fca4329b9864c301d6e4de7d9b0b411a97bd66d5ee9fe00cfbc58406d6e
7
+ data.tar.gz: d6ce4cf362160793d49d1d6d00444352c24b03eda9cb22be079d37ce65e37ee42e918be33ade5b76df761670d8bde4837dcd6c7a3893b09048774aee2a2e5fd2
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.5.0] - 2025-12-12
6
+
7
+ ### Changed
8
+ - **Minor release**: Bumped version to 0.5.0 to reflect latest stable changes and internal improvements
9
+
10
+ ## [0.4.9] - 2025-11-30
11
+
12
+ ### Fixed
13
+ - **Rails Integration**: Fixed `LocalJumpError: unexpected return` when `ActiveRabbit` is installed but not configured
14
+ - This error occurred when `subscribed` callbacks tried to return early if configuration was missing
15
+ - Changed `return` to `next` in Railtie subscription blocks
16
+
5
17
  ## [0.4.8] - 2025-11-27
6
18
 
7
19
  ### Added
@@ -16,6 +16,7 @@ module ActiveRabbit
16
16
  attr_accessor :before_send_event, :before_send_exception
17
17
  attr_accessor :dedupe_window # Time window in seconds for error deduplication (0 = disabled)
18
18
  attr_accessor :revision
19
+ attr_accessor :disable_console_logs
19
20
 
20
21
  def initialize
21
22
  @api_url = ENV.fetch("active_rabbit_API_URL", "https://api.activerabbit.ai")
@@ -38,6 +39,7 @@ module ActiveRabbit
38
39
  @enable_performance_monitoring = true
39
40
  @enable_n_plus_one_detection = true
40
41
  @enable_pii_scrubbing = true
42
+ @disable_console_logs = true
41
43
 
42
44
  # PII scrubbing
43
45
  @pii_fields = %w[
@@ -32,25 +32,25 @@ module ActiveRabbit
32
32
  end
33
33
 
34
34
  # Send exception to API and return response
35
- configuration.logger&.info("[ActiveRabbit] Preparing to send exception: #{exception.class.name}")
36
- configuration.logger&.debug("[ActiveRabbit] Exception data: #{exception_data.inspect}")
35
+ log(:info, "[ActiveRabbit] Preparing to send exception: #{exception.class.name}")
36
+ log(:debug, "[ActiveRabbit] Exception data: #{exception_data.inspect}")
37
37
 
38
38
  # Ensure we have required fields
39
39
  unless exception_data[:exception_class] && exception_data[:message] && exception_data[:backtrace]
40
- configuration.logger&.error("[ActiveRabbit] Missing required fields in exception data")
41
- configuration.logger&.debug("[ActiveRabbit] Available fields: #{exception_data.keys.inspect}")
40
+ log(:error, "[ActiveRabbit] Missing required fields in exception data")
41
+ log(:debug, "[ActiveRabbit] Available fields: #{exception_data.keys.inspect}")
42
42
  return nil
43
43
  end
44
44
 
45
45
  response = http_client.post_exception(exception_data)
46
46
 
47
47
  if response.nil?
48
- configuration.logger&.error("[ActiveRabbit] Failed to send exception - both primary and fallback endpoints failed")
48
+ log(:error, "[ActiveRabbit] Failed to send exception - both primary and fallback endpoints failed")
49
49
  return nil
50
50
  end
51
51
 
52
- configuration.logger&.info("[ActiveRabbit] Exception successfully sent to API")
53
- configuration.logger&.debug("[ActiveRabbit] API Response: #{response.inspect}")
52
+ log(:info, "[ActiveRabbit] Exception successfully sent to API")
53
+ log(:debug, "[ActiveRabbit] API Response: #{response.inspect}")
54
54
  response
55
55
  end
56
56
 
@@ -60,6 +60,22 @@ module ActiveRabbit
60
60
 
61
61
  private
62
62
 
63
+ def log(level, message)
64
+ cfg = configuration
65
+ return if cfg&.disable_console_logs
66
+
67
+ logger = cfg&.logger
68
+ return unless logger
69
+
70
+ case level
71
+ when :info then logger.info(message)
72
+ when :debug then logger.debug(message)
73
+ when :error then logger.error(message)
74
+ end
75
+
76
+ rescue
77
+ end
78
+
63
79
  def build_exception_data(exception:, context:, user_id:, tags:, handled: nil)
64
80
  parsed_bt = parse_backtrace(exception.backtrace || [])
65
81
  backtrace_lines = parsed_bt.map { |frame| frame[:line] }
@@ -132,10 +148,10 @@ module ActiveRabbit
132
148
  end
133
149
 
134
150
  # Log what we're sending
135
- configuration.logger&.debug("[ActiveRabbit] Built exception data:")
136
- configuration.logger&.debug("[ActiveRabbit] - Required fields: class=#{data[:exception_class]}, message=#{data[:message]}, backtrace=#{data[:backtrace]&.first}")
137
- configuration.logger&.debug("[ActiveRabbit] - Error details: type=#{data[:error_type]}, source=#{data[:error_source]}, component=#{data[:error_component]}")
138
- configuration.logger&.debug("[ActiveRabbit] - Request info: path=#{data[:request_path]}, method=#{data[:request_method]}, action=#{data[:controller_action]}")
151
+ log(:debug, "[ActiveRabbit] Built exception data:")
152
+ log(:debug, "[ActiveRabbit] - Required fields: class=#{data[:exception_class]}, message=#{data[:message]}, backtrace=#{data[:backtrace]&.first}")
153
+ log(:debug, "[ActiveRabbit] - Error details: type=#{data[:error_type]}, source=#{data[:error_source]}, component=#{data[:error_component]}")
154
+ log(:debug, "[ActiveRabbit] - Request info: path=#{data[:request_path]}, method=#{data[:request_method]}, action=#{data[:controller_action]}")
139
155
 
140
156
  data
141
157
  end
@@ -37,33 +37,33 @@ module ActiveRabbit
37
37
  # Primary endpoint path
38
38
  path = "/api/v1/events/errors"
39
39
 
40
- configuration.logger&.info("[ActiveRabbit] Sending exception to API...")
41
- configuration.logger&.debug("[ActiveRabbit] Exception payload (pre-JSON): #{safe_preview(exception_data_with_type)}")
42
- configuration.logger&.debug("[ActiveRabbit] Target path: #{path}")
40
+ log(:info, "[ActiveRabbit] Sending exception to API...")
41
+ log(:debug, "[ActiveRabbit] Exception payload (pre-JSON): #{safe_preview(exception_data_with_type)}")
42
+ log(:debug, "[ActiveRabbit] Target path: #{path}")
43
43
 
44
44
  begin
45
45
  # Primary endpoint attempt
46
- configuration.logger&.info("[ActiveRabbit] Making request to primary endpoint: POST #{path}")
46
+ log(:info, "[ActiveRabbit] Making request to primary endpoint: POST #{path}")
47
47
  response = enqueue_request(:post, path, exception_data_with_type)
48
- configuration.logger&.info("[ActiveRabbit] Exception sent successfully (errors endpoint)")
48
+ log(:info, "[ActiveRabbit] Exception sent successfully (errors endpoint)")
49
49
  return response
50
50
  rescue => e
51
- configuration.logger&.error("[ActiveRabbit] Primary send failed: #{e.class}: #{e.message}")
52
- configuration.logger&.error("[ActiveRabbit] Primary error backtrace: #{e.backtrace&.first(3)}")
53
- configuration.logger&.debug("[ActiveRabbit] Falling back to /api/v1/events with type=error")
51
+ log(:error, "[ActiveRabbit] Primary send failed: #{e.class}: #{e.message}")
52
+ log(:error, "[ActiveRabbit] Primary error backtrace: #{e.backtrace&.first(3)}")
53
+ log(:debug, "[ActiveRabbit] Falling back to /api/v1/events with type=error")
54
54
 
55
55
  begin
56
56
  # Fallback to generic events endpoint
57
57
  fallback_path = "/api/v1/events"
58
58
  fallback_body = { type: "error", data: exception_data_with_type }
59
- configuration.logger&.info("[ActiveRabbit] Making request to fallback endpoint: POST #{fallback_path}")
59
+ log(:info, "[ActiveRabbit] Making request to fallback endpoint: POST #{fallback_path}")
60
60
  response = enqueue_request(:post, fallback_path, fallback_body)
61
- configuration.logger&.info("[ActiveRabbit] Exception sent via fallback endpoint")
61
+ log(:info, "[ActiveRabbit] Exception sent via fallback endpoint")
62
62
  return response
63
63
  rescue => e2
64
- configuration.logger&.error("[ActiveRabbit] Fallback send failed: #{e2.class}: #{e2.message}")
65
- configuration.logger&.error("[ActiveRabbit] Fallback error backtrace: #{e2.backtrace&.first(3)}")
66
- configuration.logger&.error("[ActiveRabbit] All exception sending attempts failed")
64
+ log(:error, "[ActiveRabbit] Fallback send failed: #{e2.class}: #{e2.message}")
65
+ log(:error, "[ActiveRabbit] Fallback error backtrace: #{e2.backtrace&.first(3)}")
66
+ log(:error, "[ActiveRabbit] All exception sending attempts failed")
67
67
  nil
68
68
  end
69
69
  end
@@ -85,10 +85,10 @@ module ActiveRabbit
85
85
  end
86
86
 
87
87
  # Send batch to API
88
- configuration.logger&.info("[ActiveRabbit] Sending batch of #{events.length} events...")
88
+ log(:info, "[ActiveRabbit] Sending batch of #{events.length} events...")
89
89
  response = make_request(:post, "/api/v1/events/batch", { events: events })
90
- configuration.logger&.info("[ActiveRabbit] Batch sent successfully")
91
- configuration.logger&.debug("[ActiveRabbit] Batch response: #{response.inspect}")
90
+ log(:info, "[ActiveRabbit] Batch sent successfully")
91
+ log(:debug, "[ActiveRabbit] Batch response: #{response.inspect}")
92
92
  response
93
93
  end
94
94
 
@@ -109,7 +109,7 @@ module ActiveRabbit
109
109
 
110
110
  JSON.parse(res.body)
111
111
  rescue => e
112
- @configuration.logger&.error("[ActiveRabbit] HTTP POST failed: #{e.class}: #{e.message}")
112
+ log(:error, "[ActiveRabbit] HTTP POST failed: #{e.class}: #{e.message}")
113
113
  nil
114
114
  end
115
115
 
@@ -126,18 +126,18 @@ module ActiveRabbit
126
126
  def flush
127
127
  return if @request_queue.empty?
128
128
 
129
- configuration.logger&.info("[ActiveRabbit] Starting flush with #{@request_queue.length} items")
129
+ log(:info, "[ActiveRabbit] Starting flush with #{@request_queue.length} items")
130
130
  batch = @request_queue.shift(@request_queue.length)
131
131
  return if batch.empty?
132
132
 
133
133
  begin
134
- configuration.logger&.info("[ActiveRabbit] Sending batch of #{batch.length} items")
134
+ log(:info, "[ActiveRabbit] Sending batch of #{batch.length} items")
135
135
  response = post_batch(batch)
136
- configuration.logger&.info("[ActiveRabbit] Batch sent successfully: #{response.inspect}")
136
+ log(:info, "[ActiveRabbit] Batch sent successfully: #{response.inspect}")
137
137
  response
138
138
  rescue => e
139
- configuration.logger&.error("[ActiveRabbit] Failed to send batch: #{e.message}")
140
- configuration.logger&.error("[ActiveRabbit] Backtrace: #{e.backtrace&.first(3)}")
139
+ log(:error, "[ActiveRabbit] Failed to send batch: #{e.message}")
140
+ log(:error, "[ActiveRabbit] Backtrace: #{e.backtrace&.first(3)}")
141
141
  raise APIError, "Failed to send batch: #{e.message}"
142
142
  end
143
143
  end
@@ -161,8 +161,8 @@ module ActiveRabbit
161
161
  timestamp: Time.now.to_f
162
162
  }
163
163
 
164
- configuration.logger&.info("[ActiveRabbit] Enqueueing request: #{method} #{path}")
165
- configuration.logger&.debug("[ActiveRabbit] Request data: #{data.inspect}")
164
+ log(:info, "[ActiveRabbit] Enqueueing request: #{method} #{path}")
165
+ log(:debug, "[ActiveRabbit] Request data: #{data.inspect}")
166
166
 
167
167
  @request_queue << formatted_data
168
168
 
@@ -190,9 +190,9 @@ module ActiveRabbit
190
190
  # Ensure path starts with a single leading slash
191
191
  normalized_path = path.start_with?("/") ? path : "/#{path}"
192
192
  uri = URI.join(current_base, normalized_path)
193
- configuration.logger&.info("[ActiveRabbit] Making request: #{method.upcase} #{uri}")
194
- configuration.logger&.debug("[ActiveRabbit] Request headers: X-Project-Token=#{configuration.api_key}, X-Project-ID=#{configuration.project_id}")
195
- configuration.logger&.debug("[ActiveRabbit] Request body: #{safe_preview(data)}")
193
+ log(:info, "[ActiveRabbit] Making request: #{method.upcase} #{uri}")
194
+ log(:debug, "[ActiveRabbit] Request headers: X-Project-Token=#{configuration.api_key}, X-Project-ID=#{configuration.project_id}")
195
+ log(:debug, "[ActiveRabbit] Request body: #{safe_preview(data)}")
196
196
 
197
197
  # Retry logic with exponential backoff
198
198
  retries = 0
@@ -200,17 +200,17 @@ module ActiveRabbit
200
200
 
201
201
  begin
202
202
  response = perform_request(uri, method, data)
203
- configuration.logger&.info("[ActiveRabbit] Response status: #{response.code}")
204
- configuration.logger&.debug("[ActiveRabbit] Response headers: #{response.to_hash.inspect}")
205
- configuration.logger&.debug("[ActiveRabbit] Response body: #{response.body}")
203
+ log(:info, "[ActiveRabbit] Response status: #{response.code}")
204
+ log(:debug, "[ActiveRabbit] Response headers: #{response.to_hash.inspect}")
205
+ log(:debug, "[ActiveRabbit] Response body: #{response.body}")
206
206
 
207
207
  result = handle_response(response)
208
- configuration.logger&.debug("[ActiveRabbit] Parsed response: #{result.inspect}")
208
+ log(:debug, "[ActiveRabbit] Parsed response: #{result.inspect}")
209
209
  result
210
210
  rescue RetryableError => e
211
211
  if retries < max_retries
212
212
  retries += 1
213
- configuration.logger&.info("[ActiveRabbit] Retrying request (#{retries}/#{max_retries})")
213
+ log(:info, "[ActiveRabbit] Retrying request (#{retries}/#{max_retries})")
214
214
  sleep(configuration.retry_delay * (2 ** (retries - 1)))
215
215
  retry
216
216
  end
@@ -218,7 +218,7 @@ module ActiveRabbit
218
218
  rescue Net::OpenTimeout, Net::ReadTimeout => e
219
219
  if retries < max_retries && should_retry_error?(e)
220
220
  retries += 1
221
- configuration.logger&.info("[ActiveRabbit] Retrying request after timeout (#{retries}/#{max_retries})")
221
+ log(:info, "[ActiveRabbit] Retrying request after timeout (#{retries}/#{max_retries})")
222
222
  sleep(configuration.retry_delay * (2 ** (retries - 1))) # Exponential backoff
223
223
  retry
224
224
  end
@@ -226,24 +226,24 @@ module ActiveRabbit
226
226
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError => e
227
227
  if retries < max_retries
228
228
  retries += 1
229
- configuration.logger&.info("[ActiveRabbit] Retrying request after connection error (#{retries}/#{max_retries})")
229
+ log(:info, "[ActiveRabbit] Retrying request after connection error (#{retries}/#{max_retries})")
230
230
  sleep(configuration.retry_delay * (2 ** (retries - 1)))
231
231
  retry
232
232
  end
233
233
  raise APIError, "Connection failed after #{retries} retries: #{e.message}"
234
234
  rescue APIError, RateLimitError => e
235
235
  # Re-raise API errors as-is
236
- configuration.logger&.error("[ActiveRabbit] API error: #{e.class}: #{e.message}")
236
+ log(:error, "[ActiveRabbit] API error: #{e.class}: #{e.message}")
237
237
  raise e
238
238
  rescue => e
239
- configuration.logger&.error("[ActiveRabbit] Request failed: #{e.class}: #{e.message}")
240
- configuration.logger&.error("[ActiveRabbit] Backtrace: #{e.backtrace&.first(3)}")
239
+ log(:error, "[ActiveRabbit] Request failed: #{e.class}: #{e.message}")
240
+ log(:error, "[ActiveRabbit] Backtrace: #{e.backtrace&.first(3)}")
241
241
  raise APIError, "Request failed: #{e.message}"
242
242
  end
243
243
  end
244
244
 
245
245
  def perform_request(uri, method, data)
246
- configuration.logger&.debug("[ActiveRabbit] Making HTTP request: #{method.upcase} #{uri}")
246
+ log(:debug, "[ActiveRabbit] Making HTTP request: #{method.upcase} #{uri}")
247
247
  http = Net::HTTP.new(uri.host, uri.port)
248
248
 
249
249
  # Configure SSL if HTTPS
@@ -270,7 +270,7 @@ module ActiveRabbit
270
270
  raise ArgumentError, "Unsupported HTTP method: #{method}"
271
271
  end
272
272
 
273
- configuration.logger&.debug("[ActiveRabbit] Request path: #{uri.request_uri}")
273
+ log(:debug, "[ActiveRabbit] Request path: #{uri.request_uri}")
274
274
 
275
275
  # Set headers
276
276
  request['Content-Type'] = 'application/json'
@@ -291,8 +291,8 @@ module ActiveRabbit
291
291
  end
292
292
 
293
293
  def handle_response(response)
294
- configuration.logger&.debug("[ActiveRabbit] Response code: #{response.code}")
295
- configuration.logger&.debug("[ActiveRabbit] Response body: #{response.body}")
294
+ log(:debug, "[ActiveRabbit] Response code: #{response.code}")
295
+ log(:debug, "[ActiveRabbit] Response body: #{response.body}")
296
296
 
297
297
  case response.code.to_i
298
298
  when 200..299
@@ -300,23 +300,23 @@ module ActiveRabbit
300
300
  if response.body && !response.body.empty?
301
301
  begin
302
302
  parsed = JSON.parse(response.body)
303
- configuration.logger&.debug("[ActiveRabbit] Parsed response: #{parsed.inspect}")
303
+ log(:debug, "[ActiveRabbit] Parsed response: #{parsed.inspect}")
304
304
  parsed
305
305
  rescue JSON::ParserError => e
306
- configuration.logger&.error("[ActiveRabbit] Failed to parse response: #{e.message}")
307
- configuration.logger&.error("[ActiveRabbit] Raw response: #{response.body}")
306
+ log(:error, "[ActiveRabbit] Failed to parse response: #{e.message}")
307
+ log(:error, "[ActiveRabbit] Raw response: #{response.body}")
308
308
  response.body
309
309
  end
310
310
  else
311
- configuration.logger&.debug("[ActiveRabbit] Empty response body")
311
+ log(:debug, "[ActiveRabbit] Empty response body")
312
312
  {}
313
313
  end
314
314
  when 429
315
- configuration.logger&.error("[ActiveRabbit] Rate limit exceeded")
315
+ log(:error, "[ActiveRabbit] Rate limit exceeded")
316
316
  raise RateLimitError, "Rate limit exceeded"
317
317
  when 400..499
318
318
  error_message = extract_error_message(response)
319
- configuration.logger&.error("[ActiveRabbit] Client error (#{response.code}): #{error_message}")
319
+ log(:error, "[ActiveRabbit] Client error (#{response.code}): #{error_message}")
320
320
  raise APIError, "Client error (#{response.code}): #{error_message}"
321
321
  when 500..599
322
322
  error_message = extract_error_message(response)
@@ -324,11 +324,11 @@ module ActiveRabbit
324
324
  configuration.logger&.warn("[ActiveRabbit] Retryable server error (#{response.code}): #{error_message}")
325
325
  raise RetryableError, "Server error (#{response.code}): #{error_message}"
326
326
  else
327
- configuration.logger&.error("[ActiveRabbit] Server error (#{response.code}): #{error_message}")
327
+ log(:error, "[ActiveRabbit] Server error (#{response.code}): #{error_message}")
328
328
  raise APIError, "Server error (#{response.code}): #{error_message}"
329
329
  end
330
330
  else
331
- configuration.logger&.error("[ActiveRabbit] Unexpected response code: #{response.code}")
331
+ log(:error, "[ActiveRabbit] Unexpected response code: #{response.code}")
332
332
  raise APIError, "Unexpected response code: #{response.code}"
333
333
  end
334
334
  end
@@ -383,7 +383,22 @@ module ActiveRabbit
383
383
  s = obj.inspect
384
384
  s.length > 2000 ? s[0,2000] + "...(truncated)" : s
385
385
  end
386
- end
387
386
 
387
+ def log(level, message)
388
+ return if configuration.disable_console_logs
389
+
390
+ logger = configuration.logger
391
+ return unless logger
392
+
393
+ case level
394
+ when :info
395
+ logger.info(message)
396
+ when :debug
397
+ logger.debug(message)
398
+ when :error
399
+ logger.error(message)
400
+ end
401
+ end
402
+ end
388
403
  end
389
404
  end
@@ -21,40 +21,46 @@ module ActiveRabbit
21
21
  config.active_rabbit = ActiveSupport::OrderedOptions.new
22
22
 
23
23
  initializer "active_rabbit.configure", after: :initialize_logger do |app|
24
- if Rails.env.development?
25
- puts "\n=== ActiveRabbit Configure ==="
26
- puts "Environment: #{Rails.env}"
27
- puts "Already configured? #{ActiveRabbit::Client.configured?}"
28
- puts "================================\n"
24
+ apply_rails_configuration(app.config.active_rabbit)
25
+
26
+ if ActiveRabbit::Client.configuration && !ActiveRabbit::Client.configuration.disable_console_logs
27
+ if Rails.env.development?
28
+ ar_puts "\n=== ActiveRabbit Configure ==="
29
+ ar_puts "Environment: #{Rails.env}"
30
+ ar_puts "Already configured? #{ActiveRabbit::Client.configured?}"
31
+ ar_puts "================================\n"
32
+ end
29
33
  end
30
34
 
31
35
  # Configure ActiveRabbit from Rails configuration
32
36
  ActiveRabbit::Client.configure do |config|
33
- config.environment = Rails.env
34
- config.logger = Rails.logger rescue Logger.new(STDOUT)
35
- config.release = detect_release(app)
37
+ config.environment ||= Rails.env
38
+ config.logger ||= Rails.logger rescue Logger.new(STDOUT)
39
+ config.release ||= detect_release(app)
36
40
  end
37
41
 
38
- if Rails.env.development?
39
- puts "\n=== ActiveRabbit Post-Configure ==="
40
- puts "Now configured? #{ActiveRabbit::Client.configured?}"
41
- puts "Configuration: #{ActiveRabbit::Client.configuration.inspect}"
42
- puts "================================\n"
43
- end
42
+ # if ActiveRabbit::Client.configuration && !ActiveRabbit::Client.configuration.disable_console_logs
43
+ # if Rails.env.development?
44
+ # ar_puts "\n=== ActiveRabbit Post-Configure ==="
45
+ # ar_puts "Now configured? #{ActiveRabbit::Client.configured?}"
46
+ # ar_puts "Configuration: #{ActiveRabbit::Client.configuration.inspect}"
47
+ # ar_puts "================================\n"
48
+ # end
49
+ # end
44
50
 
45
51
  # Set up exception tracking
46
52
  setup_exception_tracking(app) if ActiveRabbit::Client.configured?
47
53
  end
48
54
 
49
55
  initializer "active_rabbit.subscribe_to_notifications", after: :load_config_initializers do |app|
50
- Rails.logger.info "[ActiveRabbit] Setting up performance notifications subscriptions"
56
+ ar_log(:info, "[ActiveRabbit] Setting up performance notifications subscriptions")
51
57
  # Subscribe regardless; each handler guards on configured?
52
58
  subscribe_to_controller_events
53
59
  subscribe_to_active_record_events
54
60
  subscribe_to_action_view_events
55
61
  subscribe_to_action_mailer_events if defined?(ActionMailer)
56
62
  subscribe_to_exception_notifications
57
- Rails.logger.info "[ActiveRabbit] Subscriptions setup complete"
63
+ ar_log(:info, "[ActiveRabbit] Subscriptions setup complete")
58
64
 
59
65
  # Defer complex subscriptions until after initialization
60
66
  app.config.after_initialize do
@@ -85,83 +91,83 @@ module ActiveRabbit
85
91
  # Configure middleware after logger is initialized to avoid init cycles
86
92
  initializer "active_rabbit.add_middleware", after: :initialize_logger do |app|
87
93
  if Rails.env.development?
88
- puts "\n=== ActiveRabbit Railtie Loading ==="
89
- puts "Rails Environment: #{Rails.env}"
90
- puts "Rails Middleware Stack Phase: #{app.middleware.respond_to?(:middlewares) ? 'Ready' : 'Not Ready'}"
91
- puts "================================\n"
92
- puts "\n=== Initial Middleware Stack ==="
93
- puts "(not available at this boot phase)"
94
- puts "=======================\n"
94
+ ar_puts "\n=== ActiveRabbit Railtie Loading ==="
95
+ ar_puts "Rails Environment: #{Rails.env}"
96
+ ar_puts "Rails Middleware Stack Phase: #{app.middleware.respond_to?(:middlewares) ? 'Ready' : 'Not Ready'}"
97
+ ar_puts "================================\n"
98
+ ar_puts "\n=== Initial Middleware Stack ==="
99
+ ar_puts "(not available at this boot phase)"
100
+ ar_puts "=======================\n"
95
101
  end
96
102
 
97
- puts "\n=== Adding ActiveRabbit Middleware ===" if Rails.env.development?
103
+ ar_puts "\n=== Adding ActiveRabbit Middleware ===" if Rails.env.development?
98
104
  # Handle both development (DebugExceptions) and production (ShowExceptions)
99
105
  if defined?(ActionDispatch::DebugExceptions)
100
- puts "[ActiveRabbit] Found DebugExceptions, configuring middleware..." if Rails.env.development?
106
+ ar_puts "[ActiveRabbit] Found DebugExceptions, configuring middleware..." if Rails.env.development?
101
107
 
102
108
  # First remove any existing middleware to avoid duplicates
103
109
  begin
104
110
  app.config.middleware.delete(ActiveRabbit::Client::ExceptionMiddleware)
105
111
  app.config.middleware.delete(ActiveRabbit::Client::RequestContextMiddleware)
106
112
  app.config.middleware.delete(ActiveRabbit::Client::RoutingErrorCatcher)
107
- puts "[ActiveRabbit] Cleaned up existing middleware" if Rails.env.development?
113
+ ar_puts "[ActiveRabbit] Cleaned up existing middleware" if Rails.env.development?
108
114
  rescue => e
109
- puts "[ActiveRabbit] Error cleaning middleware: #{e.message}"
115
+ ar_puts "[ActiveRabbit] Error cleaning middleware: #{e.message}"
110
116
  end
111
117
 
112
118
  # Insert middleware in the correct order
113
- puts "[ActiveRabbit] Inserting middleware..." if Rails.env.development?
119
+ ar_puts "[ActiveRabbit] Inserting middleware..." if Rails.env.development?
114
120
 
115
121
  # Insert ErrorCaptureMiddleware after DebugExceptions to rely on rescue path
116
122
  app.config.middleware.insert_after(ActionDispatch::DebugExceptions, ActiveRabbit::Middleware::ErrorCaptureMiddleware)
117
123
 
118
124
  # Insert RequestContextMiddleware early in the stack
119
- puts "[ActiveRabbit] Inserting RequestContextMiddleware before RequestId" if Rails.env.development?
125
+ ar_puts "[ActiveRabbit] Inserting RequestContextMiddleware before RequestId" if Rails.env.development?
120
126
  app.config.middleware.insert_before(ActionDispatch::RequestId, ActiveRabbit::Client::RequestContextMiddleware)
121
127
 
122
128
  # Insert ExceptionMiddleware before Rails' exception handlers (kept for env-based reporting)
123
- puts "[ActiveRabbit] Inserting ExceptionMiddleware before DebugExceptions" if Rails.env.development?
129
+ ar_puts "[ActiveRabbit] Inserting ExceptionMiddleware before DebugExceptions" if Rails.env.development?
124
130
  app.config.middleware.insert_before(ActionDispatch::DebugExceptions, ActiveRabbit::Client::ExceptionMiddleware)
125
131
 
126
132
  # Insert RoutingErrorCatcher after Rails' exception handlers
127
- puts "[ActiveRabbit] Inserting RoutingErrorCatcher after DebugExceptions" if Rails.env.development?
133
+ ar_puts "[ActiveRabbit] Inserting RoutingErrorCatcher after DebugExceptions" if Rails.env.development?
128
134
  app.config.middleware.insert_after(ActionDispatch::DebugExceptions, ActiveRabbit::Client::RoutingErrorCatcher)
129
135
 
130
- puts "[ActiveRabbit] Middleware insertion complete" if Rails.env.development?
136
+ ar_puts "[ActiveRabbit] Middleware insertion complete" if Rails.env.development?
131
137
 
132
138
  elsif defined?(ActionDispatch::ShowExceptions)
133
- puts "[ActiveRabbit] Found ShowExceptions, configuring middleware..." if Rails.env.development?
139
+ ar_puts "[ActiveRabbit] Found ShowExceptions, configuring middleware..." if Rails.env.development?
134
140
 
135
141
  # First remove any existing middleware to avoid duplicates
136
142
  begin
137
143
  app.config.middleware.delete(ActiveRabbit::Client::ExceptionMiddleware)
138
144
  app.config.middleware.delete(ActiveRabbit::Client::RequestContextMiddleware)
139
145
  app.config.middleware.delete(ActiveRabbit::Client::RoutingErrorCatcher)
140
- puts "[ActiveRabbit] Cleaned up existing middleware" if Rails.env.development?
146
+ ar_puts "[ActiveRabbit] Cleaned up existing middleware" if Rails.env.development?
141
147
  rescue => e
142
- puts "[ActiveRabbit] Error cleaning middleware: #{e.message}"
148
+ ar_puts "[ActiveRabbit] Error cleaning middleware: #{e.message}"
143
149
  end
144
150
 
145
151
  # Insert middleware in the correct order
146
- puts "[ActiveRabbit] Inserting middleware..." if Rails.env.development?
152
+ ar_puts "[ActiveRabbit] Inserting middleware..." if Rails.env.development?
147
153
 
148
154
  # Insert ErrorCaptureMiddleware after ShowExceptions
149
155
  app.config.middleware.insert_after(ActionDispatch::ShowExceptions, ActiveRabbit::Middleware::ErrorCaptureMiddleware)
150
156
 
151
157
  # Insert RequestContextMiddleware early in the stack
152
- puts "[ActiveRabbit] Inserting RequestContextMiddleware before RequestId" if Rails.env.development?
158
+ ar_puts "[ActiveRabbit] Inserting RequestContextMiddleware before RequestId" if Rails.env.development?
153
159
  app.config.middleware.insert_before(ActionDispatch::RequestId, ActiveRabbit::Client::RequestContextMiddleware)
154
160
 
155
161
  # Insert ExceptionMiddleware before Rails' exception handlers
156
- puts "[ActiveRabbit] Inserting ExceptionMiddleware before ShowExceptions" if Rails.env.development?
162
+ ar_puts "[ActiveRabbit] Inserting ExceptionMiddleware before ShowExceptions" if Rails.env.development?
157
163
  app.config.middleware.insert_before(ActionDispatch::ShowExceptions, ActiveRabbit::Client::ExceptionMiddleware)
158
164
 
159
165
  # Insert RoutingErrorCatcher after Rails' exception handlers
160
- puts "[ActiveRabbit] Inserting RoutingErrorCatcher after ShowExceptions" if Rails.env.development?
166
+ ar_puts "[ActiveRabbit] Inserting RoutingErrorCatcher after ShowExceptions" if Rails.env.development?
161
167
  app.config.middleware.insert_after(ActionDispatch::ShowExceptions, ActiveRabbit::Client::RoutingErrorCatcher)
162
168
 
163
169
  else
164
- puts "[ActiveRabbit] No exception handlers found, using fallback configuration" if Rails.env.development?
170
+ ar_puts "[ActiveRabbit] No exception handlers found, using fallback configuration" if Rails.env.development?
165
171
  app.config.middleware.use(ActiveRabbit::Middleware::ErrorCaptureMiddleware)
166
172
  app.config.middleware.use(ActiveRabbit::Client::RequestContextMiddleware)
167
173
  app.config.middleware.use(ActiveRabbit::Client::ExceptionMiddleware)
@@ -169,9 +175,9 @@ module ActiveRabbit
169
175
  end
170
176
 
171
177
  if Rails.env.development?
172
- puts "\n=== Final Middleware Stack ==="
173
- puts "(will be printed after initialize)"
174
- puts "=======================\n"
178
+ ar_puts "\n=== Final Middleware Stack ==="
179
+ ar_puts "(will be printed after initialize)"
180
+ ar_puts "=======================\n"
175
181
  end
176
182
 
177
183
  # Add debug wrappers in development
@@ -180,41 +186,42 @@ module ActiveRabbit
180
186
  ActiveRabbit::Client::ExceptionMiddleware.class_eval do
181
187
  alias_method :__ar_original_call, :call unless method_defined?(:__ar_original_call)
182
188
  def call(env)
183
- puts "\n=== ExceptionMiddleware Enter ==="
184
- puts "Path: #{env['PATH_INFO']}"
185
- puts "Method: #{env['REQUEST_METHOD']}"
186
- puts "Current Exception: #{env['action_dispatch.exception']&.class} - #{env['action_dispatch.exception']&.message}"
187
- puts "Current Error: #{env['action_dispatch.error']&.class} - #{env['action_dispatch.error']&.message}"
188
- puts "Rack Exception: #{env['rack.exception']&.class} - #{env['rack.exception']&.message}"
189
- puts "Exception Backtrace: #{env['action_dispatch.exception']&.backtrace&.first(3)&.join("\n ")}"
190
- puts "Error Backtrace: #{env['action_dispatch.error']&.backtrace&.first(3)&.join("\n ")}"
191
- puts "Rack Backtrace: #{env['rack.exception']&.backtrace&.first(3)&.join("\n ")}"
192
- puts "============================\n"
189
+ cfg = ActiveRabbit::Client.configuration
190
+ ar_puts "\n=== ExceptionMiddleware Enter ==="
191
+ ar_puts "Path: #{env['PATH_INFO']}"
192
+ ar_puts "Method: #{env['REQUEST_METHOD']}"
193
+ ar_puts "Current Exception: #{env['action_dispatch.exception']&.class} - #{env['action_dispatch.exception']&.message}"
194
+ ar_puts "Current Error: #{env['action_dispatch.error']&.class} - #{env['action_dispatch.error']&.message}"
195
+ ar_puts "Rack Exception: #{env['rack.exception']&.class} - #{env['rack.exception']&.message}"
196
+ ar_puts "Exception Backtrace: #{env['action_dispatch.exception']&.backtrace&.first(3)&.join("\n ")}"
197
+ ar_puts "Error Backtrace: #{env['action_dispatch.error']&.backtrace&.first(3)&.join("\n ")}"
198
+ ar_puts "Rack Backtrace: #{env['rack.exception']&.backtrace&.first(3)&.join("\n ")}"
199
+ ar_puts "============================\n"
193
200
 
194
201
  begin
195
202
  status, headers, body = __ar_original_call(env)
196
- puts "\n=== ExceptionMiddleware Exit (Success) ==="
197
- puts "Status: #{status}"
198
- puts "Headers: #{headers.inspect}"
199
- puts "Final Exception: #{env['action_dispatch.exception']&.class} - #{env['action_dispatch.exception']&.message}"
200
- puts "Final Error: #{env['action_dispatch.error']&.class} - #{env['action_dispatch.error']&.message}"
201
- puts "Final Rack Exception: #{env['rack.exception']&.class} - #{env['rack.exception']&.message}"
202
- puts "Final Exception Backtrace: #{env['action_dispatch.exception']&.backtrace&.first(3)&.join("\n ")}"
203
- puts "Final Error Backtrace: #{env['action_dispatch.error']&.backtrace&.first(3)&.join("\n ")}"
204
- puts "Final Rack Backtrace: #{env['rack.exception']&.backtrace&.first(3)&.join("\n ")}"
205
- puts "===========================\n"
203
+ ar_puts "\n=== ExceptionMiddleware Exit (Success) ==="
204
+ ar_puts "Status: #{status}"
205
+ ar_puts "Headers: #{headers.inspect}"
206
+ ar_puts "Final Exception: #{env['action_dispatch.exception']&.class} - #{env['action_dispatch.exception']&.message}"
207
+ ar_puts "Final Error: #{env['action_dispatch.error']&.class} - #{env['action_dispatch.error']&.message}"
208
+ ar_puts "Final Rack Exception: #{env['rack.exception']&.class} - #{env['rack.exception']&.message}"
209
+ ar_puts "Final Exception Backtrace: #{env['action_dispatch.exception']&.backtrace&.first(3)&.join("\n ")}"
210
+ ar_puts "Final Error Backtrace: #{env['action_dispatch.error']&.backtrace&.first(3)&.join("\n ")}"
211
+ ar_puts "Final Rack Backtrace: #{env['rack.exception']&.backtrace&.first(3)&.join("\n ")}"
212
+ ar_puts "===========================\n"
206
213
  [status, headers, body]
207
214
  rescue => e
208
- puts "\n=== ExceptionMiddleware Exit (Error) ==="
209
- puts "Error: #{e.class} - #{e.message}"
210
- puts "Error Backtrace: #{e.backtrace&.first(3)&.join("\n ")}"
211
- puts "Original Exception: #{env['action_dispatch.exception']&.class} - #{env['action_dispatch.exception']&.message}"
212
- puts "Original Error: #{env['action_dispatch.error']&.class} - #{env['action_dispatch.error']&.message}"
213
- puts "Original Rack Exception: #{env['rack.exception']&.class} - #{env['rack.exception']&.message}"
214
- puts "Original Exception Backtrace: #{env['action_dispatch.exception']&.backtrace&.first(3)&.join("\n ")}"
215
- puts "Original Error Backtrace: #{env['action_dispatch.error']&.backtrace&.first(3)&.join("\n ")}"
216
- puts "Original Rack Backtrace: #{env['rack.exception']&.backtrace&.first(3)&.join("\n ")}"
217
- puts "===========================\n"
215
+ ar_puts "\n=== ExceptionMiddleware Exit (Error) ==="
216
+ ar_puts "Error: #{e.class} - #{e.message}"
217
+ ar_puts "Error Backtrace: #{e.backtrace&.first(3)&.join("\n ")}"
218
+ ar_puts "Original Exception: #{env['action_dispatch.exception']&.class} - #{env['action_dispatch.exception']&.message}"
219
+ ar_puts "Original Error: #{env['action_dispatch.error']&.class} - #{env['action_dispatch.error']&.message}"
220
+ ar_puts "Original Rack Exception: #{env['rack.exception']&.class} - #{env['rack.exception']&.message}"
221
+ ar_puts "Original Exception Backtrace: #{env['action_dispatch.exception']&.backtrace&.first(3)&.join("\n ")}"
222
+ ar_puts "Original Error Backtrace: #{env['action_dispatch.error']&.backtrace&.first(3)&.join("\n ")}"
223
+ ar_puts "Original Rack Backtrace: #{env['rack.exception']&.backtrace&.first(3)&.join("\n ")}"
224
+ ar_puts "===========================\n"
218
225
  raise
219
226
  end
220
227
  end
@@ -224,23 +231,23 @@ module ActiveRabbit
224
231
  ActiveRabbit::Client::RoutingErrorCatcher.class_eval do
225
232
  alias_method :__ar_routing_original_call, :call unless method_defined?(:__ar_routing_original_call)
226
233
  def call(env)
227
- puts "\n=== RoutingErrorCatcher Enter ==="
228
- puts "Path: #{env['PATH_INFO']}"
229
- puts "Method: #{env['REQUEST_METHOD']}"
230
- puts "Status: #{env['action_dispatch.exception']&.class}"
231
- puts "============================\n"
234
+ ar_puts "\n=== RoutingErrorCatcher Enter ==="
235
+ ar_puts "Path: #{env['PATH_INFO']}"
236
+ ar_puts "Method: #{env['REQUEST_METHOD']}"
237
+ ar_puts "Status: #{env['action_dispatch.exception']&.class}"
238
+ ar_puts "============================\n"
232
239
 
233
240
  begin
234
241
  status, headers, body = __ar_routing_original_call(env)
235
- puts "\n=== RoutingErrorCatcher Exit (Success) ==="
236
- puts "Status: #{status}"
237
- puts "===========================\n"
242
+ ar_puts "\n=== RoutingErrorCatcher Exit (Success) ==="
243
+ ar_puts "Status: #{status}"
244
+ ar_puts "===========================\n"
238
245
  [status, headers, body]
239
246
  rescue => e
240
- puts "\n=== RoutingErrorCatcher Exit (Error) ==="
241
- puts "Error: #{e.class} - #{e.message}"
242
- puts "Backtrace: #{e.backtrace&.first(3)&.join("\n ")}"
243
- puts "===========================\n"
247
+ ar_puts "\n=== RoutingErrorCatcher Exit (Error) ==="
248
+ ar_puts "Error: #{e.class} - #{e.message}"
249
+ ar_puts "Backtrace: #{e.backtrace&.first(3)&.join("\n ")}"
250
+ ar_puts "===========================\n"
244
251
  raise
245
252
  end
246
253
  end
@@ -250,18 +257,18 @@ module ActiveRabbit
250
257
  # In development, add a hook to verify middleware after initialization
251
258
  if Rails.env.development?
252
259
  app.config.after_initialize do
253
- Rails.logger.info "\n=== ActiveRabbit Configuration ==="
254
- Rails.logger.info "Version: #{ActiveRabbit::Client::VERSION}"
255
- Rails.logger.info "Environment: #{Rails.env}"
256
- Rails.logger.info "API URL: #{ActiveRabbit::Client.configuration.api_url}"
257
- Rails.logger.info "================================"
260
+ ar_log(:info, "\n=== ActiveRabbit Configuration ===")
261
+ ar_log(:info, "Version: #{ActiveRabbit::Client::VERSION}")
262
+ ar_log(:info, "Environment: #{Rails.env}")
263
+ ar_log(:info, "API URL: #{ActiveRabbit::Client.configuration.api_url}")
264
+ ar_log(:info, "================================")
258
265
 
259
- Rails.logger.info "\n=== Middleware Stack ==="
266
+ ar_log(:info, "\n=== Middleware Stack ===")
260
267
  (Rails.application.middleware.middlewares rescue []).each do |mw|
261
268
  klass = (mw.respond_to?(:klass) ? mw.klass.name : mw.to_s) rescue mw.inspect
262
- Rails.logger.info " #{klass}"
269
+ ar_log(:info, " #{klass}")
263
270
  end
264
- Rails.logger.info "======================="
271
+ ar_log(:info, "=======================")
265
272
 
266
273
  # Skip missing-middleware warnings in development since we may inject via alternate paths
267
274
  unless Rails.env.development?
@@ -284,7 +291,7 @@ module ActiveRabbit
284
291
  end
285
292
  end
286
293
 
287
- Rails.logger.info "[ActiveRabbit] Middleware configured successfully"
294
+ ar_log(:info, "[ActiveRabbit] Middleware configured successfully")
288
295
  end
289
296
 
290
297
  initializer "active_rabbit.error_reporter" do |app|
@@ -374,8 +381,8 @@ module ActiveRabbit
374
381
  begin
375
382
  reporting_file, reporting_line = ActiveRabbit::Reporting.method(:report_exception).source_location
376
383
  http_file, http_line = ActiveRabbit::Client::HttpClient.instance_method(:post_exception).source_location
377
- Rails.logger.info "[ActiveRabbit] Reporting loaded from #{reporting_file}:#{reporting_line}" if defined?(Rails)
378
- Rails.logger.info "[ActiveRabbit] HttpClient#post_exception from #{http_file}:#{http_line}" if defined?(Rails)
384
+ ar_log(:info, "[ActiveRabbit] Reporting loaded from #{reporting_file}:#{reporting_line}") if defined?(Rails)
385
+ ar_log(:info, "[ActiveRabbit] HttpClient#post_exception from #{http_file}:#{http_line}") if defined?(Rails)
379
386
  rescue => e
380
387
  Rails.logger.debug "[ActiveRabbit] boot diagnostics failed: #{e.message}" if defined?(Rails)
381
388
  end
@@ -384,6 +391,34 @@ module ActiveRabbit
384
391
 
385
392
  private
386
393
 
394
+ def ar_puts(msg)
395
+ cfg = ActiveRabbit::Client.configuration
396
+ return if cfg && cfg.disable_console_logs
397
+ puts msg
398
+ end
399
+
400
+ def ar_log(level, msg)
401
+ cfg = ActiveRabbit::Client.configuration
402
+ return if cfg && cfg.disable_console_logs
403
+ Rails.logger.public_send(level, msg) if Rails.logger
404
+ end
405
+
406
+ def apply_rails_configuration(rails_config)
407
+ return unless rails_config
408
+
409
+ options = rails_config.respond_to?(:to_h) ? rails_config.to_h : rails_config
410
+ return if options.nil? || options.empty?
411
+
412
+ ActiveRabbit::Client.configure do |config|
413
+ options.each do |key, value|
414
+ next if value.nil?
415
+
416
+ writer = "#{key}="
417
+ config.public_send(writer, value) if config.respond_to?(writer)
418
+ end
419
+ end
420
+ end
421
+
387
422
  def setup_exception_tracking(app)
388
423
  # Handle uncaught exceptions in development
389
424
  if Rails.env.development? || Rails.env.test?
@@ -392,19 +427,19 @@ module ActiveRabbit
392
427
  end
393
428
 
394
429
  def subscribe_to_controller_events
395
- Rails.logger.info "[ActiveRabbit] Subscribing to controller events (configured=#{ActiveRabbit::Client.configured?})"
430
+ ar_log(:info, "[ActiveRabbit] Subscribing to controller events (configured=#{ActiveRabbit::Client.configured?})")
396
431
 
397
432
  ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, started, finished, unique_id, payload|
398
433
  begin
399
434
  unless ActiveRabbit::Client.configured?
400
435
  Rails.logger.debug "[ActiveRabbit] Skipping performance tracking - not configured"
401
- return
436
+ next
402
437
  end
403
438
 
404
439
  duration_ms = ((finished - started) * 1000).round(2)
405
440
 
406
- Rails.logger.info "[ActiveRabbit] 📊 Controller action: #{payload[:controller]}##{payload[:action]} - #{duration_ms}ms"
407
- Rails.logger.info "[ActiveRabbit] 📊 DB runtime: #{payload[:db_runtime]}, View runtime: #{payload[:view_runtime]}"
441
+ ar_log(:info, "[ActiveRabbit] 📊 Controller action: #{payload[:controller]}##{payload[:action]} - #{duration_ms}ms")
442
+ ar_log(:info, "[ActiveRabbit] 📊 DB runtime: #{payload[:db_runtime]}, View runtime: #{payload[:view_runtime]}")
408
443
 
409
444
  ActiveRabbit::Client.track_performance(
410
445
  "controller.action",
@@ -672,7 +707,7 @@ module ActiveRabbit
672
707
 
673
708
  def call(env)
674
709
  # debug start - using Rails.logger to ensure it appears in development.log
675
- Rails.logger.info "[AR] ExceptionMiddleware ENTER path=#{env['PATH_INFO']}" if defined?(Rails)
710
+ ar_log(:info, "[AR] ExceptionMiddleware ENTER path=#{env['PATH_INFO']}") if defined?(Rails)
676
711
  warn "[AR] ExceptionMiddleware ENTER path=#{env['PATH_INFO']}"
677
712
  warn "[AR] Current exceptions in env:"
678
713
  warn " - action_dispatch.exception: #{env['action_dispatch.exception']&.class}"
@@ -686,12 +721,12 @@ module ActiveRabbit
686
721
 
687
722
  # Check for exceptions in env after app call
688
723
  if (ex = env["action_dispatch.exception"] || env["rack.exception"] || env["action_dispatch.error"])
689
- Rails.logger.info "[AR] env exception present: #{ex.class}: #{ex.message}" if defined?(Rails)
724
+ ar_log(:info, "[AR] env exception present: #{ex.class}: #{ex.message}") if defined?(Rails)
690
725
  warn "[AR] env exception present: #{ex.class}: #{ex.message}"
691
726
  warn "[AR] Exception backtrace: #{ex.backtrace&.first(3)&.join("\n ")}"
692
727
  safe_report(ex, env, 'Rails rescued exception')
693
728
  else
694
- Rails.logger.info "[AR] env exception NOT present" if defined?(Rails)
729
+ ar_log(:info, "[AR] env exception NOT present") if defined?(Rails)
695
730
  warn "[AR] env exception NOT present"
696
731
  warn "[AR] Final env check:"
697
732
  warn " - action_dispatch.exception: #{env['action_dispatch.exception']&.class}"
@@ -703,7 +738,7 @@ module ActiveRabbit
703
738
  [status, headers, body]
704
739
  rescue => e
705
740
  # Primary path: catch raw exceptions before Rails rescuers
706
- Rails.logger.info "[AR] RESCUE caught: #{e.class}: #{e.message}" if defined?(Rails)
741
+ ar_log(:info, "[AR] RESCUE caught: #{e.class}: #{e.message}") if defined?(Rails)
707
742
  warn "[AR] RESCUE caught: #{e.class}: #{e.message}"
708
743
  warn "[AR] Rescue backtrace: #{e.backtrace&.first(3)&.join("\n ")}"
709
744
 
@@ -748,7 +783,7 @@ module ActiveRabbit
748
783
  result = ActiveRabbit::Client.track_exception(exception, context: context)
749
784
  warn "[AR] Track result: #{result.inspect}"
750
785
 
751
- Rails.logger.info "[ActiveRabbit] Tracked #{source}: #{exception.class.name} - #{exception.message}" if defined?(Rails)
786
+ ar_log(:info, "[ActiveRabbit] Tracked #{source}: #{exception.class.name} - #{exception.message}") if defined?(Rails)
752
787
  rescue => tracking_error
753
788
  # Log tracking errors but don't let them interfere with exception handling
754
789
  warn "[AR] Error in safe_report: #{tracking_error.class} - #{tracking_error.message}"
@@ -1,7 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
1
  module ActiveRabbit
4
2
  module Client
5
- VERSION = "0.4.8"
3
+ VERSION = "0.5.0"
6
4
  end
7
5
  end
@@ -77,8 +77,8 @@ module ActiveRabbit
77
77
  result = exception_tracker.track_exception(**args)
78
78
 
79
79
  # Log the result
80
- configuration.logger&.info("[ActiveRabbit] Exception tracked: #{exception.class.name}")
81
- configuration.logger&.debug("[ActiveRabbit] Exception tracking result: #{result.inspect}")
80
+ ActiveRabbit::Client.log(:info, "[ActiveRabbit] Exception tracked: #{exception.class.name}")
81
+ ActiveRabbit::Client.log(:debug, "[ActiveRabbit] Exception tracking result: #{result.inspect}")
82
82
 
83
83
  result
84
84
  end
@@ -142,6 +142,17 @@ module ActiveRabbit
142
142
  http_client.post("/api/v1/deploys", payload)
143
143
  end
144
144
 
145
+ def log(level, message)
146
+ cfg = configuration
147
+ return if cfg.nil? || cfg.disable_console_logs
148
+
149
+ case level
150
+ when :info then cfg.logger&.info(message)
151
+ when :debug then cfg.logger&.debug(message)
152
+ when :error then cfg.logger&.error(message)
153
+ end
154
+ end
155
+
145
156
  private
146
157
 
147
158
  def event_processor
@@ -13,7 +13,7 @@ module ActiveRabbit
13
13
  begin
14
14
  ActiveRabbit::Reporting.report_exception(e, env: env, handled: false, source: "middleware", force: true)
15
15
  rescue => inner
16
- Rails.logger&.error("[ActiveRabbit] ErrorCaptureMiddleware failed: #{inner.class}: #{inner.message}") if defined?(Rails)
16
+ ActiveRabbit::Client.log(:error, "[ActiveRabbit] ErrorCaptureMiddleware failed: #{inner.class}: #{inner.message}")
17
17
  end
18
18
  raise
19
19
  end
@@ -40,7 +40,7 @@ module ActiveRabbit
40
40
  force: force)
41
41
  rescue => e
42
42
  if defined?(Rails)
43
- Rails.logger&.error("[ActiveRabbit] report_exception failed: #{e.class}: #{e.message}")
43
+ ActiveRabbit::Client.log(:error, "[ActiveRabbit] report_exception failed: #{e.class}: #{e.message}")
44
44
  end
45
45
  nil
46
46
  end
@@ -8,7 +8,7 @@ module ActiveRabbit
8
8
  begin
9
9
  ActiveRabbit::Reporting.report_exception(error, env: env, handled: true, source: "router", force: true)
10
10
  rescue => e
11
- Rails.logger&.error("[ActiveRabbit] NotFoundApp failed to report: #{e.class}: #{e.message}") if defined?(Rails)
11
+ ActiveRabbit::Client.log(:error, "[ActiveRabbit] NotFoundApp failed to report: #{e.class}: #{e.message}")
12
12
  end
13
13
  [404, { "Content-Type" => "text/plain" }, ["Not Found"]]
14
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerabbit-ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.8
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Shapalov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-27 00:00:00.000000000 Z
11
+ date: 2025-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby