activerabbit-ai 0.4.0 → 0.4.2

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.
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRabbit
4
+ module Middleware
5
+ class ErrorCaptureMiddleware
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ @app.call(env)
12
+ rescue => e
13
+ begin
14
+ ActiveRabbit::Reporting.report_exception(e, env: env, handled: false, source: "middleware", force: true)
15
+ rescue => inner
16
+ Rails.logger&.error("[ActiveRabbit] ErrorCaptureMiddleware failed: #{inner.class}: #{inner.message}") if defined?(Rails)
17
+ end
18
+ raise
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module ActiveRabbit
6
+ module Reporting
7
+ module_function
8
+
9
+ def report_exception(exception, env: nil, context: {}, handled: false, source: "rails", force: false)
10
+ return unless defined?(ActiveRabbit::Client) && ActiveRabbit::Client.configured?
11
+
12
+ enriched_context = (context || {}).dup
13
+ req_info = env ? rack_request_info(env) : { request: {}, routing: {} }
14
+ enriched_context[:request] ||= req_info[:request]
15
+ enriched_context[:routing] ||= req_info[:routing]
16
+ enriched_context[:source] ||= source
17
+ enriched_context[:handled] = handled if !enriched_context.key?(:handled)
18
+
19
+ # Enrich for routing errors so UI shows controller action and 404 specifics
20
+ if defined?(ActionController::RoutingError) && exception.is_a?(ActionController::RoutingError)
21
+ enriched_context[:controller_action] ||= 'Routing#not_found'
22
+ enriched_context[:error_type] ||= 'route_not_found'
23
+ enriched_context[:error_status] ||= 404
24
+ enriched_context[:error_component] ||= 'ActionDispatch'
25
+ enriched_context[:error_source] ||= 'Router'
26
+ enriched_context[:tags] = (enriched_context[:tags] || {}).merge(error_type: 'routing_error', severity: 'warning')
27
+ end
28
+
29
+ ActiveRabbit::Client.track_exception(exception,
30
+ context: enriched_context,
31
+ handled: handled,
32
+ force: force)
33
+ rescue => e
34
+ if defined?(Rails)
35
+ Rails.logger&.error("[ActiveRabbit] report_exception failed: #{e.class}: #{e.message}")
36
+ end
37
+ nil
38
+ end
39
+
40
+ def rack_request_info(env)
41
+ req = ActionDispatch::Request.new(env)
42
+ {
43
+ request: {
44
+ method: req.request_method,
45
+ path: req.fullpath,
46
+ ip_address: req.ip,
47
+ user_agent: req.user_agent,
48
+ request_id: req.request_id
49
+ },
50
+ routing: {
51
+ path: req.path,
52
+ params: (req.respond_to?(:filtered_parameters) ? req.filtered_parameters : (env["action_dispatch.request.parameters"] || {})),
53
+ controller: env["action_controller.instance"]&.class&.name,
54
+ action: (env["action_dispatch.request.parameters"]&.dig("action"))
55
+ }
56
+ }
57
+ rescue
58
+ { request: {}, routing: {} }
59
+ end
60
+ end
61
+ end
62
+
63
+
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRabbit
4
+ module Routing
5
+ class NotFoundApp
6
+ def call(env)
7
+ error = ActionController::RoutingError.new("No route matches #{env['REQUEST_METHOD']} #{env['PATH_INFO']}")
8
+ begin
9
+ ActiveRabbit::Reporting.report_exception(error, env: env, handled: true, source: "router", force: true)
10
+ rescue => e
11
+ Rails.logger&.error("[ActiveRabbit] NotFoundApp failed to report: #{e.class}: #{e.message}") if defined?(Rails)
12
+ end
13
+ [404, { "Content-Type" => "text/plain" }, ["Not Found"]]
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+
File without changes
data/lib/active_rabbit.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "active_rabbit/client"
4
+ require_relative "active_rabbit/routing/not_found_app"
4
5
 
