1
0
Fork 0
mirror of https://github.com/mperham/sidekiq.git synced 2022-11-09 13:52:34 -05:00

Update Web UI, add new Busy tab with process heartbeat and job info

This commit is contained in:
Mike Perham 2014-03-06 21:30:11 -08:00
parent ee7e181bd6
commit ff9db33666
10 changed files with 80 additions and 47 deletions

View file

@ -11,6 +11,8 @@ Please see [Upgrading.md](Upgrading.md) for more comprehensive upgrade notes.
exposing these jobs.
- **Process Heartbeat** - each Sidekiq process will ping Redis every 5
seconds to give an accurate summary of the Sidekiq population at work.
- The Workers tab is now renamed to Busy and contains a list of live
Sidekiq processes with a heartbeat.
- **Remove official support for Ruby 1.9** Things still might work but
I no longer actively test on it.
- **Remove built-in support for Redis-to-Go**.
@ -23,6 +25,8 @@ Please see [Upgrading.md](Upgrading.md) for more comprehensive upgrade notes.
version to pick up Sidekiq support.
- Remove deprecated Sidekiq::Client.registered\_\* APIs
- Remove deprecated support for the old Sidekiq::Worker#retries\_exhausted method.
- Remove usage of the term 'Worker' in the UI for clarity. Users would call both threads and
processes 'workers'. Instead, use "Thread", "Process" or "Job".
2.17.7
-----------

View file

@ -470,8 +470,8 @@ module Sidekiq
live = ProcessSet.new.map {|x| /\A#{x['hostname']}:#{x['process_id']}-/ }
msgs = Sidekiq.redis do |conn|
workers = conn.smembers("workers")
to_rem = workers.delete_if {|w| !live.any? {|identity| w =~ identity } }
conn.srem('workers', *to_rem) unless to_rem.empty?
to_rem = workers.reject {|w| live.any? {|identity| w =~ identity } }
conn.srem('workers', to_rem) unless to_rem.empty?
workers.empty? ? {} : conn.mapped_mget(*workers.map {|w| "worker:#{w}" })
end

View file

@ -58,6 +58,7 @@ module Sidekiq
manager.heartbeat({
'key' => "#{hostname}:#{$$}",
'hostname' => hostname,
'started_at' => Time.now.to_f,
'pid' => $$,
'process_id' => process_id,
'tag' => tag.strip,

View file

@ -20,7 +20,7 @@ module Sidekiq
DEFAULT_TABS = {
"Dashboard" => '',
"Workers" => 'workers',
"Busy" => 'busy',
"Queues" => 'queues',
"Retries" => 'retries',
"Scheduled" => 'scheduled',
@ -38,8 +38,8 @@ module Sidekiq
alias_method :tabs, :custom_tabs
end
get "/workers" do
erb :workers
get "/busy" do
erb :busy
end
get "/queues" do

View file

@ -363,12 +363,12 @@ class TestApi < Sidekiq::Test
assert false
end
pdata = { 'pid' => $$, 'hostname' => hostname, 'process_id' => process_id, 'key' => "#{hostname}:#{$$}", 'at' => Time.now.to_f }
pdata = { 'pid' => $$, 'hostname' => hostname, 'process_id' => process_id, 'key' => "#{hostname}:#{$$}", 'at' => Time.now.to_f, 'started_at' => Time.now.to_i }
Sidekiq.redis do |conn|
conn.hset('processes', pdata['key'], Sidekiq.dump_json(pdata))
end
s = "worker:#{hostname}:#{process_id}-12345"
s = "#{hostname}:#{process_id}-12345"
data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => Time.now.to_i })
Sidekiq.redis do |c|
c.multi do
@ -384,6 +384,7 @@ class TestApi < Sidekiq::Test
assert_equal Time.now.year, Time.at(y['run_at']).year
end
assert_equal 1, w.size
s = "#{hostname}:#{process_id}-12346"
data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => (Time.now.to_i - 2*60*60) })
Sidekiq.redis do |c|

View file

