mirror of
https://github.com/mperham/sidekiq.git
synced 2022-11-09 13:52:34 -05:00
Add dashboard.
This commit is contained in:
parent
2062963e20
commit
cc5165ed3d
6 changed files with 516 additions and 6 deletions
|
@ -203,12 +203,28 @@ module Sidekiq
|
|||
redirect "#{root_path}scheduled"
|
||||
end
|
||||
|
||||
get '/dashboard' do
|
||||
@redis_info = Sidekiq.redis{ |conn| conn.info }
|
||||
stats_history = Sidekiq::Stats::History.new((params[:days] || 30).to_i)
|
||||
@processed_history = stats_history.processed
|
||||
@failed_history = stats_history.failed
|
||||
slim :dashboard
|
||||
end
|
||||
|
||||
get '/dashboard/update' do
|
||||
stats = Sidekiq::Stats.new
|
||||
|
||||
content_type :json
|
||||
Sidekiq.dump_json({ processed: stats.processed, failed: stats.failed })
|
||||
end
|
||||
|
||||
def self.tabs
|
||||
@tabs ||= {
|
||||
"Workers" =>'',
|
||||
"Queues" =>'queues',
|
||||
"Retries" =>'retries',
|
||||
"Scheduled" =>'scheduled'
|
||||
"Scheduled" =>'scheduled',
|
||||
"Dashboard" =>'dashboard'
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
(function(e){function n(){var t=r(this);if(!isNaN(t.datetime)){e(this).text(i(t.datetime))}return this}function r(n){n=e(n);if(!n.data("timeago")){n.data("timeago",{datetime:t.datetime(n)});var r=e.trim(n.text());if(r.length>0&&!(t.isTime(n)&&n.attr("title"))){n.attr("title",r)}}return n.data("timeago")}function i(e){return t.inWords(s(e))}function s(e){return(new Date).getTime()-e.getTime()}e.timeago=function(t){if(t instanceof Date){return i(t)}else if(typeof t==="string"){return i(e.timeago.parse(t))}else if(typeof t==="number"){return i(new Date(t))}else{return i(e.timeago.datetime(t))}};var t=e.timeago;e.extend(e.timeago,{settings:{refreshMillis:6e4,allowFuture:false,strings:{prefixAgo:null,prefixFromNow:null,suffixAgo:"ago",suffixFromNow:"from now",seconds:"less than a minute",minute:"about a minute",minutes:"%d minutes",hour:"about an hour",hours:"about %d hours",day:"a day",days:"%d days",month:"about a month",months:"%d months",year:"about a year",years:"%d years",wordSeparator:" ",numbers:[]}},inWords:function(t){function l(r,i){var s=e.isFunction(r)?r(i,t):r;var o=n.numbers&&n.numbers[i]||i;return s.replace(/%d/i,o)}var n=this.settings.strings;var r=n.prefixAgo;var i=n.suffixAgo;if(this.settings.allowFuture){if(t<0){r=n.prefixFromNow;i=n.suffixFromNow}}var s=Math.abs(t)/1e3;var o=s/60;var u=o/60;var a=u/24;var f=a/365;var c=s<45&&l(n.seconds,Math.round(s))||s<90&&l(n.minute,1)||o<45&&l(n.minutes,Math.round(o))||o<90&&l(n.hour,1)||u<24&&l(n.hours,Math.round(u))||u<42&&l(n.day,1)||a<30&&l(n.days,Math.round(a))||a<45&&l(n.month,1)||a<365&&l(n.months,Math.round(a/30))||f<1.5&&l(n.year,1)||l(n.years,Math.round(f));var h=n.wordSeparator===undefined?" ":n.wordSeparator;return e.trim([r,c,i].join(h))},parse:function(t){var n=e.trim(t);n=n.replace(/\.\d+/,"");n=n.replace(/-/,"/").replace(/-/,"/");n=n.replace(/T/," ").replace(/Z/," UTC");n=n.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2");return new Date(n)},datetime:function(n){var r=t.isTime(n)?e(n).attr("datetime"):e(n).attr("title");return t.parse(r)},isTime:function(t){return e(t).get(0).tagName.toLowerCase()==="time"}});e.fn.timeago=function(){var e=this;e.each(n);var r=t.settings;if(r.refreshMillis>0){setInterval(function(){e.each(n)},r.refreshMillis)}return e};document.createElement("abbr");document.createElement("time")})(jQuery)
|
||||
|
||||
Sidekiq = {};
|
||||
|
||||
$(function() {
|
||||
$.timeago.settings.allowFuture = true;
|
||||
$.timeago.settings.refreshMillis = 0;
|
||||
|
@ -36,4 +38,3 @@ $(function() {
|
|||
return confirm($(this).attr('data-confirm'));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
115
web/assets/javascripts/dashboard.js
Normal file
115
web/assets/javascripts/dashboard.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -487,3 +487,346 @@ img.smallogo {
|
|||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.stat {
|
||||
float: left;
|
||||
text-align: center;
|
||||
margin-right: 20px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding: 5px;
|
||||
width: 150px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat p {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.history-heading {
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.history-graph {
|
||||
font-size: 0.8em;
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.history-graph.active {
|
||||
background-color: #B1003E;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.history-graph.active:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Rickshaw */
|
||||
|
||||
.rickshaw_graph .detail {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
transition: opacity 0.25s linear;
|
||||
-moz-transition: opacity 0.25s linear;
|
||||
-o-transition: opacity 0.25s linear;
|
||||
-webkit-transition: opacity 0.25s linear;
|
||||
}
|
||||
.rickshaw_graph .detail.inactive {
|
||||
opacity: 0;
|
||||
}
|
||||
.rickshaw_graph .detail .item.active {
|
||||
opacity: 1;
|
||||
}
|
||||
.rickshaw_graph .detail .x_label {
|
||||
font-family: Arial, sans-serif;
|
||||
border-radius: 3px;
|
||||
padding: 6px;
|
||||
opacity: 0.5;
|
||||
border: 1px solid #e0e0e0;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
background: white;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rickshaw_graph .detail .item {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
border-radius: 3px;
|
||||
padding: 0.25em;
|
||||
font-size: 12px;
|
||||
font-family: Arial, sans-serif;
|
||||
opacity: 0;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
color: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||
margin-left: 1em;
|
||||
margin-top: -1em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rickshaw_graph .detail .item.active {
|
||||
opacity: 1;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
.rickshaw_graph .detail .item:before {
|
||||
content: "\25c2";
|
||||
position: absolute;
|
||||
left: -0.5em;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
width: 0;
|
||||
}
|
||||
.rickshaw_graph .detail .dot {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
margin-left: -4px;
|
||||
margin-top: -3px;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||
background: white;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
display: none;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
.rickshaw_graph .detail .dot.active {
|
||||
display: block;
|
||||
}
|
||||
/* graph */
|
||||
|
||||
.rickshaw_graph {
|
||||
position: relative;
|
||||
}
|
||||
.rickshaw_graph svg {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ticks */
|
||||
|
||||
.rickshaw_graph .x_tick {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 0px;
|
||||
border-left: 1px dotted rgba(0, 0, 0, 0.2);
|
||||
pointer-events: none;
|
||||
}
|
||||
.rickshaw_graph .x_tick .title {
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
font-family: Arial, sans-serif;
|
||||
opacity: 0.5;
|
||||
white-space: nowrap;
|
||||
margin-left: 3px;
|
||||
bottom: 1px;
|
||||
}
|
||||
|
||||
/* annotations */
|
||||
|
||||
.rickshaw_annotation_timeline {
|
||||
height: 1px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.rickshaw_annotation_timeline .annotation {
|
||||
position: absolute;
|
||||
height: 6px;
|
||||
width: 6px;
|
||||
margin-left: -2px;
|
||||
top: -3px;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.rickshaw_graph .annotation_line {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: -6px;
|
||||
width: 0px;
|
||||
border-left: 2px solid rgba(0, 0, 0, 0.3);
|
||||
display: none;
|
||||
}
|
||||
.rickshaw_graph .annotation_line.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.rickshaw_graph .annotation_range {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: -6px;
|
||||
z-index: -10;
|
||||
}
|
||||
.rickshaw_graph .annotation_range.active {
|
||||
display: block;
|
||||
}
|
||||
.rickshaw_graph .annotation_range.active.offscreen {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rickshaw_annotation_timeline .annotation .content {
|
||||
background: white;
|
||||
color: black;
|
||||
opacity: 0.9;
|
||||
padding: 5px 5px;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
font-size: 12px;
|
||||
padding: 6px 8px 8px;
|
||||
top: 18px;
|
||||
left: -11px;
|
||||
width: 160px;
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rickshaw_annotation_timeline .annotation .content:before {
|
||||
content: "\25b2";
|
||||
position: absolute;
|
||||
top: -11px;
|
||||
color: white;
|
||||
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
.rickshaw_annotation_timeline .annotation.active,
|
||||
.rickshaw_annotation_timeline .annotation:hover {
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
cursor: none;
|
||||
}
|
||||
.rickshaw_annotation_timeline .annotation .content:hover {
|
||||
z-index: 50;
|
||||
}
|
||||
.rickshaw_annotation_timeline .annotation.active .content {
|
||||
display: block;
|
||||
}
|
||||
.rickshaw_annotation_timeline .annotation:hover .content {
|
||||
display: block;
|
||||
z-index: 50;
|
||||
}
|
||||
.rickshaw_graph .y_axis {
|
||||
fill: none;
|
||||
}
|
||||
.rickshaw_graph .y_ticks .tick {
|
||||
stroke: rgba(0, 0, 0, 0.16);
|
||||
stroke-width: 2px;
|
||||
shape-rendering: crisp-edges;
|
||||
pointer-events: none;
|
||||
}
|
||||
.rickshaw_graph .y_grid .tick {
|
||||
z-index: -1;
|
||||
stroke: rgba(0, 0, 0, 0.20);
|
||||
stroke-width: 1px;
|
||||
stroke-dasharray: 1 1;
|
||||
}
|
||||
.rickshaw_graph .y_grid path {
|
||||
fill: none;
|
||||
stroke: none;
|
||||
}
|
||||
.rickshaw_graph .y_ticks path {
|
||||
fill: none;
|
||||
stroke: #808080;
|
||||
}
|
||||
.rickshaw_graph .y_ticks text {
|
||||
opacity: 0.5;
|
||||
font-size: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.rickshaw_graph .x_tick.glow .title,
|
||||
.rickshaw_graph .y_ticks.glow text {
|
||||
fill: black;
|
||||
color: black;
|
||||
text-shadow:
|
||||
-1px 1px 0 rgba(255, 255, 255, 0.1),
|
||||
1px -1px 0 rgba(255, 255, 255, 0.1),
|
||||
1px 1px 0 rgba(255, 255, 255, 0.1),
|
||||
0px 1px 0 rgba(255, 255, 255, 0.1),
|
||||
0px -1px 0 rgba(255, 255, 255, 0.1),
|
||||
1px 0px 0 rgba(255, 255, 255, 0.1),
|
||||
-1px 0px 0 rgba(255, 255, 255, 0.1),
|
||||
-1px -1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.rickshaw_graph .x_tick.inverse .title,
|
||||
.rickshaw_graph .y_ticks.inverse text {
|
||||
fill: white;
|
||||
color: white;
|
||||
text-shadow:
|
||||
-1px 1px 0 rgba(0, 0, 0, 0.8),
|
||||
1px -1px 0 rgba(0, 0, 0, 0.8),
|
||||
1px 1px 0 rgba(0, 0, 0, 0.8),
|
||||
0px 1px 0 rgba(0, 0, 0, 0.8),
|
||||
0px -1px 0 rgba(0, 0, 0, 0.8),
|
||||
1px 0px 0 rgba(0, 0, 0, 0.8),
|
||||
-1px 0px 0 rgba(0, 0, 0, 0.8),
|
||||
-1px -1px 0 rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
.rickshaw_legend {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
background: #404040;
|
||||
display: inline-block;
|
||||
padding: 12px 5px;
|
||||
border-radius: 2px;
|
||||
position: relative;
|
||||
}
|
||||
.rickshaw_legend:hover {
|
||||
z-index: 10;
|
||||
}
|
||||
.rickshaw_legend .swatch {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.rickshaw_legend .line {
|
||||
clear: both;
|
||||
line-height: 140%;
|
||||
padding-right: 15px;
|
||||
}
|
||||
.rickshaw_legend .line .swatch {
|
||||
display: inline-block;
|
||||
margin-right: 3px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.rickshaw_legend .label {
|
||||
white-space: nowrap;
|
||||
display: inline;
|
||||
}
|
||||
.rickshaw_legend .action:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.rickshaw_legend .action {
|
||||
margin-right: 0.2em;
|
||||
font-size: 10px;
|
||||
opacity: 0.2;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
.rickshaw_legend .line.disabled {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.rickshaw_legend ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rickshaw_legend li {
|
||||
padding: 0 0 0 2px;
|
||||
min-width: 80px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rickshaw_legend li:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.rickshaw_legend li:active {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
|
|
36
web/views/dashboard.slim
Normal file
36
web/views/dashboard.slim
Normal file
|
@ -0,0 +1,36 @@
|
|||
script type="text/javascript" src="#{{root_path}}javascripts/dashboard.js"
|
||||
|
||||
h3 Dashboard
|
||||
|
||||
h5 Real-time Jobs
|
||||
#realtime
|
||||
|
||||
h5
|
||||
span.history-heading History
|
||||
a href="#{{current_path}}" class="history-graph #{{"active" if params[:days].nil? || params[:days] == "30"}}" 1 month
|
||||
a href="#{{current_path}}?days=90" class="history-graph #{{"active" if params[:days] == "90"}}" 3 month
|
||||
a href="#{{current_path}}?days=180" class="history-graph #{{"active" if params[:days] == "180"}}" 6 month
|
||||
#history data-processed="#{Sidekiq.dump_json(@processed_history)}" data-failed="#{Sidekiq.dump_json(@failed_history)}" data-update-url="#{{current_path}}/update"
|
||||
|
||||
br
|
||||
h5 Redis
|
||||
|
||||
.stat
|
||||
h3= @redis_info.fetch("redis_version")
|
||||
p Version
|
||||
|
||||
.stat
|
||||
h3= @redis_info.fetch("uptime_in_days")
|
||||
p Uptime (days)
|
||||
|
||||
.stat
|
||||
h3= @redis_info.fetch("connected_clients")
|
||||
p Connections
|
||||
|
||||
.stat
|
||||
h3= @redis_info.fetch("used_memory_human")
|
||||
p Memory Usage
|
||||
|
||||
.stat
|
||||
h3= @redis_info.fetch("used_memory_peak_human")
|
||||
p Peak Memory Usage
|
|
@ -1,9 +1,10 @@
|
|||
doctype html
|
||||
html
|
||||
head
|
||||
title= Sidekiq::NAME
|
||||
link href='#{{root_path}}stylesheets/bootstrap.css' media='screen' rel='stylesheet' type='text/css'
|
||||
link href='#{{root_path}}stylesheets/application.css' media='screen' rel='stylesheet' type='text/css'
|
||||
title= Sidekiq::NAME
|
||||
script type="text/javascript" src="#{{root_path}}javascripts/application.js"
|
||||
|
||||
- if params[:poll]
|
||||
javascript:
|
||||
|
@ -40,6 +41,4 @@ html
|
|||
a#live-poll.btn.btn-block.btn-primary href='#{{root_path}}#{{current_path}}?poll=true' Live Poll
|
||||
|
||||
.span10
|
||||
== yield
|
||||
|
||||
script type="text/javascript" src="#{{root_path}}javascripts/application.js"
|
||||
== yield
|
Loading…
Add table
Reference in a new issue