mirror of
https://github.com/endofunky/sidetiq.git
synced 2022-11-09 13:53:30 -05:00
Show job history in web extension.
This commit is contained in:
parent
1186088a4f
commit
5b20e39ca0
12 changed files with 198 additions and 61 deletions
|
@ -24,7 +24,7 @@ module Sidetiq
|
||||||
end
|
end
|
||||||
|
|
||||||
configure do |config|
|
configure do |config|
|
||||||
config.worker_history = 100
|
config.worker_history = 50
|
||||||
config.resolution = 1
|
config.resolution = 1
|
||||||
config.lock_expire = 1000
|
config.lock_expire = 1000
|
||||||
config.utc = false
|
config.utc = false
|
||||||
|
|
|
@ -32,8 +32,8 @@ module Sidetiq
|
||||||
error: "",
|
error: "",
|
||||||
exception: "",
|
exception: "",
|
||||||
backtrace: "",
|
backtrace: "",
|
||||||
processor: "#{Socket.gethostname}:#{Process.pid}-#{Thread.current.object_id}",
|
node: "#{Socket.gethostname}:#{Process.pid}-#{Thread.current.object_id}",
|
||||||
processed: Time.now.iso8601
|
timestamp: Time.now.iso8601
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
22
lib/sidetiq/views/_worker_nav.erb
Normal file
22
lib/sidetiq/views/_worker_nav.erb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<div class="span3">
|
||||||
|
<ul class="nav nav-list sidetiq-sidenav">
|
||||||
|
<li>
|
||||||
|
<a href="/sidetiq">
|
||||||
|
<i class="icon-chevron-right"></i>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/sidetiq/<%= @worker.name %>/schedule">
|
||||||
|
<i class="icon-chevron-right"></i>
|
||||||
|
Job Schedule
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/sidetiq/<%= @worker.name %>/history">
|
||||||
|
<i class="icon-chevron-right"></i>
|
||||||
|
Job History
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
36
lib/sidetiq/views/assets/styles.css
Normal file
36
lib/sidetiq/views/assets/styles.css
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<style>
|
||||||
|
.sidetiq-container {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidetiq-sidenav {
|
||||||
|
width: 228px;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
-webkit-border-radius: 6px;
|
||||||
|
-moz-border-radius: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidetiq-sidenav > li > a {
|
||||||
|
display: block;
|
||||||
|
width: 190px \9;
|
||||||
|
margin: 0 0 -1px;
|
||||||
|
padding: 8px 14px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
j
|
||||||
|
.sidetiq-sidenav > li:first-child > a {
|
||||||
|
-webkit-border-radius: 6px 6px 0 0;
|
||||||
|
-moz-border-radius: 6px 6px 0 0;
|
||||||
|
border-radius: 6px 6px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidetiq-sidenav > li:last-child > a {
|
||||||
|
-webkit-border-radius: 0 0 6px 6px;
|
||||||
|
-moz-border-radius: 0 0 6px 6px;
|
||||||
|
border-radius: 0 0 6px 6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<% @schedules.each do |worker, schedule| %>
|
<% @schedules.each do |worker, schedule| %>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="<%= "#{root_path}sidetiq/#{worker.name}" %>"><%= worker.name %></a>
|
<a href="<%= "#{root_path}sidetiq/#{worker.name}/schedule" %>"><%= worker.name %></a>
|
||||||
<td><%= worker.get_sidekiq_options["queue"] %></td>
|
<td><%= worker.get_sidekiq_options["queue"] %></td>
|
||||||
<td>
|
<td>
|
||||||
<%= relative_time(schedule.next_occurrence(@time)) %>
|
<%= relative_time(schedule.next_occurrence(@time)) %>
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
<header class="row">
|
|
||||||
<div class="span5">
|
|
||||||
<h3>Recurring Job: <%= @worker.name %></h3>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<% if (recurrences = @schedule.recurrence_rules).length > 0 %>
|
|
||||||
<table class="table table-striped table-bordered table-white" style="width: 100%; margin: 0; table-layout:fixed;">
|
|
||||||
<thead>
|
|
||||||
<th>Recurrences</th>
|
|
||||||
</thead>
|
|
||||||
<% recurrences.each do |rule| %>
|
|
||||||
<tr>
|
|
||||||
<td><%= rule.to_s %></td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
|
||||||
</table>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<% if (exceptions = @schedule.exception_rules).length > 0 %>
|
|
||||||
<table class="table table-striped table-bordered table-white" style="width: 100%; margin: 0; table-layout:fixed;">
|
|
||||||
<thead>
|
|
||||||
<th>Exceptions</th>
|
|
||||||
</thead>
|
|
||||||
<% exceptions.each do |rule| %>
|
|
||||||
<tr>
|
|
||||||
<td><%= rule.to_s %></td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
|
||||||
</table>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<table class="table table-striped table-bordered table-white" style="width: 100%; margin: 0; table-layout:fixed;">
|
|
||||||
<thead>
|
|
||||||
<th style="width: 25%">Next 10 runs</th>
|
|
||||||
<th style="width: 75%" />
|
|
||||||
<% @schedule.next_occurrences(10, @time).each do |time| %>
|
|
||||||
<tr>
|
|
||||||
<td><time><%= time.getutc %></time></td>
|
|
||||||
<td><%= relative_time(time) %></td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<br />
|
|
48
lib/sidetiq/views/sidetiq_history.erb
Normal file
48
lib/sidetiq/views/sidetiq_history.erb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<%= File.read(File.join(File.dirname(__FILE__), 'views', 'assets', 'styles.css')) %>
|
||||||
|
|
||||||
|
<header class="row">
|
||||||
|
<div class="span5">
|
||||||
|
<h3>Recurring Job: <%= @worker.name %></h3>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="container-fluid sidetiq-container">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<%= erb File.read(File.join(File.dirname(__FILE__), 'views', '_worker_nav.erb')) %>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<table class="table table-striped table-bordered table-hover table-white" style="width: 100%; margin: 0; table-layout:fixed;">
|
||||||
|
<thead>
|
||||||
|
<th style="width: 10%">Status</th>
|
||||||
|
<th style="width: 20%">Timestamp</th>
|
||||||
|
<th>Details</th>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<% @history.each do |entry| %>
|
||||||
|
<% entry = JSON.parse(entry, symbolize_names: true) %>
|
||||||
|
<tr class="<%= 'error' if entry[:status] == 'failure' %>">
|
||||||
|
<td><%= entry[:status].capitalize %></td>
|
||||||
|
<td><%= Time.parse(entry[:timestamp]).strftime("%m/%d/%Y %I:%M:%S%p") %></td>
|
||||||
|
<td>
|
||||||
|
<% if entry[:status] == 'failure' %>
|
||||||
|
<a class="backtrace" href="#" onclick="$(this).next().toggle(); return false">
|
||||||
|
<%= entry[:exception] %>: <%= entry[:error] %>
|
||||||
|
</a>
|
||||||
|
<div style="display: none; overflow: auto; width: 100%; background: white; ">
|
||||||
|
<pre style="display: inline-block; font-size: 0.8em; border: none; white-space: nowrap; margin: 0">
|
||||||
|
<%= entry[:backtrace].join("<br />") %>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<p>
|
||||||
|
<span>Node: <%= entry[:node] %></span>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
0
lib/sidetiq/views/sidetiq_history.rb
Normal file
0
lib/sidetiq/views/sidetiq_history.rb
Normal file
59
lib/sidetiq/views/sidetiq_schedule.erb
Normal file
59
lib/sidetiq/views/sidetiq_schedule.erb
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<%= File.read(File.join(File.dirname(__FILE__), 'views', 'assets', 'styles.css')) %>
|
||||||
|
|
||||||
|
<header class="row">
|
||||||
|
<div class="span5">
|
||||||
|
<h3>Recurring Job: <%= @worker.name %></h3>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="container-fluid sidetiq-container">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<%= erb File.read(File.join(File.dirname(__FILE__), 'views', '_worker_nav.erb')) %>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<% if (recurrences = @schedule.recurrence_rules).length > 0 %>
|
||||||
|
<table class="table table-striped table-bordered table-hover table-white" style="width: 100%; margin: 0; table-layout:fixed;">
|
||||||
|
<thead>
|
||||||
|
<th>Recurrences</th>
|
||||||
|
</thead>
|
||||||
|
<% recurrences.each do |rule| %>
|
||||||
|
<tr>
|
||||||
|
<td><%= rule.to_s %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<% if (exceptions = @schedule.exception_rules).length > 0 %>
|
||||||
|
<table class="table table-striped table-bordered table-hover table-white" style="width: 100%; margin: 0; table-layout:fixed;">
|
||||||
|
<thead>
|
||||||
|
<th>Exceptions</th>
|
||||||
|
</thead>
|
||||||
|
<% exceptions.each do |rule| %>
|
||||||
|
<tr>
|
||||||
|
<td><%= rule.to_s %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<table class="table table-striped table-bordered table-hover table-white" style="width: 100%; margin: 0; table-layout:fixed;">
|
||||||
|
<thead>
|
||||||
|
<th style="width: 25%">Next 10 runs</th>
|
||||||
|
<th style="width: 75%" />
|
||||||
|
<% @schedule.next_occurrences(10, @time).each do |time| %>
|
||||||
|
<tr>
|
||||||
|
<td><time><%= time.getutc %></time></td>
|
||||||
|
<td><%= relative_time(time) %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
|
@ -11,7 +11,7 @@ module Sidetiq
|
||||||
erb File.read(File.join(VIEWS, 'sidetiq.erb'))
|
erb File.read(File.join(VIEWS, 'sidetiq.erb'))
|
||||||
end
|
end
|
||||||
|
|
||||||
app.get "/sidetiq/:name" do
|
app.get "/sidetiq/:name/schedule" do
|
||||||
halt 404 unless (name = params[:name])
|
halt 404 unless (name = params[:name])
|
||||||
|
|
||||||
@time = Sidetiq.clock.gettime
|
@time = Sidetiq.clock.gettime
|
||||||
|
@ -20,7 +20,23 @@ module Sidetiq
|
||||||
worker.name == name
|
worker.name == name
|
||||||
end.flatten
|
end.flatten
|
||||||
|
|
||||||
erb File.read(File.join(VIEWS, 'sidetiq_details.erb'))
|
erb File.read(File.join(VIEWS, 'sidetiq_schedule.erb'))
|
||||||
|
end
|
||||||
|
|
||||||
|
app.get "/sidetiq/:name/history" do
|
||||||
|
halt 404 unless (name = params[:name])
|
||||||
|
|
||||||
|
@time = Sidetiq.clock.gettime
|
||||||
|
|
||||||
|
@worker, @schedule = Sidetiq.schedules.select do |worker, _|
|
||||||
|
worker.name == name
|
||||||
|
end.flatten
|
||||||
|
|
||||||
|
@history = Sidekiq.redis do |redis|
|
||||||
|
redis.lrange("sidetiq:#{@worker.name}:history", 0, -1)
|
||||||
|
end
|
||||||
|
|
||||||
|
erb File.read(File.join(VIEWS, 'sidetiq_history.erb'))
|
||||||
end
|
end
|
||||||
|
|
||||||
app.post "/sidetiq/:name/trigger" do
|
app.post "/sidetiq/:name/trigger" do
|
||||||
|
|
|
@ -21,8 +21,8 @@ class TestHistory < Sidetiq::TestCase
|
||||||
assert_empty actual[:backtrace]
|
assert_empty actual[:backtrace]
|
||||||
assert_empty actual[:exception]
|
assert_empty actual[:exception]
|
||||||
|
|
||||||
refute_empty actual[:processor]
|
refute_empty actual[:node]
|
||||||
refute_empty actual[:processed]
|
refute_empty actual[:timestamp]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_failure
|
def test_failure
|
||||||
|
@ -45,8 +45,8 @@ class TestHistory < Sidetiq::TestCase
|
||||||
assert_equal "StandardError", actual[:exception]
|
assert_equal "StandardError", actual[:exception]
|
||||||
refute_empty actual[:backtrace]
|
refute_empty actual[:backtrace]
|
||||||
|
|
||||||
refute_empty actual[:processor]
|
refute_empty actual[:node]
|
||||||
refute_empty actual[:processed]
|
refute_empty actual[:timestamp]
|
||||||
end
|
end
|
||||||
|
|
||||||
def middlewared
|
def middlewared
|
||||||
|
|
|
@ -33,8 +33,13 @@ class TestWeb < Sidetiq::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_details_page
|
def test_history_page
|
||||||
get "/sidetiq/ScheduledWorker"
|
get "/sidetiq/ScheduledWorker/history"
|
||||||
|
assert_equal 200, last_response.status
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_schedule_page
|
||||||
|
get "/sidetiq/ScheduledWorker/schedule"
|
||||||
assert_equal 200, last_response.status
|
assert_equal 200, last_response.status
|
||||||
schedule = clock.schedules[ScheduledWorker]
|
schedule = clock.schedules[ScheduledWorker]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue