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.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +430 -0
  4. data/Rakefile +6 -0
  5. data/app/assets/config/rails_nexus_manifest.js +2 -0
  6. data/app/assets/javascripts/rails_nexus/controllers.js +603 -0
  7. data/app/assets/stylesheets/rails_nexus/application.css +1964 -0
  8. data/app/controllers/rails_nexus/analytics_controller.rb +361 -0
  9. data/app/controllers/rails_nexus/application_controller.rb +15 -0
  10. data/app/controllers/rails_nexus/backup_controller.rb +91 -0
  11. data/app/controllers/rails_nexus/cron_jobs_controller.rb +64 -0
  12. data/app/controllers/rails_nexus/database_health_controller.rb +128 -0
  13. data/app/controllers/rails_nexus/logged_exceptions_controller.rb +227 -0
  14. data/app/controllers/rails_nexus/n1_patterns_controller.rb +10 -0
  15. data/app/controllers/rails_nexus/settings_controller.rb +100 -0
  16. data/app/controllers/rails_nexus/source_code_controller.rb +39 -0
  17. data/app/controllers/rails_nexus/stats_controller.rb +494 -0
  18. data/app/controllers/rails_nexus/workflow_controller.rb +96 -0
  19. data/app/helpers/rails_nexus/application_helper.rb +5 -0
  20. data/app/helpers/rails_nexus/logged_exceptions_helper.rb +254 -0
  21. data/app/helpers/rails_nexus/source_code_helper.rb +107 -0
  22. data/app/javascript/controllers/rails_nexus_controller.js +380 -0
  23. data/app/javascript/controllers/rails_nexus_detail_controller.js +165 -0
  24. data/app/javascript/controllers/rails_nexus_sidebar_controller.js +15 -0
  25. data/app/javascript/controllers/rails_nexus_theme_controller.js +31 -0
  26. data/app/javascript/rails_nexus/application.js +17 -0
  27. data/app/jobs/rails_nexus/application_job.rb +4 -0
  28. data/app/mailers/rails_nexus/application_mailer.rb +6 -0
  29. data/app/models/rails_nexus/application_record.rb +5 -0
  30. data/app/models/rails_nexus/backup.rb +107 -0
  31. data/app/models/rails_nexus/base_record.rb +26 -0
  32. data/app/models/rails_nexus/comment.rb +13 -0
  33. data/app/models/rails_nexus/cron_job.rb +72 -0
  34. data/app/models/rails_nexus/database_stat.rb +128 -0
  35. data/app/models/rails_nexus/event.rb +101 -0
  36. data/app/models/rails_nexus/logged_exception.rb +864 -0
  37. data/app/models/rails_nexus/logged_exception_n1.rb +87 -0
  38. data/app/models/rails_nexus/metric.rb +107 -0
  39. data/app/models/rails_nexus/nginx_metric.rb +112 -0
  40. data/app/models/rails_nexus/server_metric.rb +168 -0
  41. data/app/models/rails_nexus/webhook_delivery.rb +64 -0
  42. data/app/services/rails_nexus/backup_service.rb +275 -0
  43. data/app/views/layouts/rails_nexus/application.html.erb +185 -0
  44. data/app/views/rails_nexus/analytics/index.html.erb +363 -0
  45. data/app/views/rails_nexus/backup/files.html.erb +53 -0
  46. data/app/views/rails_nexus/backup/index.html.erb +211 -0
  47. data/app/views/rails_nexus/backup/settings.html.erb +158 -0
  48. data/app/views/rails_nexus/cron_jobs/index.html.erb +141 -0
  49. data/app/views/rails_nexus/database_health/index.html.erb +139 -0
  50. data/app/views/rails_nexus/logged_exceptions/_comments_list.html.erb +50 -0
  51. data/app/views/rails_nexus/logged_exceptions/_exceptions.html.erb +190 -0
  52. data/app/views/rails_nexus/logged_exceptions/_feed.html.erb +3 -0
  53. data/app/views/rails_nexus/logged_exceptions/_filter_group.html.erb +10 -0
  54. data/app/views/rails_nexus/logged_exceptions/_show.html.erb +554 -0
  55. data/app/views/rails_nexus/logged_exceptions/_workflow_panel.html.erb +118 -0
  56. data/app/views/rails_nexus/logged_exceptions/clear.turbo_stream.erb +6 -0
  57. data/app/views/rails_nexus/logged_exceptions/destroy.turbo_stream.erb +2 -0
  58. data/app/views/rails_nexus/logged_exceptions/destroy_all.turbo_stream.erb +6 -0
  59. data/app/views/rails_nexus/logged_exceptions/feed.rss.builder +20 -0
  60. data/app/views/rails_nexus/logged_exceptions/index.html.erb +323 -0
  61. data/app/views/rails_nexus/logged_exceptions/query.html.erb +3 -0
  62. data/app/views/rails_nexus/logged_exceptions/query.turbo_stream.erb +6 -0
  63. data/app/views/rails_nexus/logged_exceptions/show.html.erb +3 -0
  64. data/app/views/rails_nexus/logged_exceptions/show.turbo_stream.erb +5 -0
  65. data/app/views/rails_nexus/n1_patterns/index.html.erb +153 -0
  66. data/app/views/rails_nexus/settings/index.html.erb +140 -0
  67. data/app/views/rails_nexus/stats/index.html.erb +569 -0
  68. data/config/importmap.rb +15 -0
  69. data/config/initializers/date_formats.rb +5 -0
  70. data/config/initializers/rails_nexus.rb +18 -0
  71. data/config/locales/en.yml +47 -0
  72. data/config/routes.rb +58 -0
  73. data/db/migrate/20240330122311_create_rails_nexus_logged_exceptions.rb +22 -0
  74. data/lib/generators/rails_nexus/backup_generator.rb +70 -0
  75. data/lib/generators/rails_nexus/customize_generator.rb +159 -0
  76. data/lib/generators/rails_nexus/install_generator.rb +61 -0
  77. data/lib/generators/rails_nexus/templates/INSTALL.md +9 -0
  78. data/lib/generators/rails_nexus/templates/backup/backup_helper.sh +152 -0
  79. data/lib/generators/rails_nexus/templates/backup/config.rb +27 -0
  80. data/lib/generators/rails_nexus/templates/backup/models/daily_backup.rb +24 -0
  81. data/lib/generators/rails_nexus/templates/backup/models/full_backup.rb +35 -0
  82. data/lib/generators/rails_nexus/templates/backup/models/sync_backup.rb +43 -0
  83. data/lib/generators/rails_nexus/templates/backup/mysql-config/db_config.cnf +15 -0
  84. data/lib/generators/rails_nexus/templates/backup/schedule.rb +28 -0
  85. data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_controller.js +310 -0
  86. data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_detail_controller.js +98 -0
  87. data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_sidebar_controller.js +15 -0
  88. data/lib/generators/rails_nexus/templates/javascript/controllers/rails_nexus_theme_controller.js +30 -0
  89. data/lib/generators/rails_nexus/templates/migration.rb +24 -0
  90. data/lib/generators/rails_nexus/templates/migration_advanced_features.rb +30 -0
  91. data/lib/generators/rails_nexus/templates/migration_cron_jobs.rb +22 -0
  92. data/lib/generators/rails_nexus/templates/migration_new_schema.rb +120 -0
  93. data/lib/generators/rails_nexus/templates/migration_platform_detection.rb +11 -0
  94. data/lib/generators/rails_nexus/templates/migration_webhook_deliveries.rb +21 -0
  95. data/lib/generators/rails_nexus/templates/migration_workflow.rb +29 -0
  96. data/lib/generators/rails_nexus/templates/rails_nexus.rb +96 -0
  97. data/lib/generators/rails_nexus/templates/views/layouts/rails_nexus/application.html.erb +129 -0
  98. data/lib/generators/rails_nexus/templates/views/rails_nexus/logged_exceptions/_exceptions.html.erb +123 -0
  99. data/lib/generators/rails_nexus/templates/views/rails_nexus/logged_exceptions/_show.html.erb +297 -0
  100. data/lib/generators/rails_nexus/templates/views/rails_nexus/logged_exceptions/index.html.erb +113 -0
  101. data/lib/rails_nexus/breadcrumbs.rb +161 -0
  102. data/lib/rails_nexus/cleanup.rb +32 -0
  103. data/lib/rails_nexus/configuration.rb +319 -0
  104. data/lib/rails_nexus/engine.rb +135 -0
  105. data/lib/rails_nexus/logger.rb +188 -0
  106. data/lib/rails_nexus/notifications.rb +105 -0
  107. data/lib/rails_nexus/ransack_config.rb +4 -0
  108. data/lib/rails_nexus/storm_protection.rb +124 -0
  109. data/lib/rails_nexus/version.rb +3 -0
  110. data/lib/rails_nexus.rb +133 -0
  111. data/lib/tasks/rails_nexus.rake +230 -0
  112. data/lib/tasks/rails_nexus_tasks.rake +37 -0
  113. data/rails_nexus.gemspec +36 -0
  114. 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
+ [![Gem Version](https://badge.fury.io/rb/rails_nexus.svg)](https://rubygems.org/gems/rails_nexus)
6
+ [![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-ea4aaa)](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
@@ -0,0 +1,6 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ require "bundler/gem_tasks"
@@ -0,0 +1,2 @@
1
+ //= link_directory ../stylesheets/rails_nexus .css
2
+ //= link_directory ../javascripts/rails_nexus .js