resque-cleanerer 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 169e0b85f5b87c2b4fe7a19a763ab2b8a2db96f5625021b2a1888b71dd670e26
4
+ data.tar.gz: b3246d131619b8f8ff3612aa87b1958fe81df8b31f117a94681804dca3d56e35
5
+ SHA512:
6
+ metadata.gz: a4c8a7104f3251aa8dc3e25823265cb8d7c4cef6b070e9f9e3cdef652792928f95d237fd19f6f61c8c412f43ec4f09db4745a4c2e1f19917f43ac781adb25ce7
7
+ data.tar.gz: 5fb2ca512f0b3f06628e6a4f9b7a5044257a36c717ba107d06bd6ff45ef43b05a3c495e51cc02f2d1b5867018fdc496be968b7b2df0aa54b4a7f67cdf56c2fac
data/CHANGELOG.md ADDED
@@ -0,0 +1,92 @@
1
+ ## 0.4.1 (2018-01-25)
2
+
3
+ * Remove Requeue version lock (#46)
4
+
5
+ ## 0.4.0 (2017-11-20)
6
+
7
+ * Render CSS as ERB partial to make Rails 5 compatible (#45)
8
+
9
+ ## 0.3.2 (2016-03-09)
10
+
11
+ * Handle failure JSON with nil on payload safely (#40)
12
+
13
+ ## 0.3.1 (2016-01-28)
14
+
15
+ * Bug fix: fix the issue regex is not applied on bulk clearance (#36)
16
+
17
+ ## 0.3.0 (2014-05-27)
18
+
19
+ * Search by regex (#27)
20
+ * Show stats by exception (#29)
21
+ * Stop supporting ruby 1.8.x and 1.9.2
22
+ * Escape query parameters (#30)
23
+
24
+ ## 0.2.12 (2013-12-03)
25
+
26
+ * Remove Resque::Helpers include (#23)
27
+ * Tweak Gemspec (#24)
28
+ * Don't use yaml format to show arguments
29
+ * Tweak README
30
+
31
+ ## 0.2.11 (2013-07-19)
32
+
33
+ * Use transaction for retry-and-clear (#22).
34
+ * Fix for CI
35
+
36
+ ## 0.2.10 (2012-10-15)
37
+
38
+ * Bug fix: use URL helper to support resque-web which is not hosted under '/'.
39
+
40
+ ## 0.2.9 (2012-05-10)
41
+
42
+ * Make limiter configurable on resque-web.
43
+
44
+ ## 0.2.8 (2012-03-19)
45
+
46
+ * UI tweak (#15)
47
+
48
+ ## 0.2.7 (2012-01-17)
49
+
50
+ * Support Travis CI
51
+ * Support failure jobs without payload information (#11).
52
+
53
+ ## 0.2.6 (2011-08-23)
54
+
55
+ * Follow the latest resque for date format.
56
+
57
+ ## 0.2.5 (2011-05-05)
58
+
59
+ * BUGFIX: Pagination has been broken.
60
+ * Dump a list as JSON format.
61
+
62
+ ## 0.2.4 (2011-04-19)
63
+
64
+ * BUGFIX: "Select All" ignores exception filter.
65
+
66
+ ## 0.2.3 (2011-04-11)
67
+
68
+ * Exception filter.
69
+
70
+ ## 0.2.2 (2011-04-07)
71
+
72
+ * Changed a way to load yajl/json\_gem.
73
+
74
+ ## 0.2.1 (2011-04-06)
75
+
76
+ * BUGFIX: Bulk action didn't work properly when you select all jobs.
77
+ * Removed absolute paths from html.
78
+
79
+ ## 0.2.0 (2011-04-06)
80
+
81
+ * Extended with resque-web
82
+
83
+ ## 0.1.1 (2010-12-30)
84
+
85
+ * Fixed for ruby 1.9.2
86
+ * Fixed a bug on #retried? method
87
+
88
+ ## 0.1.0 (2010-11-24)
89
+
90
+ * First official release
91
+
92
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Tatsuya Ono
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,333 @@
1
+ ResqueCleaner
2
+ =============
3
+
4
+ [github.com/ono/resque-cleaner](https://github.com/ono/resque-cleaner)
5
+
6
+ This project is not active.
7
+ Please read [this](https://github.com/ono/resque-cleaner/issues/47) before you use the library.
8
+
9
+ Description
10
+ -----------
11
+
12
+ ResqueCleaner is a [Resque](https://github.com/defunkt/resque) plugin which
13
+ aims to help you to clean up failed jobs on Resque by:
14
+
15
+ * Showing stats of failed jobs
16
+ * Retrying failed jobs
17
+ * Removing failed jobs
18
+ * Filtering failed jobs
19
+
20
+
21
+ Installation
22
+ ------------
23
+
24
+ Install as a gem:
25
+
26
+ $ gem install resque-cleaner
27
+
28
+
29
+ Resque-Web integration
30
+ ----------------------
31
+
32
+ ![Screen 1](https://github.com/ono/resque-cleaner/raw/master/misc/resque-cleaner-main.png)
33
+ ![Screen 2](misc/resque-cleaner-list-with-regex.png)
34
+
35
+
36
+ Configuration
37
+ -------------
38
+
39
+ At first, you have to load ResqueCleaner to enable the Cleaner tab. Here is
40
+ an example step.
41
+
42
+ 1. Create a configuration file for resque-web
43
+ <br/>```touch [app_dir]/config/resque-web.rb```
44
+
45
+ 2. Add the following line into the file
46
+ <br/>```require 'resque-cleaner'```
47
+
48
+ 3. Then pass the file when you start resque-web
49
+ <br/>```% resque-web [app_dir]/config/resque-web.rb```
50
+
51
+ You can also configure [limiter](https://github.com/ono/resque-cleaner#limiter)
52
+ in the file.
53
+
54
+ e.g.
55
+
56
+ ```ruby
57
+ require 'resque-cleaner'
58
+ module Resque::Plugins
59
+ ResqueCleaner::Limiter.default_maximum = 10_000
60
+ end
61
+ ```
62
+
63
+ Console
64
+ -------
65
+
66
+ Hopefully a situation of your failed jobs is simple enough to get figured out through
67
+ the web interface. But, if not, a powerful filtering feature of ResqueCleaner may help
68
+ you to understand what is going on with your console(irb).
69
+
70
+ **Create Instance**
71
+
72
+ ```ruby
73
+ > cleaner = Resque::Plugins::ResqueCleaner.new
74
+ ```
75
+
76
+ **Show Stats**
77
+
78
+ Shows stats of failed jobs grouped by date.
79
+
80
+ ```ruby
81
+ > cleaner.stats_by_date
82
+ 2009/03/13: 6
83
+ 2009/11/13: 14
84
+ 2010/08/13: 22
85
+ total: 42
86
+ => {'2009/03/10' => 6, ...}
87
+ ```
88
+
89
+ You could also group them by class.
90
+
91
+ ```ruby
92
+ > cleaner.stats_by_class
93
+ BadJob: 3
94
+ HorribleJob: 7
95
+ total: 10
96
+ => {'BadJob' => 3, ...}
97
+ ```
98
+
99
+ Or you could also group them by exception.
100
+
101
+ ```ruby
102
+ > cleaner.stats_by_exception
103
+ RuntimeError: 35
104
+ SyntaxError: 7
105
+ total: 42
106
+ => {'RuntimeError' => 35, ...}
107
+ ```
108
+
109
+ You can get the ones filtered with a block: it targets only jobs which the block
110
+ evaluates true.
111
+
112
+ e.g. Show stats only of jobs entered with some arguments:
113
+
114
+ ```ruby
115
+ > cleaner.stats_by_date {|j| j["payload"]["args"].size > 0}
116
+ 2009/03/13: 3
117
+ 2009/11/13: 7
118
+ 2010/08/13: 11
119
+ total: 22
120
+ => {'2009/03/10' => 3, ...}
121
+ ```
122
+
123
+ A convenience helper for searching for failed jobs which satisfy a
124
+ regular expression:
125
+
126
+ ```ruby
127
+ cleaner.select_by_regex(/Jason/) # => all failed jobs that have "Jason" in them
128
+ ```
129
+
130
+ **Retry(Requeue) Jobs**
131
+
132
+ You can retry all failed jobs with this method.
133
+
134
+ ```ruby
135
+ > cleaner.requeue
136
+ ```
137
+
138
+ Of course, you can filter jobs with a block; it requeues only jobs which the
139
+ block evaluates true.
140
+
141
+ e.g. Retry only jobs with some arguments:
142
+
143
+ ```ruby
144
+ > cleaner.requeue {|j| j["payload"]["args"].size > 0}
145
+ ```
146
+
147
+ The job hash is extended with a module which defines some useful methods. You
148
+ can use it in the block.
149
+
150
+ e.g. Retry only jobs entered within a day:
151
+
152
+ ```ruby
153
+ > cleaner.requeue {|j| j.after?(1.day.ago)}
154
+ ```
155
+
156
+ e.g. Retry EmailJob entered with arguments within 3 days:
157
+
158
+ ```ruby
159
+ > cleaner.requeue {|j| j.after?(3.days.ago) && j.klass?(EmailJob) && j["payload"]["args"].size>0}
160
+ ```
161
+
162
+ See Helper Methods section bellow for more information.
163
+
164
+ NOTE:
165
+ [1.day.ago](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/numeric/time.rb)
166
+ is not in standard library. Using it for making explanation more understandable. It is equivalent to `Time.now - 60*60*24*3`.
167
+
168
+ **Clear Jobs**
169
+
170
+ You can clear all failed jobs with this method:
171
+
172
+ ```ruby
173
+ > cleaner.clear
174
+ ```
175
+
176
+ Like you can do with the retry method, the clear method takes a block. Here are
177
+ some examples:
178
+
179
+ ```ruby
180
+ > cleaner.clear {|j| j.retried?}
181
+ => clears all jobs already retried and returns number of the jobs.
182
+
183
+ > cleaner.clear {|j| j.queue?(:low) && j.before?('2010-10-10')}
184
+ => clears all jobs entried in :low queue before 10th October, 2010.
185
+
186
+ > cleaner.clear {|j| j.exception?("RuntimeError") && j.queue?(:low)}
187
+ => clears all jobs raised RuntimeError and queued :low queue
188
+ ```
189
+
190
+ **Retry and Clear Jobs**
191
+
192
+ You can retry(requeue) and clear failed jobs at the same time; just pass true
193
+ as an argument.
194
+
195
+ e.g. Retry EmailJob and remove from failed jobs:
196
+
197
+ ```ruby
198
+ > cleaner.requeue(true) {|j| j.klass?(EmailJob)}
199
+ ```
200
+
201
+ **Retry with other queue**
202
+
203
+ You can requeue failed jobs into other queue. In this way, you can retry failed
204
+ jobs without blocking jobs being entered by your service running in the live.
205
+
206
+ e.g. Retry failed jobs on :retry queue
207
+
208
+ ```ruby
209
+ > cleaner.requeue(false, :queue => :retry)
210
+ ```
211
+
212
+ Don't forget to launch resque worker for the queue.
213
+
214
+ % QUEUE=retry rake resque:work
215
+
216
+ **Select Jobs**
217
+
218
+ You can just select the jobs of course. Here are some examples:
219
+
220
+ ```ruby
221
+ > cleaner.select {|j| j["payload"]["args"][0]=="Johonson"}
222
+ > cleaner.select {|j| j.after?(2.days.ago)}
223
+ > cleaner.select #=> returns all jobs
224
+ ```
225
+
226
+ **Helper Methods**
227
+
228
+ Here is a list of methods a failed job retained through ResqueCleaner has:
229
+
230
+ retried?: returns true if the job has already been retried.
231
+ requeued?: alias of retried?.
232
+ before?(time): returns true if the job failed before the time.
233
+ after?(time): returns true if the job failed after the time.
234
+ klass?(klass_or_name): returns true if the class of job matches.
235
+ queue?(queue_name): returns true if the queue of job matches.
236
+ exception?(exception_name): returns true if the exception matches.
237
+
238
+
239
+ Failed Job
240
+ -----------
241
+
242
+ Here is a sample of failed jobs:
243
+
244
+ {"failed_at": "2009/03/13 00:00:00",
245
+ "payload": {"args": ["Johnson"], "class": "BadJob"},
246
+ "queue": "jobs",
247
+ "worker": "localhost:7327:jobs,jobs2",
248
+ "exception": "RuntimeError",
249
+ "error": "Bad job, Johnson",
250
+ "backtrace":
251
+ ["./test/test_helper.rb:108:in `perform'",
252
+ "/opt/local/lib/ruby/gems/1.8/gems/resque-1.10.0/lib/resque/job.rb:133:in `perform'",
253
+ "/opt/local/lib/ruby/gems/1.8/gems/resque-1.10.0/lib/resque/worker.rb:157:in `perform'",
254
+ "/opt/local/lib/ruby/gems/1.8/gems/resque-1.10.0/lib/resque/worker.rb:124:in `work'",
255
+ "....(omitted)....",
256
+ "./test/test_helper.rb:41",
257
+ "test/resque_cleaner_test.rb:3"]
258
+ }
259
+
260
+
261
+ Limiter
262
+ -------
263
+
264
+ ResqueCleaner expects a disaster situation like a huge number of failed jobs are
265
+ out there. Since ResqueCleaner's filter function is running on your application
266
+ process but on your Redis, it would not respond ages if you try to deal with all
267
+ of those jobs.
268
+
269
+ ResqueCleaner supposes recent jobs are more important than old jobs. Therefore
270
+ ResqueCleaner deals with **ONLY LAST X(default=1000) JOBS**. In this way, you
271
+ could avoid slow responses. You can change the number through `limiter` attribute.
272
+
273
+ Let's see how it works with an following example.
274
+
275
+ **Sample Situation**
276
+
277
+ * Number of failed jobs: 100,000
278
+
279
+ Default limiter is 1000 so that the limiter returns 1000 as a count.
280
+
281
+ ```ruby
282
+ > cleaner.limiter.count
283
+ => 1,000
284
+ > cleaner.failure.count
285
+ => 100,000
286
+ ```
287
+
288
+ You could know if the limiter is on with on? method.
289
+
290
+ ```ruby
291
+ > cleaner.limiter.on?
292
+ => true
293
+ ```
294
+
295
+ You can change the maximum number of the limiter with maximum attribute.
296
+
297
+ ```ruby
298
+ > cleaner.limiter.maximum = 3000
299
+ => 3,000
300
+ > cleaner.limiter.count
301
+ => 3,000
302
+ > cleaner.limiter.on?
303
+ => true
304
+ ```
305
+
306
+ With limiter, ResqueCleaner's filtering targets only the last X(3000 in this
307
+ sample) failed jobs.
308
+
309
+ ```ruby
310
+ > cleaner.select.size
311
+ => 3,000
312
+ ```
313
+
314
+ The clear\_stale method deletes all jobs entered prior to the last X(3000 in
315
+ this sample) failed jobs. This calls Redis API and no iteration occurs on Ruby
316
+ application; it should be quick even if there are huge number of failed jobs.
317
+
318
+ ```ruby
319
+ > cleaner.clear_stale
320
+ > cleaner.failure.count
321
+ => 3,000
322
+ > cleaner.limiter.count
323
+ => 3,000
324
+ > cleaner.limiter.on?
325
+ => false
326
+ ```
327
+
328
+ Many Thanks!
329
+ ------------
330
+
331
+ To our [Contributors](https://github.com/ono/resque-cleaner/contributors)
332
+
333
+
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ #
2
+ # Setup
3
+ #
4
+
5
+ # load 'tasks/redis.rake'
6
+ #require 'rake/testtask'
7
+
8
+ $LOAD_PATH.unshift 'lib'
9
+ #require 'resque/tasks'
10
+
11
+ def command?(command)
12
+ system("type #{command} > /dev/null 2>&1")
13
+ end
14
+
15
+
16
+ #
17
+ # Tests
18
+ #
19
+
20
+ task :default => :test
21
+
22
+ desc "Run the test suite"
23
+ task :test do
24
+ rg = command?(:rg)
25
+ Dir['test/**/*_test.rb'].each do |f|
26
+ rg ? sh("rg #{f}") : ruby(f)
27
+ end
28
+ end
29
+
30
+ if command? :kicker
31
+ desc "Launch Kicker (like autotest)"
32
+ task :kicker do
33
+ puts "Kicking... (ctrl+c to cancel)"
34
+ exec "kicker -e rake test lib examples"
35
+ end
36
+ end
37
+
38
+
@@ -0,0 +1 @@
1
+ require 'resque_cleaner'
@@ -0,0 +1,63 @@
1
+ <style type="text/css" media="screen">
2
+ #main .cleaner .title h1 { float: left }
3
+
4
+ #main .cleaner .sub_header {color: #888; font-size: 80%; font-weight: bold}
5
+
6
+ #main .cleaner .control_panel {
7
+ margin: 5px 0 10px; padding: 5px; background: #eee; display: inline-block;
8
+ -webkit-border-radius:5px; border:1px solid #ccc;
9
+ }
10
+
11
+ #main .cleaner #exec { color: black; }
12
+ #main .cleaner #exec select { margin-right: 20px }
13
+ #main .cleaner #exec a { margin-right: 5px}
14
+ #main .cleaner #exec a.disabled { color: #aaa}
15
+
16
+ #main .cleaner table.class_list { width: auto }
17
+ #main .cleaner td.number { text-align: right }
18
+ #main .cleaner tr.total { border-top: 3px double #ccc}
19
+
20
+ #main .cleaner form { float: none; margin: 0}
21
+
22
+ #main .cleaner .warning { margin: 30px 0; padding: 10px; background: #fdd; display: inline-block; }
23
+
24
+ #main .clearfix:after {
25
+ content: ".";
26
+ display: block;
27
+ height: 0;
28
+ clear: both;
29
+ visibility: hidden;
30
+ }
31
+ #main .cleaner ul.failed {
32
+ margin-bottom: 10px
33
+ }
34
+
35
+ #main .cleaner .list_info{
36
+ color: #999; text-align: center;
37
+ }
38
+ #main .cleaner .list_info a{
39
+ color: #666
40
+ }
41
+ #main .cleaner .list_info .list_summary{
42
+ vertical-align: baseline;
43
+ display: inline-block;
44
+ margin: 0; padding:0;
45
+ }
46
+ #main .cleaner ul.pagination {
47
+ display: inline-block;
48
+ vertical-align: baseline;
49
+ margin:0; padding:0;
50
+ }
51
+ #main .cleaner ul.pagination li {
52
+ list-style:none; float: left; padding: 0 3px;
53
+ }
54
+ #main .cleaner ul.pagination li.current {
55
+ color: #333; font-weight: bold;
56
+ }
57
+ #main .cleaner ul.pagination li.summary{
58
+ padding-right: 10px
59
+ }
60
+ #main .cleaner div.dump{
61
+ float: right
62
+ }
63
+ </style>
@@ -0,0 +1,13 @@
1
+ <div class="warning">
2
+ <p>
3
+ There are more than <%= @cleaner.limiter.maximum%> jobs. ResqueCleaner handles only recent <%= @cleaner.limiter.maximum %> jobs. See the Limiter section on <a href="https://github.com/ono/resque-cleaner" target="_blank">README</a> for more detail.
4
+ </p>
5
+ <p>
6
+ <form method="post" action="cleaner_stale">
7
+ <input type="hidden" name="action" value="clear_stale" />
8
+ <input type="submit" onclick="return confirm('Are you sure?')" value="Clear all jobs older than <%= @cleaner.limiter.count %>th job."/>
9
+ (<%= @cleaner.failure.count - @cleaner.limiter.maximum %> jobs will be cleared)
10
+ </form>
11
+ </p>
12
+ </div>
13
+
@@ -0,0 +1,54 @@
1
+ <div class="list_info clearfix">
2
+
3
+ <ul class="pagination">
4
+ <li class="summary">
5
+ <%= @paginate.first_index%> - <%= @paginate.last_index%> / <%= @paginate.total_size%>
6
+ </li>
7
+ <% if @paginate.max_page>1 %>
8
+ <% if @paginate.first_page? %>
9
+ <li class="prev off">&lt;&lt;newer</li>
10
+ <% else %>
11
+ <li class="prev"><a href="<%= @paginate.page_url(:prev)%>">&lt;&lt;newer</a></li>
12
+ <% end %>
13
+
14
+ <% 1.upto(6<@paginate.max_page ? 6 : @paginate.max_page) do |pg| %>
15
+ <% if @paginate.page==pg %>
16
+ <li class="current"><%=pg%></li>
17
+ <% else %>
18
+ <li><a href="<%= @paginate.page_url(pg)%>"><%=pg%></a></li>
19
+ <% end %>
20
+ <% end %>
21
+
22
+ <% if @paginate.max_page > 6 %>
23
+ <% if @paginate.max_page!=@paginate.page %>
24
+ <% if @paginate.page>7 %>
25
+ <li class="off">...</li>
26
+ <% end %>
27
+ <% if @paginate.page>6 %>
28
+ <li class="current"><%=@paginate.page%></li>
29
+ <% end %>
30
+ <% end %>
31
+ <% if @paginate.max_page>7 && @paginate.page+1!=@paginate.max_page %>
32
+ <li class="off">...</li>
33
+ <% end %>
34
+
35
+ <% if @paginate.max_page==@paginate.page %>
36
+ <li class="current"><%=@paginate.max_page%></li>
37
+ <% else %>
38
+ <li><a href="<%= @paginate.page_url(@paginate.max_page)%>"><%=@paginate.max_page%></a></li>
39
+ <% end %>
40
+ <% end %>
41
+
42
+ <% if @paginate.last_page? %>
43
+ <li class="next off">older&gt;&gt;</li>
44
+ <% else %>
45
+ <li class="next"><a href="<%= @paginate.page_url(:next)%>">older&gt;&gt;</a></li>
46
+ <% end %>
47
+ <% end %>
48
+
49
+ </ul>
50
+ <div class="dump">
51
+ <a href="<%= @dump_url%>" target="_blank">Dump</a>
52
+ </div>
53
+ </div>
54
+
@@ -0,0 +1,44 @@
1
+ <table class="class_list">
2
+ <tr>
3
+ <th><%= type.gsub('klass','class').capitalize %></th>
4
+ <th>Failed</th>
5
+ <th>In last 1 hour</th>
6
+ <th>In last 3 hours</th>
7
+ <th>In last 24 hours</th>
8
+ <th>In last 3 days</th>
9
+ <th>In last 7 days</th>
10
+ </tr>
11
+ <% @stats[type.to_sym].each do |field,count| %>
12
+ <tr>
13
+ <% filter = "#{q}=#{CGI.escape(field)}" %>
14
+ <td><%= field %></td>
15
+ <td class="number">
16
+ <a href="cleaner_list?<%=filter%>"><%= count[:total] %></a>
17
+ </td>
18
+ <td class="number">
19
+ <a href="cleaner_list?<%=filter%>&f=1"><%= count[:h1] %></a>
20
+ </td>
21
+ <td class="number">
22
+ <a href="cleaner_list?<%=filter%>&f=3"><%= count[:h3] %></a>
23
+ </td>
24
+ <td class="number">
25
+ <a href="cleaner_list?<%=filter%>&f=24"><%= count[:d1] %></a>
26
+ </td>
27
+ <td class="number">
28
+ <a href="cleaner_list?<%=filter%>&f=72"><%= count[:d3] %></a>
29
+ </td>
30
+ <td class="number">
31
+ <a href="cleaner_list?<%=filter%>&f=168"><%= count[:d7] %></a>
32
+ </td>
33
+ </tr>
34
+ <% end %>
35
+ <tr class="total">
36
+ <td>Total</td>
37
+ <td class="number"><a href="cleaner_list"><%= @total[:total] %></a></td>
38
+ <td class="number"><a href="cleaner_list?f=1"><%= @total[:h1] %></a></td>
39
+ <td class="number"><a href="cleaner_list?f=3"><%= @total[:h3] %></a></td>
40
+ <td class="number"><a href="cleaner_list?f=24"><%= @total[:d1] %></a></td>
41
+ <td class="number"><a href="cleaner_list?f=72"><%= @total[:d3] %></a></td>
42
+ <td class="number"><a href="cleaner_list?f=168"><%= @total[:d7] %></a></td>
43
+ </tr>
44
+ </table>
@@ -0,0 +1,25 @@
1
+ <%= erb File.read(ResqueCleaner::Server.erb_path("_cleaner_styles.erb")) %>
2
+
3
+ <div class="cleaner">
4
+ <div class="title clearfix">
5
+ <h1>Group by class</h1>
6
+ </div>
7
+
8
+ <%= erb(
9
+ File.read(ResqueCleaner::Server.erb_path("_stats.erb")),
10
+ locals: {q: 'c', type: 'klass'}
11
+ ) %>
12
+
13
+ <div class="title clearfix">
14
+ <h1>Group by exception</h1>
15
+ </div>
16
+
17
+ <%= erb(
18
+ File.read(ResqueCleaner::Server.erb_path("_stats.erb")),
19
+ locals: {q: 'ex', type: 'exception'}
20
+ ) %>
21
+
22
+ <% if @cleaner.limiter.on? %>
23
+ <%= erb File.read(ResqueCleaner::Server.erb_path("_limiter.erb")) %>
24
+ <% end %>
25
+ </div>