@ -30,13 +30,14 @@ class TestWeb < Sidekiq::Test
it 'can display workers' do
Sidekiq.redis do |conn|
conn.hset('processes', 'foo:1234', Sidekiq.dump_json('key' => 'foo:1234', 'hostname' => 'foo', 'process_id' => '1234', 'started_at' => Time.now.to_f, 'at' => Time.now.to_f))
identity = 'foo:1234-123abc:default'
conn.sadd('workers', identity)
hash = {:queue => 'critical', :payload => { 'class' => WebWorker.name, 'args' => [1,'abc'] }, :run_at => Time.now.to_i }
conn.setex("worker:#{identity}", 10, Sidekiq.dump_json(hash))
end
get '/workers'
get '/busy'
assert_equal 200, last_response.status
assert_match /status-active/, last_response.body
assert_match /critical/, last_response.body
@ -286,7 +287,7 @@ class TestWeb < Sidekiq::Test
conn.setex("worker:#{identity}", 10, Sidekiq.dump_json(hash))
end
get '/workers'
get '/busy'
assert_equal 200, last_response.status
assert_match /FailWorker/, last_response.body
assert last_response.body.include?( "&lt;a&gt;hello&lt;&#x2F;a&gt;" )

View file

@ -64,3 +64,7 @@ en: # <---- change this to your locale code
DeadJobs: Dead Jobs
NoDeadJobsFound: No dead jobs were found
Dead: Dead
Processes: Processes
Thread: Thread
Threads: Threads
Jobs: Jobs

View file

@ -1,22 +0,0 @@
<table class="workers table table-hover table-bordered table-striped table-white">
<thead>
<th><%= t('Worker') %></th>
<th><%= t('Queue') %></th>
<th><%= t('Class') %></th>
<th><%= t('Arguments') %></th>
<th><%= t('Started') %></th>
</thead>
<% workers.each_with_index do |(worker, msg), index| %>
<tr>
<td><%= worker %></td>
<td>
<a href="<%= root_path %>queues/<%= msg['queue'] %>"><%= msg['queue'] %></a>
</td>
<td><%= msg['payload']['class'] %></td>
<td>
<div class="args"><%= display_args(msg['payload']['args']) %></div>
</td>
<td><%= relative_time(Time.at(msg['run_at'])) %></td>
</tr>
<% end %>
</table>

60
web/views/busy.erb Normal file
View file

@ -0,0 +1,60 @@
<div class="row header">
<div class="col-sm-7">
<h3><%= t('Processes') %></h3>
</div>
</div>
<table class="processes table table-hover table-bordered table-striped table-white">
<thead>
<th><%= t('Name') %></th>
<th><%= t('Started') %></th>
<th><%= t('Threads') %></th>
<th><%= t('Busy') %></th>
</thead>
<% Sidekiq::ProcessSet.new.each_with_index do |process, index| %>
<tr>
<td><%= process['key'] %></td>
<td><%= relative_time(Time.at(process['started_at'])) %></td>
<td><%= process['concurrency'] %></td>
<td><%= process['busy'] %></td>
</tr>
<% end %>
</table>
<div class="row header">
<div class="col-sm-7">
<h3><%= t('Jobs') %></h3>
</div>
</div>
<table class="workers table table-hover table-bordered table-striped table-white">
<thead>
<th><%= t('Thread') %></th>
<th><%= t('Queue') %></th>
<th><%= t('Class') %></th>
<th><%= t('Arguments') %></th>
<th><%= t('Started') %></th>
</thead>
<% workers.each_with_index do |(thread, msg), index| %>
<tr>
<td><%= thread %></td>
<td>
<a href="<%= root_path %>queues/<%= msg['queue'] %>"><%= msg['queue'] %></a>
</td>
<td><%= msg['payload']['class'] %></td>
<td>
<div class="args"><%= display_args(msg['payload']['args']) %></div>
</td>
<td><%= relative_time(Time.at(msg['run_at'])) %></td>
</tr>
<% end %>
</table>
<% if workers_size > 0 %>
<div class="row">
<div class="col-sm-2 pull-right">
<form action="<%= root_path %>reset" method="post">
<button class="btn btn-primary btn-block" type="submit"><%= t('ClearWorkerList') %></button>
</form>
</div>
</div>
<% end %>

View file

@ -1,16 +0,0 @@
<div class="row header">
<div class="col-sm-7">
<h3><%= t('Workers') %></h3>
</div>
</div>
<%= erb :_workers %>
<% if workers_size > 0 %>
<div class="row">
<div class="col-sm-2 pull-right">
<form action="<%= root_path %>reset" method="post">
<button class="btn btn-primary btn-block" type="submit"><%= t('ClearWorkerList') %></button>
</form>
</div>
</div>
<% end %>