rails_error_dashboard 0.1.23 → 0.1.24
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 +4 -4
- data/app/controllers/rails_error_dashboard/errors_controller.rb +18 -18
- data/app/helpers/rails_error_dashboard/application_helper.rb +11 -2
- data/app/models/rails_error_dashboard/application.rb +18 -8
- data/app/models/rails_error_dashboard/error_logs_record.rb +9 -10
- data/app/views/layouts/rails_error_dashboard.html.erb +6 -2
- data/app/views/rails_error_dashboard/errors/index.html.erb +1 -1
- data/db/migrate/20260106094233_add_application_to_error_logs.rb +2 -2
- data/lib/generators/rails_error_dashboard/install/install_generator.rb +10 -1
- data/lib/generators/rails_error_dashboard/install/templates/initializer.rb +6 -0
- data/lib/rails_error_dashboard/commands/log_error.rb +3 -3
- data/lib/rails_error_dashboard/engine.rb +14 -0
- data/lib/rails_error_dashboard/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ca536416dd8806b35ae7b3bda7aaad734d7d12f9af382db58db91ac8cfa3d3e
|
|
4
|
+
data.tar.gz: c015a441f1aea077f1cd742f008d1a5cc08749247e6e00714994a421c4a32e98
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f7e9246fd8327c6f6a7109e6c283cc42ae4eeaa85125b0eddf96f53128d7560acefac4303b2367d7d82fb07287ac05907f8929a58644bf41768702dc6120951
|
|
7
|
+
data.tar.gz: 6b952f9198afcfeb7d40b44a118d29303eb8bac87cc52ca0635c394c111b05ce94f877f56cb498b87c036519b90a0a692dc03b3aab155c1265588be8c72eca50
|
|
@@ -6,6 +6,23 @@ module RailsErrorDashboard
|
|
|
6
6
|
|
|
7
7
|
before_action :authenticate_dashboard_user!
|
|
8
8
|
|
|
9
|
+
FILTERABLE_PARAMS = %i[
|
|
10
|
+
error_type
|
|
11
|
+
unresolved
|
|
12
|
+
platform
|
|
13
|
+
application_id
|
|
14
|
+
search
|
|
15
|
+
severity
|
|
16
|
+
timeframe
|
|
17
|
+
frequency
|
|
18
|
+
status
|
|
19
|
+
assigned_to
|
|
20
|
+
priority_level
|
|
21
|
+
hide_snoozed
|
|
22
|
+
sort_by
|
|
23
|
+
sort_direction
|
|
24
|
+
].freeze
|
|
25
|
+
|
|
9
26
|
def overview
|
|
10
27
|
# Get dashboard stats using Query
|
|
11
28
|
@stats = Queries::DashboardStats.call
|
|
@@ -266,24 +283,7 @@ module RailsErrorDashboard
|
|
|
266
283
|
end
|
|
267
284
|
|
|
268
285
|
def filter_params
|
|
269
|
-
|
|
270
|
-
error_type: params[:error_type],
|
|
271
|
-
unresolved: params[:unresolved],
|
|
272
|
-
platform: params[:platform],
|
|
273
|
-
application_id: params[:application_id],
|
|
274
|
-
search: params[:search],
|
|
275
|
-
severity: params[:severity],
|
|
276
|
-
timeframe: params[:timeframe],
|
|
277
|
-
frequency: params[:frequency],
|
|
278
|
-
# Phase 3: Workflow filter params
|
|
279
|
-
status: params[:status],
|
|
280
|
-
assigned_to: params[:assigned_to],
|
|
281
|
-
priority_level: params[:priority_level],
|
|
282
|
-
hide_snoozed: params[:hide_snoozed],
|
|
283
|
-
# Sorting params
|
|
284
|
-
sort_by: params[:sort_by],
|
|
285
|
-
sort_direction: params[:sort_direction]
|
|
286
|
-
}
|
|
286
|
+
params.permit(*FILTERABLE_PARAMS).to_h.symbolize_keys
|
|
287
287
|
end
|
|
288
288
|
|
|
289
289
|
def authenticate_dashboard_user!
|
|
@@ -81,6 +81,15 @@ module RailsErrorDashboard
|
|
|
81
81
|
RailsErrorDashboard.configuration.dashboard_username || ENV["USER"] || "unknown"
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
# Returns a sanitized hash of filter params safe for query links
|
|
85
|
+
# @param extra_keys [Array<Symbol>] Additional permitted keys for specific contexts
|
|
86
|
+
# @return [Hash] Whitelisted params for building URLs
|
|
87
|
+
def permitted_filter_params(extra_keys: [])
|
|
88
|
+
base_keys = RailsErrorDashboard::ErrorsController::FILTERABLE_PARAMS + %i[page per_page days]
|
|
89
|
+
allowed_keys = base_keys + Array(extra_keys)
|
|
90
|
+
params.permit(*allowed_keys).to_h.symbolize_keys
|
|
91
|
+
end
|
|
92
|
+
|
|
84
93
|
# Generates a sortable column header link
|
|
85
94
|
# @param label [String] The column label to display
|
|
86
95
|
# @param column [String] The column name to sort by
|
|
@@ -103,8 +112,8 @@ module RailsErrorDashboard
|
|
|
103
112
|
"⇅" # Unsorted indicator
|
|
104
113
|
end
|
|
105
114
|
|
|
106
|
-
# Preserve
|
|
107
|
-
link_params =
|
|
115
|
+
# Preserve whitelisted filter params while adding sort params
|
|
116
|
+
link_params = permitted_filter_params.merge(sort_by: column, sort_direction: new_direction)
|
|
108
117
|
|
|
109
118
|
link_to errors_path(link_params), class: "text-decoration-none" do
|
|
110
119
|
content_tag(:span, "#{label} ", class: current_sort == column ? "fw-bold" : "") +
|
|
@@ -12,22 +12,32 @@ module RailsErrorDashboard
|
|
|
12
12
|
scope :ordered_by_name, -> { order(:name) }
|
|
13
13
|
|
|
14
14
|
# Class method for finding or creating with caching
|
|
15
|
-
#
|
|
15
|
+
# Caches application IDs (not objects) to avoid stale ActiveRecord references
|
|
16
|
+
# This is safer with transactional fixtures and database rollbacks
|
|
16
17
|
def self.find_or_create_by_name(name)
|
|
17
|
-
# Try to find in cache
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
# Try to find ID in cache
|
|
19
|
+
cached_id = Rails.cache.read("error_dashboard/application_id/#{name}")
|
|
20
|
+
if cached_id
|
|
21
|
+
# Verify the cached ID still exists in database
|
|
22
|
+
# (could have been deleted in tests with transactional rollback)
|
|
23
|
+
cached_record = find_by(id: cached_id)
|
|
24
|
+
return cached_record if cached_record
|
|
25
|
+
# Cache was stale, clear it
|
|
26
|
+
Rails.cache.delete("error_dashboard/application_id/#{name}")
|
|
27
|
+
end
|
|
20
28
|
|
|
21
|
-
# Try to find existing
|
|
29
|
+
# Try to find existing in database
|
|
22
30
|
found = find_by(name: name)
|
|
23
31
|
if found
|
|
24
|
-
|
|
32
|
+
# Cache the ID (not the object) for future lookups
|
|
33
|
+
Rails.cache.write("error_dashboard/application_id/#{name}", found.id, expires_in: 1.hour)
|
|
25
34
|
return found
|
|
26
35
|
end
|
|
27
36
|
|
|
28
|
-
# Create if not found
|
|
37
|
+
# Create if not found
|
|
29
38
|
created = create!(name: name)
|
|
30
|
-
|
|
39
|
+
# Cache the ID (not the object)
|
|
40
|
+
Rails.cache.write("error_dashboard/application_id/#{name}", created.id, expires_in: 1.hour)
|
|
31
41
|
created
|
|
32
42
|
end
|
|
33
43
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Abstract base class for models stored in the
|
|
3
|
+
# Abstract base class for models stored in the error dashboard database
|
|
4
4
|
#
|
|
5
5
|
# By default, this connects to the same database as the main application.
|
|
6
6
|
#
|
|
7
|
-
# To enable a separate error
|
|
7
|
+
# To enable a separate error dashboard database:
|
|
8
8
|
# 1. Set use_separate_database: true in the gem configuration
|
|
9
|
-
# 2.
|
|
10
|
-
# 3.
|
|
11
|
-
# 4. Run: rails db:
|
|
9
|
+
# 2. Set database: :error_dashboard (or your custom name) in the gem configuration
|
|
10
|
+
# 3. Configure error_dashboard settings in config/database.yml
|
|
11
|
+
# 4. Run: rails db:create
|
|
12
|
+
# 5. Run: rails db:migrate
|
|
12
13
|
#
|
|
13
14
|
# Benefits of separate database:
|
|
14
15
|
# - Performance isolation (error logging doesn't slow down user requests)
|
|
@@ -25,10 +26,8 @@ module RailsErrorDashboard
|
|
|
25
26
|
class ErrorLogsRecord < ActiveRecord::Base
|
|
26
27
|
self.abstract_class = true
|
|
27
28
|
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
connects_to database: { writing: :error_logs, reading: :error_logs }
|
|
32
|
-
end
|
|
29
|
+
# Database connection will be configured by the engine initializer
|
|
30
|
+
# after the user's configuration is loaded
|
|
31
|
+
# See lib/rails_error_dashboard/engine.rb
|
|
33
32
|
end
|
|
34
33
|
end
|
|
@@ -866,16 +866,20 @@
|
|
|
866
866
|
<% end %>
|
|
867
867
|
</button>
|
|
868
868
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="appSwitcher">
|
|
869
|
+
<%
|
|
870
|
+
base_route_params = request.path_parameters.slice(:controller, :action)
|
|
871
|
+
current_filter_params = permitted_filter_params
|
|
872
|
+
%>
|
|
869
873
|
<li>
|
|
870
874
|
<%= link_to "All Applications",
|
|
871
|
-
url_for(
|
|
875
|
+
url_for(base_route_params.merge(current_filter_params.except(:application_id))),
|
|
872
876
|
class: "dropdown-item #{'active' unless params[:application_id].present?}" %>
|
|
873
877
|
</li>
|
|
874
878
|
<li><hr class="dropdown-divider"></li>
|
|
875
879
|
<% @applications.each do |app_name, app_id| %>
|
|
876
880
|
<li>
|
|
877
881
|
<%= link_to app_name,
|
|
878
|
-
url_for(
|
|
882
|
+
url_for(base_route_params.merge(current_filter_params.merge(application_id: app_id))),
|
|
879
883
|
class: "dropdown-item #{params[:application_id].to_s == app_id.to_s ? 'active' : ''}" %>
|
|
880
884
|
</li>
|
|
881
885
|
<% end %>
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
<% active_filters.each do |filter| %>
|
|
159
159
|
<%
|
|
160
160
|
# Build URL without this specific filter
|
|
161
|
-
filter_params =
|
|
161
|
+
filter_params = permitted_filter_params.except(filter[:param])
|
|
162
162
|
%>
|
|
163
163
|
<%= link_to errors_path(filter_params), class: "badge bg-primary text-decoration-none filter-pill" do %>
|
|
164
164
|
<%= filter[:label] %>
|
|
@@ -7,11 +7,11 @@ class AddApplicationToErrorLogs < ActiveRecord::Migration[7.0]
|
|
|
7
7
|
add_index :rails_error_dashboard_error_logs, :application_id
|
|
8
8
|
|
|
9
9
|
add_index :rails_error_dashboard_error_logs,
|
|
10
|
-
[:application_id, :occurred_at],
|
|
10
|
+
[ :application_id, :occurred_at ],
|
|
11
11
|
name: 'index_error_logs_on_app_occurred'
|
|
12
12
|
|
|
13
13
|
add_index :rails_error_dashboard_error_logs,
|
|
14
|
-
[:application_id, :resolved],
|
|
14
|
+
[ :application_id, :resolved ],
|
|
15
15
|
name: 'index_error_logs_on_app_resolved'
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -18,6 +18,7 @@ module RailsErrorDashboard
|
|
|
18
18
|
class_option :async_logging, type: :boolean, default: false, desc: "Enable async error logging"
|
|
19
19
|
class_option :error_sampling, type: :boolean, default: false, desc: "Enable error sampling (reduce volume)"
|
|
20
20
|
class_option :separate_database, type: :boolean, default: false, desc: "Use separate database for errors"
|
|
21
|
+
class_option :database, type: :string, default: nil, desc: "Database name to use for errors (e.g., 'error_dashboard')"
|
|
21
22
|
# Advanced analytics options
|
|
22
23
|
class_option :baseline_alerts, type: :boolean, default: false, desc: "Enable baseline anomaly alerts"
|
|
23
24
|
class_option :similar_errors, type: :boolean, default: false, desc: "Enable fuzzy error matching"
|
|
@@ -185,6 +186,7 @@ module RailsErrorDashboard
|
|
|
185
186
|
@enable_async_logging = @selected_features&.dig(:async_logging) || options[:async_logging]
|
|
186
187
|
@enable_error_sampling = @selected_features&.dig(:error_sampling) || options[:error_sampling]
|
|
187
188
|
@enable_separate_database = @selected_features&.dig(:separate_database) || options[:separate_database]
|
|
189
|
+
@database_name = options[:database]
|
|
188
190
|
|
|
189
191
|
# Advanced Analytics
|
|
190
192
|
@enable_baseline_alerts = @selected_features&.dig(:baseline_alerts) || options[:baseline_alerts]
|
|
@@ -275,7 +277,14 @@ module RailsErrorDashboard
|
|
|
275
277
|
say " → Set PAGERDUTY_INTEGRATION_KEY in .env", :yellow if @enable_pagerduty
|
|
276
278
|
say " → Set WEBHOOK_URLS in .env", :yellow if @enable_webhooks
|
|
277
279
|
say " → Ensure Sidekiq/Solid Queue running", :yellow if @enable_async_logging
|
|
278
|
-
|
|
280
|
+
if @enable_separate_database
|
|
281
|
+
if @database_name
|
|
282
|
+
say " → Configure '#{@database_name}' database in database.yml", :yellow
|
|
283
|
+
else
|
|
284
|
+
say " → Configure database in database.yml and set config.database", :yellow
|
|
285
|
+
end
|
|
286
|
+
say " See docs/guides/DATABASE_OPTIONS.md for details", :yellow
|
|
287
|
+
end
|
|
279
288
|
|
|
280
289
|
say "\n"
|
|
281
290
|
say "Next Steps:", :cyan
|
|
@@ -153,6 +153,11 @@ RailsErrorDashboard.configure do |config|
|
|
|
153
153
|
# Errors will be stored in a dedicated database
|
|
154
154
|
# See docs/guides/DATABASE_OPTIONS.md for setup instructions
|
|
155
155
|
config.use_separate_database = true
|
|
156
|
+
<% if @database_name -%>
|
|
157
|
+
config.database = :<%= @database_name %>
|
|
158
|
+
<% else -%>
|
|
159
|
+
# config.database = :error_dashboard # Uncomment and set your database name
|
|
160
|
+
<% end -%>
|
|
156
161
|
# To disable: Set config.use_separate_database = false
|
|
157
162
|
|
|
158
163
|
<% else -%>
|
|
@@ -160,6 +165,7 @@ RailsErrorDashboard.configure do |config|
|
|
|
160
165
|
# Errors are stored in your main application database
|
|
161
166
|
# To enable: Set config.use_separate_database = true and configure database.yml
|
|
162
167
|
config.use_separate_database = false
|
|
168
|
+
# config.database = :error_dashboard # Database name when using separate database
|
|
163
169
|
|
|
164
170
|
<% end -%>
|
|
165
171
|
# ============================================================================
|
|
@@ -143,15 +143,15 @@ module RailsErrorDashboard
|
|
|
143
143
|
# Find or create application for multi-app support
|
|
144
144
|
def find_or_create_application
|
|
145
145
|
app_name = RailsErrorDashboard.configuration.application_name ||
|
|
146
|
-
ENV[
|
|
146
|
+
ENV["APPLICATION_NAME"] ||
|
|
147
147
|
(defined?(Rails) && Rails.application.class.module_parent_name) ||
|
|
148
|
-
|
|
148
|
+
"Rails Application"
|
|
149
149
|
|
|
150
150
|
Application.find_or_create_by_name(app_name)
|
|
151
151
|
rescue => e
|
|
152
152
|
RailsErrorDashboard::Logger.error("[RailsErrorDashboard] Failed to find/create application: #{e.message}")
|
|
153
153
|
# Fallback: try to find any application or create default
|
|
154
|
-
Application.first || Application.create!(name:
|
|
154
|
+
Application.first || Application.create!(name: "Default Application")
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
# Trigger notification callbacks for error logging
|
|
@@ -2,6 +2,20 @@ module RailsErrorDashboard
|
|
|
2
2
|
class Engine < ::Rails::Engine
|
|
3
3
|
isolate_namespace RailsErrorDashboard
|
|
4
4
|
|
|
5
|
+
# Configure database connection for error models
|
|
6
|
+
# This runs early, before middleware setup, but after database.yml is loaded
|
|
7
|
+
initializer "rails_error_dashboard.database", before: :load_config_initializers do
|
|
8
|
+
config.after_initialize do
|
|
9
|
+
if RailsErrorDashboard.configuration&.use_separate_database
|
|
10
|
+
database_name = RailsErrorDashboard.configuration&.database || :error_dashboard
|
|
11
|
+
|
|
12
|
+
RailsErrorDashboard::ErrorLogsRecord.connects_to(
|
|
13
|
+
database: { writing: database_name, reading: database_name }
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
5
19
|
# Initialize the engine
|
|
6
20
|
initializer "rails_error_dashboard.middleware" do |app|
|
|
7
21
|
# Enable Flash middleware for Error Dashboard routes in API-only apps
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_error_dashboard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.24
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anjan Jagirdar
|
|
@@ -83,16 +83,16 @@ dependencies:
|
|
|
83
83
|
name: httparty
|
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
|
-
- - "
|
|
86
|
+
- - ">="
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version:
|
|
88
|
+
version: 0.24.0
|
|
89
89
|
type: :runtime
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
|
-
- - "
|
|
93
|
+
- - ">="
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version:
|
|
95
|
+
version: 0.24.0
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: turbo-rails
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -386,7 +386,7 @@ metadata:
|
|
|
386
386
|
source_code_uri: https://github.com/AnjanJ/rails_error_dashboard
|
|
387
387
|
changelog_uri: https://github.com/AnjanJ/rails_error_dashboard/blob/main/CHANGELOG.md
|
|
388
388
|
post_install_message: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n
|
|
389
|
-
\ Rails Error Dashboard v0.1.
|
|
389
|
+
\ Rails Error Dashboard v0.1.24\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
|
|
390
390
|
First time? Quick start:\n rails generate rails_error_dashboard:install\n rails
|
|
391
391
|
db:migrate\n # Add to config/routes.rb:\n mount RailsErrorDashboard::Engine
|
|
392
392
|
=> '/error_dashboard'\n\n\U0001F504 Upgrading from v0.1.x?\n rails db:migrate\n
|