aivory_monitor 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +343 -0
- data/lib/aivory_monitor/backend_connection.rb +363 -0
- data/lib/aivory_monitor/config.rb +71 -0
- data/lib/aivory_monitor/exception_capture.rb +466 -0
- data/lib/aivory_monitor/models.rb +113 -0
- data/lib/aivory_monitor/version.rb +5 -0
- data/lib/aivory_monitor.rb +213 -0
- metadata +96 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "aivory_monitor/version"
|
|
4
|
+
require_relative "aivory_monitor/config"
|
|
5
|
+
require_relative "aivory_monitor/models"
|
|
6
|
+
require_relative "aivory_monitor/backend_connection"
|
|
7
|
+
require_relative "aivory_monitor/exception_capture"
|
|
8
|
+
|
|
9
|
+
# AIVory Monitor Ruby Agent
|
|
10
|
+
#
|
|
11
|
+
# Usage:
|
|
12
|
+
# require 'aivory_monitor'
|
|
13
|
+
#
|
|
14
|
+
# AIVoryMonitor.init(
|
|
15
|
+
# api_key: 'your-api-key',
|
|
16
|
+
# environment: 'production'
|
|
17
|
+
# )
|
|
18
|
+
#
|
|
19
|
+
# Or using environment variables:
|
|
20
|
+
# AIVoryMonitor.init # Uses AIVORY_* environment variables
|
|
21
|
+
#
|
|
22
|
+
module AIVoryMonitor
|
|
23
|
+
class Error < StandardError; end
|
|
24
|
+
|
|
25
|
+
@instance = nil
|
|
26
|
+
@initialized = false
|
|
27
|
+
@mutex = Mutex.new
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
# Initializes the AIVory Monitor agent.
|
|
31
|
+
#
|
|
32
|
+
# @param api_key [String] API key for authentication
|
|
33
|
+
# @param backend_url [String] WebSocket URL for the backend
|
|
34
|
+
# @param environment [String] Environment name (production, staging, etc.)
|
|
35
|
+
# @param application_name [String, nil] Application name
|
|
36
|
+
# @param sampling_rate [Float] Sampling rate for exceptions (0.0 to 1.0)
|
|
37
|
+
# @param max_variable_depth [Integer] Maximum depth for variable capture
|
|
38
|
+
# @param debug [Boolean] Enable debug logging
|
|
39
|
+
# @param enable_breakpoints [Boolean] Enable non-breaking breakpoints
|
|
40
|
+
def init(
|
|
41
|
+
api_key: nil,
|
|
42
|
+
backend_url: nil,
|
|
43
|
+
environment: nil,
|
|
44
|
+
application_name: nil,
|
|
45
|
+
sampling_rate: nil,
|
|
46
|
+
max_variable_depth: nil,
|
|
47
|
+
debug: nil,
|
|
48
|
+
enable_breakpoints: nil
|
|
49
|
+
)
|
|
50
|
+
@mutex.synchronize do
|
|
51
|
+
if @initialized
|
|
52
|
+
puts "[AIVory Monitor] Agent already initialized"
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
config = Config.new(
|
|
57
|
+
api_key: api_key,
|
|
58
|
+
backend_url: backend_url,
|
|
59
|
+
environment: environment,
|
|
60
|
+
application_name: application_name,
|
|
61
|
+
sampling_rate: sampling_rate,
|
|
62
|
+
max_variable_depth: max_variable_depth,
|
|
63
|
+
debug: debug,
|
|
64
|
+
enable_breakpoints: enable_breakpoints
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
begin
|
|
68
|
+
config.validate!
|
|
69
|
+
rescue ArgumentError => e
|
|
70
|
+
puts "[AIVory Monitor] Configuration error: #{e.message}"
|
|
71
|
+
return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
puts "[AIVory Monitor] Initializing agent v#{VERSION}"
|
|
75
|
+
puts "[AIVory Monitor] Environment: #{config.environment}"
|
|
76
|
+
|
|
77
|
+
@config = config
|
|
78
|
+
@connection = BackendConnection.new(config)
|
|
79
|
+
@exception_capture = ExceptionCapture.new(config, @connection)
|
|
80
|
+
|
|
81
|
+
# Install exception handlers
|
|
82
|
+
@exception_capture.install
|
|
83
|
+
|
|
84
|
+
# Connect to backend
|
|
85
|
+
@connection.connect
|
|
86
|
+
|
|
87
|
+
# Register at_exit handler
|
|
88
|
+
at_exit { shutdown }
|
|
89
|
+
|
|
90
|
+
@initialized = true
|
|
91
|
+
puts "[AIVory Monitor] Agent initialized successfully"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Manually captures an exception.
|
|
96
|
+
#
|
|
97
|
+
# @param exception [Exception] The exception to capture
|
|
98
|
+
# @param context [Hash, nil] Additional context
|
|
99
|
+
def capture_exception(exception, context = nil)
|
|
100
|
+
return unless @initialized && @exception_capture
|
|
101
|
+
|
|
102
|
+
merged_context = (@custom_context || {}).merge(context || {})
|
|
103
|
+
merged_context[:user] = @user if @user
|
|
104
|
+
|
|
105
|
+
@exception_capture.capture(exception, merged_context)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Sets custom context that will be sent with all captures.
|
|
109
|
+
#
|
|
110
|
+
# @param context [Hash] Context to add
|
|
111
|
+
def set_context(context)
|
|
112
|
+
return unless @initialized
|
|
113
|
+
|
|
114
|
+
@custom_context ||= {}
|
|
115
|
+
@custom_context.merge!(context)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Sets the current user for context.
|
|
119
|
+
#
|
|
120
|
+
# @param user [Hash] User info with :id, :email, :username keys
|
|
121
|
+
def set_user(user)
|
|
122
|
+
return unless @initialized
|
|
123
|
+
|
|
124
|
+
@user = user
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Shuts down the agent gracefully.
|
|
128
|
+
def shutdown
|
|
129
|
+
@mutex.synchronize do
|
|
130
|
+
return unless @initialized
|
|
131
|
+
|
|
132
|
+
puts "[AIVory Monitor] Shutting down agent" if @config&.debug
|
|
133
|
+
|
|
134
|
+
@exception_capture&.uninstall
|
|
135
|
+
@connection&.disconnect
|
|
136
|
+
|
|
137
|
+
@initialized = false
|
|
138
|
+
@config = nil
|
|
139
|
+
@connection = nil
|
|
140
|
+
@exception_capture = nil
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Checks if the agent is initialized.
|
|
145
|
+
#
|
|
146
|
+
# @return [Boolean]
|
|
147
|
+
def initialized?
|
|
148
|
+
@initialized
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Checks if connected to the backend.
|
|
152
|
+
#
|
|
153
|
+
# @return [Boolean]
|
|
154
|
+
def connected?
|
|
155
|
+
@initialized && @connection&.connected?
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Gets the current config (for testing).
|
|
159
|
+
#
|
|
160
|
+
# @return [Config, nil]
|
|
161
|
+
attr_reader :config
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Rails integration
|
|
166
|
+
if defined?(Rails::Railtie)
|
|
167
|
+
module AIVoryMonitor
|
|
168
|
+
class Railtie < Rails::Railtie
|
|
169
|
+
initializer "aivory_monitor.configure" do |app|
|
|
170
|
+
AIVoryMonitor.init
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
config.after_initialize do
|
|
174
|
+
if defined?(ActionController::Base)
|
|
175
|
+
ActionController::Base.class_eval do
|
|
176
|
+
rescue_from Exception do |exception|
|
|
177
|
+
AIVoryMonitor.capture_exception(exception, {
|
|
178
|
+
controller: self.class.name,
|
|
179
|
+
action: action_name,
|
|
180
|
+
params: request.filtered_parameters
|
|
181
|
+
})
|
|
182
|
+
raise exception
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Sidekiq integration
|
|
192
|
+
if defined?(Sidekiq)
|
|
193
|
+
module AIVoryMonitor
|
|
194
|
+
class SidekiqMiddleware
|
|
195
|
+
def call(worker, job, queue)
|
|
196
|
+
yield
|
|
197
|
+
rescue Exception => e
|
|
198
|
+
AIVoryMonitor.capture_exception(e, {
|
|
199
|
+
worker: worker.class.name,
|
|
200
|
+
queue: queue,
|
|
201
|
+
job_id: job["jid"]
|
|
202
|
+
})
|
|
203
|
+
raise e
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
Sidekiq.configure_server do |config|
|
|
209
|
+
config.server_middleware do |chain|
|
|
210
|
+
chain.add AIVoryMonitor::SidekiqMiddleware
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: aivory_monitor
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- AIVory
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-18 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: websocket-client-simple
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0.6'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0.6'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rspec
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '3.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '3.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rubocop
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.0'
|
|
55
|
+
description: Real-time exception monitoring with AI-powered analysis for Ruby applications.
|
|
56
|
+
Captures exceptions, stack traces, and local variables with zero performance impact.
|
|
57
|
+
email:
|
|
58
|
+
- support@aivory.net
|
|
59
|
+
executables: []
|
|
60
|
+
extensions: []
|
|
61
|
+
extra_rdoc_files: []
|
|
62
|
+
files:
|
|
63
|
+
- LICENSE
|
|
64
|
+
- README.md
|
|
65
|
+
- lib/aivory_monitor.rb
|
|
66
|
+
- lib/aivory_monitor/backend_connection.rb
|
|
67
|
+
- lib/aivory_monitor/config.rb
|
|
68
|
+
- lib/aivory_monitor/exception_capture.rb
|
|
69
|
+
- lib/aivory_monitor/models.rb
|
|
70
|
+
- lib/aivory_monitor/version.rb
|
|
71
|
+
homepage: https://aivory.net/monitor/
|
|
72
|
+
licenses:
|
|
73
|
+
- MIT
|
|
74
|
+
metadata:
|
|
75
|
+
source_code_uri: https://github.com/aivorynet/agent-ruby
|
|
76
|
+
bug_tracker_uri: https://github.com/aivorynet/agent-ruby/issues
|
|
77
|
+
post_install_message:
|
|
78
|
+
rdoc_options: []
|
|
79
|
+
require_paths:
|
|
80
|
+
- lib
|
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
|
+
requirements:
|
|
83
|
+
- - ">="
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: 2.7.0
|
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - ">="
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '0'
|
|
91
|
+
requirements: []
|
|
92
|
+
rubygems_version: 3.5.22
|
|
93
|
+
signing_key:
|
|
94
|
+
specification_version: 4
|
|
95
|
+
summary: AIVory Monitor - Runtime exception monitoring agent for Ruby applications
|
|
96
|
+
test_files: []
|