rails_nexus 2.0.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/MIT-LICENSE +20 -0
- data/README.md +430 -0
- data/Rakefile +6 -0
- data/app/assets/config/rails_nexus_manifest.js +2 -0
- data/app/assets/javascripts/rails_nexus/controllers.js +603 -0
- data/app/assets/stylesheets/rails_nexus/application.css +1964 -0
- data/app/controllers/rails_nexus/analytics_controller.rb +361 -0
- data/app/controllers/rails_nexus/application_controller.rb +15 -0
- data/app/controllers/rails_nexus/backup_controller.rb +91 -0
- data/app/controllers/rails_nexus/cron_jobs_controller.rb +64 -0
- data/app/controllers/rails_nexus/database_health_controller.rb +128 -0
- data/app/controllers/rails_nexus/logged_exceptions_controller.rb +227 -0
- data/app/controllers/rails_nexus/n1_patterns_controller.rb +10 -0
- data/app/controllers/rails_nexus/settings_controller.rb +100 -0
- data/app/controllers/rails_nexus/source_code_controller.rb +39 -0
- data/app/controllers/rails_nexus/stats_controller.rb +494 -0
- data/app/controllers/rails_nexus/workflow_controller.rb +96 -0
- data/app/helpers/rails_nexus/application_helper.rb +5 -0
- data/app/helpers/rails_nexus/logged_exceptions_helper.rb +254 -0
- data/app/helpers/rails_nexus/source_code_helper.rb +107 -0
- data/app/javascript/controllers/rails_nexus_controller.js +380 -0
- data/app/javascript/controllers/rails_nexus_detail_controller.js +165 -0
- data/app/javascript/controllers/rails_nexus_sidebar_controller.js +15 -0
- data/app/javascript/controllers/rails_nexus_theme_controller.js +31 -0
- data/app/javascript/rails_nexus/application.js +17 -0
- data/app/jobs/rails_nexus/application_job.rb +4 -0
- data/app/mailers/rails_nexus/application_mailer.rb +6 -0
- data/app/models/rails_nexus/application_record.rb +5 -0
- data/app/models/rails_nexus/backup.rb +107 -0
- data/app/models/rails_nexus/base_record.rb +26 -0
- data/app/models/rails_nexus/comment.rb +13 -0
- data/app/models/rails_nexus/cron_job.rb +72 -0
- data/app/models/rails_nexus/database_stat.rb +128 -0
- data/app/models/rails_nexus/event.rb +101 -0
- data/app/models/rails_nexus/logged_exception.rb +864 -0
- data/app/models/rails_nexus/logged_exception_n1.rb +87 -0
- data/app/models/rails_nexus/metric.rb +107 -0
- data/app/models/rails_nexus/nginx_metric.rb +112 -0
- data/app/models/rails_nexus/server_metric.rb +168 -0
- data/app/models/rails_nexus/webhook_delivery.rb +64 -0
- data/app/services/rails_nexus/backup_service.rb +275 -0
- data/app/views/layouts/rails_nexus/application.html.erb +185 -0
- data/app/views/rails_nexus/analytics/index.html.erb +363 -0
- data/app/views/rails_nexus/backup/files.html.erb +53 -0
- data/app/views/rails_nexus/backup/index.html.erb +211 -0
- data/app/views/rails_nexus/backup/settings.html.erb +158 -0
- data/app/views/rails_nexus/cron_jobs/index.html.erb +141 -0
- data/app/views/rails_nexus/database_health/index.html.erb +139 -0
- data/app/views/rails_nexus/logged_exceptions/_comments_list.html.erb +50 -0
- data/app/views/rails_nexus/logged_exceptions/_exceptions.html.erb +190 -0
- data/app/views/rails_nexus/logged_exceptions/_feed.html.erb +3 -0
- data/app/views/rails_nexus/logged_exceptions/_filter_group.html.erb +10 -0
- data/app/views/rails_nexus/logged_exceptions/_show.html.erb +554 -0
- data/app/views/rails_nexus/logged_exceptions/_workflow_panel.html.erb +118 -0
- data/app/views/rails_nexus/logged_exceptions/clear.turbo_stream.erb +6 -0
- data/app/views/rails_nexus/logged_exceptions/destroy.turbo_stream.erb +2 -0
- data/app/views/rails_nexus/logged_exceptions/destroy_all.turbo_stream.erb +6 -0
- data/app/views/rails_nexus/logged_exceptions/feed.rss.builder +20 -0
- data/app/views/rails_nexus/logged_exceptions/index.html.erb +323 -0
- data/app/views/rails_nexus/logged_exceptions/query.html.erb +3 -0
- data/app/views/rails_nexus/logged_exceptions/query.turbo_stream.erb +6 -0
- data/app/views/rails_nexus/logged_exceptions/show.html.erb +3 -0
- data/app/views/rails_nexus/logged_exceptions/show.turbo_stream.erb +5 -0
- data/app/views/rails_nexus/n1_patterns/index.html.erb +153 -0
- data/app/views/rails_nexus/settings/index.html.erb +140 -0
- data/app/views/rails_nexus/stats/index.html.erb +569 -0
- data/config/importmap.rb +15 -0
- data/config/initializers/date_formats.rb +5 -0
- data/config/initializers/rails_nexus.rb +18 -0
- data/config/locales/en.yml +47 -0
- data/config/routes.rb +58 -0
- data/db/migrate/20240330122311_create_rails_nexus_logged_exceptions.rb +22 -0
- data/lib/generators/rails_nexus/backup_generator.rb +70 -0
- data/lib/generators/rails_nexus/customize_generator.rb +159 -0
- data/lib/generators/rails_nexus/install_generator.rb +61 -0
- data/lib/generators/rails_nexus/templates/INSTALL.md +9 -0
- data/lib/generators/rails_nexus/templates/backup/backup_helper.sh +152 -0
- data/lib/generators/rails_nexus/templates/backup/config.rb +27 -0
- data/lib/generators/rails_nexus/templates/backup/models/daily_backup.rb +24 -0
- data/lib/generators/rails_nexus/templates/backup/models/full_backup.rb +35 -0
- data/lib/generators/rails_nexus/templates/backup/models/sync_backup.rb +43 -0
- data/lib/generators/rails_nexus/templates/backup/mysql-config/db_config.cnf +15 -0
- data/lib/generators/rails_nexus/templates/backup/schedule.rb +28 -0
- data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_controller.js +310 -0
- data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_detail_controller.js +98 -0
- data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_sidebar_controller.js +15 -0
- data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_theme_controller.js +30 -0
- data/lib/generators/rails_nexus/templates/migration.rb +24 -0
- data/lib/generators/rails_nexus/templates/migration_advanced_features.rb +30 -0
- data/lib/generators/rails_nexus/templates/migration_cron_jobs.rb +22 -0
- data/lib/generators/rails_nexus/templates/migration_new_schema.rb +120 -0
- data/lib/generators/rails_nexus/templates/migration_platform_detection.rb +11 -0
- data/lib/generators/rails_nexus/templates/migration_webhook_deliveries.rb +21 -0
- data/lib/generators/rails_nexus/templates/migration_workflow.rb +29 -0
- data/lib/generators/rails_nexus/templates/rails_nexus.rb +96 -0
- data/lib/generators/rails_nexus/templates/views/layouts/rails_nexus/application.html.erb +129 -0
- data/lib/generators/rails_nexus/templates/views/rails_nexus/logged_exceptions/_exceptions.html.erb +123 -0
- data/lib/generators/rails_nexus/templates/views/rails_nexus/logged_exceptions/_show.html.erb +297 -0
- data/lib/generators/rails_nexus/templates/views/rails_nexus/logged_exceptions/index.html.erb +113 -0
- data/lib/rails_nexus/breadcrumbs.rb +161 -0
- data/lib/rails_nexus/cleanup.rb +32 -0
- data/lib/rails_nexus/configuration.rb +319 -0
- data/lib/rails_nexus/engine.rb +135 -0
- data/lib/rails_nexus/logger.rb +188 -0
- data/lib/rails_nexus/notifications.rb +105 -0
- data/lib/rails_nexus/ransack_config.rb +4 -0
- data/lib/rails_nexus/storm_protection.rb +124 -0
- data/lib/rails_nexus/version.rb +3 -0
- data/lib/rails_nexus.rb +133 -0
- data/lib/tasks/rails_nexus.rake +230 -0
- data/lib/tasks/rails_nexus_tasks.rake +37 -0
- data/rails_nexus.gemspec +36 -0
- metadata +252 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 33e67e4702cc5b31061fc12c76dc25c647717f12fbecf14fa485a0b910c969ad
|
|
4
|
+
data.tar.gz: d4f46f7b519cd0a8d99212f03aba8537b761fbce9ddbce081198d9c4d9204f44
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d31501ea96c117ce8b2f86867760be1982e7af7ed89ed21cfad27681a9dc5cd0a1260bc907abf1288cf1b45bdd5613989c6b31a518a028d641500d54ca5db7dd
|
|
7
|
+
data.tar.gz: 9cb09061f96d7d2478c5147867c90029859737b2dbfdd939721ec4c9c5a50103a0da94bb0e2e6d1ed4582186d2cc86e300ab5ccc9339755041870f3f3cbc9f37
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright Tamiru Hailu
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# RailsNexus
|
|
2
|
+
|
|
3
|
+
### The extensible control plane for Rails applications
|
|
4
|
+
|
|
5
|
+
[](https://rubygems.org/gems/rails_nexus)
|
|
6
|
+
[](https://github.com/sponsors/tamiru)
|
|
7
|
+
|
|
8
|
+
RailsNexus is an extensible operations and administration console for Rails applications. It provides everything you need to monitor, debug, and manage your Rails app in production — all from a single dashboard.
|
|
9
|
+
|
|
10
|
+
**One gem. All your ops.**
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
### 🚨 Error Monitoring
|
|
15
|
+
- **Exception Dashboard** — Dark/light theme, keyboard shortcuts, tabbed detail view
|
|
16
|
+
- **Cause Chains** — Track root cause through chained exceptions
|
|
17
|
+
- **Breadcrumbs** — Activity trail leading up to each error
|
|
18
|
+
- **Storm Protection** — Circuit breaker for error floods
|
|
19
|
+
- **User Impact Ranking** — See which errors affect the most users
|
|
20
|
+
- **Platform Detection** — iOS, Android, Web, and API with automatic categorization
|
|
21
|
+
|
|
22
|
+
### 📊 Real-time Analytics
|
|
23
|
+
- **Error Trends** — Hourly, daily, and weekly exception patterns
|
|
24
|
+
- **Platform Health** — Per-platform error rates and response times
|
|
25
|
+
- **Correlation Insights** — Time-based, controller-based, and user-based correlations
|
|
26
|
+
- **Baseline Monitoring** — Detect anomalies against historical averages
|
|
27
|
+
- **Occurrence Patterns** — Cyclical and burst detection
|
|
28
|
+
- **N+1 Query Detection** — Automatic N+1 pattern identification
|
|
29
|
+
|
|
30
|
+
### ⏰ Cron Job Monitoring
|
|
31
|
+
- **Job Tracking** — Track scheduled job runs, failures, and history
|
|
32
|
+
- **Success Rates** — Per-job and overall success metrics
|
|
33
|
+
- **Execution Times** — Monitor job duration and detect slow jobs
|
|
34
|
+
- **Cleanup** — Automatic old job record removal
|
|
35
|
+
|
|
36
|
+
### 💾 Backup Management
|
|
37
|
+
- **Backup Dashboard** — Health status, model listing, recent backups
|
|
38
|
+
- **File Browser** — View all backup files with size, age, and format
|
|
39
|
+
- **Trigger from UI** — Run backups directly from the dashboard
|
|
40
|
+
- **Settings Editor** — Configure paths, thresholds, and notifications
|
|
41
|
+
- **Health Monitoring** — Alerts when backups are stale or missing
|
|
42
|
+
- **Cron Schedule** — View and manage backup schedules
|
|
43
|
+
|
|
44
|
+
### 🖥️ Server Statistics
|
|
45
|
+
- **Memory Usage** — RAM and swap monitoring
|
|
46
|
+
- **CPU Metrics** — Load average and processor count
|
|
47
|
+
- **Ruby/Rails Info** — Versions and runtime details
|
|
48
|
+
- **Process Info** — Puma workers, thread counts
|
|
49
|
+
- **Sidekiq Stats** — Queue sizes, workers, processed/failed
|
|
50
|
+
|
|
51
|
+
### 🗄️ Database Health
|
|
52
|
+
- **Connection Pool** — Live pool status and utilization
|
|
53
|
+
- **Table Statistics** — Row counts, sizes, and growth
|
|
54
|
+
- **Index Usage** — Index hit rates and missing indexes
|
|
55
|
+
- **Slow Queries** — N+1 and slow query detection
|
|
56
|
+
|
|
57
|
+
### 🔄 Workflow Management
|
|
58
|
+
- **Assignment** — Assign exceptions to team members
|
|
59
|
+
- **Priority** — Set critical/high/medium/low priority levels
|
|
60
|
+
- **Snooze** — Temporarily silence exceptions (1h, 4h, 1d, 1w)
|
|
61
|
+
- **Mute** — Permanently silence resolved exceptions
|
|
62
|
+
- **Comments** — Add notes and status changes
|
|
63
|
+
|
|
64
|
+
### 🔍 Source Code Integration
|
|
65
|
+
- **Inline Source** — View source code directly in backtraces
|
|
66
|
+
- **Git Blame** — See who wrote each line and when
|
|
67
|
+
- **On-demand Loading** — AJAX-powered source fetching
|
|
68
|
+
- **Security** — Path traversal protection, read-only access
|
|
69
|
+
|
|
70
|
+
### 🔔 Notifications
|
|
71
|
+
- **Webhooks** — POST to Slack, Discord, or custom endpoints
|
|
72
|
+
- **Telegram** — Built-in notifier with rate limiting
|
|
73
|
+
- **Sidekiq Middleware** — Automatic background job exception logging
|
|
74
|
+
|
|
75
|
+
### 🛠️ Developer Experience
|
|
76
|
+
- **Keyboard Shortcuts** — Full keyboard navigation (`/`, `j`, `k`, `Enter`, `?`)
|
|
77
|
+
- **Dark/Light Theme** — Auto-detect or manual toggle, remembers preference
|
|
78
|
+
- **Ransack Search** — Advanced search and filtering
|
|
79
|
+
- **RSS Feed** — Subscribe to exception updates
|
|
80
|
+
- **Cleanup/R retention** — Auto-delete old exceptions
|
|
81
|
+
- **Structured Logging** — JSON log output with request context
|
|
82
|
+
- **Tailwind-compatible** — Works with or without Tailwind CSS
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
- Ruby 3.2 or newer
|
|
87
|
+
- Rails 8.0 or newer
|
|
88
|
+
- A database supported by Active Record
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
Add RailsNexus to your application:
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
# Gemfile
|
|
96
|
+
gem "rails_nexus"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Run the install generator:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
bundle install
|
|
103
|
+
bin/rails generate rails_nexus:install
|
|
104
|
+
bin/rails db:migrate
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This will:
|
|
108
|
+
1. Copy the database migration with proper indexes.
|
|
109
|
+
2. Create a configuration initializer at `config/initializers/rails_nexus.rb`.
|
|
110
|
+
3. Mount the engine in your routes.
|
|
111
|
+
4. Add `rescue_from Exception, with: :log_exception_handler` to `ApplicationController`.
|
|
112
|
+
|
|
113
|
+
The dashboard is now available at `/rails_nexus`.
|
|
114
|
+
|
|
115
|
+
### Optional UI customization
|
|
116
|
+
|
|
117
|
+
The mounted dashboard already includes its CSS, Turbo, and Stimulus controllers.
|
|
118
|
+
To copy the UI into your host application for customization, run:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
bin/rails generate rails_nexus:customize
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This generates:
|
|
125
|
+
- Self-contained layout with sidebar, topbar, and theme toggle
|
|
126
|
+
- Tabbed detail view with metadata grid
|
|
127
|
+
- Keyboard shortcuts dialog
|
|
128
|
+
- Stimulus controllers for theme, sidebar, and interactions
|
|
129
|
+
|
|
130
|
+
Options: `--layout-only`, `--views-only`, `--stimulus-only`, `--initializer-only`
|
|
131
|
+
|
|
132
|
+
## Start logging exceptions
|
|
133
|
+
|
|
134
|
+
Include `RailsNexus::ExceptionLoggable` in your application controller:
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
class ApplicationController < ActionController::Base
|
|
138
|
+
include RailsNexus::ExceptionLoggable
|
|
139
|
+
end
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
RailsNexus logs the exception and then re-raises it so Rails keeps its normal error handling.
|
|
143
|
+
|
|
144
|
+
### API controllers
|
|
145
|
+
|
|
146
|
+
For `ActionController::API` subclasses (e.g., API namespaces):
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
class Api::V1::BaseController < ActionController::API
|
|
150
|
+
include RailsNexus::ExceptionLoggable
|
|
151
|
+
end
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Background jobs (Sidekiq)
|
|
155
|
+
|
|
156
|
+
RailsNexus automatically logs Sidekiq job exceptions when the middleware is configured:
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
# config/initializers/sidekiq.rb
|
|
160
|
+
Sidekiq.configure_server do |config|
|
|
161
|
+
config.server_middleware do |chain|
|
|
162
|
+
chain.add RailsNexusSidekiqMiddleware
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Protect the dashboard
|
|
168
|
+
|
|
169
|
+
The dashboard contains sensitive information. **Do not expose it to unauthenticated users.**
|
|
170
|
+
|
|
171
|
+
By default, the dashboard returns `403 Forbidden` for all requests. Configure authentication:
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
# config/initializers/rails_nexus.rb
|
|
175
|
+
Rails.application.config.to_prepare do
|
|
176
|
+
RailsNexus.configure do |config|
|
|
177
|
+
config.auth_block = lambda do |controller|
|
|
178
|
+
controller.current_user&.admin?
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Configuration
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
# config/initializers/rails_nexus.rb
|
|
188
|
+
Rails.application.config.to_prepare do
|
|
189
|
+
RailsNexus.configure do |config|
|
|
190
|
+
# ─── General ─────────────────────────────────────────────
|
|
191
|
+
config.application_name = "My App" # Dashboard title
|
|
192
|
+
config.per_page = 50 # Items per page (default: 30)
|
|
193
|
+
|
|
194
|
+
# ─── Authentication ──────────────────────────────────────
|
|
195
|
+
config.auth_block = lambda do |controller|
|
|
196
|
+
controller.current_user&.admin?
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# ─── Exception Data ──────────────────────────────────────
|
|
200
|
+
config.exception_data = lambda do |controller|
|
|
201
|
+
{
|
|
202
|
+
user_id: controller.current_user&.id,
|
|
203
|
+
request_id: controller.request.request_id,
|
|
204
|
+
environment: Rails.env
|
|
205
|
+
}
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# ─── Notifications ───────────────────────────────────────
|
|
209
|
+
config.after_create = lambda do |exception|
|
|
210
|
+
MyNotifier.alert(exception)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
config.webhooks = ["https://hooks.slack.com/services/xxx"]
|
|
214
|
+
config.webhook_timeout = 5
|
|
215
|
+
config.webhook_headers = { "Authorization" => "Bearer token" }
|
|
216
|
+
|
|
217
|
+
# ─── Cleanup ─────────────────────────────────────────────
|
|
218
|
+
config.retention_days = 90 # Auto-delete after N days
|
|
219
|
+
|
|
220
|
+
# ─── Appearance ──────────────────────────────────────────
|
|
221
|
+
config.theme = "auto" # "light", "dark", or "auto"
|
|
222
|
+
config.body_class = "" # Custom body CSS class
|
|
223
|
+
config.use_host_layout = false # Use host app's layout
|
|
224
|
+
|
|
225
|
+
# ─── Advanced UI ─────────────────────────────────────────
|
|
226
|
+
config.show_stats = true # Stats overview cards
|
|
227
|
+
config.keyboard_shortcuts = true # Keyboard shortcuts
|
|
228
|
+
config.enable_navigation = true # Prev/next in detail view
|
|
229
|
+
config.backtrace_limit = 30 # Frames before collapse
|
|
230
|
+
config.show_metadata = true # Metadata grid
|
|
231
|
+
config.show_environment = false # Environment tab
|
|
232
|
+
config.show_request = true # Request params tab
|
|
233
|
+
config.page_size_options = [25, 50, 100] # Page size selector
|
|
234
|
+
|
|
235
|
+
# ─── Sidebar Links ───────────────────────────────────────
|
|
236
|
+
config.sidebar_links = [
|
|
237
|
+
{ label: "GitHub", url: "https://github.com/myorg/myapp" },
|
|
238
|
+
{ label: "Docs", url: "/docs" }
|
|
239
|
+
]
|
|
240
|
+
|
|
241
|
+
# ─── Logging ─────────────────────────────────────────────
|
|
242
|
+
config.logging_enabled = true
|
|
243
|
+
config.log_level = :info # :debug, :info, :warn, :error, :fatal
|
|
244
|
+
config.log_file = "log/rails_nexus.log" # JSON log file (nil = none)
|
|
245
|
+
config.log_backtrace = true
|
|
246
|
+
config.log_params = true
|
|
247
|
+
config.log_user_info = true
|
|
248
|
+
config.log_backtrace_limit = 20
|
|
249
|
+
config.deduplication_enabled = false
|
|
250
|
+
config.deduplication_window = 300 # Seconds
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Keyboard shortcuts
|
|
256
|
+
|
|
257
|
+
Press `?` in the dashboard to see all shortcuts:
|
|
258
|
+
|
|
259
|
+
| Key | Action |
|
|
260
|
+
|---|---|
|
|
261
|
+
| `/` | Focus search |
|
|
262
|
+
| `j` or `↓` | Navigate down |
|
|
263
|
+
| `k` or `↑` | Navigate up |
|
|
264
|
+
| `Enter` | Open selected exception |
|
|
265
|
+
| `p` or `←` | Previous exception |
|
|
266
|
+
| `n` or `→` | Next exception |
|
|
267
|
+
| `t` | Toggle dark/light theme |
|
|
268
|
+
| `1`-`5` | Switch tabs |
|
|
269
|
+
| `Esc` | Close panel / Clear |
|
|
270
|
+
| `?` | Show shortcuts dialog |
|
|
271
|
+
|
|
272
|
+
## Search & Filter
|
|
273
|
+
|
|
274
|
+
- **Exception Type** — Select dropdown, auto-submits on change
|
|
275
|
+
- **Source** — Exact controller/action filter
|
|
276
|
+
- **Platform and Priority** — Narrow errors by client and workflow priority
|
|
277
|
+
- **Status and Assignee** — Show active, muted, snoozed, or unassigned errors
|
|
278
|
+
- **Occurrences** — Focus on repeatedly occurring fingerprints
|
|
279
|
+
- **Time Range** — Today, 3 days, 7 days, 30 days
|
|
280
|
+
- **Search** — Search message, exception class, controller, and action with a 400ms debounce
|
|
281
|
+
- **Sortable Columns** — Sort by exception, platform, source, message, count, workflow, or last seen
|
|
282
|
+
- **Active Filters** — Pills with one-click dismiss
|
|
283
|
+
|
|
284
|
+
RailsNexus uses Ransack for filtering and sorting and Pagy for bounded, configurable pagination. Filter, sort, page-size, and page parameters are preserved across Turbo Frame updates.
|
|
285
|
+
|
|
286
|
+
## Notifications
|
|
287
|
+
|
|
288
|
+
### Webhooks
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
config.webhooks = [
|
|
292
|
+
"https://hooks.slack.com/services/T00/B00/xxx",
|
|
293
|
+
"https://discord.com/api/webhooks/xxx"
|
|
294
|
+
]
|
|
295
|
+
config.webhook_timeout = 5
|
|
296
|
+
config.webhook_headers = { "Authorization" => "Bearer token" }
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
POST JSON to each URL on every new exception:
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"exception_class": "RuntimeError",
|
|
303
|
+
"controller_name": "users",
|
|
304
|
+
"action_name": "show",
|
|
305
|
+
"message": "Something went wrong",
|
|
306
|
+
"created_at": "2026-08-22T12:00:00Z",
|
|
307
|
+
"dashboard_url": "http://localhost:3000/rails_nexus/logged_exceptions/42"
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Telegram
|
|
312
|
+
|
|
313
|
+
Set `TELEGRAM_TOKEN` and `TELEGRAM_CHAT_ID` environment variables:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
export TELEGRAM_TOKEN="your-bot-token"
|
|
317
|
+
export TELEGRAM_CHAT_ID="your-chat-id"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Configure the notifier:
|
|
321
|
+
|
|
322
|
+
```ruby
|
|
323
|
+
config.after_create = lambda do |exception|
|
|
324
|
+
RailsNexus::TelegramNotifier.new.notify(exception)
|
|
325
|
+
end
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Rate limiting: 10-minute cooldown per exception class + controller combination.
|
|
329
|
+
|
|
330
|
+
## Cleanup / Retention
|
|
331
|
+
|
|
332
|
+
```ruby
|
|
333
|
+
config.retention_days = 90 # Auto-delete after 90 days
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Rake tasks:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
rake rails_nexus:cleanup # Delete exceptions older than retention_days
|
|
340
|
+
rake rails_nexus:stats # Show exception statistics
|
|
341
|
+
rake rails_nexus:tail # Tail JSON logs in real-time
|
|
342
|
+
rake rails_nexus:export # Export exceptions to JSON
|
|
343
|
+
rake rails_nexus:test_webhook # Test webhook configuration
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Frontend setup
|
|
347
|
+
|
|
348
|
+
### Hotwire (default)
|
|
349
|
+
|
|
350
|
+
RailsNexus includes `importmap-rails`, `turbo-rails`, and `stimulus-rails` as dependencies. Its namespaced importmap is automatically composed into the host application, so no frontend installation step is needed.
|
|
351
|
+
|
|
352
|
+
### Styling
|
|
353
|
+
|
|
354
|
+
RailsNexus ships with its own CSS (`rails_nexus/application.css`) that works out of the box with dark/light themes. The engine layout does not depend on the host application's stylesheet.
|
|
355
|
+
|
|
356
|
+
#### Tailwind CSS
|
|
357
|
+
|
|
358
|
+
If your app uses Tailwind, add the gem's views as a source:
|
|
359
|
+
|
|
360
|
+
```css
|
|
361
|
+
/* Tailwind v4 */
|
|
362
|
+
@import "tailwindcss";
|
|
363
|
+
@source "/path/to/rails_nexus/app/views";
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### Asset pipelines
|
|
367
|
+
|
|
368
|
+
The engine registers its JavaScript path and precompile assets automatically. Both Propshaft and Sprockets hosts can mount RailsNexus without changing the host asset manifest.
|
|
369
|
+
|
|
370
|
+
The entry point is `rails_nexus/application`; it does not replace or depend on the host app's `application` entry point. Turbo and Stimulus are served locally from their Rails gems rather than from a CDN.
|
|
371
|
+
|
|
372
|
+
### Stimulus controllers
|
|
373
|
+
|
|
374
|
+
Four controllers are included and registered by the engine's entry point:
|
|
375
|
+
|
|
376
|
+
| Controller | Registered as | Purpose |
|
|
377
|
+
|---|---|---|
|
|
378
|
+
| `rails_nexus_controller.js` | `rails_nexus` | Keyboard nav, search, tabs, copy, backtrace expand |
|
|
379
|
+
| `rails_nexus_detail_controller.js` | `rails_nexus-detail` | Exception detail interactions |
|
|
380
|
+
| `rails_nexus_sidebar_controller.js` | `rails_nexus-sidebar` | Mobile drawer toggle |
|
|
381
|
+
| `rails_nexus_theme_controller.js` | `rails_nexus-theme` | Dark/light/auto theme toggle |
|
|
382
|
+
|
|
383
|
+
## Data storage
|
|
384
|
+
|
|
385
|
+
The engine creates a `rails_nexus_exceptions` table with columns for exception class, controller/action, message, backtrace, request, environment, user information, user agent, remote IP, and timestamps.
|
|
386
|
+
|
|
387
|
+
Exception records can contain secrets. Apply your normal database encryption, retention, backup, and access-control policies.
|
|
388
|
+
|
|
389
|
+
## Generators
|
|
390
|
+
|
|
391
|
+
| Generator | Description |
|
|
392
|
+
|---|---|
|
|
393
|
+
| `rails generate rails_nexus:install` | Full setup (migration, initializer, routes) |
|
|
394
|
+
| `rails generate rails_nexus:install --modern` | Install + generate all customizations |
|
|
395
|
+
| `rails generate rails_nexus:customize` | Generate customizable views, layout, and JS |
|
|
396
|
+
| `rails generate rails_nexus:customize --layout-only` | Only the layout |
|
|
397
|
+
| `rails generate rails_nexus:customize --views-only` | Only the views |
|
|
398
|
+
| `rails generate rails_nexus:customize --stimulus-only` | Only the Stimulus controller |
|
|
399
|
+
|
|
400
|
+
## Development
|
|
401
|
+
|
|
402
|
+
Run the test suite:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
cd /path/to/rails_nexus
|
|
406
|
+
RAILS_ENV=test bundle exec rails test
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Build the gem:
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
gem build rails_nexus.gemspec
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
The repository includes a Rails dummy application under `test/dummy` for engine integration testing.
|
|
416
|
+
|
|
417
|
+
## Support
|
|
418
|
+
|
|
419
|
+
If you find RailsNexus useful, consider supporting the project:
|
|
420
|
+
|
|
421
|
+
- ⭐ **Star the repo** — Help others discover RailsNexus
|
|
422
|
+
- 🐛 **Report issues** — Help improve the gem
|
|
423
|
+
- 💡 **Contribute** — Submit pull requests
|
|
424
|
+
- 💰 **Sponsor** — [GitHub Sponsors](https://github.com/sponsors/tamiru)
|
|
425
|
+
|
|
426
|
+
Your support helps maintain and improve RailsNexus for the Rails community.
|
|
427
|
+
|
|
428
|
+
## License
|
|
429
|
+
|
|
430
|
+
RailsNexus is released under the [MIT License](MIT-LICENSE).
|
data/Rakefile
ADDED