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
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9cd9562d57c9dd817e379e42470aaf15c8961fc17469c20b6fef9ee67ff19f61
|
|
4
|
+
data.tar.gz: cea2016eab1e3e1cc26f4db1bd7cabdc851e1a11587edf934b71be16301373d1
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e7d8da3e4f472c47a40e6c36ae74cab4b67b90ac1ce961b9b9d54ca402ac97e65ed1d871bb882b2f7a51ccd1af8f1df0c69670edb1b5bfe44c3c75e044162767
|
|
7
|
+
data.tar.gz: 22be0f73a6fcb28375e410812a069de56163fa229e7753357d2caeab7061b1977dcf8b254cc8fa6232a2f6595553752825f06bd52ed2238900ee539aa9d70202
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ILSCIPIO GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# AIVory Monitor - Ruby Agent
|
|
2
|
+
|
|
3
|
+
Real-time exception monitoring with AI-powered analysis for Ruby applications. Captures exceptions, stack traces, and local variables with zero performance impact.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Ruby 2.7 or higher
|
|
8
|
+
- Network access to AIVory backend (wss://api.aivory.net)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
### Using RubyGems
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
gem install aivory_monitor
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Using Bundler
|
|
19
|
+
|
|
20
|
+
Add to your `Gemfile`:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
gem 'aivory_monitor'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then run:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bundle install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Basic Initialization
|
|
35
|
+
|
|
36
|
+
Initialize the agent at the start of your application:
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
require 'aivory_monitor'
|
|
40
|
+
|
|
41
|
+
AIVoryMonitor.init(
|
|
42
|
+
api_key: 'your-api-key',
|
|
43
|
+
environment: 'production'
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Using Environment Variables
|
|
48
|
+
|
|
49
|
+
Set environment variables and initialize without arguments:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
export AIVORY_API_KEY=your-api-key
|
|
53
|
+
export AIVORY_ENVIRONMENT=production
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
require 'aivory_monitor'
|
|
58
|
+
|
|
59
|
+
AIVoryMonitor.init
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Manual Exception Capture
|
|
63
|
+
|
|
64
|
+
Capture exceptions manually with additional context:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
begin
|
|
68
|
+
risky_operation
|
|
69
|
+
rescue => e
|
|
70
|
+
AIVoryMonitor.capture_exception(e, {
|
|
71
|
+
user_id: current_user.id,
|
|
72
|
+
request_id: request.uuid,
|
|
73
|
+
custom_data: { foo: 'bar' }
|
|
74
|
+
})
|
|
75
|
+
raise
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Setting User Context
|
|
80
|
+
|
|
81
|
+
Associate exceptions with specific users:
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
AIVoryMonitor.set_user({
|
|
85
|
+
id: user.id,
|
|
86
|
+
email: user.email,
|
|
87
|
+
username: user.username
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Setting Custom Context
|
|
92
|
+
|
|
93
|
+
Add persistent context sent with all captures:
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
AIVoryMonitor.set_context({
|
|
97
|
+
version: '1.2.3',
|
|
98
|
+
region: 'us-west-2',
|
|
99
|
+
tenant: 'acme-corp'
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Rails Integration
|
|
104
|
+
|
|
105
|
+
The agent automatically integrates with Rails. Add to your `Gemfile`:
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
gem 'aivory_monitor'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Create `config/initializers/aivory_monitor.rb`:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
AIVoryMonitor.init(
|
|
115
|
+
api_key: ENV['AIVORY_API_KEY'],
|
|
116
|
+
environment: Rails.env,
|
|
117
|
+
application_name: 'my-rails-app'
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The agent will automatically capture:
|
|
122
|
+
- Controller exceptions with request parameters
|
|
123
|
+
- Background job failures (Sidekiq)
|
|
124
|
+
- Uncaught exceptions throughout the application
|
|
125
|
+
|
|
126
|
+
### Sinatra Integration
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
require 'sinatra'
|
|
130
|
+
require 'aivory_monitor'
|
|
131
|
+
|
|
132
|
+
AIVoryMonitor.init(
|
|
133
|
+
api_key: ENV['AIVORY_API_KEY'],
|
|
134
|
+
environment: ENV['RACK_ENV'] || 'development',
|
|
135
|
+
application_name: 'my-sinatra-app'
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
error do
|
|
139
|
+
exception = env['sinatra.error']
|
|
140
|
+
AIVoryMonitor.capture_exception(exception, {
|
|
141
|
+
path: request.path,
|
|
142
|
+
method: request.request_method,
|
|
143
|
+
params: params
|
|
144
|
+
})
|
|
145
|
+
'Internal Server Error'
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
get '/' do
|
|
149
|
+
'Hello World'
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Rack Middleware
|
|
154
|
+
|
|
155
|
+
For other Rack-based frameworks:
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
require 'aivory_monitor'
|
|
159
|
+
|
|
160
|
+
AIVoryMonitor.init
|
|
161
|
+
|
|
162
|
+
use Rack::Builder do
|
|
163
|
+
use Rack::CommonLogger
|
|
164
|
+
|
|
165
|
+
run lambda { |env|
|
|
166
|
+
begin
|
|
167
|
+
# Your application code
|
|
168
|
+
[200, {'Content-Type' => 'text/plain'}, ['OK']]
|
|
169
|
+
rescue => e
|
|
170
|
+
AIVoryMonitor.capture_exception(e, {
|
|
171
|
+
path: env['PATH_INFO'],
|
|
172
|
+
method: env['REQUEST_METHOD']
|
|
173
|
+
})
|
|
174
|
+
raise
|
|
175
|
+
end
|
|
176
|
+
}
|
|
177
|
+
end
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Configuration
|
|
181
|
+
|
|
182
|
+
The agent can be configured using environment variables or initialization parameters.
|
|
183
|
+
|
|
184
|
+
| Environment Variable | Parameter | Description | Default |
|
|
185
|
+
|---------------------|-----------|-------------|---------|
|
|
186
|
+
| `AIVORY_API_KEY` | `api_key` | API key for authentication | Required |
|
|
187
|
+
| `AIVORY_BACKEND_URL` | `backend_url` | Backend WebSocket URL | `wss://api.aivory.net/ws/monitor/agent` |
|
|
188
|
+
| `AIVORY_ENVIRONMENT` | `environment` | Environment name (production, staging, etc.) | `production` |
|
|
189
|
+
| `AIVORY_APPLICATION_NAME` | `application_name` | Application identifier | Auto-detected |
|
|
190
|
+
| `AIVORY_SAMPLING_RATE` | `sampling_rate` | Exception sampling rate (0.0 to 1.0) | `1.0` |
|
|
191
|
+
| `AIVORY_MAX_DEPTH` | `max_variable_depth` | Maximum depth for variable capture | `3` |
|
|
192
|
+
| `AIVORY_DEBUG` | `debug` | Enable debug logging | `false` |
|
|
193
|
+
| `AIVORY_ENABLE_BREAKPOINTS` | `enable_breakpoints` | Enable non-breaking breakpoints | `false` |
|
|
194
|
+
|
|
195
|
+
### Configuration Example
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
AIVoryMonitor.init(
|
|
199
|
+
api_key: 'your-api-key',
|
|
200
|
+
backend_url: 'wss://api.aivory.net/ws/monitor/agent',
|
|
201
|
+
environment: 'production',
|
|
202
|
+
application_name: 'my-app',
|
|
203
|
+
sampling_rate: 1.0,
|
|
204
|
+
max_variable_depth: 3,
|
|
205
|
+
debug: false,
|
|
206
|
+
enable_breakpoints: true
|
|
207
|
+
)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Building from Source
|
|
211
|
+
|
|
212
|
+
Clone the repository and build the gem:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
git clone https://github.com/aivory/aivory-monitor.git
|
|
216
|
+
cd aivory-monitor/monitor-agents/agent-ruby
|
|
217
|
+
bundle install
|
|
218
|
+
gem build aivory_monitor.gemspec
|
|
219
|
+
gem install aivory_monitor-1.0.0.gem
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Running Tests
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
bundle exec rspec
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Linting
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
bundle exec rubocop
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## How It Works
|
|
235
|
+
|
|
236
|
+
The AIVory Monitor Ruby agent uses standard Ruby exception handling mechanisms to capture runtime errors:
|
|
237
|
+
|
|
238
|
+
1. **At-Exit Hooks**: Registers an `at_exit` handler to capture unhandled exceptions before the process terminates.
|
|
239
|
+
|
|
240
|
+
2. **Thread Exception Reporting**: Hooks into `Thread.report_on_exception` to capture exceptions in background threads.
|
|
241
|
+
|
|
242
|
+
3. **Exception Capture**: When an exception occurs:
|
|
243
|
+
- Captures the full stack trace with file names and line numbers
|
|
244
|
+
- Extracts local variables at each stack frame (up to configured depth)
|
|
245
|
+
- Collects thread information and system context
|
|
246
|
+
- Serializes the data and sends it to the AIVory backend via WebSocket
|
|
247
|
+
|
|
248
|
+
4. **Non-Breaking Operation**: All capture operations are non-blocking and designed to have minimal performance impact. Failures in the agent never affect your application.
|
|
249
|
+
|
|
250
|
+
5. **WebSocket Connection**: Maintains a persistent connection to the AIVory backend for real-time exception streaming and bidirectional communication (breakpoint commands, configuration updates).
|
|
251
|
+
|
|
252
|
+
## Framework Support
|
|
253
|
+
|
|
254
|
+
### Rails
|
|
255
|
+
|
|
256
|
+
- Automatic initialization via Railtie
|
|
257
|
+
- Controller exception capture with request context
|
|
258
|
+
- ActionMailer exception capture
|
|
259
|
+
- Works with Rails 5.0+
|
|
260
|
+
|
|
261
|
+
### Sidekiq
|
|
262
|
+
|
|
263
|
+
- Automatic middleware injection
|
|
264
|
+
- Captures job failures with worker context
|
|
265
|
+
- Includes job ID, queue name, and arguments
|
|
266
|
+
|
|
267
|
+
### Other Frameworks
|
|
268
|
+
|
|
269
|
+
The agent works with any Ruby application or framework. For frameworks without automatic integration, use manual initialization and exception capture as shown in the usage examples.
|
|
270
|
+
|
|
271
|
+
## Troubleshooting
|
|
272
|
+
|
|
273
|
+
### Agent Not Capturing Exceptions
|
|
274
|
+
|
|
275
|
+
Check that the agent is initialized:
|
|
276
|
+
|
|
277
|
+
```ruby
|
|
278
|
+
puts AIVoryMonitor.initialized? # Should return true
|
|
279
|
+
puts AIVoryMonitor.connected? # Should return true
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Enable debug logging:
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
AIVoryMonitor.init(
|
|
286
|
+
api_key: 'your-api-key',
|
|
287
|
+
debug: true
|
|
288
|
+
)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Connection Issues
|
|
292
|
+
|
|
293
|
+
Verify your API key is correct and the backend URL is reachable:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
export AIVORY_DEBUG=true
|
|
297
|
+
ruby your_app.rb
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Check for firewall rules blocking WebSocket connections to `wss://api.aivory.net`.
|
|
301
|
+
|
|
302
|
+
### High Memory Usage
|
|
303
|
+
|
|
304
|
+
If capturing large objects causes memory issues, reduce the variable capture depth:
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
AIVoryMonitor.init(
|
|
308
|
+
api_key: 'your-api-key',
|
|
309
|
+
max_variable_depth: 1 # Reduce from default of 3
|
|
310
|
+
)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Or enable sampling to capture only a percentage of exceptions:
|
|
314
|
+
|
|
315
|
+
```ruby
|
|
316
|
+
AIVoryMonitor.init(
|
|
317
|
+
api_key: 'your-api-key',
|
|
318
|
+
sampling_rate: 0.1 # Capture 10% of exceptions
|
|
319
|
+
)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Rails Not Loading Agent
|
|
323
|
+
|
|
324
|
+
Ensure the gem is in your `Gemfile` and you've run `bundle install`. Create an initializer at `config/initializers/aivory_monitor.rb` to explicitly initialize if needed.
|
|
325
|
+
|
|
326
|
+
### Sidekiq Jobs Not Being Captured
|
|
327
|
+
|
|
328
|
+
The Sidekiq middleware is automatically loaded if Sidekiq is detected. Ensure you're loading the agent before Sidekiq workers start:
|
|
329
|
+
|
|
330
|
+
```ruby
|
|
331
|
+
# config/initializers/aivory_monitor.rb
|
|
332
|
+
AIVoryMonitor.init
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Support
|
|
336
|
+
|
|
337
|
+
- Documentation: https://aivory.net/monitor/docs
|
|
338
|
+
- GitHub Issues: https://github.com/aivory/aivory-monitor/issues
|
|
339
|
+
- Email: support@aivory.net
|
|
340
|
+
|
|
341
|
+
## License
|
|
342
|
+
|
|
343
|
+
MIT License. See LICENSE file for details.
|