sidekiq-failures 0.4.5 → 1.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.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +37 -0
- data/CHANGELOG.md +35 -4
- data/Gemfile +6 -0
- data/README.md +13 -6
- data/lib/sidekiq/failures/locales/ja.yml +6 -0
- data/lib/sidekiq/failures/locales/pt-BR.yml +5 -0
- data/lib/sidekiq/failures/locales/zh-cn.yml +5 -0
- data/lib/sidekiq/failures/middleware.rb +3 -2
- data/lib/sidekiq/failures/sorted_entry.rb +8 -1
- data/lib/sidekiq/failures/version.rb +1 -1
- data/lib/sidekiq/failures/views/failure.erb +37 -29
- data/lib/sidekiq/failures/views/failure_legacy.erb +31 -0
- data/lib/sidekiq/failures/views/failures.erb +106 -78
- data/lib/sidekiq/failures/views/failures_legacy.erb +105 -0
- data/lib/sidekiq/failures/web_extension.rb +126 -28
- data/lib/sidekiq/failures.rb +38 -7
- data/sidekiq-failures.gemspec +10 -3
- data/test/failures_test.rb +16 -0
- data/test/middleware_test.rb +87 -82
- data/test/test_helper.rb +5 -5
- data/test/web_extension_test.rb +156 -89
- metadata +30 -15
- data/.travis.yml +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ba0a7d8ecb1ed1f847be0918723281d6c12d7f40a4780c089340cc8e687183f3
|
4
|
+
data.tar.gz: 10aca014769f8883c9de557bded7ac01287276924ad314ec1006d6d0e1c332bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bc85386b596a67b27e00b6c2efed3377f8377bb89dd4eb128336b0f1bf4150acd361c3be1f1ed8dce233710031f3bd9b17d09d4c85b7ee7673da67ba7649d89
|
7
|
+
data.tar.gz: 236381eb70f14564b3dd43fc715ad8ac3f5578973b4c20fb95f8f6cfcedadb82db922c1cb8eafed13e6c5189d5218ec0c959dbe559592413b727da2ef18fed25
|
@@ -0,0 +1,37 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
fail-fast: false
|
14
|
+
matrix:
|
15
|
+
ruby: [2.6, 2.7, '3.0', 3.1, 3.4.3]
|
16
|
+
sidekiq: [4.2, 5.2, 6.2, 8.0.3]
|
17
|
+
services:
|
18
|
+
redis:
|
19
|
+
image: redis
|
20
|
+
options: >-
|
21
|
+
--health-cmd "redis-cli ping"
|
22
|
+
--health-interval 10s
|
23
|
+
--health-timeout 5s
|
24
|
+
--health-retries 5
|
25
|
+
ports:
|
26
|
+
- 6379:6379
|
27
|
+
env:
|
28
|
+
SIDEKIQ_VERSION: ~> ${{ matrix.sidekiq }}
|
29
|
+
steps:
|
30
|
+
- uses: actions/checkout@v4
|
31
|
+
- name: Set up Ruby
|
32
|
+
uses: ruby/setup-ruby@v1
|
33
|
+
with:
|
34
|
+
bundler-cache: true # 'bundle install' and cache gems
|
35
|
+
ruby-version: ${{ matrix.ruby }}
|
36
|
+
- name: Run tests
|
37
|
+
run: bundle exec rake
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,36 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
## 1.1.0
|
4
|
+
|
5
|
+
* Add support for Sidekiq 8.x (#145 @navidemad)
|
6
|
+
* Fix nil exception in safe_relative_time (#152 @leedrum)
|
7
|
+
|
8
|
+
## 1.0.4
|
9
|
+
|
10
|
+
* Sanitize failure text on the failure details page (#144 @mcasper)
|
11
|
+
|
12
|
+
## 1.0.3
|
13
|
+
|
14
|
+
* Expand failure descriptions with pure JS (#141 @icyleaf)
|
15
|
+
|
16
|
+
## 1.0.2
|
17
|
+
|
18
|
+
* Pass now required argument to Sidekiq's JobRetry.new (#140 @mcasper)
|
19
|
+
|
20
|
+
## 1.0.1
|
21
|
+
|
22
|
+
* Add license config to the gemspec (#115 @reiz)
|
23
|
+
* Guard against failure error_message being `nil` (#122 @mcasper)
|
24
|
+
* Fix filtering failures with 0 results on Sidekiq Pro (#125 @substars)
|
25
|
+
|
26
|
+
## 1.0.0
|
27
|
+
|
28
|
+
* WebUI improvements (@bbtfr)
|
29
|
+
* Use ActiveJob to display info when available (@dreyks)
|
30
|
+
* New locales (@ryohashimoto @gurgelrenan)
|
31
|
+
* Sidekiq 4 and higher compatibility (@davekrupinski )
|
32
|
+
* Sidekiq 5 fixes (@fidelisrafael)
|
33
|
+
|
3
34
|
## 0.4.5
|
4
35
|
|
5
36
|
* Limit error message to 500 symbols (@antonzaytsev)
|
@@ -35,8 +66,8 @@
|
|
35
66
|
## 0.3.0
|
36
67
|
|
37
68
|
* Bump sidekiq dependency to sidekiq >= 2.14.0
|
38
|
-
* Remove slim templates and
|
39
|
-
* Escape exception info when
|
69
|
+
* Remove slim templates and dependency
|
70
|
+
* Escape exception info when outputting to html
|
40
71
|
* Add `Sidekiq::Failures.reset_failures` helper method
|
41
72
|
* Add `Sidekiq::Failures.count` helper method (@zanker)
|
42
73
|
* Adhere to sidekiq approach of showing UTC times
|
@@ -59,8 +90,8 @@
|
|
59
90
|
* Added processor identity to failure data (@krasnoukhov)
|
60
91
|
* Handle Sidekiq::Shutdown exceptions (@krasnoukhov)
|
61
92
|
* Add failures maximum count option (@mathieulaporte)
|
62
|
-
* User
|
63
|
-
* Removed web
|
93
|
+
* User Exception#message instead of Exception#to_s (@supaspoida)
|
94
|
+
* Removed web dependencies (@LongMan)
|
64
95
|
* Stop overloading find_template (@zquestz)
|
65
96
|
|
66
97
|
## 0.1.0
|
data/Gemfile
CHANGED
@@ -4,3 +4,9 @@ source 'https://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
gem 'sidekiq', ENV['SIDEKIQ_VERSION'] if ENV['SIDEKIQ_VERSION']
|
7
|
+
|
8
|
+
# to test Pro-specific functionality, set SIDEKIQ_PRO_CREDS on `bundle install`
|
9
|
+
# and SIDEKIQ_PRO_VERSION on `bundle install` and `rake test`
|
10
|
+
source "https://#{ENV['SIDEKIQ_PRO_CREDS']}@enterprise.contribsys.com/" do
|
11
|
+
gem 'sidekiq-pro', ENV['SIDEKIQ_PRO_VERSION'] if ENV['SIDEKIQ_PRO_VERSION']
|
12
|
+
end if ENV['SIDEKIQ_PRO_VERSION']
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Sidekiq::Failures
|
1
|
+
# Sidekiq::Failures 
|
2
2
|
|
3
3
|
Keeps track of Sidekiq failed jobs and adds a tab to the Web UI to let you browse
|
4
4
|
them. Makes use of Sidekiq's custom tabs and middleware chain.
|
@@ -20,6 +20,8 @@ gem 'sidekiq-failures'
|
|
20
20
|
Simply having the gem in your Gemfile is enough to get you started. Your failed
|
21
21
|
jobs will be visible via a Failures tab in the Web UI.
|
22
22
|
|
23
|
+
If you have not previously used the Web UI, it is a part of the Sidekiq gem. [See Sidekiq's docs about Web UI here.](https://github.com/mperham/sidekiq/wiki/Monitoring#web-ui)
|
24
|
+
|
23
25
|
## Configuring
|
24
26
|
|
25
27
|
### Maximum Tracked Failures
|
@@ -125,18 +127,23 @@ influenced by `failures_max_count`.
|
|
125
127
|
Sidekiq::Failures.count
|
126
128
|
```
|
127
129
|
|
128
|
-
### Reset Failures
|
130
|
+
### Reset and clear Failures
|
131
|
+
|
132
|
+
Gives a convenient way of resetting Sidekiq Failure stored failed jobs programmatically.
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
Sidekiq::Failures.clear_failures
|
136
|
+
```
|
129
137
|
|
130
|
-
|
131
|
-
Takes an options hash and if the `counter` key is present also resets Sidekiq own failed stats.
|
138
|
+
To reset Sidekiq own failed *stats*.
|
132
139
|
|
133
140
|
```ruby
|
134
|
-
Sidekiq::Failures.
|
141
|
+
Sidekiq::Failures.reset_failure_count
|
135
142
|
```
|
136
143
|
|
137
144
|
## Dependencies
|
138
145
|
|
139
|
-
Depends on Sidekiq >=
|
146
|
+
Depends on Sidekiq >= 4.0.0
|
140
147
|
|
141
148
|
## Contributing
|
142
149
|
|
@@ -80,11 +80,12 @@ module Sidekiq
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def retry_middleware
|
83
|
-
@retry_middleware ||=
|
83
|
+
@retry_middleware ||=
|
84
|
+
Sidekiq::Failures.retry_middleware_class.new(@config || {})
|
84
85
|
end
|
85
86
|
|
86
87
|
def default_max_retries
|
87
|
-
Sidekiq::
|
88
|
+
Sidekiq::Failures.retry_middleware_class::DEFAULT_MAX_RETRY_ATTEMPTS
|
88
89
|
end
|
89
90
|
|
90
91
|
def hostname
|
@@ -11,7 +11,14 @@ module Sidekiq
|
|
11
11
|
|
12
12
|
def retry_failure
|
13
13
|
Sidekiq.redis do |conn|
|
14
|
-
|
14
|
+
# from Redis v6.2.0, zrangebyscore is deprecated and zrange with BYSCORE is used
|
15
|
+
# option byscore is available from redis-rb v4.6.0
|
16
|
+
results = if Gem::Version.new(conn.info["redis_version"].to_s) >= Gem::Version.new('6.2.0') &&
|
17
|
+
(Gem.loaded_specs['redis'].nil? || Gem.loaded_specs['redis'].version >= Gem::Version.new('4.6.0'))
|
18
|
+
conn.zrange(Sidekiq::Failures::LIST_KEY, score.to_i, score.to_i, byscore: true)
|
19
|
+
else
|
20
|
+
conn.zrangebyscore(Sidekiq::Failures::LIST_KEY, score, score)
|
21
|
+
end
|
15
22
|
conn.zremrangebyscore(Sidekiq::Failures::LIST_KEY, score, score)
|
16
23
|
results.map do |message|
|
17
24
|
msg = Sidekiq.load_json(message)
|
@@ -1,31 +1,39 @@
|
|
1
1
|
<%= erb :_job_info, :locals => {:job => @failure, :type => :failure} %>
|
2
2
|
|
3
|
-
<
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
</
|
3
|
+
<section>
|
4
|
+
<header>
|
5
|
+
<h2><%= t('Error') %></h2>
|
6
|
+
</header>
|
7
|
+
|
8
|
+
<div class="table_container">
|
9
|
+
<table>
|
10
|
+
<tbody>
|
11
|
+
<tr>
|
12
|
+
<th><%= t('ErrorClass') %></th>
|
13
|
+
<td>
|
14
|
+
<code><%= h @failure['error_class'] %></code>
|
15
|
+
</td>
|
16
|
+
</tr>
|
17
|
+
<tr>
|
18
|
+
<th><%= t('ErrorMessage') %></th>
|
19
|
+
<td><%= h @failure['error_message'] %></td>
|
20
|
+
</tr>
|
21
|
+
<% if !@failure['error_backtrace'].nil? %>
|
22
|
+
<tr>
|
23
|
+
<th><%= t('ErrorBacktrace') %></th>
|
24
|
+
<td>
|
25
|
+
<code><%= @failure['error_backtrace'].join("<br/>") %></code>
|
26
|
+
</td>
|
27
|
+
</tr>
|
28
|
+
<% end %>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<form action="<%= root_path %>failures/<%= job_params(@failure, @failure.score) %>" method="post">
|
34
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
35
|
+
<a class="btn btn-default" href="<%= root_path %>failures"><%= t('GoBack') %></a>
|
36
|
+
<input class="btn btn-primary" type="submit" name="retry" value="<%= t('RetryNow') %>" />
|
37
|
+
<input class="btn btn-danger" type="submit" name="delete" value="<%= t('Delete') %>" />
|
38
|
+
</form>
|
39
|
+
</section>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<%= erb :_job_info, :locals => {:job => @failure, :type => :failure} %>
|
2
|
+
|
3
|
+
<h3><%= t('Error') %></h3>
|
4
|
+
<table class="error table table-bordered table-striped">
|
5
|
+
<tbody>
|
6
|
+
<tr>
|
7
|
+
<th><%= t('ErrorClass') %></th>
|
8
|
+
<td>
|
9
|
+
<code><%= h @failure['error_class'] %></code>
|
10
|
+
</td>
|
11
|
+
</tr>
|
12
|
+
<tr>
|
13
|
+
<th><%= t('ErrorMessage') %></th>
|
14
|
+
<td><%= h @failure['error_message'] %></td>
|
15
|
+
</tr>
|
16
|
+
<% if !@failure['error_backtrace'].nil? %>
|
17
|
+
<tr>
|
18
|
+
<th><%= t('ErrorBacktrace') %></th>
|
19
|
+
<td>
|
20
|
+
<code><%= @failure['error_backtrace'].join("<br/>") %></code>
|
21
|
+
</td>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
24
|
+
</tbody>
|
25
|
+
</table>
|
26
|
+
<form class="form-horizontal" action="<%= root_path %>failures/<%= job_params(@failure, @failure.score) %>" method="post">
|
27
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
28
|
+
<a class="btn" href="<%= root_path %>failures"><%= t('GoBack') %></a>
|
29
|
+
<input class="btn btn-primary" type="submit" name="retry" value="<%= t('RetryNow') %>" />
|
30
|
+
<input class="btn btn-danger" type="submit" name="delete" value="<%= t('Delete') %>" />
|
31
|
+
</form>
|
@@ -1,85 +1,113 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
<section>
|
2
|
+
<header>
|
3
|
+
<h1>
|
4
|
+
<span class="title"><%= t('FailedJobs') %></span>
|
5
|
+
<span class="badge badge-secondary"><%= number_with_delimiter(@failures.count) %></span>
|
6
|
+
</h1>
|
7
|
+
<% if @failures.count > 0 && @total_size > @count %>
|
7
8
|
<%= erb :_paging, :locals => { :url => "#{root_path}failures" } %>
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
</header>
|
9
|
+
<% end %>
|
10
|
+
<%= filtering('failures') if respond_to?(:filtering) %>
|
11
|
+
</header>
|
12
12
|
|
13
|
-
<% if @failures.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
</td>
|
57
|
-
</tr>
|
58
|
-
<% end %>
|
59
|
-
</table>
|
60
|
-
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="<%= t('RetryNow') %>" />
|
61
|
-
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="<%= t('Delete') %>" />
|
62
|
-
</form>
|
13
|
+
<% if @failures.count > 0 %>
|
14
|
+
<form action="<%= root_path %>failures" method="post">
|
15
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
16
|
+
<div class="table_container">
|
17
|
+
<table>
|
18
|
+
<thead>
|
19
|
+
<tr>
|
20
|
+
<th width="20px" class="table-checkbox">
|
21
|
+
<label>
|
22
|
+
<input type="checkbox" class="check_all" />
|
23
|
+
</label>
|
24
|
+
</th>
|
25
|
+
<th><%= t('FailedAt') %></th>
|
26
|
+
<th><%= t('Queue') %></th>
|
27
|
+
<th><%= t('Worker') %></th>
|
28
|
+
<th><%= t('Arguments') %></th>
|
29
|
+
<th><%= t('Error') %></th>
|
30
|
+
</tr>
|
31
|
+
</thead>
|
32
|
+
<% @failures.each do |entry| %>
|
33
|
+
<tr>
|
34
|
+
<td class="table-checkbox">
|
35
|
+
<label>
|
36
|
+
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
|
37
|
+
</label>
|
38
|
+
</td>
|
39
|
+
<td>
|
40
|
+
<a href="<%= root_path %>failures/<%= job_params(entry.item, entry.score) %>"><%= safe_relative_time(entry['failed_at']) %></a>
|
41
|
+
</td>
|
42
|
+
<td>
|
43
|
+
<a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
|
44
|
+
</td>
|
45
|
+
<td><%= entry.respond_to?(:display_class) ? entry.display_class : entry.klass %></td>
|
46
|
+
<td>
|
47
|
+
<code>
|
48
|
+
<div class="args"><%= display_args(entry.respond_to?(:display_args) ? entry.display_args : entry.args) %></div>
|
49
|
+
</code>
|
50
|
+
</td>
|
51
|
+
<td>
|
52
|
+
<% error_class = entry['error_class'].to_s %>
|
53
|
+
<% error_message = entry['error_message'].to_s %>
|
54
|
+
<% error_text = "#{h(error_class)}: #{h(error_message)}" %>
|
55
|
+
<% truncated_error = truncate(error_text, 200) %>
|
63
56
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
57
|
+
<% if entry['error_backtrace'] %>
|
58
|
+
<details>
|
59
|
+
<summary>
|
60
|
+
<%= truncated_error %>
|
61
|
+
</summary>
|
62
|
+
<% if entry['error_backtrace'] %>
|
63
|
+
<code>
|
64
|
+
<%= entry['error_backtrace'].join("<br/>") %>
|
65
|
+
</code>
|
66
|
+
<% end %>
|
67
|
+
</details>
|
68
|
+
<% else %>
|
69
|
+
<div>
|
70
|
+
<%= truncated_error %>
|
71
|
+
</div>
|
72
|
+
<% end %>
|
73
|
+
<div>
|
74
|
+
<span>Processor: <%= entry['processor'] %></span>
|
75
|
+
</div>
|
76
|
+
</td>
|
77
|
+
</tr>
|
78
|
+
<% end %>
|
79
|
+
</table>
|
80
|
+
</div>
|
81
|
+
<div class="buttons-row">
|
82
|
+
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="<%= t('RetryNow') %>" />
|
83
|
+
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="<%= t('Delete') %>" />
|
84
|
+
</div>
|
85
|
+
</form>
|
72
86
|
|
73
|
-
|
74
|
-
|
75
|
-
|
87
|
+
<div class="buttons-row">
|
88
|
+
<form action="<%= root_path %>failures/all/delete" method="post">
|
89
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
90
|
+
<input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSure') %>" />
|
91
|
+
</form>
|
92
|
+
<form action="<%= root_path %>failures/all/retry" method="post">
|
93
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
94
|
+
<input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="<%= t('RetryAll') %>" data-confirm="<%= t('AreYouSure') %>" />
|
95
|
+
</form>
|
76
96
|
</div>
|
97
|
+
|
98
|
+
<% if @failures.count > 0 && @total_size > @count %>
|
99
|
+
<div>
|
100
|
+
<%= erb :_paging, :locals => { :url => "#{root_path}failures" } %>
|
101
|
+
</div>
|
102
|
+
<% end %>
|
103
|
+
<% else %>
|
104
|
+
<div class="alert alert-success"><%= t('NoFailedJobsFound') %></div>
|
77
105
|
<% end %>
|
78
106
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
<
|
83
|
-
|
84
|
-
|
85
|
-
</
|
107
|
+
<div class="buttons-row">
|
108
|
+
<form action="<%= root_path %>failures/all/reset" method="post">
|
109
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
110
|
+
<input class="btn btn-danger btn-xs pull-right" type="submit" name="reset" value="<%= t('ResetCounter') %>" data-confirm="<%= t('AreYouSure') %>" />
|
111
|
+
</form>
|
112
|
+
</div>
|
113
|
+
</section>
|
@@ -0,0 +1,105 @@
|
|
1
|
+
<header class="row">
|
2
|
+
<div class="col-sm-5">
|
3
|
+
<h3><%= t('FailedJobs') %></h3>
|
4
|
+
</div>
|
5
|
+
<% if @failures.count > 0 && @total_size > @count %>
|
6
|
+
<div class="col-sm-4">
|
7
|
+
<%= erb :_paging, :locals => { :url => "#{root_path}failures" } %>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
<%= filtering('failures') if respond_to?(:filtering) %>
|
11
|
+
</header>
|
12
|
+
|
13
|
+
<% if @failures.count > 0 %>
|
14
|
+
<form action="<%= root_path %>failures" method="post">
|
15
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
16
|
+
<table class="table table-striped table-bordered table-white">
|
17
|
+
<thead>
|
18
|
+
<tr>
|
19
|
+
<th width="20px" class="table-checkbox">
|
20
|
+
<label>
|
21
|
+
<input type="checkbox" class="check_all" />
|
22
|
+
</label>
|
23
|
+
</th>
|
24
|
+
<th><%= t('FailedAt') %></th>
|
25
|
+
<th><%= t('Queue') %></th>
|
26
|
+
<th><%= t('Worker') %></th>
|
27
|
+
<th><%= t('Arguments') %></th>
|
28
|
+
<th><%= t('Error') %></th>
|
29
|
+
</tr>
|
30
|
+
</thead>
|
31
|
+
<% @failures.each do |entry| %>
|
32
|
+
<tr>
|
33
|
+
<td class="table-checkbox">
|
34
|
+
<label>
|
35
|
+
<input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
|
36
|
+
</label>
|
37
|
+
</td>
|
38
|
+
<td>
|
39
|
+
<a href="<%= root_path %>failures/<%= job_params(entry.item, entry.score) %>"><%= safe_relative_time(entry['failed_at']) %></a>
|
40
|
+
</td>
|
41
|
+
<td>
|
42
|
+
<a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
|
43
|
+
</td>
|
44
|
+
<td><%= entry.respond_to?(:display_class) ? entry.display_class : entry.klass %></td>
|
45
|
+
<td>
|
46
|
+
<div class="args"><%= display_args(entry.respond_to?(:display_args) ? entry.display_args : entry.args) %></div>
|
47
|
+
</td>
|
48
|
+
<td style="overflow: auto; padding: 10px;">
|
49
|
+
<a class="backtrace" href="javascript:void(0)", onclick="toggle_error_backtrace(this)">
|
50
|
+
<%= h entry['error_class'] %>: <%= h entry['error_message'].to_s.size > 500 ? entry['error_message'][0..500] + '...' : entry['error_message'] %>
|
51
|
+
</a>
|
52
|
+
<pre style="display: none; background: none; border: 0; width: 100%; max-height: 30em; font-size: 0.8em; white-space: nowrap; overflow: auto;">
|
53
|
+
<%= entry['error_backtrace'].join("<br />") if entry['error_backtrace'] %>
|
54
|
+
</pre>
|
55
|
+
<p>
|
56
|
+
<span>Processor: <%= entry['processor'] %></span>
|
57
|
+
</p>
|
58
|
+
</td>
|
59
|
+
</tr>
|
60
|
+
<% end %>
|
61
|
+
</table>
|
62
|
+
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="<%= t('RetryNow') %>" />
|
63
|
+
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="<%= t('Delete') %>" />
|
64
|
+
</form>
|
65
|
+
|
66
|
+
<form action="<%= root_path %>failures/all/delete" method="post">
|
67
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
68
|
+
<input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSure') %>" />
|
69
|
+
</form>
|
70
|
+
<form action="<%= root_path %>failures/all/retry" method="post">
|
71
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
72
|
+
<input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="<%= t('RetryAll') %>" data-confirm="<%= t('AreYouSure') %>" />
|
73
|
+
</form>
|
74
|
+
|
75
|
+
<% if @failures.count > 0 && @total_size > @count %>
|
76
|
+
<div class="col-sm-4">
|
77
|
+
<%= erb :_paging, :locals => { :url => "#{root_path}failures" } %>
|
78
|
+
</div>
|
79
|
+
<% end %>
|
80
|
+
|
81
|
+
<script>
|
82
|
+
function toggle_error_backtrace(e) {
|
83
|
+
let x = e.nextElementSibling;
|
84
|
+
if (x.style.display === "none") {
|
85
|
+
x.style.display = "block";
|
86
|
+
} else {
|
87
|
+
x.style.display = "none";
|
88
|
+
}
|
89
|
+
}
|
90
|
+
</script>
|
91
|
+
|
92
|
+
<style type="text/css">
|
93
|
+
@media only screen and (prefers-color-scheme: dark) {
|
94
|
+
pre {
|
95
|
+
color: white
|
96
|
+
}
|
97
|
+
}
|
98
|
+
</style>
|
99
|
+
<% else %>
|
100
|
+
<div class="alert alert-success"><%= t('NoFailedJobsFound') %></div>
|
101
|
+
<% end %>
|
102
|
+
<form action="<%= root_path %>failures/all/reset" method="post">
|
103
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
104
|
+
<input class="btn btn-danger btn-xs pull-right" type="submit" name="reset" value="<%= t('ResetCounter') %>" data-confirm="<%= t('AreYouSure') %>" />
|
105
|
+
</form>
|