5
- # Require Rails integration if Rails is available
6
- require_relative "active_rabbit/client/railtie" if defined?(Rails)
6
+ # Load Rails integration
7
+ if defined?(Rails)
8
+ begin
9
+ require_relative "active_rabbit/client/railtie"
10
+ rescue => e
11
+ warn "[ActiveRabbit] Rails integration failed: #{e.message}" if Rails.env&.development?
12
+ warn "[ActiveRabbit] Backtrace: #{e.backtrace.first(5).join(', ')}" if Rails.env&.development?
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ #!/bin/bash
2
+
3
+ # Script to set up local gem testing in Docker
4
+ # Run this from your Rails app directory
5
+
6
+ echo "Setting up local ActiveRabbit gem testing..."
7
+
8
+ # Check if we're in a Rails app directory
9
+ if [ ! -f "Gemfile" ]; then
10
+ echo "Error: No Gemfile found. Please run this from your Rails app directory."
11
+ exit 1
12
+ fi
13
+
14
+ # Backup original Gemfile
15
+ cp Gemfile Gemfile.backup
16
+
17
+ # Add local gem path to Gemfile
18
+ echo "" >> Gemfile
19
+ echo "# Local ActiveRabbit gem for testing" >> Gemfile
20
+ echo "gem 'activerabbit-ai', path: '/app/gems/active_rabbit-client'" >> Gemfile
21
+
22
+ echo "✅ Added local gem path to Gemfile"
23
+
24
+ # Create docker-compose override for local development
25
+ cat > docker-compose.override.yml << EOF
26
+ version: '3.8'
27
+ services:
28
+ web:
29
+ volumes:
30
+ # Mount local ActiveRabbit gem
31
+ - /Users/alex/GPT/activeagent/active_rabbit-client:/app/gems/active_rabbit-client:ro
32
+ environment:
33
+ - ACTIVERABBIT_API_KEY=9b3344ba8775e8ab11fd47e04534ae81e938180a23de603e60b5ec4346652f06
34
+ - ACTIVERABBIT_PROJECT_ID=1
35
+ - ACTIVERABBIT_API_URL=http://host.docker.internal:3000
36
+ EOF
37
+
38
+ echo "✅ Created docker-compose.override.yml"
39
+
40
+ echo ""
41
+ echo "🚀 Setup complete! Now run:"
42
+ echo " docker-compose down"
43
+ echo " docker-compose build"
44
+ echo " docker-compose up"
45
+ echo ""
46
+ echo "To restore original setup:"
47
+ echo " mv Gemfile.backup Gemfile"
48
+ echo " rm docker-compose.override.yml"
data/test_net_http.rb ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ # Simple test script for the new Net::HTTP implementation
3
+
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
5
+
6
+ require 'active_rabbit/client/version'
7
+ require 'active_rabbit/client/configuration'
8
+ require 'active_rabbit/client/http_client'
9
+
10
+ puts "🚀 Testing ActiveRabbit Net::HTTP Implementation"
11
+ puts "=" * 50
12
+
13
+ # Test configuration
14
+ config = ActiveRabbit::Client::Configuration.new
15
+ config.api_key = "test_api_key_123"
16
+ config.api_url = "https://httpbin.org" # Use httpbin for testing
17
+ config.timeout = 10
18
+ config.open_timeout = 5
19
+ config.retry_count = 2
20
+ config.retry_delay = 1
21
+
22
+ puts "✅ Configuration created"
23
+
24
+ # Test HTTP client
25
+ begin
26
+ http_client = ActiveRabbit::Client::HttpClient.new(config)
27
+ puts "✅ HTTP Client created"
28
+
29
+ # Test a simple GET-like request (httpbin.org/post accepts POST)
30
+ puts "\n📡 Testing HTTP request..."
31
+
32
+ response = http_client.send(:make_request, :post, "post", {
33
+ test: "data",
34
+ gem_version: ActiveRabbit::Client::VERSION,
35
+ timestamp: Time.now.to_i
36
+ })
37
+
38
+ puts "✅ HTTP request successful!"
39
+ puts "Response keys: #{response.keys.join(', ')}" if response.is_a?(Hash)
40
+
41
+ rescue => e
42
+ puts "❌ HTTP request failed: #{e.message}"
43
+ puts " #{e.class}: #{e.backtrace.first}"
44
+ end
45
+
46
+ puts "\n" + "=" * 50
47
+ puts "🎉 Net::HTTP implementation test completed!"
data/test_with_api.rb ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env ruby
2
+ # Test script to verify ActiveRabbit is working with your API
3
+
4
+ require 'net/http'
5
+ require 'json'
6
+ require 'time'
7
+
8
+ puts "🚀 Testing ActiveRabbit Integration with Your API"
9
+ puts "=" * 50
10
+
11
+ # Your configuration
12
+ API_KEY = "9b3344ba8775e8ab11fd47e04534ae81e938180a23de603e60b5ec4346652f06"
13
+ PROJECT_ID = "1"
14
+ API_URL = "http://localhost:3000"
15
+
16
+ puts "Configuration:"
17
+ puts "- API URL: #{API_URL}"
18
+ puts "- Project ID: #{PROJECT_ID}"
19
+ puts "- API Key: #{API_KEY[0..10]}..."
20
+
21
+ # Test 1: Check API connectivity
22
+ puts "\n📡 Testing API connectivity..."
23
+ begin
24
+ uri = URI("#{API_URL}/api/v1/test/connection")
25
+ http = Net::HTTP.new(uri.host, uri.port)
26
+
27
+ request = Net::HTTP::Post.new(uri.path)
28
+ request['Content-Type'] = 'application/json'
29
+ request['X-Project-Token'] = API_KEY
30
+ request['X-Project-ID'] = PROJECT_ID
31
+ request.body = JSON.generate({
32
+ gem_version: "0.3.1",
33
+ timestamp: Time.now.iso8601
34
+ })
35
+
36
+ response = http.request(request)
37
+
38
+ if [200,201].include?(response.code.to_i)
39
+ puts "✅ API connection successful!"
40
+ puts " Response: #{response.body}"
41
+ else
42
+ puts "❌ API connection failed with status: #{response.code}"
43
+ puts " Response: #{response.body}"
44
+ end
45
+ rescue => e
46
+ puts "❌ API connection error: #{e.message}"
47
+ end
48
+
49
+ # Test 2: Send a test exception
50
+ puts "\n🐛 Testing exception tracking..."
51
+ begin
52
+ uri = URI("#{API_URL}/api/v1/events/errors")
53
+ http = Net::HTTP.new(uri.host, uri.port)
54
+
55
+ request = Net::HTTP::Post.new(uri.path)
56
+ request['Content-Type'] = 'application/json'
57
+ request['X-Project-Token'] = API_KEY
58
+ request['X-Project-ID'] = PROJECT_ID
59
+
60
+ exception_data = {
61
+ type: "TestError",
62
+ message: "This is a test exception from ActiveRabbit gem",
63
+ backtrace: [
64
+ { filename: "test_script.rb", lineno: 42, method: "test_method", line: "test_script.rb:42:in `test_method'" }
65
+ ],
66
+ fingerprint: "test_fingerprint_123",
67
+ timestamp: Time.now.iso8601(3),
68
+ environment: "development",
69
+ context: {
70
+ request: {
71
+ method: "GET",
72
+ path: "/test",
73
+ user_agent: "ActiveRabbit-Test/1.0"
74
+ }
75
+ },
76
+ event_type: "error"
77
+ }
78
+
79
+ request.body = JSON.generate(exception_data)
80
+
81
+ response = http.request(request)
82
+
83
+ if [200,201].include?(response.code.to_i)
84
+ puts "✅ Exception tracking successful!"
85
+ puts " Response: #{response.body}"
86
+ else
87
+ puts "❌ Exception tracking failed with status: #{response.code}"
88
+ puts " Response: #{response.body}"
89
+ end
90
+ rescue => e
91
+ puts "❌ Exception tracking error: #{e.message}"
92
+ end
93
+
94
+ # Test 3: Send test performance data
95
+ puts "\n⚡ Testing performance tracking..."
96
+ begin
97
+ uri = URI("#{API_URL}/api/v1/events/performance")
98
+ http = Net::HTTP.new(uri.host, uri.port)
99
+
100
+ request = Net::HTTP::Post.new(uri.path)
101
+ request['Content-Type'] = 'application/json'
102
+ request['X-Project-Token'] = API_KEY
103
+ request['X-Project-ID'] = PROJECT_ID
104
+
105
+ performance_data = {
106
+ name: "controller.action",
107
+ duration_ms: 150.5,
108
+ metadata: {
109
+ controller: "TestController",
110
+ action: "index",
111
+ method: "GET",
112
+ path: "/test"
113
+ },
114
+ timestamp: Time.now.iso8601(3),
115
+ environment: "development",
116
+ event_type: "performance"
117
+ }
118
+
119
+ request.body = JSON.generate(performance_data)
120
+
121
+ response = http.request(request)
122
+
123
+ if [200,201].include?(response.code.to_i)
124
+ puts "✅ Performance tracking successful!"
125
+ puts " Response: #{response.body}"
126
+ else
127
+ puts "❌ Performance tracking failed with status: #{response.code}"
128
+ puts " Response: #{response.body}"
129
+ end
130
+ rescue => e
131
+ puts "❌ Performance tracking error: #{e.message}"
132
+ end
133
+
134
+ # Test 4: Make requests to your app to trigger ActiveRabbit
135
+ puts "\n🌐 Testing requests to your app (port 3003)..."
136
+
137
+ test_urls = [
138
+ "http://localhost:3003/",
139
+ "http://localhost:3003/nonexistent-page", # Should trigger 404
140
+ "http://localhost:3003/test-error" # Might trigger an error
141
+ ]
142
+
143
+ test_urls.each do |url|
144
+ puts "\nTesting: #{url}"
145
+ begin
146
+ uri = URI(url)
147
+ http = Net::HTTP.new(uri.host, uri.port)
148
+ http.read_timeout = 5
149
+
150
+ request = Net::HTTP::Get.new(uri.path)
151
+ request['User-Agent'] = 'ActiveRabbit-Test/1.0'
152
+
153
+ response = http.request(request)
154
+ puts " Status: #{response.code} #{response.message}"
155
+
156
+ if response.code.to_i >= 400
157
+ puts " ⚠️ This should trigger ActiveRabbit error tracking!"
158
+ end
159
+
160
+ rescue => e
161
+ puts " Error: #{e.message}"
162
+ puts " ⚠️ This should trigger ActiveRabbit exception tracking!"
163
+ end
164
+ end
165
+
166
+ puts "\n" + "=" * 50
167
+ puts "🎉 Test completed!"
168
+ puts "Check your ActiveRabbit dashboard at #{API_URL} for tracked events."
169
+ puts "=" * 50
data/trigger_errors.rb ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ # Script to trigger errors in your app and test ActiveRabbit
3
+
4
+ require 'net/http'
5
+
6
+ puts "🐛 Triggering errors in your app to test ActiveRabbit..."
7
+ puts "=" * 50
8
+
9
+ test_urls = [
10
+ "http://localhost:3003/",
11
+ "http://localhost:3003/trigger-error", # This might cause an exception
12
+ "http://localhost:3003/users/999999", # Non-existent user
13
+ "http://localhost:3003/admin/secret", # Unauthorized access
14
+ "http://localhost:3003/api/v1/test", # API endpoint that might not exist
15
+ ]
16
+
17
+ test_urls.each_with_index do |url, index|
18
+ puts "\n#{index + 1}. Testing: #{url}"
19
+
20
+ begin
21
+ uri = URI(url)
22
+ http = Net::HTTP.new(uri.host, uri.port)
23
+ http.read_timeout = 10
24
+
25
+ request = Net::HTTP::Get.new(uri.path)
26
+ request['User-Agent'] = 'ActiveRabbit-ErrorTest/1.0'
27
+
28
+ response = http.request(request)
29
+
30
+ puts " Status: #{response.code} #{response.message}"
31
+
32
+ case response.code.to_i
33
+ when 200..299
34
+ puts " ✅ Success - Normal request"
35
+ when 404
36
+ puts " ⚠️ 404 Not Found - This should be tracked by ActiveRabbit!"
37
+ when 500..599
38
+ puts " 🚨 Server Error - This should definitely be tracked by ActiveRabbit!"
39
+ else
40
+ puts " ⚠️ #{response.code} Error - This should be tracked by ActiveRabbit!"
41
+ end
42
+
43
+ rescue => e
44
+ puts " 💥 Exception: #{e.class}: #{e.message}"
45
+ puts " 🚨 This network error should be tracked by ActiveRabbit!"
46
+ end
47
+
48
+ # Small delay between requests
49
+ sleep(0.5)
50
+ end
51
+
52
+ puts "\n" + "=" * 50
53
+ puts "✅ Test completed!"
54
+ puts ""
55
+ puts "Now check your ActiveRabbit logs and dashboard:"
56
+ puts "1. Check ActiveRabbit API logs at http://localhost:3000"
57
+ puts "2. Look for error entries in your ActiveRabbit database"
58
+ puts "3. Check your app logs on port 3003 for ActiveRabbit activity"
59
+ puts ""
60
+ puts "If ActiveRabbit is working, you should see:"
61
+ puts "- Exception tracking logs in your app"
62
+ puts "- HTTP requests to localhost:3000/api/v1/events/errors"
63
+ puts "- Error entries in your ActiveRabbit dashboard"
64
+ puts "=" * 50
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.0
4
+ version: 0.4.2
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-09-04 00:00:00.000000000 Z
11
+ date: 2025-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -81,12 +81,18 @@ files:
81
81
  - README.md
