solid_errors 0.3.4 → 0.4.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 +113 -11
- data/app/controllers/solid_errors/application_controller.rb +20 -0
- data/app/controllers/solid_errors/errors_controller.rb +11 -1
- data/app/mailers/solid_errors/error_mailer.rb +15 -0
- data/app/models/solid_errors/backtrace_line.rb +6 -5
- data/app/models/solid_errors/occurrence.rb +6 -0
- data/app/views/layouts/solid_errors/_style.html +1114 -0
- data/app/views/layouts/solid_errors/application.html.erb +11 -1085
- data/app/views/solid_errors/error_mailer/error_occurred.html.erb +17 -0
- data/app/views/solid_errors/error_mailer/error_occurred.text.erb +0 -0
- data/app/views/solid_errors/errors/_error.html.erb +98 -27
- data/app/views/solid_errors/errors/_row.html.erb +31 -0
- data/app/views/solid_errors/errors/index.html.erb +1 -1
- data/app/views/solid_errors/errors/show.html.erb +5 -101
- data/app/views/solid_errors/occurrences/_collection.html.erb +38 -3
- data/app/views/solid_errors/occurrences/_occurrence.html.erb +9 -4
- data/lib/generators/solid_errors/install/templates/create_solid_errors_tables.rb.erb +5 -6
- data/lib/solid_errors/engine.rb +1 -1
- data/lib/solid_errors/sanitizer.rb +1 -1
- data/lib/solid_errors/subscriber.rb +3 -2
- data/lib/solid_errors/version.rb +1 -1
- data/lib/solid_errors.rb +17 -2
- metadata +78 -3
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<title>Solid Errors | <%= @error.emoji %> <%= @error.exception_class %></title>
|
|
4
|
+
<%= render "layouts/solid_errors/style" %>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<%= render "solid_errors/errors/error",
|
|
8
|
+
error: @error,
|
|
9
|
+
show_actions: false %>
|
|
10
|
+
|
|
11
|
+
<br>
|
|
12
|
+
<br>
|
|
13
|
+
|
|
14
|
+
<%= render "solid_errors/occurrences/occurrence",
|
|
15
|
+
occurrence: @occurrence %>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
File without changes
|
|
@@ -1,31 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
<%# locals: (error:, show_actions: true) -%>
|
|
2
|
+
|
|
3
|
+
<%= tag.section id: dom_id(error), class: "space-y-6" do %>
|
|
4
|
+
<div class="flex justify-between items-center">
|
|
5
|
+
<%= tag.h1 class: "font-bold flex items-center text-2xl gap-2" do %>
|
|
4
6
|
<%= error.emoji %>
|
|
5
|
-
|
|
6
|
-
<strong><code><%= error.exception_class %></code></strong>
|
|
7
|
-
<% end %>
|
|
7
|
+
<code><%= error.exception_class %></code>
|
|
8
8
|
from
|
|
9
9
|
<em><code><%= error.source %></code></em>
|
|
10
|
-
</div>
|
|
11
|
-
<pre class="whitespace-pre-wrap ml-6 mt-4"><%= error.message %></pre>
|
|
12
|
-
</td>
|
|
13
|
-
<td scope="col" class="whitespace-nowrap px-3 py-4 pt-7 text-gray-500 text-right">
|
|
14
|
-
<%= error.occurrences.size %>
|
|
15
|
-
</td>
|
|
16
|
-
<td scope="col" class="whitespace-nowrap px-3 py-4 pt-7 text-gray-500 text-right">
|
|
17
|
-
<% last_seen_at = error.occurrences.maximum(:created_at) %>
|
|
18
|
-
<abbr title="<%= last_seen_at.iso8601 %>" class="cursor-help">
|
|
19
|
-
<%= time_tag last_seen_at, time_ago_in_words(last_seen_at, scope: 'datetime.distance_in_words.short') %>
|
|
20
|
-
</abbr>
|
|
21
|
-
</td>
|
|
22
|
-
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-3">
|
|
23
|
-
<%= button_to error_path(error), method: :patch, class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-transparent text-blue-500 border-blue-500 hover:ring-blue-200 hover:ring-8", params: { error: { resolved_at: Time.now } } do %>
|
|
24
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
|
|
25
|
-
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0"/>
|
|
26
|
-
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0z"/>
|
|
27
|
-
</svg>
|
|
28
|
-
<span>Resolve<span class="sr-only">, Error #<%= error.id %></span></span>
|
|
29
10
|
<% end %>
|
|
30
|
-
|
|
31
|
-
|
|
11
|
+
|
|
12
|
+
<small class="text-base">
|
|
13
|
+
#<code><%= error.id %></code>
|
|
14
|
+
</small>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<pre class=""><%= error.message %></pre>
|
|
18
|
+
|
|
19
|
+
<dl class="flex-1 grid grid-cols-2 gap-x-4">
|
|
20
|
+
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
21
|
+
<dt class="font-bold">
|
|
22
|
+
<%= SolidErrors::Error.human_attribute_name(:first_seen) %>
|
|
23
|
+
</dt>
|
|
24
|
+
<dd class="inline-flex items-center gap-1">
|
|
25
|
+
<% first_seen_at = error.occurrences.minimum(:created_at) %>
|
|
26
|
+
|
|
27
|
+
<abbr title="<%= first_seen_at.iso8601 %>" class="cursor-help">
|
|
28
|
+
<%= time_tag first_seen_at, "#{time_ago_in_words(first_seen_at)} ago" %>
|
|
29
|
+
</abbr>
|
|
30
|
+
</dd>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
33
|
+
<dt class="font-bold">
|
|
34
|
+
<%= SolidErrors::Error.human_attribute_name(:last_seen) %>
|
|
35
|
+
</dt>
|
|
36
|
+
<dd class="inline-flex items-center gap-1">
|
|
37
|
+
<% last_seen_at = error.occurrences.maximum(:created_at) %>
|
|
38
|
+
|
|
39
|
+
<abbr title="<%= last_seen_at.iso8601 %>" class="cursor-help">
|
|
40
|
+
<%= time_tag last_seen_at, "#{time_ago_in_words(last_seen_at)} ago" %>
|
|
41
|
+
</abbr>
|
|
42
|
+
</dd>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
45
|
+
<dt class="font-bold">
|
|
46
|
+
<%= SolidErrors::Error.human_attribute_name(:occurrences) %>
|
|
47
|
+
</dt>
|
|
48
|
+
<dd class="inline-flex items-center gap-1">
|
|
49
|
+
<%= error.occurrences.size %>
|
|
50
|
+
</dd>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
53
|
+
<dt class="font-bold">
|
|
54
|
+
<%= SolidErrors::Error.human_attribute_name(:exception_class) %>
|
|
55
|
+
</dt>
|
|
56
|
+
<dd class="inline-flex items-center gap-1">
|
|
57
|
+
<code><%= error.exception_class %></code>
|
|
58
|
+
</dd>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
61
|
+
<dt class="font-bold">
|
|
62
|
+
<%= SolidErrors::Error.human_attribute_name(:severity) %>
|
|
63
|
+
</dt>
|
|
64
|
+
<dd class="inline-flex items-center gap-1">
|
|
65
|
+
<%= error.emoji %>
|
|
66
|
+
<span class="<%= error.badge_classes %>">
|
|
67
|
+
<%= error.severity %>
|
|
68
|
+
</span>
|
|
69
|
+
</dd>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
72
|
+
<dt class="font-bold">
|
|
73
|
+
<%= SolidErrors::Error.human_attribute_name(:source) %>
|
|
74
|
+
</dt>
|
|
75
|
+
<dd class="inline-flex items-center gap-1">
|
|
76
|
+
<em><%= error.source %></em>
|
|
77
|
+
</dd>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="flex items-start justify-between flex-wrap gap-x-2">
|
|
80
|
+
<dt class="font-bold">
|
|
81
|
+
<%= SolidErrors::Error.human_attribute_name(:project_root) %>
|
|
82
|
+
</dt>
|
|
83
|
+
<dd class="">
|
|
84
|
+
<span><%= SolidErrors::BacktraceLine::RAILS_ROOT %></span>
|
|
85
|
+
</dd>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="flex items-start justify-between flex-wrap gap-x-2">
|
|
88
|
+
<dt class="font-bold">
|
|
89
|
+
<%= SolidErrors::Error.human_attribute_name(:gem_root) %>
|
|
90
|
+
</dt>
|
|
91
|
+
<dd class="">
|
|
92
|
+
<ul>
|
|
93
|
+
<% Gem.path.each do |path| %>
|
|
94
|
+
<li><%= path %></li>
|
|
95
|
+
<% end %>
|
|
96
|
+
</ul>
|
|
97
|
+
</dd>
|
|
98
|
+
</div>
|
|
99
|
+
</dl>
|
|
100
|
+
|
|
101
|
+
<%= render "solid_errors/errors/actions", error: error if show_actions %>
|
|
102
|
+
<% end %>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<tr class="even:bg-gray-50 align-top">
|
|
2
|
+
<td scope="col" class="whitespace-wrap py-4 pl-4 pr-3 font-medium text-gray-900 sm:pl-3">
|
|
3
|
+
<div>
|
|
4
|
+
<%= error.emoji %>
|
|
5
|
+
<%= link_to error_path(error), class: "text-blue-400 underline inline-flex items-baseline gap-1" do %>
|
|
6
|
+
<strong><code><%= error.exception_class %></code></strong>
|
|
7
|
+
<% end %>
|
|
8
|
+
from
|
|
9
|
+
<em><code><%= error.source %></code></em>
|
|
10
|
+
</div>
|
|
11
|
+
<pre class="whitespace-pre-wrap ml-6 mt-4"><%= error.message %></pre>
|
|
12
|
+
</td>
|
|
13
|
+
<td scope="col" class="whitespace-nowrap px-3 py-4 pt-7 text-gray-500 text-right">
|
|
14
|
+
<%= error.occurrences_count %>
|
|
15
|
+
</td>
|
|
16
|
+
<td scope="col" class="whitespace-nowrap px-3 py-4 pt-7 text-gray-500 text-right">
|
|
17
|
+
<% last_seen_at = DateTime.strptime(error.recent_occurrence, "%Y-%m-%d %H:%M:%S.%N") %>
|
|
18
|
+
<abbr title="<%= last_seen_at.iso8601 %>" class="cursor-help">
|
|
19
|
+
<%= time_tag last_seen_at, time_ago_in_words(last_seen_at, scope: 'datetime.distance_in_words.short') %>
|
|
20
|
+
</abbr>
|
|
21
|
+
</td>
|
|
22
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-3">
|
|
23
|
+
<%= button_to error_path(error), method: :patch, class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-transparent text-blue-500 border-blue-500 hover:ring-blue-200 hover:ring-8", params: { error: { resolved_at: Time.now } } do %>
|
|
24
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
|
|
25
|
+
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0"/>
|
|
26
|
+
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0z"/>
|
|
27
|
+
</svg>
|
|
28
|
+
<span>Resolve<span class="sr-only">, Error #<%= error.id %></span></span>
|
|
29
|
+
<% end %>
|
|
30
|
+
</td>
|
|
31
|
+
</tr>
|
|
@@ -1,107 +1,11 @@
|
|
|
1
|
-
<%=
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
<%= @error.emoji %>
|
|
5
|
-
<code><%= @error.exception_class %></code>
|
|
6
|
-
from
|
|
7
|
-
<em><code><%= @error.source %></code></em>
|
|
8
|
-
<% end %>
|
|
9
|
-
|
|
10
|
-
<small class="text-base">
|
|
11
|
-
#<code><%= @error.id %></code>
|
|
12
|
-
</small>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<pre class=""><%= @error.message %></pre>
|
|
16
|
-
|
|
17
|
-
<dl class="flex-1 grid grid-cols-2 gap-x-4">
|
|
18
|
-
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
19
|
-
<dt class="font-bold">
|
|
20
|
-
<%= SolidErrors::Error.human_attribute_name(:first_seen) %>
|
|
21
|
-
</dt>
|
|
22
|
-
<dd class="inline-flex items-center gap-1">
|
|
23
|
-
<% first_seen_at = @error.occurrences.minimum(:created_at) %>
|
|
24
|
-
|
|
25
|
-
<abbr title="<%= first_seen_at.iso8601 %>" class="cursor-help">
|
|
26
|
-
<%= time_tag first_seen_at, "#{time_ago_in_words(first_seen_at)} ago" %>
|
|
27
|
-
</abbr>
|
|
28
|
-
</dd>
|
|
29
|
-
</div>
|
|
30
|
-
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
31
|
-
<dt class="font-bold">
|
|
32
|
-
<%= SolidErrors::Error.human_attribute_name(:last_seen) %>
|
|
33
|
-
</dt>
|
|
34
|
-
<dd class="inline-flex items-center gap-1">
|
|
35
|
-
<% last_seen_at = @error.occurrences.maximum(:created_at) %>
|
|
36
|
-
|
|
37
|
-
<abbr title="<%= last_seen_at.iso8601 %>" class="cursor-help">
|
|
38
|
-
<%= time_tag last_seen_at, "#{time_ago_in_words(last_seen_at)} ago" %>
|
|
39
|
-
</abbr>
|
|
40
|
-
</dd>
|
|
41
|
-
</div>
|
|
42
|
-
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
43
|
-
<dt class="font-bold">
|
|
44
|
-
<%= SolidErrors::Error.human_attribute_name(:occurrences) %>
|
|
45
|
-
</dt>
|
|
46
|
-
<dd class="inline-flex items-center gap-1">
|
|
47
|
-
<%= @error.occurrences.size %>
|
|
48
|
-
</dd>
|
|
49
|
-
</div>
|
|
50
|
-
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
51
|
-
<dt class="font-bold">
|
|
52
|
-
<%= SolidErrors::Error.human_attribute_name(:exception_class) %>
|
|
53
|
-
</dt>
|
|
54
|
-
<dd class="inline-flex items-center gap-1">
|
|
55
|
-
<code><%= @error.exception_class %></code>
|
|
56
|
-
</dd>
|
|
57
|
-
</div>
|
|
58
|
-
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
59
|
-
<dt class="font-bold">
|
|
60
|
-
<%= SolidErrors::Error.human_attribute_name(:severity) %>
|
|
61
|
-
</dt>
|
|
62
|
-
<dd class="inline-flex items-center gap-1">
|
|
63
|
-
<%= @error.emoji %>
|
|
64
|
-
<span class="<%= @error.badge_classes %>">
|
|
65
|
-
<%= @error.severity %>
|
|
66
|
-
</span>
|
|
67
|
-
</dd>
|
|
68
|
-
</div>
|
|
69
|
-
<div class="flex items-center justify-between flex-wrap gap-x-2">
|
|
70
|
-
<dt class="font-bold">
|
|
71
|
-
<%= SolidErrors::Error.human_attribute_name(:source) %>
|
|
72
|
-
</dt>
|
|
73
|
-
<dd class="inline-flex items-center gap-1">
|
|
74
|
-
<em><%= @error.source %></em>
|
|
75
|
-
</dd>
|
|
76
|
-
</div>
|
|
77
|
-
<div class="flex items-start justify-between flex-wrap gap-x-2">
|
|
78
|
-
<dt class="font-bold">
|
|
79
|
-
<%= SolidErrors::Error.human_attribute_name(:project_root) %>
|
|
80
|
-
</dt>
|
|
81
|
-
<dd class="">
|
|
82
|
-
<span><%= SolidErrors::BacktraceLine::RAILS_ROOT %></span>
|
|
83
|
-
</dd>
|
|
84
|
-
</div>
|
|
85
|
-
<div class="flex items-start justify-between flex-wrap gap-x-2">
|
|
86
|
-
<dt class="font-bold">
|
|
87
|
-
<%= SolidErrors::Error.human_attribute_name(:gem_root) %>
|
|
88
|
-
</dt>
|
|
89
|
-
<dd class="">
|
|
90
|
-
<ul>
|
|
91
|
-
<% Gem.path.each do |path| %>
|
|
92
|
-
<li><%= path %></li>
|
|
93
|
-
<% end %>
|
|
94
|
-
</ul>
|
|
95
|
-
</dd>
|
|
96
|
-
</div>
|
|
97
|
-
</dl>
|
|
98
|
-
|
|
99
|
-
<%= render "solid_errors/errors/actions", error: @error %>
|
|
100
|
-
<% end %>
|
|
1
|
+
<%= render "solid_errors/errors/error",
|
|
2
|
+
error: @error,
|
|
3
|
+
show_actions: true %>
|
|
101
4
|
|
|
102
5
|
<br>
|
|
103
6
|
<br>
|
|
104
7
|
|
|
105
8
|
<%= render "solid_errors/occurrences/collection",
|
|
106
|
-
occurrences: @
|
|
9
|
+
occurrences: @occurrences,
|
|
10
|
+
page: @page,
|
|
107
11
|
titled: true %>
|
|
@@ -6,9 +6,44 @@
|
|
|
6
6
|
<h2 class="font-bold text-2xl">
|
|
7
7
|
Occurrences
|
|
8
8
|
</h2>
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
<div class="flex gap-x-4 pb-2">
|
|
10
|
+
<p class="text-right">
|
|
11
|
+
<% page_count = page.count %>
|
|
12
|
+
<% if page_count.zero? %>
|
|
13
|
+
No posts found
|
|
14
|
+
<% elsif page.pages == 1 %>
|
|
15
|
+
<strong><%= page_count %></strong> total
|
|
16
|
+
<% else %>
|
|
17
|
+
<strong><%= page.from %>-<%= page.to %></strong> of <strong><%= page_count %></strong>
|
|
18
|
+
<% end %>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<nav aria-label="Pages">
|
|
22
|
+
<% if (first_page = page.first) %>
|
|
23
|
+
<a href="<%= url_for(params.to_unsafe_hash.merge(page: first_page)) %>" aria-label="First" class="border border-black text-black bg-white py-1 px-2 cursor-pointer hover:bg-black hover:text-white">«</a>
|
|
24
|
+
<% else %>
|
|
25
|
+
<a role="link" aria-disabled="true" aria-label="First" class="border text-gray-500 bg-white py-1 px-2">«</a>
|
|
26
|
+
<% end %>
|
|
27
|
+
|
|
28
|
+
<% if (prev_page = page.prev) %>
|
|
29
|
+
<a href="<%= url_for(params.to_unsafe_hash.merge(page: prev_page)) %>" aria-label="Previous" class="border border-black text-black bg-white py-1 px-2 cursor-pointer hover:bg-black hover:text-white">‹</a>
|
|
30
|
+
<% else %>
|
|
31
|
+
<a role="link" aria-disabled="true" aria-label="Previous" class="border text-gray-500 bg-white py-1 px-2">‹</a>
|
|
32
|
+
<% end %>
|
|
33
|
+
|
|
34
|
+
<% if (next_page = page.next) %>
|
|
35
|
+
<a href="<%= url_for(params.to_unsafe_hash.merge(page: next_page)) %>" aria-label="Next" class="border border-black text-black bg-white py-1 px-2 cursor-pointer hover:bg-black hover:text-white">›</a>
|
|
36
|
+
<% else %>
|
|
37
|
+
<a role="link" aria-disabled="true" aria-label="Next" class="border text-gray-500 bg-white py-1 px-2">›</a>
|
|
38
|
+
<% end %>
|
|
39
|
+
|
|
40
|
+
<% if (last_page = page.last) %>
|
|
41
|
+
<a href="<%= url_for(params.to_unsafe_hash.merge(page: last_page)) %>" aria-label="Last" class="border border-black text-black bg-white py-1 px-2 cursor-pointer hover:bg-black hover:text-white">»</a>
|
|
42
|
+
<% else %>
|
|
43
|
+
<a role="link" aria-disabled="true" aria-label="Last" class="border text-gray-500 bg-white py-1 px-2">»</a>
|
|
44
|
+
<% end %>
|
|
45
|
+
</nav>
|
|
46
|
+
</div>
|
|
12
47
|
</div>
|
|
13
48
|
<% end %>
|
|
14
49
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<% seen_at = occurrence.created_at %>
|
|
2
2
|
<% backtrace = occurrence.parsed_backtrace %>
|
|
3
|
+
<% open ||= (defined?(occurrence_counter) && occurrence_counter.zero?) || true %>
|
|
3
4
|
|
|
4
5
|
<%= tag.section id: dom_id(occurrence), class: "" do %>
|
|
5
|
-
<%= tag.details open:
|
|
6
|
+
<%= tag.details open: open do %>
|
|
6
7
|
<summary class="hover:bg-gray-50 p-2 rounded cursor-pointer">
|
|
7
8
|
<%= time_tag seen_at, seen_at %>
|
|
8
9
|
(<em><%= time_ago_in_words(seen_at) %> ago</em>)
|
|
@@ -27,9 +28,13 @@
|
|
|
27
28
|
<% backtrace.lines.each_with_index do |line, i| %>
|
|
28
29
|
<%= tag.details open: line.application? || i.zero? do %>
|
|
29
30
|
<summary class="hover:bg-gray-50 px-2 py-1 rounded cursor-pointer">
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
<% if line.filtered_file %>
|
|
32
|
+
<span class="text-gray-500"><%= File.dirname(line.filtered_file) %>/</span><span class="text-blue-500 font-medium"><%= File.basename(line.filtered_file) %></span>:<span class="text-gray-900 font-medium"><%= line.filtered_number %></span>
|
|
33
|
+
<span class="text-gray-500">in</span>
|
|
34
|
+
<code class="text-green-500 font-medium"><%= line.filtered_method %></code>
|
|
35
|
+
<% else %>
|
|
36
|
+
<span class="text-gray-500"><%= line.unparsed_line %>
|
|
37
|
+
<% end %>
|
|
33
38
|
</summary>
|
|
34
39
|
<div><pre class="flex overflow-auto rounded-b-lg bg-slate-800 p-4 text-sm leading-normal text-white sm:rounded-t-lg"><code class="flex flex-col min-h-full min-w-content px-0"><% line.source.each do |n, code| %>
|
|
35
40
|
<div class="line"><span class="mr-2 text-right select-none text-gray-600"><%= n %></span><span><%= code %></span></div>
|
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
class CreateSolidErrorsTables < ActiveRecord::Migration<%= migration_version %>
|
|
4
4
|
def change
|
|
5
5
|
create_table :solid_errors do |t|
|
|
6
|
-
t.
|
|
7
|
-
t.
|
|
8
|
-
t.
|
|
9
|
-
t.
|
|
6
|
+
t.text :exception_class, null: false
|
|
7
|
+
t.text :message, null: false
|
|
8
|
+
t.text :severity, null: false
|
|
9
|
+
t.text :source
|
|
10
10
|
t.datetime :resolved_at, index: true
|
|
11
|
+
t.string :fingerprint, null: false, limit: 64, index: { unique: true }
|
|
11
12
|
|
|
12
13
|
t.timestamps
|
|
13
|
-
|
|
14
|
-
t.index [:exception_class, :message, :severity, :source], unique: true, name: "solid_error_uniqueness_index"
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
create_table :solid_errors_occurrences do |t|
|
data/lib/solid_errors/engine.rb
CHANGED
|
@@ -80,7 +80,7 @@ module SolidErrors
|
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def sanitize_string(string)
|
|
83
|
-
string.gsub
|
|
83
|
+
string = string.gsub(/#<(.*?):0x.*?>/, '#<\1>') # remove object_id
|
|
84
84
|
return string unless string.respond_to?(:size) && string.size > MAX_STRING_SIZE
|
|
85
85
|
string[0...MAX_STRING_SIZE] + TRUNCATED
|
|
86
86
|
end
|
|
@@ -30,10 +30,11 @@ module SolidErrors
|
|
|
30
30
|
severity: severity,
|
|
31
31
|
source: source
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
fingerprint = Digest::SHA256.hexdigest(error_attributes.values.join)
|
|
34
|
+
if (record = SolidErrors::Error.find_by(fingerprint: fingerprint))
|
|
34
35
|
record.update!(resolved_at: nil, updated_at: Time.now)
|
|
35
36
|
else
|
|
36
|
-
record = SolidErrors::Error.create!(error_attributes)
|
|
37
|
+
record = SolidErrors::Error.create!(error_attributes.merge(fingerprint: fingerprint))
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
SolidErrors::Occurrence.create(
|
data/lib/solid_errors/version.rb
CHANGED
data/lib/solid_errors.rb
CHANGED
|
@@ -7,8 +7,11 @@ require_relative "solid_errors/engine"
|
|
|
7
7
|
|
|
8
8
|
module SolidErrors
|
|
9
9
|
mattr_accessor :connects_to
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
mattr_writer :username
|
|
11
|
+
mattr_writer :password
|
|
12
|
+
mattr_writer :send_emails
|
|
13
|
+
mattr_writer :email_from
|
|
14
|
+
mattr_writer :email_to
|
|
12
15
|
|
|
13
16
|
class << self
|
|
14
17
|
# use method instead of attr_accessor to ensure
|
|
@@ -22,5 +25,17 @@ module SolidErrors
|
|
|
22
25
|
def password
|
|
23
26
|
@password ||= ENV["SOLIDERRORS_PASSWORD"] || @@password
|
|
24
27
|
end
|
|
28
|
+
|
|
29
|
+
def send_emails?
|
|
30
|
+
@send_emails ||= ENV["SOLIDERRORS_SEND_EMAILS"] || @@send_emails || true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def email_from
|
|
34
|
+
@email_from ||= ENV["SOLIDERRORS_EMAIL_FROM"] || @@email_from || "solid_errors@noreply.com"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def email_to
|
|
38
|
+
@email_to ||= ENV["SOLIDERRORS_EMAIL_TO"] || @@email_to
|
|
39
|
+
end
|
|
25
40
|
end
|
|
26
41
|
end
|
metadata
CHANGED
|
@@ -1,17 +1,87 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solid_errors
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stephen Margheim
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-04-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: actionmailer
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '7.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '7.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: actionpack
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '7.0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '7.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: actionview
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '7.0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '7.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: activerecord
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '7.0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '7.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: activesupport
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '7.0'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '7.0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: railties
|
|
15
85
|
requirement: !ruby/object:Gem::Requirement
|
|
16
86
|
requirements:
|
|
17
87
|
- - "~>"
|
|
@@ -49,14 +119,19 @@ files:
|
|
|
49
119
|
- Rakefile
|
|
50
120
|
- app/controllers/solid_errors/application_controller.rb
|
|
51
121
|
- app/controllers/solid_errors/errors_controller.rb
|
|
122
|
+
- app/mailers/solid_errors/error_mailer.rb
|
|
52
123
|
- app/models/solid_errors/backtrace.rb
|
|
53
124
|
- app/models/solid_errors/backtrace_line.rb
|
|
54
125
|
- app/models/solid_errors/error.rb
|
|
55
126
|
- app/models/solid_errors/occurrence.rb
|
|
56
127
|
- app/models/solid_errors/record.rb
|
|
128
|
+
- app/views/layouts/solid_errors/_style.html
|
|
57
129
|
- app/views/layouts/solid_errors/application.html.erb
|
|
130
|
+
- app/views/solid_errors/error_mailer/error_occurred.html.erb
|
|
131
|
+
- app/views/solid_errors/error_mailer/error_occurred.text.erb
|
|
58
132
|
- app/views/solid_errors/errors/_actions.html.erb
|
|
59
133
|
- app/views/solid_errors/errors/_error.html.erb
|
|
134
|
+
- app/views/solid_errors/errors/_row.html.erb
|
|
60
135
|
- app/views/solid_errors/errors/index.html.erb
|
|
61
136
|
- app/views/solid_errors/errors/show.html.erb
|
|
62
137
|
- app/views/solid_errors/occurrences/_collection.html.erb
|