sidekiq-job-stats 0.1.4 → 0.1.6
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/Gemfile.lock +1 -1
- data/lib/sidekiq_job_stats/helpers/stats.rb +19 -1
- data/lib/sidekiq_job_stats/history.rb +6 -0
- data/lib/sidekiq_job_stats/statistic.rb +1 -1
- data/lib/sidekiq_job_stats/version.rb +1 -1
- data/lib/sidekiq_job_stats/web_extension.rb +50 -7
- data/lib/sidekiq_job_stats.rb +19 -2
- data/lib/web/assets/job_stats/css/job_stats.css +39 -0
- data/lib/web/views/job_histories.erb +80 -28
- data/lib/web/views/job_stats.erb +74 -52
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f971c77fc2f53fd5b4264823f52f3acafee05584e9e9cf7f43b5c649e471f782
|
|
4
|
+
data.tar.gz: a6980a4641f6f69dec11b8ef1a68ef6fb1ccd4de18b99f19252201fc9246ef80
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d1e422ea264542dc53e457432f3d5ba37fabbaa27d14f22e128b59b8a2c062bf23561948dcd2a252db222e69d54d95330c1ab37a313d83cf93ad3ddc72843732
|
|
7
|
+
data.tar.gz: 3432cb1e96008daeb1353db8aad4c99e13a850a993b124b3ec3e82130cac11754ae2c426984359f563270930132eff4e9baaf79cf376fe935a94ae82bce3107f
|
data/Gemfile.lock
CHANGED
|
@@ -2,7 +2,15 @@ module SidekiqJobStats
|
|
|
2
2
|
module Helpers
|
|
3
3
|
module Stats
|
|
4
4
|
def stat_header(stat_name)
|
|
5
|
-
|
|
5
|
+
label = stat_name.to_s.gsub(/_/, " ").capitalize
|
|
6
|
+
job_stats_sort_th(label, stat_name.to_s)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def job_stats_sort_th(label, key)
|
|
10
|
+
dir = (@sort == key && @direction == "asc") ? "desc" : "asc"
|
|
11
|
+
css = @sort == key ? "sort-#{@direction}" : ""
|
|
12
|
+
url = "#{root_path}job_stats?sort=#{key}&direction=#{dir}"
|
|
13
|
+
"<th class='#{css}'><a href='#{url}'>#{label}</a></th>"
|
|
6
14
|
end
|
|
7
15
|
|
|
8
16
|
def display_stat(stat, stat_name, format)
|
|
@@ -21,6 +29,16 @@ module SidekiqJobStats
|
|
|
21
29
|
def mb_display(num)
|
|
22
30
|
num.blank? ? "" : "#{num}MB"
|
|
23
31
|
end
|
|
32
|
+
|
|
33
|
+
# Sidekiq 6/7 stores enqueued_at as seconds (~1.7e9).
|
|
34
|
+
# Sidekiq 8+ stores it as milliseconds (~1.7e12).
|
|
35
|
+
def format_enqueued_at(value)
|
|
36
|
+
return "" unless value
|
|
37
|
+
ts = value.to_f
|
|
38
|
+
return value if ts.zero?
|
|
39
|
+
ts /= 1000.0 if ts > 1_000_000_000_000
|
|
40
|
+
Time.at(ts)
|
|
41
|
+
end
|
|
24
42
|
end
|
|
25
43
|
end
|
|
26
44
|
end
|
|
@@ -20,6 +20,12 @@ module SidekiqJobStats
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
def all_job_histories
|
|
24
|
+
Sidekiq.redis do |conn|
|
|
25
|
+
conn.lrange(job_history_key, 0, -1).map { |h| JSON.parse(h) }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
def histories_recorded
|
|
24
30
|
Sidekiq.redis do |conn|
|
|
25
31
|
conn.llen(job_history_key)
|
|
@@ -14,7 +14,7 @@ module SidekiqJobStats
|
|
|
14
14
|
:longest_job_day, :longest_job_month, to: :duration
|
|
15
15
|
delegate :job_memory_usage_avg_day, :job_memory_usage_avg_month, :peak_memory_usage_day,
|
|
16
16
|
:peak_memory_usage_month, to: :memory_usage
|
|
17
|
-
delegate :job_histories, :histories_recorded, to: :history
|
|
17
|
+
delegate :job_histories, :all_job_histories, :histories_recorded, to: :history
|
|
18
18
|
delegate :name, to: :job_class
|
|
19
19
|
|
|
20
20
|
def self.find_all
|
|
@@ -6,30 +6,73 @@ module SidekiqJobStats
|
|
|
6
6
|
module WebExtension
|
|
7
7
|
ROOT = File.expand_path('../web', __dir__)
|
|
8
8
|
|
|
9
|
+
STAT_SORT_KEYS = %w[
|
|
10
|
+
name jobs_enqueued jobs_performed_day jobs_performed_month
|
|
11
|
+
job_rolling_avg_day job_rolling_avg_month longest_job_day longest_job_month
|
|
12
|
+
job_memory_usage_avg_day job_memory_usage_avg_month
|
|
13
|
+
peak_memory_usage_day peak_memory_usage_month
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
9
16
|
def self.registered(app)
|
|
10
17
|
app.helpers Helpers::Stats
|
|
11
18
|
|
|
12
19
|
app.get '/job_stats' do
|
|
13
|
-
|
|
20
|
+
sort_param = respond_to?(:url_params) ? url_params("sort") : params[:sort]
|
|
21
|
+
dir_param = respond_to?(:url_params) ? url_params("direction") : params[:direction]
|
|
22
|
+
@sort = WebExtension::STAT_SORT_KEYS.include?(sort_param.to_s) ? sort_param.to_s : "name"
|
|
23
|
+
@direction = %w[asc desc].include?(dir_param) ? dir_param : "asc"
|
|
24
|
+
|
|
25
|
+
@jobs = SidekiqJobStats::Statistic.find_all
|
|
26
|
+
@jobs.sort! do |a, b|
|
|
27
|
+
av = @sort == "name" ? a.name.to_s : a.send(@sort.to_sym)
|
|
28
|
+
bv = @sort == "name" ? b.name.to_s : b.send(@sort.to_sym)
|
|
29
|
+
result = begin
|
|
30
|
+
Float(av.to_s) <=> Float(bv.to_s)
|
|
31
|
+
rescue ArgumentError, TypeError
|
|
32
|
+
av.to_s <=> bv.to_s
|
|
33
|
+
end
|
|
34
|
+
@direction == "desc" ? -(result || 0) : (result || 0)
|
|
35
|
+
end
|
|
14
36
|
|
|
15
37
|
render(:erb, File.read("#{ROOT}/views/job_stats.erb"))
|
|
16
38
|
end
|
|
17
39
|
|
|
18
40
|
app.get '/job_stats/job_history/:job_class' do
|
|
19
|
-
|
|
41
|
+
klass = route_params(:job_class) || params[:job_class]
|
|
42
|
+
@job_class = SidekiqJobStats::Statistic.find_all.find { |j| j.job_class.to_s == klass }
|
|
20
43
|
|
|
21
44
|
@start = 0
|
|
22
|
-
|
|
45
|
+
start_param = respond_to?(:url_params) ? url_params("start") : params[:start]
|
|
46
|
+
@start = start_param.to_i if start_param && !start_param.empty?
|
|
23
47
|
@limit = 100
|
|
24
|
-
|
|
48
|
+
limit_param = respond_to?(:url_params) ? url_params("limit") : params[:limit]
|
|
49
|
+
@limit = limit_param.to_i if limit_param && !limit_param.empty?
|
|
50
|
+
|
|
51
|
+
sort_param = respond_to?(:url_params) ? url_params("sort") : params[:sort]
|
|
52
|
+
dir_param = respond_to?(:url_params) ? url_params("direction") : params[:direction]
|
|
53
|
+
@sort = sort_param.to_s
|
|
54
|
+
@direction = %w[asc desc].include?(dir_param) ? dir_param : "asc"
|
|
25
55
|
|
|
26
|
-
@histories = @job_class.job_histories(@start, @limit)
|
|
27
56
|
@size = @job_class.histories_recorded
|
|
28
57
|
|
|
58
|
+
if @sort.empty?
|
|
59
|
+
@histories = @job_class.job_histories(@start, @limit)
|
|
60
|
+
else
|
|
61
|
+
all = @job_class.all_job_histories
|
|
62
|
+
all.sort! do |a, b|
|
|
63
|
+
av, bv = a[@sort], b[@sort]
|
|
64
|
+
result = begin
|
|
65
|
+
Float(av.to_s) <=> Float(bv.to_s)
|
|
66
|
+
rescue ArgumentError
|
|
67
|
+
av.to_s <=> bv.to_s
|
|
68
|
+
end
|
|
69
|
+
@direction == "desc" ? -(result || 0) : (result || 0)
|
|
70
|
+
end
|
|
71
|
+
@histories = all[@start, @limit] || []
|
|
72
|
+
end
|
|
73
|
+
|
|
29
74
|
render(:erb, File.read("#{ROOT}/views/job_histories.erb"))
|
|
30
75
|
end
|
|
31
|
-
|
|
32
|
-
app.settings.locales << File.expand_path('locales', ROOT)
|
|
33
76
|
end
|
|
34
77
|
end
|
|
35
78
|
end
|
data/lib/sidekiq_job_stats.rb
CHANGED
|
@@ -19,5 +19,22 @@ module Sidekiq
|
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
Sidekiq::
|
|
23
|
-
Sidekiq::Web.
|
|
22
|
+
if Sidekiq::MAJOR >= 8
|
|
23
|
+
Sidekiq::Web.configure do |config|
|
|
24
|
+
config.register_extension(
|
|
25
|
+
SidekiqJobStats::WebExtension,
|
|
26
|
+
name: "job_stats",
|
|
27
|
+
tab: ["Job stats"],
|
|
28
|
+
index: "job_stats",
|
|
29
|
+
root_dir: File.expand_path("../web", __FILE__),
|
|
30
|
+
asset_paths: ["css"]
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
Sidekiq::Web.register(SidekiqJobStats::WebExtension)
|
|
35
|
+
Sidekiq::Web.tabs['Job stats'] = 'job_stats'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.sortable-table .table_container {
|
|
2
|
+
max-height: 500px;
|
|
3
|
+
overflow: auto;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.sortable-table th {
|
|
7
|
+
position: sticky;
|
|
8
|
+
top: -1px;
|
|
9
|
+
background-color: var(--color-elevated);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.sortable-table th a {
|
|
13
|
+
display: block;
|
|
14
|
+
color: inherit;
|
|
15
|
+
text-decoration: none;
|
|
16
|
+
padding-right: 1.4em;
|
|
17
|
+
position: relative;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.sortable-table th a:hover {
|
|
21
|
+
text-decoration: underline;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sortable-table th a::after {
|
|
25
|
+
content: "⇅";
|
|
26
|
+
position: absolute;
|
|
27
|
+
right: 0;
|
|
28
|
+
opacity: 0.25;
|
|
29
|
+
font-size: 0.8em;
|
|
30
|
+
font-weight: normal;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.sortable-table th.sort-asc,
|
|
34
|
+
.sortable-table th.sort-desc {
|
|
35
|
+
background-color: var(--color-selected);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sortable-table th.sort-asc a::after { content: "▲"; opacity: 1; color: var(--color-primary); }
|
|
39
|
+
.sortable-table th.sort-desc a::after { content: "▼"; opacity: 1; color: var(--color-primary); }
|
|
@@ -1,23 +1,56 @@
|
|
|
1
|
+
<% if respond_to?(:style_tag) %>
|
|
2
|
+
<% style_tag "job_stats/css/job_stats.css" %>
|
|
3
|
+
<% else %>
|
|
1
4
|
<style>
|
|
2
|
-
table {
|
|
3
|
-
text-align: left;
|
|
4
|
-
position: relative;
|
|
5
|
-
border-collapse: separate;
|
|
6
|
-
border-spacing: 0;
|
|
7
|
-
}
|
|
5
|
+
.sortable-table .fixTableHead { max-height: 500px; overflow: auto; }
|
|
8
6
|
|
|
9
|
-
th {
|
|
7
|
+
.sortable-table th {
|
|
10
8
|
position: sticky;
|
|
11
9
|
top: 0;
|
|
12
10
|
background-color: #F9F8F8;
|
|
13
|
-
border-bottom: 1px solid #
|
|
11
|
+
border-bottom: 1px solid #ddd;
|
|
12
|
+
white-space: nowrap;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.sortable-table th a {
|
|
16
|
+
display: block;
|
|
17
|
+
color: inherit;
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
padding-right: 1.4em;
|
|
20
|
+
position: relative;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
.
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
.sortable-table th a:hover { text-decoration: underline; }
|
|
24
|
+
|
|
25
|
+
.sortable-table th a::after {
|
|
26
|
+
content: "⇅";
|
|
27
|
+
position: absolute;
|
|
28
|
+
right: 0;
|
|
29
|
+
opacity: 0.25;
|
|
30
|
+
font-size: 0.8em;
|
|
31
|
+
font-weight: normal;
|
|
19
32
|
}
|
|
33
|
+
|
|
34
|
+
.sortable-table th.sort-asc,
|
|
35
|
+
.sortable-table th.sort-desc { background-color: #EEF4FF; }
|
|
36
|
+
|
|
37
|
+
.sortable-table th.sort-asc a::after { content: "▲"; opacity: 1; color: #4A7FD4; }
|
|
38
|
+
.sortable-table th.sort-desc a::after { content: "▼"; opacity: 1; color: #4A7FD4; }
|
|
20
39
|
</style>
|
|
40
|
+
<% end %>
|
|
41
|
+
|
|
42
|
+
<%
|
|
43
|
+
def history_sort_url(root, path, sort_key, current_sort, current_dir, start, limit)
|
|
44
|
+
dir = (current_sort == sort_key && current_dir == "asc") ? "desc" : "asc"
|
|
45
|
+
"#{root}#{path}?sort=#{sort_key}&direction=#{dir}&start=0&limit=#{limit}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def pagination_url(root, path, start, limit, sort, direction)
|
|
49
|
+
url = "#{root}#{path}?start=#{start}&limit=#{limit}"
|
|
50
|
+
url += "&sort=#{sort}&direction=#{direction}" unless sort.to_s.empty?
|
|
51
|
+
url
|
|
52
|
+
end
|
|
53
|
+
%>
|
|
21
54
|
|
|
22
55
|
<h1>Sidekiq Job Histories</h1>
|
|
23
56
|
|
|
@@ -26,33 +59,52 @@
|
|
|
26
59
|
</p>
|
|
27
60
|
<h2><%= @job_class.job_class.to_s %></h2>
|
|
28
61
|
|
|
29
|
-
|
|
30
|
-
|
|
62
|
+
<%if @start > 0 || @start + @limit <= @size %>
|
|
63
|
+
<p class='pagination'>
|
|
64
|
+
<% if @start > 0 %>
|
|
65
|
+
<a href="<%= pagination_url(root_path, request.path_info, [0, @start - @limit].max, @limit, @sort, @direction) %>" class='less'>« less</a>
|
|
66
|
+
<% end %>
|
|
67
|
+
<% if @start + @limit <= @size %>
|
|
68
|
+
<a href="<%= pagination_url(root_path, request.path_info, @start + @limit, @limit, @sort, @direction) %>" class='more'>more »</a>
|
|
69
|
+
<% end %>
|
|
70
|
+
</p>
|
|
71
|
+
<%end%>
|
|
72
|
+
|
|
73
|
+
<div class="sortable-table">
|
|
74
|
+
<div class="table_container">
|
|
75
|
+
<table>
|
|
31
76
|
<thead>
|
|
32
77
|
<tr>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
78
|
+
<% [
|
|
79
|
+
["Process", "process"],
|
|
80
|
+
["Enqueued time", "enqueued_at"],
|
|
81
|
+
["Started at", "started_at"],
|
|
82
|
+
["Finished at", "finished_at"],
|
|
83
|
+
["Duration", "duration"],
|
|
84
|
+
["Arguments", "payload"],
|
|
85
|
+
["Success", "status"],
|
|
86
|
+
["Exception", "exception"],
|
|
87
|
+
].each do |label, key| %>
|
|
88
|
+
<% css = @sort == key ? "sort-#{@direction}" : "" %>
|
|
89
|
+
<th class="<%= css %>">
|
|
90
|
+
<a href="<%= history_sort_url(root_path, request.path_info, key, @sort, @direction, @start, @limit) %>"><%= label %></a>
|
|
91
|
+
</th>
|
|
92
|
+
<% end %>
|
|
41
93
|
</tr>
|
|
42
94
|
</thead>
|
|
43
95
|
<tbody>
|
|
44
96
|
<% @histories.each do |history| %>
|
|
45
97
|
<% if history.is_a? Hash %>
|
|
46
98
|
<tr>
|
|
47
|
-
<td>
|
|
99
|
+
<td>
|
|
48
100
|
<%= history["process"] %>
|
|
49
101
|
<% Array(history["tags"]).each do |tag| %>
|
|
50
102
|
<span class="label label-info jobtag"><%= tag %></span>
|
|
51
103
|
<% end %>
|
|
52
104
|
</td>
|
|
53
|
-
<td><span class="time"><%=
|
|
105
|
+
<td><span class="time"><%= format_enqueued_at(history["enqueued_at"]) %></span></td>
|
|
54
106
|
<td><span class="time"><%= history["started_at"] %></span></td>
|
|
55
|
-
<td><span class="time"><%= history["finished_at"]%></span></td>
|
|
107
|
+
<td><span class="time"><%= history["finished_at"] %></span></td>
|
|
56
108
|
<td><%= history["duration"] %>s</td>
|
|
57
109
|
<td><div class="args"><%= history["payload"] %></div></td>
|
|
58
110
|
<td><%= history["status"] %></td>
|
|
@@ -62,16 +114,16 @@
|
|
|
62
114
|
<% end %>
|
|
63
115
|
</tbody>
|
|
64
116
|
</table>
|
|
117
|
+
</div>
|
|
65
118
|
</div>
|
|
66
119
|
|
|
67
120
|
<%if @start > 0 || @start + @limit <= @size %>
|
|
68
121
|
<p class='pagination'>
|
|
69
|
-
<% if @start
|
|
70
|
-
<a href="<%= root_path
|
|
122
|
+
<% if @start > 0 %>
|
|
123
|
+
<a href="<%= pagination_url(root_path, request.path_info, [0, @start - @limit].max, @limit, @sort, @direction) %>" class='less'>« less</a>
|
|
71
124
|
<% end %>
|
|
72
125
|
<% if @start + @limit <= @size %>
|
|
73
|
-
<a href="<%= root_path
|
|
126
|
+
<a href="<%= pagination_url(root_path, request.path_info, @start + @limit, @limit, @sort, @direction) %>" class='more'>more »</a>
|
|
74
127
|
<% end %>
|
|
75
128
|
</p>
|
|
76
129
|
<%end%>
|
|
77
|
-
|
data/lib/web/views/job_stats.erb
CHANGED
|
@@ -1,23 +1,43 @@
|
|
|
1
|
+
<% if respond_to?(:style_tag) %>
|
|
2
|
+
<% style_tag "job_stats/css/job_stats.css" %>
|
|
3
|
+
<% else %>
|
|
1
4
|
<style>
|
|
2
|
-
table {
|
|
3
|
-
text-align: left;
|
|
4
|
-
position: relative;
|
|
5
|
-
border-collapse: separate;
|
|
6
|
-
border-spacing: 0;
|
|
7
|
-
}
|
|
5
|
+
.sortable-table .fixTableHead { max-height: 500px; overflow: auto; }
|
|
8
6
|
|
|
9
|
-
th {
|
|
7
|
+
.sortable-table th {
|
|
10
8
|
position: sticky;
|
|
11
9
|
top: 0;
|
|
12
10
|
background-color: #F9F8F8;
|
|
13
|
-
border-bottom: 1px solid #
|
|
11
|
+
border-bottom: 1px solid #ddd;
|
|
12
|
+
white-space: nowrap;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.sortable-table th a {
|
|
16
|
+
display: block;
|
|
17
|
+
color: inherit;
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
padding-right: 1.4em;
|
|
20
|
+
position: relative;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
.
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
.sortable-table th a:hover { text-decoration: underline; }
|
|
24
|
+
|
|
25
|
+
.sortable-table th a::after {
|
|
26
|
+
content: "⇅";
|
|
27
|
+
position: absolute;
|
|
28
|
+
right: 0;
|
|
29
|
+
opacity: 0.25;
|
|
30
|
+
font-size: 0.8em;
|
|
31
|
+
font-weight: normal;
|
|
19
32
|
}
|
|
33
|
+
|
|
34
|
+
.sortable-table th.sort-asc,
|
|
35
|
+
.sortable-table th.sort-desc { background-color: #EEF4FF; }
|
|
36
|
+
|
|
37
|
+
.sortable-table th.sort-asc a::after { content: "▲"; opacity: 1; color: #4A7FD4; }
|
|
38
|
+
.sortable-table th.sort-desc a::after { content: "▼"; opacity: 1; color: #4A7FD4; }
|
|
20
39
|
</style>
|
|
40
|
+
<% end %>
|
|
21
41
|
|
|
22
42
|
<h1>Sidekiq Job Stats</h1>
|
|
23
43
|
|
|
@@ -25,44 +45,46 @@
|
|
|
25
45
|
This page displays statistics about jobs that have been executed.
|
|
26
46
|
</p>
|
|
27
47
|
|
|
28
|
-
<div class="
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
</
|
|
48
|
+
<div class="sortable-table">
|
|
49
|
+
<div class="table_container">
|
|
50
|
+
<table>
|
|
51
|
+
<thead>
|
|
52
|
+
<tr>
|
|
53
|
+
<%= job_stats_sort_th("Name", "name") %>
|
|
54
|
+
<%= stat_header(:jobs_enqueued) %>
|
|
55
|
+
<%= stat_header(:jobs_performed_day) %>
|
|
56
|
+
<%= stat_header(:jobs_performed_month) %>
|
|
57
|
+
<%= stat_header(:job_rolling_avg_day) %>
|
|
58
|
+
<%= stat_header(:job_rolling_avg_month) %>
|
|
59
|
+
<%= stat_header(:longest_job_day) %>
|
|
60
|
+
<%= stat_header(:longest_job_month) %>
|
|
61
|
+
<%= stat_header(:job_memory_usage_avg_day) %>
|
|
62
|
+
<%= stat_header(:job_memory_usage_avg_month) %>
|
|
63
|
+
<%= stat_header(:peak_memory_usage_day) %>
|
|
64
|
+
<%= stat_header(:peak_memory_usage_month) %>
|
|
65
|
+
</tr>
|
|
66
|
+
</thead>
|
|
67
|
+
<tbody>
|
|
68
|
+
<% @jobs.each do |job| %>
|
|
69
|
+
<tr>
|
|
70
|
+
<td>
|
|
71
|
+
<%= job.name %>
|
|
72
|
+
<a href='<%= "#{root_path}job_stats/job_history/#{job.name}" %>'>[history]</a>
|
|
73
|
+
</td>
|
|
74
|
+
<%= display_stat(job, :jobs_enqueued, :number_display) %>
|
|
75
|
+
<%= display_stat(job, :jobs_performed_day, :number_display) %>
|
|
76
|
+
<%= display_stat(job, :jobs_performed_month, :number_display) %>
|
|
77
|
+
<%= display_stat(job, :job_rolling_avg_day, :time_display) %>
|
|
78
|
+
<%= display_stat(job, :job_rolling_avg_month, :time_display) %>
|
|
79
|
+
<%= display_stat(job, :longest_job_day, :time_display) %>
|
|
80
|
+
<%= display_stat(job, :longest_job_month, :time_display) %>
|
|
81
|
+
<%= display_stat(job, :job_memory_usage_avg_day, :mb_display) %>
|
|
82
|
+
<%= display_stat(job, :job_memory_usage_avg_month, :mb_display) %>
|
|
83
|
+
<%= display_stat(job, :peak_memory_usage_day, :mb_display) %>
|
|
84
|
+
<%= display_stat(job, :peak_memory_usage_month, :mb_display) %>
|
|
85
|
+
</tr>
|
|
86
|
+
<% end %>
|
|
87
|
+
</tbody>
|
|
88
|
+
</table>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sidekiq-job-stats
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- isliusar
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-04-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: sidekiq
|
|
@@ -64,6 +64,7 @@ files:
|
|
|
64
64
|
- lib/sidekiq_job_stats/statistic.rb
|
|
65
65
|
- lib/sidekiq_job_stats/version.rb
|
|
66
66
|
- lib/sidekiq_job_stats/web_extension.rb
|
|
67
|
+
- lib/web/assets/job_stats/css/job_stats.css
|
|
67
68
|
- lib/web/views/job_histories.erb
|
|
68
69
|
- lib/web/views/job_stats.erb
|
|
69
70
|
- sidekiq-job-stats.gemspec
|
|
@@ -75,7 +76,7 @@ metadata:
|
|
|
75
76
|
homepage_uri: https://github.com/sliusar-ihor/sidekiq-job-stats
|
|
76
77
|
source_code_uri: https://github.com/sliusar-ihor/sidekiq-job-stats
|
|
77
78
|
changelog_uri: https://github.com/sliusar-ihor/sidekiq-job-stats
|
|
78
|
-
post_install_message:
|
|
79
|
+
post_install_message:
|
|
79
80
|
rdoc_options: []
|
|
80
81
|
require_paths:
|
|
81
82
|
- lib
|
|
@@ -90,8 +91,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
90
91
|
- !ruby/object:Gem::Version
|
|
91
92
|
version: '0'
|
|
92
93
|
requirements: []
|
|
93
|
-
rubygems_version: 3.
|
|
94
|
-
signing_key:
|
|
94
|
+
rubygems_version: 3.0.3.1
|
|
95
|
+
signing_key:
|
|
95
96
|
specification_version: 4
|
|
96
97
|
summary: Tracks jobs performed, failed, and the duration of the last 100 jobs for
|
|
97
98
|
each job type.
|