82
82
  - Rakefile
83
83
  - TESTING_GUIDE.md
84
+ - check_api_data.rb
84
85
  - examples/rails_app_testing.rb
85
86
  - examples/rails_integration.rb
86
87
  - examples/standalone_usage.rb
88
+ - lib/active_rabbit-client.gemspec
87
89
  - lib/active_rabbit.rb
88
90
  - lib/active_rabbit/client.rb
91
+ - lib/active_rabbit/client/action_mailer_patch.rb
92
+ - lib/active_rabbit/client/active_job_extensions.rb
89
93
  - lib/active_rabbit/client/configuration.rb
94
+ - lib/active_rabbit/client/dedupe.rb
95
+ - lib/active_rabbit/client/error_reporter.rb
90
96
  - lib/active_rabbit/client/event_processor.rb
91
97
  - lib/active_rabbit/client/exception_tracker.rb
92
98
  - lib/active_rabbit/client/http_client.rb
@@ -96,9 +102,16 @@ files:
96
102
  - lib/active_rabbit/client/railtie.rb
97
103
  - lib/active_rabbit/client/sidekiq_middleware.rb
98
104
  - lib/active_rabbit/client/version.rb
105
+ - lib/active_rabbit/middleware/error_capture_middleware.rb
106
+ - lib/active_rabbit/reporting.rb
107
+ - lib/active_rabbit/routing/not_found_app.rb
99
108
  - script/test_production_readiness.rb
100
109
  - script/test_rails_integration.rb
110
+ - setup_local_gem_testing.sh
101
111
  - sig/active_rabbit/client.rbs
112
+ - test_net_http.rb
113
+ - test_with_api.rb
114
+ - trigger_errors.rb
102
115
  homepage: https://github.com/bugrabbit/active_rabbit-client
103
116
  licenses:
104
117
  - MIT