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 +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/active_rabbit/client/configuration.rb +2 -0
- data/lib/active_rabbit/client/exception_tracker.rb +27 -11
- data/lib/active_rabbit/client/http_client.rb +65 -50
- data/lib/active_rabbit/client/railtie.rb +140 -105
- data/lib/active_rabbit/client/version.rb +1 -3
- data/lib/active_rabbit/client.rb +13 -2
- data/lib/active_rabbit/middleware/error_capture_middleware.rb +1 -1
- data/lib/active_rabbit/reporting.rb +1 -1
- data/lib/active_rabbit/routing/not_found_app.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 915dd514027b844f4959d32085c1c26dfb69924b911fe31472c9f89eeaba0fd5
|
|
4
|
+
data.tar.gz: 128a2fe0aaaf197b72ee457c1f240df1057d63c029fd65dba5a92f890ff18de5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
36
|
-
|
|
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
|
-
|
|
41
|
-
|
|
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
|
-
|
|
48
|
+
log(:error, "[ActiveRabbit] Failed to send exception - both primary and fallback endpoints failed")
|
|
49
49
|
return nil
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
46
|
+
log(:info, "[ActiveRabbit] Making request to primary endpoint: POST #{path}")
|
|
47
47
|
response = enqueue_request(:post, path, exception_data_with_type)
|
|
48
|
-
|
|
48
|
+
log(:info, "[ActiveRabbit] Exception sent successfully (errors endpoint)")
|
|
49
49
|
return response
|
|
50
50
|
rescue => e
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
59
|
+
log(:info, "[ActiveRabbit] Making request to fallback endpoint: POST #{fallback_path}")
|
|
60
60
|
response = enqueue_request(:post, fallback_path, fallback_body)
|
|
61
|
-
|
|
61
|
+
log(:info, "[ActiveRabbit] Exception sent via fallback endpoint")
|
|
62
62
|
return response
|
|
63
63
|
rescue => e2
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
88
|
+
log(:info, "[ActiveRabbit] Sending batch of #{events.length} events...")
|
|
89
89
|
response = make_request(:post, "/api/v1/events/batch", { events: events })
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
134
|
+
log(:info, "[ActiveRabbit] Sending batch of #{batch.length} items")
|
|
135
135
|
response = post_batch(batch)
|
|
136
|
-
|
|
136
|
+
log(:info, "[ActiveRabbit] Batch sent successfully: #{response.inspect}")
|
|
137
137
|
response
|
|
138
138
|
rescue => e
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
165
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
236
|
+
log(:error, "[ActiveRabbit] API error: #{e.class}: #{e.message}")
|
|
237
237
|
raise e
|
|
238
238
|
rescue => e
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
295
|
-
|
|
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
|
-
|
|
303
|
+
log(:debug, "[ActiveRabbit] Parsed response: #{parsed.inspect}")
|
|
304
304
|
parsed
|
|
305
305
|
rescue JSON::ParserError => e
|
|
306
|
-
|
|
307
|
-
|
|
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
|
-
|
|
311
|
+
log(:debug, "[ActiveRabbit] Empty response body")
|
|
312
312
|
{}
|
|
313
313
|
end
|
|
314
314
|
when 429
|
|
315
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
34
|
-
config.logger
|
|
35
|
-
config.release
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
113
|
+
ar_puts "[ActiveRabbit] Cleaned up existing middleware" if Rails.env.development?
|
|
108
114
|
rescue => e
|
|
109
|
-
|
|
115
|
+
ar_puts "[ActiveRabbit] Error cleaning middleware: #{e.message}"
|
|
110
116
|
end
|
|
111
117
|
|
|
112
118
|
# Insert middleware in the correct order
|
|
113
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
136
|
+
ar_puts "[ActiveRabbit] Middleware insertion complete" if Rails.env.development?
|
|
131
137
|
|
|
132
138
|
elsif defined?(ActionDispatch::ShowExceptions)
|
|
133
|
-
|
|
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
|
-
|
|
146
|
+
ar_puts "[ActiveRabbit] Cleaned up existing middleware" if Rails.env.development?
|
|
141
147
|
rescue => e
|
|
142
|
-
|
|
148
|
+
ar_puts "[ActiveRabbit] Error cleaning middleware: #{e.message}"
|
|
143
149
|
end
|
|
144
150
|
|
|
145
151
|
# Insert middleware in the correct order
|
|
146
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
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
|
-
|
|
269
|
+
ar_log(:info, " #{klass}")
|
|
263
270
|
end
|
|
264
|
-
|
|
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
|
-
|
|
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
|
-
|
|
378
|
-
|
|
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
|
-
|
|
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
|
-
|
|
436
|
+
next
|
|
402
437
|
end
|
|
403
438
|
|
|
404
439
|
duration_ms = ((finished - started) * 1000).round(2)
|
|
405
440
|
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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}"
|
data/lib/active_rabbit/client.rb
CHANGED
|
@@ -77,8 +77,8 @@ module ActiveRabbit
|
|
|
77
77
|
result = exception_tracker.track_exception(**args)
|
|
78
78
|
|
|
79
79
|
# Log the result
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
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
|
+
date: 2025-12-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|