railscope 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.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +227 -0
  5. data/Rakefile +12 -0
  6. data/app/assets/stylesheets/railscope/application.css +504 -0
  7. data/app/controllers/railscope/api/entries_controller.rb +103 -0
  8. data/app/controllers/railscope/application_controller.rb +12 -0
  9. data/app/controllers/railscope/dashboard_controller.rb +33 -0
  10. data/app/controllers/railscope/entries_controller.rb +29 -0
  11. data/app/helpers/railscope/dashboard_helper.rb +157 -0
  12. data/app/jobs/railscope/application_job.rb +6 -0
  13. data/app/jobs/railscope/purge_job.rb +15 -0
  14. data/app/models/railscope/application_record.rb +12 -0
  15. data/app/models/railscope/entry.rb +51 -0
  16. data/app/views/layouts/railscope/application.html.erb +14 -0
  17. data/app/views/railscope/application/index.html.erb +1 -0
  18. data/app/views/railscope/dashboard/index.html.erb +70 -0
  19. data/app/views/railscope/entries/show.html.erb +93 -0
  20. data/client/.gitignore +1 -0
  21. data/client/index.html +12 -0
  22. data/client/package-lock.json +2735 -0
  23. data/client/package.json +28 -0
  24. data/client/postcss.config.js +6 -0
  25. data/client/src/App.tsx +60 -0
  26. data/client/src/api/client.ts +25 -0
  27. data/client/src/api/entries.ts +36 -0
  28. data/client/src/components/Layout.tsx +17 -0
  29. data/client/src/components/PlaceholderPage.tsx +32 -0
  30. data/client/src/components/Sidebar.tsx +198 -0
  31. data/client/src/components/ui/Badge.tsx +67 -0
  32. data/client/src/components/ui/Card.tsx +38 -0
  33. data/client/src/components/ui/JsonViewer.tsx +80 -0
  34. data/client/src/components/ui/Pagination.tsx +45 -0
  35. data/client/src/components/ui/SearchInput.tsx +70 -0
  36. data/client/src/components/ui/Table.tsx +68 -0
  37. data/client/src/index.css +28 -0
  38. data/client/src/lib/hooks.ts +37 -0
  39. data/client/src/lib/types.ts +61 -0
  40. data/client/src/lib/utils.ts +38 -0
  41. data/client/src/main.tsx +13 -0
  42. data/client/src/screens/cache/Index.tsx +15 -0
  43. data/client/src/screens/client-requests/Index.tsx +15 -0
  44. data/client/src/screens/commands/Index.tsx +133 -0
  45. data/client/src/screens/commands/Show.tsx +395 -0
  46. data/client/src/screens/dumps/Index.tsx +15 -0
  47. data/client/src/screens/events/Index.tsx +15 -0
  48. data/client/src/screens/exceptions/Index.tsx +155 -0
  49. data/client/src/screens/exceptions/Show.tsx +480 -0
  50. data/client/src/screens/gates/Index.tsx +15 -0
  51. data/client/src/screens/jobs/Index.tsx +153 -0
  52. data/client/src/screens/jobs/Show.tsx +529 -0
  53. data/client/src/screens/logs/Index.tsx +15 -0
  54. data/client/src/screens/mail/Index.tsx +15 -0
  55. data/client/src/screens/models/Index.tsx +15 -0
  56. data/client/src/screens/notifications/Index.tsx +15 -0
  57. data/client/src/screens/queries/Index.tsx +159 -0
  58. data/client/src/screens/queries/Show.tsx +346 -0
  59. data/client/src/screens/redis/Index.tsx +15 -0
  60. data/client/src/screens/requests/Index.tsx +123 -0
  61. data/client/src/screens/requests/Show.tsx +395 -0
  62. data/client/src/screens/schedule/Index.tsx +15 -0
  63. data/client/src/screens/views/Index.tsx +141 -0
  64. data/client/src/screens/views/Show.tsx +337 -0
  65. data/client/tailwind.config.js +22 -0
  66. data/client/tsconfig.json +25 -0
  67. data/client/tsconfig.node.json +10 -0
  68. data/client/vite.config.ts +37 -0
  69. data/config/routes.rb +17 -0
  70. data/db/migrate/20260131023242_create_railscope_entries.rb +41 -0
  71. data/lib/generators/railscope/install_generator.rb +33 -0
  72. data/lib/generators/railscope/templates/initializer.rb +34 -0
  73. data/lib/railscope/context.rb +91 -0
  74. data/lib/railscope/engine.rb +85 -0
  75. data/lib/railscope/entry_data.rb +112 -0
  76. data/lib/railscope/filter.rb +113 -0
  77. data/lib/railscope/middleware.rb +162 -0
  78. data/lib/railscope/storage/base.rb +90 -0
  79. data/lib/railscope/storage/database.rb +83 -0
  80. data/lib/railscope/storage/redis_storage.rb +314 -0
  81. data/lib/railscope/subscribers/base_subscriber.rb +52 -0
  82. data/lib/railscope/subscribers/command_subscriber.rb +237 -0
  83. data/lib/railscope/subscribers/exception_subscriber.rb +113 -0
  84. data/lib/railscope/subscribers/job_subscriber.rb +249 -0
  85. data/lib/railscope/subscribers/query_subscriber.rb +130 -0
  86. data/lib/railscope/subscribers/request_subscriber.rb +121 -0
  87. data/lib/railscope/subscribers/view_subscriber.rb +201 -0
  88. data/lib/railscope/version.rb +5 -0
  89. data/lib/railscope.rb +145 -0
  90. data/lib/tasks/railscope_sample.rake +30 -0
  91. data/public/railscope/assets/app.css +1 -0
  92. data/public/railscope/assets/app.js +70 -0
  93. data/public/railscope/assets/index.html +13 -0
  94. data/sig/railscope.rbs +4 -0
  95. metadata +157 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 20e48ad7fe43ee5328e378275905e48d2143baa04911db450d21e1d15e1003db
