rails_error_dashboard 0.8.3 → 0.9.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 +4 -4
- data/README.md +35 -0
- data/app/controllers/rails_error_dashboard/application_controller.rb +156 -0
- data/app/controllers/rails_error_dashboard/errors_controller.rb +95 -73
- data/app/controllers/rails_error_dashboard/locales_controller.rb +87 -0
- data/app/helpers/rails_error_dashboard/application_helper.rb +20 -14
- data/app/helpers/rails_error_dashboard/backtrace_helper.rb +15 -6
- data/app/helpers/rails_error_dashboard/i18n_helper.rb +154 -0
- data/app/helpers/rails_error_dashboard/mailer_i18n_helper.rb +69 -0
- data/app/helpers/rails_error_dashboard/overview_helper.rb +18 -6
- data/app/helpers/rails_error_dashboard/user_agent_helper.rb +25 -11
- data/app/jobs/rails_error_dashboard/application_job.rb +5 -0
- data/app/jobs/rails_error_dashboard/baseline_alert_job.rb +18 -16
- data/app/jobs/rails_error_dashboard/concerns/localized_job.rb +83 -0
- data/app/jobs/rails_error_dashboard/discord_error_notification_job.rb +4 -2
- data/app/jobs/rails_error_dashboard/email_error_notification_job.rb +4 -2
- data/app/jobs/rails_error_dashboard/pagerduty_error_notification_job.rb +6 -2
- data/app/jobs/rails_error_dashboard/scheduled_digest_job.rb +8 -3
- data/app/jobs/rails_error_dashboard/slack_error_notification_job.rb +6 -4
- data/app/jobs/rails_error_dashboard/storm_notification_job.rb +26 -8
- data/app/jobs/rails_error_dashboard/webhook_error_notification_job.rb +4 -2
- data/app/mailers/rails_error_dashboard/application_mailer.rb +14 -0
- data/app/mailers/rails_error_dashboard/digest_mailer.rb +18 -2
- data/app/mailers/rails_error_dashboard/error_notification_mailer.rb +19 -2
- data/app/views/layouts/rails_error_dashboard.html.erb +255 -92
- data/app/views/rails_error_dashboard/digest_mailer/digest_summary.html.erb +23 -22
- data/app/views/rails_error_dashboard/digest_mailer/digest_summary.text.erb +30 -19
- data/app/views/rails_error_dashboard/error_notification_mailer/error_alert.html.erb +18 -16
- data/app/views/rails_error_dashboard/error_notification_mailer/error_alert.text.erb +21 -14
- data/app/views/rails_error_dashboard/errors/_ai_help_panel.html.erb +11 -7
- data/app/views/rails_error_dashboard/errors/_breadcrumbs_group.html.erb +45 -38
- data/app/views/rails_error_dashboard/errors/_co_occurring_errors.html.erb +17 -14
- data/app/views/rails_error_dashboard/errors/_discussion.html.erb +27 -9
- data/app/views/rails_error_dashboard/errors/_error_cascades.html.erb +25 -21
- data/app/views/rails_error_dashboard/errors/_error_info.html.erb +25 -22
- data/app/views/rails_error_dashboard/errors/_error_row.html.erb +24 -12
- data/app/views/rails_error_dashboard/errors/_instance_variables.html.erb +12 -11
- data/app/views/rails_error_dashboard/errors/_issue_section.html.erb +19 -13
- data/app/views/rails_error_dashboard/errors/_llm_summary.html.erb +14 -14
- data/app/views/rails_error_dashboard/errors/_local_variables.html.erb +8 -8
- data/app/views/rails_error_dashboard/errors/_modals.html.erb +60 -52
- data/app/views/rails_error_dashboard/errors/_pattern_insights.html.erb +59 -49
- data/app/views/rails_error_dashboard/errors/_request_context.html.erb +23 -20
- data/app/views/rails_error_dashboard/errors/_show_scripts.html.erb +14 -14
- data/app/views/rails_error_dashboard/errors/_sidebar_metadata.html.erb +118 -93
- data/app/views/rails_error_dashboard/errors/_similar_errors.html.erb +18 -12
- data/app/views/rails_error_dashboard/errors/_source_code.html.erb +20 -5
- data/app/views/rails_error_dashboard/errors/_stats.html.erb +5 -5
- data/app/views/rails_error_dashboard/errors/_timeline.html.erb +7 -7
- data/app/views/rails_error_dashboard/errors/_user_errors_table.html.erb +15 -12
- data/app/views/rails_error_dashboard/errors/actioncable_health_summary.html.erb +25 -25
- data/app/views/rails_error_dashboard/errors/activestorage_health_summary.html.erb +28 -28
- data/app/views/rails_error_dashboard/errors/analytics.html.erb +82 -82
- data/app/views/rails_error_dashboard/errors/cache_health_summary.html.erb +27 -27
- data/app/views/rails_error_dashboard/errors/correlation.html.erb +61 -57
- data/app/views/rails_error_dashboard/errors/database_health_summary.html.erb +64 -65
- data/app/views/rails_error_dashboard/errors/deprecations.html.erb +23 -23
- data/app/views/rails_error_dashboard/errors/diagnostic_dumps.html.erb +48 -36
- data/app/views/rails_error_dashboard/errors/index.html.erb +121 -70
- data/app/views/rails_error_dashboard/errors/job_health_summary.html.erb +30 -30
- data/app/views/rails_error_dashboard/errors/llm_health_summary.html.erb +38 -39
- data/app/views/rails_error_dashboard/errors/n_plus_one_summary.html.erb +28 -25
- data/app/views/rails_error_dashboard/errors/overview.html.erb +45 -39
- data/app/views/rails_error_dashboard/errors/platform_comparison.html.erb +45 -44
- data/app/views/rails_error_dashboard/errors/rack_attack_summary.html.erb +39 -28
- data/app/views/rails_error_dashboard/errors/releases.html.erb +46 -47
- data/app/views/rails_error_dashboard/errors/settings/_value_badge.html.erb +48 -44
- data/app/views/rails_error_dashboard/errors/settings.html.erb +122 -112
- data/app/views/rails_error_dashboard/errors/show.html.erb +44 -37
- data/app/views/rails_error_dashboard/errors/storms.html.erb +30 -24
- data/app/views/rails_error_dashboard/errors/swallowed_exceptions.html.erb +26 -26
- data/app/views/rails_error_dashboard/errors/user_impact.html.erb +31 -30
- data/config/locales/de.yml +2007 -0
- data/config/locales/en.yml +2719 -0
- data/config/locales/es.yml +2079 -0
- data/config/locales/fr.yml +2082 -0
- data/config/locales/it.yml +2060 -0
- data/config/locales/ja.yml +1802 -0
- data/config/locales/pl.yml +2108 -0
- data/config/locales/pt-BR.yml +2064 -0
- data/config/locales/ru.yml +2109 -0
- data/config/locales/uk.yml +2106 -0
- data/config/locales/zh-CN.yml +1791 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20260325000001_fix_swallowed_exceptions_index_for_mysql.rb +9 -3
- data/lib/rails_error_dashboard/commands/batch_delete_errors.rb +3 -1
- data/lib/rails_error_dashboard/commands/batch_mute_errors.rb +4 -2
- data/lib/rails_error_dashboard/commands/batch_resolve_errors.rb +4 -2
- data/lib/rails_error_dashboard/commands/batch_unmute_errors.rb +4 -2
- data/lib/rails_error_dashboard/commands/create_issue.rb +5 -3
- data/lib/rails_error_dashboard/commands/link_existing_issue.rb +4 -2
- data/lib/rails_error_dashboard/commands/log_error.rb +1 -1
- data/lib/rails_error_dashboard/configuration.rb +23 -0
- data/lib/rails_error_dashboard/current.rb +56 -0
- data/lib/rails_error_dashboard/i18n_store.rb +293 -0
- data/lib/rails_error_dashboard/private_backend.rb +213 -0
- data/lib/rails_error_dashboard/services/baseline_alert_payload_builder.rb +89 -22
- data/lib/rails_error_dashboard/services/digest_builder.rb +21 -7
- data/lib/rails_error_dashboard/services/discord_payload_builder.rb +27 -15
- data/lib/rails_error_dashboard/services/error_notification_dispatcher.rb +10 -5
- data/lib/rails_error_dashboard/services/localized_time_formatter.rb +117 -0
- data/lib/rails_error_dashboard/services/notification_helpers.rb +87 -4
- data/lib/rails_error_dashboard/services/pagerduty_payload_builder.rb +22 -5
- data/lib/rails_error_dashboard/services/slack_payload_builder.rb +48 -28
- data/lib/rails_error_dashboard/services/storm_protection/gate.rb +2 -1
- data/lib/rails_error_dashboard/services/webhook_payload_builder.rb +15 -1
- data/lib/rails_error_dashboard/translation.rb +39 -0
- data/lib/rails_error_dashboard/version.rb +1 -1
- data/lib/rails_error_dashboard.rb +4 -0
- data/lib/tasks/error_dashboard.rake +5 -1
- metadata +24 -4
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
<!-- Similar Errors (Fuzzy Matching) -->
|
|
2
2
|
<% if RailsErrorDashboard.configuration.enable_similar_errors && error.respond_to?(:similar_errors) %>
|
|
3
|
-
|
|
3
|
+
<%# The threshold drives both the query and the hint below, so it is
|
|
4
|
+
named once rather than written as a literal in the prose too. %>
|
|
5
|
+
<% similarity_threshold = 0.6 %>
|
|
6
|
+
<% similar = error.similar_errors(threshold: similarity_threshold, limit: 5) %>
|
|
4
7
|
<% if similar.any? %>
|
|
5
|
-
|
|
8
|
+
<%# The locale is part of the cache key: this fragment contains
|
|
9
|
+
translated text, and without it the first locale to render an
|
|
10
|
+
error would be served to every other one. %>
|
|
11
|
+
<% cache [error, 'similar_errors_v3', red_locale, similar.map { |s| s[:error]&.updated_at }.compact.max] do %>
|
|
6
12
|
<div class="card mb-4" id="section-similar-errors">
|
|
7
13
|
<div class="card-header">
|
|
8
14
|
<h5 class="mb-0">
|
|
9
|
-
<i class="bi bi-diagram-3"></i>
|
|
10
|
-
<span class="badge bg-info text-dark"
|
|
15
|
+
<i class="bi bi-diagram-3"></i> <%= red_t("red.errors.similar_errors.title") %>
|
|
16
|
+
<span class="badge bg-info text-dark"><%= red_t("red.errors.similar_errors.badge") %></span>
|
|
11
17
|
</h5>
|
|
12
|
-
<small class="text-muted"
|
|
18
|
+
<small class="text-muted"><%= red_t("red.errors.similar_errors.hint", threshold: (similarity_threshold * 100).round) %></small>
|
|
13
19
|
</div>
|
|
14
20
|
<div class="card-body p-0">
|
|
15
21
|
<div class="table-responsive">
|
|
16
22
|
<table class="table table-hover mb-0">
|
|
17
23
|
<thead class="table-light">
|
|
18
24
|
<tr>
|
|
19
|
-
<th
|
|
20
|
-
<th
|
|
21
|
-
<th
|
|
22
|
-
<th
|
|
23
|
-
<th
|
|
25
|
+
<th><%= red_t("red.errors.similar_errors.column_similarity") %></th>
|
|
26
|
+
<th><%= red_t("red.errors.similar_errors.column_error_type") %></th>
|
|
27
|
+
<th><%= red_t("red.errors.similar_errors.column_message") %></th>
|
|
28
|
+
<th><%= red_t("red.errors.similar_errors.column_platform") %></th>
|
|
29
|
+
<th><%= red_t("red.errors.similar_errors.column_occurrences") %></th>
|
|
24
30
|
<th></th>
|
|
25
31
|
</tr>
|
|
26
32
|
</thead>
|
|
@@ -59,9 +65,9 @@
|
|
|
59
65
|
<span class="badge badge-api"><i class="bi bi-server"></i> <%= similar_error.platform || 'API' %></span>
|
|
60
66
|
<% end %>
|
|
61
67
|
</td>
|
|
62
|
-
<td><span class="badge bg-primary"><%= similar_error.occurrence_count
|
|
68
|
+
<td><span class="badge bg-primary"><%= red_tp("red.errors.similar_errors.occurrences", count: similar_error.occurrence_count) %></span></td>
|
|
63
69
|
<td>
|
|
64
|
-
<%= link_to "
|
|
70
|
+
<%= link_to red_t("red.errors.similar_errors.view"), error_path(similar_error), class: "btn btn-sm btn-outline-primary" %>
|
|
65
71
|
</td>
|
|
66
72
|
</tr>
|
|
67
73
|
<% end %>
|
|
@@ -20,10 +20,18 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
22
|
<% if repo_link %>
|
|
23
|
+
<%
|
|
24
|
+
# Repository host names are brands and stay English; only the
|
|
25
|
+
# sentence around the name is translated.
|
|
26
|
+
repo_host = if repo_link.include?("github") then "GitHub"
|
|
27
|
+
elsif repo_link.include?("gitlab") then "GitLab"
|
|
28
|
+
else "Bitbucket"
|
|
29
|
+
end
|
|
30
|
+
%>
|
|
23
31
|
<%= link_to repo_link, target: "_blank", rel: "noopener",
|
|
24
32
|
class: "btn btn-sm btn-primary",
|
|
25
|
-
title: "
|
|
26
|
-
<i class="bi bi-box-arrow-up-right"></i>
|
|
33
|
+
title: red_t("red.errors.source_code.view_on", host: repo_host) do %>
|
|
34
|
+
<i class="bi bi-box-arrow-up-right"></i> <%= red_t("red.errors.source_code.view_source") %>
|
|
27
35
|
<% end %>
|
|
28
36
|
<% end %>
|
|
29
37
|
</div>
|
|
@@ -38,7 +46,9 @@
|
|
|
38
46
|
</div>
|
|
39
47
|
<div class="d-flex align-items-center gap-1">
|
|
40
48
|
<i class="bi bi-clock"></i>
|
|
41
|
-
|
|
49
|
+
<%# One key, not a duration concatenated with " ago": several
|
|
50
|
+
languages put the equivalent of "ago" before the duration. %>
|
|
51
|
+
<span><%= red_t("red.time.ago", duration: time_ago_in_words(blame_data[:date])) %></span>
|
|
42
52
|
</div>
|
|
43
53
|
<% if blame_data[:commit_message] %>
|
|
44
54
|
<div class="d-flex align-items-center gap-1 flex-grow-1">
|
|
@@ -66,7 +76,12 @@
|
|
|
66
76
|
<% if coverage_data %>
|
|
67
77
|
<div class="px-3 py-1 bg-info bg-opacity-10 border-bottom">
|
|
68
78
|
<small class="text-info">
|
|
69
|
-
|
|
79
|
+
<%# One sentence with the colours interpolated, not a sentence cut
|
|
80
|
+
into pieces by two <span>s — the clause order is not the same
|
|
81
|
+
in every language. %>
|
|
82
|
+
<i class="bi bi-broadcast"></i> <%= red_t("red.errors.source_code.coverage_legend_html",
|
|
83
|
+
executed: tag.span(red_t("red.errors.source_code.coverage_green"), class: "text-success"),
|
|
84
|
+
not_executed: tag.span(red_t("red.errors.source_code.coverage_gray"), class: "text-secondary")) %>
|
|
70
85
|
</small>
|
|
71
86
|
</div>
|
|
72
87
|
<% end %>
|
|
@@ -83,7 +98,7 @@
|
|
|
83
98
|
<!-- Error message if source couldn't be read -->
|
|
84
99
|
<div class="alert alert-warning mt-2 mb-2 py-2">
|
|
85
100
|
<i class="bi bi-exclamation-triangle"></i>
|
|
86
|
-
<small
|
|
101
|
+
<small><%= red_t("red.errors.source_code.read_failed", message: source_data[:error]) %></small>
|
|
87
102
|
</div>
|
|
88
103
|
<% end %>
|
|
89
104
|
<% end %>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="col">
|
|
3
3
|
<div class="card stat-card">
|
|
4
4
|
<div class="card-body">
|
|
5
|
-
<div class="stat-label mb-2"
|
|
5
|
+
<div class="stat-label mb-2"><%= red_t("red.errors.stats.today") %></div>
|
|
6
6
|
<div class="stat-value text-info"><%= stats[:total_today] %></div>
|
|
7
7
|
</div>
|
|
8
8
|
</div>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<div class="col">
|
|
11
11
|
<div class="card stat-card">
|
|
12
12
|
<div class="card-body">
|
|
13
|
-
<div class="stat-label mb-2"
|
|
13
|
+
<div class="stat-label mb-2"><%= red_t("red.errors.stats.this_week") %></div>
|
|
14
14
|
<div class="stat-value text-primary"><%= stats[:total_week] %></div>
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<div class="col">
|
|
19
19
|
<div class="card stat-card">
|
|
20
20
|
<div class="card-body">
|
|
21
|
-
<div class="stat-label mb-2"
|
|
21
|
+
<div class="stat-label mb-2"><%= red_t("red.errors.stats.unresolved") %></div>
|
|
22
22
|
<div class="stat-value text-danger"><%= stats[:unresolved] %></div>
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<div class="col">
|
|
27
27
|
<div class="card stat-card">
|
|
28
28
|
<div class="card-body">
|
|
29
|
-
<div class="stat-label mb-2"
|
|
29
|
+
<div class="stat-label mb-2"><%= red_t("red.errors.stats.resolved") %></div>
|
|
30
30
|
<div class="stat-value text-success"><%= stats[:resolved] %></div>
|
|
31
31
|
</div>
|
|
32
32
|
</div>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
<div class="col">
|
|
35
35
|
<div class="card stat-card">
|
|
36
36
|
<div class="card-body">
|
|
37
|
-
<div class="stat-label mb-2"
|
|
37
|
+
<div class="stat-label mb-2"><%= red_t("red.errors.stats.reopened") %></div>
|
|
38
38
|
<div class="stat-value text-warning"><%= stats[:reopened] %></div>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
<div class="card" id="section-timeline">
|
|
4
4
|
<div class="card-header">
|
|
5
5
|
<h5 class="mb-0">
|
|
6
|
-
<i class="bi bi-clock-history"></i>
|
|
7
|
-
<small class="text-muted ms-2"
|
|
6
|
+
<i class="bi bi-clock-history"></i> <%= red_t("red.errors.timeline.title") %>
|
|
7
|
+
<small class="text-muted ms-2"><%= red_t("red.errors.timeline.hint") %></small>
|
|
8
8
|
</h5>
|
|
9
9
|
</div>
|
|
10
10
|
<div class="card-body">
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<div class="flex-grow-1">
|
|
27
27
|
<% if error.id == @error.id %>
|
|
28
28
|
<strong class="text-danger">
|
|
29
|
-
<i class="bi bi-arrow-right-circle"></i>
|
|
29
|
+
<i class="bi bi-arrow-right-circle"></i> <%= red_t("red.errors.timeline.current_error") %>
|
|
30
30
|
</strong>
|
|
31
31
|
<% else %>
|
|
32
32
|
<%= link_to error_path(error), class: "text-decoration-none" do %>
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
<% if error.user_id %>
|
|
63
63
|
<span class="text-muted">
|
|
64
64
|
<i class="bi bi-person"></i>
|
|
65
|
-
|
|
65
|
+
<%= red_t("red.errors.timeline.user", id: error.user_id) %>
|
|
66
66
|
</span>
|
|
67
67
|
<% end %>
|
|
68
68
|
|
|
@@ -78,9 +78,9 @@
|
|
|
78
78
|
<% if error.resolution_comment.present? %>
|
|
79
79
|
data-bs-toggle="tooltip"
|
|
80
80
|
data-bs-placement="top"
|
|
81
|
-
title="
|
|
81
|
+
title="<%= red_t("red.errors.timeline.notes_tooltip", notes: error.resolution_comment.truncate(150)) %>"
|
|
82
82
|
<% end %>>
|
|
83
|
-
<i class="bi bi-check-circle"></i>
|
|
83
|
+
<i class="bi bi-check-circle"></i> <%= red_t("red.errors.timeline.resolved") %>
|
|
84
84
|
</span>
|
|
85
85
|
<% end %>
|
|
86
86
|
</div>
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
<% if error.resolved? && error.resolution_comment.present? %>
|
|
89
89
|
<div style="margin-top: var(--space-2); padding: var(--space-2) var(--space-3); background: var(--status-success-bg); border: 1px solid var(--status-success); border-radius: var(--radius-sm);">
|
|
90
90
|
<small style="color: var(--status-success); font-weight: 600;">
|
|
91
|
-
<i class="bi bi-journal-text"></i>
|
|
91
|
+
<i class="bi bi-journal-text"></i> <%= red_t("red.errors.timeline.notes_label") %>
|
|
92
92
|
</small>
|
|
93
93
|
<div style="font-size: 13px; color: var(--text-primary); margin-top: 4px;">
|
|
94
94
|
<%= auto_link_urls(truncate(error.resolution_comment, length: 200), error: error).html_safe %>
|
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
<thead class="table-light">
|
|
4
4
|
<tr>
|
|
5
5
|
<% if show_rank %>
|
|
6
|
-
<th
|
|
6
|
+
<th><%= red_t("red.errors.user_errors_table.column_rank") %></th>
|
|
7
7
|
<% end %>
|
|
8
|
-
<th
|
|
8
|
+
<th><%= red_t("red.errors.user_errors_table.column_user") %></th>
|
|
9
9
|
<% if show_error_type_count %>
|
|
10
|
-
<th
|
|
10
|
+
<th><%= red_t("red.errors.user_errors_table.column_error_type_count") %></th>
|
|
11
11
|
<% end %>
|
|
12
|
-
<th
|
|
12
|
+
<th><%= red_t("red.errors.user_errors_table.column_error_count") %></th>
|
|
13
13
|
<% if show_percentage %>
|
|
14
|
-
<th
|
|
14
|
+
<th><%= red_t("red.errors.user_errors_table.column_percentage") %></th>
|
|
15
15
|
<% end %>
|
|
16
16
|
<% if show_error_types %>
|
|
17
|
-
<th
|
|
17
|
+
<th><%= red_t("red.errors.user_errors_table.column_error_types") %></th>
|
|
18
18
|
<% end %>
|
|
19
|
-
<th
|
|
19
|
+
<th><%= red_t("red.errors.user_errors_table.column_actions") %></th>
|
|
20
20
|
</tr>
|
|
21
21
|
</thead>
|
|
22
22
|
<tbody>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<% if show_error_type_count %>
|
|
30
30
|
<td>
|
|
31
31
|
<span class="badge bg-warning text-dark">
|
|
32
|
-
<%= user_data[:error_type_count] %>
|
|
32
|
+
<%= red_tp("red.errors.user_errors_table.types", count: user_data[:error_type_count]) %>
|
|
33
33
|
</span>
|
|
34
34
|
</td>
|
|
35
35
|
<% end %>
|
|
@@ -52,16 +52,19 @@
|
|
|
52
52
|
<% end %>
|
|
53
53
|
<% if show_error_types && user_data[:error_types].present? %>
|
|
54
54
|
<td>
|
|
55
|
-
|
|
55
|
+
<%# The cut-off is named once: it bounds the list and the
|
|
56
|
+
"+N more" count, which must agree. %>
|
|
57
|
+
<% shown_error_types = 3 %>
|
|
58
|
+
<% user_data[:error_types].first(shown_error_types).each do |error_type| %>
|
|
56
59
|
<code class="small me-1"><%= error_type %></code>
|
|
57
60
|
<% end %>
|
|
58
|
-
<% if user_data[:error_types].count >
|
|
59
|
-
<span class="text-muted small"
|
|
61
|
+
<% if user_data[:error_types].count > shown_error_types %>
|
|
62
|
+
<span class="text-muted small"><%= red_tp("red.errors.user_errors_table.more", count: user_data[:error_types].count - shown_error_types) %></span>
|
|
60
63
|
<% end %>
|
|
61
64
|
</td>
|
|
62
65
|
<% end %>
|
|
63
66
|
<td>
|
|
64
|
-
<%= link_to "
|
|
67
|
+
<%= link_to red_t("red.errors.user_errors_table.view_errors"), errors_path(user_id: user_data[:user_id], unresolved: '0'), class: "btn btn-sm btn-outline-primary" %>
|
|
65
68
|
</td>
|
|
66
69
|
</tr>
|
|
67
70
|
<% end %>
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
<% content_for :page_title, "
|
|
1
|
+
<% content_for :page_title, red_t("red.health.actioncable.title") %>
|
|
2
2
|
|
|
3
3
|
<div>
|
|
4
4
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
5
5
|
<h1 style="font-size: 20px; font-weight: 700; margin: 0;">
|
|
6
6
|
<i class="bi bi-broadcast me-2"></i>
|
|
7
|
-
|
|
7
|
+
<%= red_t("red.health.actioncable.title") %>
|
|
8
8
|
</h1>
|
|
9
9
|
|
|
10
10
|
<div class="btn-group" role="group">
|
|
11
11
|
<%= link_to actioncable_health_summary_errors_path(days: 7), class: "btn btn-sm #{@days == 7 ? 'btn-primary' : 'btn-outline-primary'}" do %>
|
|
12
|
-
7
|
|
12
|
+
<%= red_t("red.common.days_filter.7") %>
|
|
13
13
|
<% end %>
|
|
14
14
|
<%= link_to actioncable_health_summary_errors_path(days: 30), class: "btn btn-sm #{@days == 30 ? 'btn-primary' : 'btn-outline-primary'}" do %>
|
|
15
|
-
30
|
|
15
|
+
<%= red_t("red.common.days_filter.30") %>
|
|
16
16
|
<% end %>
|
|
17
17
|
<%= link_to actioncable_health_summary_errors_path(days: 90), class: "btn btn-sm #{@days == 90 ? 'btn-primary' : 'btn-outline-primary'}" do %>
|
|
18
|
-
90
|
|
18
|
+
<%= red_t("red.common.days_filter.90") %>
|
|
19
19
|
<% end %>
|
|
20
20
|
</div>
|
|
21
21
|
</div>
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
<% if @unique_channels == 0 %>
|
|
24
24
|
<div class="red-empty-state">
|
|
25
25
|
<i class="bi bi-broadcast display-1 text-success mb-3"></i>
|
|
26
|
-
<div class="red-empty-state-title"
|
|
26
|
+
<div class="red-empty-state-title"><%= red_t("red.health.actioncable.empty.title") %></div>
|
|
27
27
|
<p class="text-muted">
|
|
28
|
-
|
|
28
|
+
<%= red_t("red.health.actioncable.empty.message", days: @days) %>
|
|
29
29
|
</p>
|
|
30
30
|
<div class="card mx-auto" style="max-width: 500px;">
|
|
31
31
|
<div class="card-body text-start">
|
|
32
|
-
<h6
|
|
32
|
+
<h6><%= red_t("red.health.actioncable.empty.how_it_works") %></h6>
|
|
33
33
|
<ul class="mb-0">
|
|
34
|
-
<li
|
|
35
|
-
<li
|
|
36
|
-
<li
|
|
37
|
-
<li
|
|
34
|
+
<li><%= red_t("red.health.actioncable.empty.step_breadcrumbs_html") %></li>
|
|
35
|
+
<li><%= red_t("red.health.actioncable.empty.step_tracking_html") %></li>
|
|
36
|
+
<li><%= red_t("red.health.actioncable.empty.step_configured") %></li>
|
|
37
|
+
<li><%= red_t("red.health.actioncable.empty.step_capture") %></li>
|
|
38
38
|
</ul>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
<div class="card text-center">
|
|
46
46
|
<div class="card-body">
|
|
47
47
|
<div class="display-6 text-primary"><%= @unique_channels %></div>
|
|
48
|
-
<small class="text-muted"
|
|
48
|
+
<small class="text-muted"><%= red_t("red.health.actioncable.stats.active_channels") %></small>
|
|
49
49
|
</div>
|
|
50
50
|
</div>
|
|
51
51
|
</div>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<div class="card text-center">
|
|
54
54
|
<div class="card-body">
|
|
55
55
|
<div class="display-6 text-info"><%= @total_events %></div>
|
|
56
|
-
<small class="text-muted"
|
|
56
|
+
<small class="text-muted"><%= red_t("red.health.actioncable.stats.total_events") %></small>
|
|
57
57
|
</div>
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
<div class="card text-center">
|
|
62
62
|
<div class="card-body">
|
|
63
63
|
<div class="display-6 <%= @total_rejections > 0 ? 'text-danger' : 'text-success' %>"><%= @total_rejections %></div>
|
|
64
|
-
<small class="text-muted"
|
|
64
|
+
<small class="text-muted"><%= red_t("red.health.actioncable.stats.subscription_rejections") %></small>
|
|
65
65
|
</div>
|
|
66
66
|
</div>
|
|
67
67
|
</div>
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
72
72
|
<h5 class="mb-0">
|
|
73
73
|
<i class="bi bi-broadcast text-primary me-2"></i>
|
|
74
|
-
|
|
74
|
+
<%= red_t("red.health.actioncable.table.title") %>
|
|
75
75
|
<span class="badge bg-primary"><%= @unique_channels %></span>
|
|
76
76
|
</h5>
|
|
77
77
|
<small class="text-muted"><%== @pagy.info_tag %></small>
|
|
@@ -81,13 +81,13 @@
|
|
|
81
81
|
<table class="table table-hover mb-0">
|
|
82
82
|
<thead class="table-light">
|
|
83
83
|
<tr>
|
|
84
|
-
<th
|
|
85
|
-
<th width="100"
|
|
86
|
-
<th width="120"
|
|
87
|
-
<th width="120"
|
|
88
|
-
<th width="100"
|
|
89
|
-
<th width="80"
|
|
90
|
-
<th width="140"
|
|
84
|
+
<th><%= red_t("red.health.actioncable.table.column_channel") %></th>
|
|
85
|
+
<th width="100"><%= red_t("red.health.actioncable.table.column_actions") %></th>
|
|
86
|
+
<th width="120"><%= red_t("red.health.actioncable.table.column_transmissions") %></th>
|
|
87
|
+
<th width="120"><%= red_t("red.health.actioncable.table.column_subscriptions") %></th>
|
|
88
|
+
<th width="100"><%= red_t("red.health.actioncable.table.column_rejections") %></th>
|
|
89
|
+
<th width="80"><%= red_t("red.health.actioncable.table.column_errors") %></th>
|
|
90
|
+
<th width="140"><%= red_t("red.health.actioncable.table.column_last_seen") %></th>
|
|
91
91
|
</tr>
|
|
92
92
|
</thead>
|
|
93
93
|
<tbody>
|
|
@@ -115,11 +115,11 @@
|
|
|
115
115
|
<div class="card-footer border-top d-flex justify-content-between align-items-center">
|
|
116
116
|
<div>
|
|
117
117
|
<small class="text-muted">
|
|
118
|
-
<i class="bi bi-lightbulb text-warning"></i>
|
|
118
|
+
<i class="bi bi-lightbulb text-warning"></i> <%= red_t("red.health.actioncable.table.tip") %>
|
|
119
119
|
</small>
|
|
120
120
|
<small class="ms-3">
|
|
121
121
|
<a href="https://guides.rubyonrails.org/action_cable_overview.html" target="_blank" rel="noopener" class="text-decoration-none">
|
|
122
|
-
<i class="bi bi-book"></i>
|
|
122
|
+
<i class="bi bi-book"></i> <%= red_t("red.health.actioncable.table.guide_link") %> <i class="bi bi-box-arrow-up-right" style="font-size: 0.7em;"></i>
|
|
123
123
|
</a>
|
|
124
124
|
</small>
|
|
125
125
|
</div>
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
<% content_for :page_title, "
|
|
1
|
+
<% content_for :page_title, red_t("red.health.activestorage.title") %>
|
|
2
2
|
|
|
3
3
|
<div>
|
|
4
4
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
5
5
|
<h1 style="font-size: 20px; font-weight: 700; margin: 0;">
|
|
6
6
|
<i class="bi bi-cloud-arrow-up me-2"></i>
|
|
7
|
-
|
|
7
|
+
<%= red_t("red.health.activestorage.title") %>
|
|
8
8
|
</h1>
|
|
9
9
|
|
|
10
10
|
<div class="btn-group" role="group">
|
|
11
11
|
<%= link_to activestorage_health_summary_errors_path(days: 7), class: "btn btn-sm #{@days == 7 ? 'btn-primary' : 'btn-outline-primary'}" do %>
|
|
12
|
-
7
|
|
12
|
+
<%= red_t("red.common.days_filter.7") %>
|
|
13
13
|
<% end %>
|
|
14
14
|
<%= link_to activestorage_health_summary_errors_path(days: 30), class: "btn btn-sm #{@days == 30 ? 'btn-primary' : 'btn-outline-primary'}" do %>
|
|
15
|
-
30
|
|
15
|
+
<%= red_t("red.common.days_filter.30") %>
|
|
16
16
|
<% end %>
|
|
17
17
|
<%= link_to activestorage_health_summary_errors_path(days: 90), class: "btn btn-sm #{@days == 90 ? 'btn-primary' : 'btn-outline-primary'}" do %>
|
|
18
|
-
90
|
|
18
|
+
<%= red_t("red.common.days_filter.90") %>
|
|
19
19
|
<% end %>
|
|
20
20
|
</div>
|
|
21
21
|
</div>
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
<% if @unique_services == 0 %>
|
|
24
24
|
<div class="red-empty-state">
|
|
25
25
|
<i class="bi bi-cloud-arrow-up display-1 text-success mb-3"></i>
|
|
26
|
-
<div class="red-empty-state-title"
|
|
26
|
+
<div class="red-empty-state-title"><%= red_t("red.health.activestorage.empty.title") %></div>
|
|
27
27
|
<p class="text-muted">
|
|
28
|
-
|
|
28
|
+
<%= red_t("red.health.activestorage.empty.message", days: @days) %>
|
|
29
29
|
</p>
|
|
30
30
|
<div class="card mx-auto" style="max-width: 500px;">
|
|
31
31
|
<div class="card-body text-start">
|
|
32
|
-
<h6
|
|
32
|
+
<h6><%= red_t("red.health.activestorage.empty.how_it_works") %></h6>
|
|
33
33
|
<ul class="mb-0">
|
|
34
|
-
<li
|
|
35
|
-
<li
|
|
36
|
-
<li
|
|
37
|
-
<li
|
|
34
|
+
<li><%= red_t("red.health.activestorage.empty.step_breadcrumbs_html") %></li>
|
|
35
|
+
<li><%= red_t("red.health.activestorage.empty.step_tracking_html") %></li>
|
|
36
|
+
<li><%= red_t("red.health.activestorage.empty.step_configured") %></li>
|
|
37
|
+
<li><%= red_t("red.health.activestorage.empty.step_capture") %></li>
|
|
38
38
|
</ul>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
<div class="card text-center">
|
|
46
46
|
<div class="card-body">
|
|
47
47
|
<div class="display-6 text-primary"><%= @unique_services %></div>
|
|
48
|
-
<small class="text-muted"
|
|
48
|
+
<small class="text-muted"><%= red_t("red.health.activestorage.stats.storage_services") %></small>
|
|
49
49
|
</div>
|
|
50
50
|
</div>
|
|
51
51
|
</div>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<div class="card text-center">
|
|
54
54
|
<div class="card-body">
|
|
55
55
|
<div class="display-6 text-info"><%= @total_operations %></div>
|
|
56
|
-
<small class="text-muted"
|
|
56
|
+
<small class="text-muted"><%= red_t("red.health.activestorage.stats.total_operations") %></small>
|
|
57
57
|
</div>
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
<div class="card text-center">
|
|
62
62
|
<div class="card-body">
|
|
63
63
|
<div class="display-6 text-warning"><%= @errors_with_storage %></div>
|
|
64
|
-
<small class="text-muted"
|
|
64
|
+
<small class="text-muted"><%= red_t("red.health.activestorage.stats.errors_with_storage") %></small>
|
|
65
65
|
</div>
|
|
66
66
|
</div>
|
|
67
67
|
</div>
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
72
72
|
<h5 class="mb-0">
|
|
73
73
|
<i class="bi bi-cloud-arrow-up text-primary me-2"></i>
|
|
74
|
-
|
|
74
|
+
<%= red_t("red.health.activestorage.table.title") %>
|
|
75
75
|
<span class="badge bg-primary"><%= @unique_services %></span>
|
|
76
76
|
</h5>
|
|
77
77
|
<small class="text-muted"><%== @pagy.info_tag %></small>
|
|
@@ -81,16 +81,16 @@
|
|
|
81
81
|
<table class="table table-hover mb-0">
|
|
82
82
|
<thead class="table-light">
|
|
83
83
|
<tr>
|
|
84
|
-
<th
|
|
85
|
-
<th width="90"
|
|
86
|
-
<th width="100"
|
|
87
|
-
<th width="90"
|
|
88
|
-
<th width="90"
|
|
89
|
-
<th width="80"
|
|
90
|
-
<th width="100"
|
|
91
|
-
<th width="100"
|
|
92
|
-
<th width="80"
|
|
93
|
-
<th width="140"
|
|
84
|
+
<th><%= red_t("red.health.activestorage.table.column_service") %></th>
|
|
85
|
+
<th width="90"><%= red_t("red.health.activestorage.table.column_uploads") %></th>
|
|
86
|
+
<th width="100"><%= red_t("red.health.activestorage.table.column_downloads") %></th>
|
|
87
|
+
<th width="90"><%= red_t("red.health.activestorage.table.column_deletes") %></th>
|
|
88
|
+
<th width="90"><%= red_t("red.health.activestorage.table.column_exists") %></th>
|
|
89
|
+
<th width="80"><%= red_t("red.health.activestorage.table.column_total") %></th>
|
|
90
|
+
<th width="100"><%= red_t("red.health.activestorage.table.column_avg_duration") %></th>
|
|
91
|
+
<th width="100"><%= red_t("red.health.activestorage.table.column_slowest") %></th>
|
|
92
|
+
<th width="80"><%= red_t("red.health.activestorage.table.column_errors") %></th>
|
|
93
|
+
<th width="140"><%= red_t("red.health.activestorage.table.column_last_seen") %></th>
|
|
94
94
|
</tr>
|
|
95
95
|
</thead>
|
|
96
96
|
<tbody>
|
|
@@ -131,11 +131,11 @@
|
|
|
131
131
|
<div class="card-footer border-top d-flex justify-content-between align-items-center">
|
|
132
132
|
<div>
|
|
133
133
|
<small class="text-muted">
|
|
134
|
-
<i class="bi bi-lightbulb text-warning"></i>
|
|
134
|
+
<i class="bi bi-lightbulb text-warning"></i> <%= red_t("red.health.activestorage.table.tip") %>
|
|
135
135
|
</small>
|
|
136
136
|
<small class="ms-3">
|
|
137
137
|
<a href="https://guides.rubyonrails.org/active_storage_overview.html" target="_blank" rel="noopener" class="text-decoration-none">
|
|
138
|
-
<i class="bi bi-book"></i>
|
|
138
|
+
<i class="bi bi-book"></i> <%= red_t("red.health.activestorage.table.guide_link") %> <i class="bi bi-box-arrow-up-right" style="font-size: 0.7em;"></i>
|
|
139
139
|
</a>
|
|
140
140
|
</small>
|
|
141
141
|
</div>
|