4
+ data.tar.gz: 4b38dabf84090b06b4b8df241501a1d8cc8efb4186352e4e4146be07cc8b94e1
5
+ SHA512:
6
+ metadata.gz: '09038c22c62ec87672ce438011f9e1e6daea7e3528edba9deae60a3c962330124dcf74ea928b93b4bd1d909876c1b55c9f225f3fb37c93cd56a2e909a469fdb1'
7
+ data.tar.gz: 002a7e89bd8c83bcd79287c6dbe17ba55e15cceebcb126d00f7b1030714061244b54147429d22301d6ba7c6d683e00aea913b3b4cc85c4147b1e9f16ba474ff3
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2026-01-30
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Phelipe Tussolini
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # Railscope
2
+
3
+ An elegant debug assistant for Rails applications. Inspired by [Laravel Telescope](https://laravel.com/docs/telescope).
4
+
5
+ Railscope provides insight into the requests, exceptions, database queries, jobs, and more coming into your application. It's an essential companion during local development and a powerful debugging tool in production.
6
+
7
+ ## Features
8
+
9
+ - **Request Monitoring** - Track all HTTP requests with timing, status, and parameters
10
+ - **Query Logging** - Capture SQL queries with execution time and identify slow queries
11
+ - **Exception Tracking** - Log unhandled exceptions with full stack traces
12
+ - **Job Monitoring** - Monitor background jobs (enqueue and perform)
13
+ - **Context Correlation** - Link all events from the same request via `request_id`
14
+ - **Sensitive Data Filtering** - Automatic masking of passwords, tokens, and secrets
15
+ - **Dark Mode UI** - Beautiful GitHub-inspired dark interface
16
+ - **Zero Dependencies** - Works with any Rails 7+ application
17
+
18
+ ## Installation
19
+
20
+ Add to your Gemfile:
21
+
22
+ ```ruby
23
+ gem "railscope", path: "railscope" # or from git/rubygems
24
+ ```
25
+
26
+ Then run:
27
+
28
+ ```bash
29
+ bundle install
30
+ rails db:migrate
31
+ ```
32
+
33
+ Mount the engine in `config/routes.rb`:
34
+
35
+ ```ruby
36
+ Rails.application.routes.draw do
37
+ mount Railscope::Engine, at: "/railscope"
38
+ end
39
+ ```
40
+
41
+ ## Configuration
42
+
43
+ ### Enable Railscope
44
+
45
+ Railscope only runs when explicitly enabled via environment variable:
46
+
47
+ ```bash
48
+ # .env or environment
49
+ RAILSCOPE_ENABLED=true
50
+ ```
51
+
52
+ ### Full Configuration
53
+
54
+ Create `config/initializers/railscope.rb`:
55
+
56
+ ```ruby
57
+ Railscope.configure do |config|
58
+ # Data retention (default: 7 days)
59
+ config.retention_days = 30
60
+
61
+ # Paths to ignore (defaults: /railscope, /assets, /packs, /cable)
62
+ config.add_ignore_paths("/health", "/ping", "/metrics")
63
+
64
+ # Additional sensitive keys to filter
65
+ config.add_sensitive_keys(:cpf, :ssn, :bank_account)
66
+ end
67
+ ```
68
+
69
+ ### Environment Variables
70
+
71
+ | Variable | Description | Default |
72
+ |----------|-------------|---------|
73
+ | `RAILSCOPE_ENABLED` | Enable/disable recording | `false` |
74
+ | `RAILSCOPE_RETENTION_DAYS` | Days to keep entries | `7` |
75
+
76
+ ## Authorization
77
+
78
+ Protect the dashboard in production using Rails routing constraints:
79
+
80
+ ```ruby
81
+ # With Devise
82
+ authenticate :user, ->(u) { u.admin? } do
83
+ mount Railscope::Engine, at: "/railscope"
84
+ end
85
+
86
+ # With HTTP Basic Auth
87
+ Railscope::Engine.middleware.use(Rack::Auth::Basic) do |user, pass|
88
+ ActiveSupport::SecurityUtils.secure_compare(user, ENV["RAILSCOPE_USER"]) &
89
+ ActiveSupport::SecurityUtils.secure_compare(pass, ENV["RAILSCOPE_PASSWORD"])
90
+ end
91
+ mount Railscope::Engine, at: "/railscope"
92
+
93
+ # Development only
94
+ mount Railscope::Engine, at: "/railscope" if Rails.env.development?
95
+ ```
96
+
97
+ ## Usage
98
+
99
+ ### Dashboard
100
+
101
+ Access the dashboard at `/railscope` to view:
102
+
103
+ - All recorded entries with filtering by type
104
+ - Click any entry for detailed view
105
+ - Timeline showing related events from the same request
106
+ - Full payload inspection with JSON viewer
107
+
108
+ ### Entry Types
109
+
110
+ | Type | Description |
111
+ |------|-------------|
112
+ | `request` | HTTP requests with path, method, status, duration |
113
+ | `query` | SQL queries with execution time |
114
+ | `exception` | Unhandled exceptions with backtrace |
115
+ | `job_enqueue` | Background jobs when enqueued |
116
+ | `job_perform` | Background jobs when executed |
117
+
118
+ ### Adding Context
119
+
120
+ Add custom context during a request:
121
+
122
+ ```ruby
123
+ class ApplicationController < ActionController::Base
124
+ before_action :set_railscope_context
125
+
126
+ private
127
+
128
+ def set_railscope_context
129
+ return unless Railscope.enabled?
130
+
131
+ Railscope.context.user_id = current_user&.id
132
+ Railscope.context.add_tag("api_v2") if request.path.start_with?("/api/v2")
133
+ Railscope.context[:tenant_id] = current_tenant&.id
134
+ end
135
+ end
136
+ ```
137
+
138
+ ### Automatic Tags
139
+
140
+ Entries are automatically tagged:
141
+
142
+ - **Requests**: `request`, method (`get`, `post`), `error` (4xx/5xx), `slow` (>1s)
143
+ - **Queries**: `query`, type (`select`, `insert`, `update`, `delete`), `cached`, `slow` (>100ms)
144
+ - **Exceptions**: `exception`, exception class name
145
+ - **Jobs**: `job`, `enqueue`/`perform`, queue name, `failed`
146
+
147
+ ### Purging Old Entries
148
+
149
+ Run the purge job to remove entries older than `retention_days`:
150
+
151
+ ```ruby
152
+ # Manually
153
+ Railscope::PurgeJob.perform_now
154
+
155
+ # Schedule with your job scheduler (sidekiq-cron, solid_queue, etc.)
156
+ Railscope::PurgeJob.perform_later
157
+ ```
158
+
159
+ ## Filtered Parameters
160
+
161
+ Railscope automatically filters sensitive data:
162
+
163
+ **Default filtered keys:**
164
+ - `password`, `password_confirmation`
165
+ - `secret`, `token`, `api_key`
166
+ - `access_token`, `refresh_token`
167
+ - `authorization`, `credential`
168
+ - `credit_card`, `cvv`, `ssn`
169
+ - All keys from `Rails.application.config.filter_parameters`
170
+
171
+ **Auto-detected patterns:**
172
+ - Bearer tokens
173
+ - JWT tokens
174
+ - Base64 encoded secrets (40+ chars)
175
+
176
+ ## API
177
+
178
+ ### Check if enabled
179
+
180
+ ```ruby
181
+ Railscope.enabled? # => true/false
182
+ ```
183
+
184
+ ### Access current context
185
+
186
+ ```ruby
187
+ Railscope.context.request_id # Current request UUID
188
+ Railscope.context.user_id # Set user ID
189
+ Railscope.context.add_tag(tag) # Add custom tag
190
+ Railscope.context[:custom] # Custom attributes
191
+ ```
192
+
193
+ ### Query entries
194
+
195
+ ```ruby
196
+ # By type
197
+ Railscope::Entry.by_type("request")
198
+ Railscope::Entry.by_type("exception")
199
+
200
+ # By tag
201
+ Railscope::Entry.with_tag("slow")
202
+ Railscope::Entry.with_tag("error")
203
+
204
+ # Recent entries
205
+ Railscope::Entry.recent.limit(10)
206
+
207
+ # Expired entries (for cleanup)
208
+ Railscope::Entry.expired
209
+ ```
210
+
211
+ ## Performance
212
+
213
+ Railscope is designed to have minimal impact:
214
+
215
+ - Events are recorded synchronously but quickly
216
+ - Ignored paths skip all processing
217
+ - Sensitive data filtering is done once before save
218
+ - Purge job removes old entries to control database size
219
+
220
+ For high-traffic production environments, consider:
221
+ - Shorter retention periods
222
+ - Adding high-traffic paths to ignore list
223
+ - Running purge job more frequently
224
+
225
+ ## License
226
+
227
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]