sidekiq-statistic 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq-statistic might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/README.md +2 -1
- data/lib/sidekiq/statistic/base.rb +3 -1
- data/lib/sidekiq/statistic/locales/de.yml +27 -0
- data/lib/sidekiq/statistic/locales/en.yml +1 -0
- data/lib/sidekiq/statistic/locales/it.yml +27 -0
- data/lib/sidekiq/statistic/locales/ru.yml +1 -0
- data/lib/sidekiq/statistic/log_parser.rb +18 -3
- data/lib/sidekiq/statistic/middleware.rb +6 -1
- data/lib/sidekiq/statistic/statistic/realtime.rb +1 -1
- data/lib/sidekiq/statistic/statistic/workers.rb +5 -0
- data/lib/sidekiq/statistic/version.rb +1 -1
- data/lib/sidekiq/statistic/views/realtime_statistic.js +4 -2
- data/lib/sidekiq/statistic/views/sidekiq-statistic.css +31 -0
- data/lib/sidekiq/statistic/views/statistic.erb +3 -0
- data/lib/sidekiq/statistic/views/statistic.js +45 -6
- data/lib/sidekiq/statistic/views/worker.erb +1 -1
- data/lib/sidekiq/statistic/web_extension.rb +2 -2
- data/{sidekiq-history.gemspec → sidekiq-statistic.gemspec} +0 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5f72d1a3e51a38a18b09adb0e47f53c9aee1bc7
|
4
|
+
data.tar.gz: a56f6a9f5f4873da709b241cc2f58a0f15be0cb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b2dddcaa90e5ec6452edb082e9723ecd4dd77f27d611591a6c891d0078ca92ebbdb2cbbcd399123116c0683e95874b8544e2991626d3ed0a2b297640027350e
|
7
|
+
data.tar.gz: a6ac2d8b346e7a8f9cee3c85b81dddf72e4a10b72b91aa6f1810edda33b60996dc1d68550675ec9c8180e96c626e4f50812b4c7b43c659eeb05e422d84e01147
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
## HEAD
|
2
|
+
|
3
|
+
## v1.1
|
4
|
+
* 29.08.2015: Create custom tooltip for charts on index page (fix #63)
|
5
|
+
|
6
|
+
*Anton Davydov*
|
7
|
+
* 26.08.2015: Add queue to workers table in index page
|
8
|
+
|
9
|
+
*Anton Davydov*
|
10
|
+
* 25.08.2015: Italian localization
|
11
|
+
|
12
|
+
*Fabio Napoleoni*
|
13
|
+
* 25.08.2015: Fix worker naming for AJ mailers (fix #59)
|
14
|
+
|
15
|
+
*Anton Davydov*
|
16
|
+
* 21.08.2015: Use dynamic path generation for json requests (fix #56)
|
17
|
+
|
18
|
+
*Anton Davydov*
|
19
|
+
* 21.08.2015: Add button in log page for display only special job (#40)
|
20
|
+
|
21
|
+
*Anton Davydov*
|
22
|
+
* 20.08.2015: Add German Localization (#54)
|
23
|
+
|
24
|
+
*Felix Bünemann*
|
25
|
+
|
26
|
+
* 20.08.2015: Fix statistics display for nested worker classes (#48)
|
27
|
+
|
28
|
+
*Felix Bünemann*
|
29
|
+
|
1
30
|
## v1.0
|
2
31
|
* 19.08.2015: Middleware refactoring (#45)
|
3
32
|
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ Also you can check <a href="https://sidekiq-history-gem.herokuapp.com/sidekiq/st
|
|
21
21
|
## Installation
|
22
22
|
Add this line to your application's Gemfile:
|
23
23
|
|
24
|
-
gem 'sidekiq-statistic'
|
24
|
+
gem 'sidekiq-statistic'
|
25
25
|
|
26
26
|
And then execute:
|
27
27
|
|
@@ -40,6 +40,7 @@ require 'sidekiq/web'
|
|
40
40
|
require 'sidekiq-statistic'
|
41
41
|
|
42
42
|
use Rack::Session::Cookie, secret: 'some unique secret string here'
|
43
|
+
Sidekiq::Web.instance_eval { @middleware.reverse! } # Last added, First Run
|
43
44
|
run Sidekiq::Web
|
44
45
|
```
|
45
46
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
module Statistic
|
3
3
|
class Base
|
4
|
+
KEY_SEPARATOR = /(?<!:):(?!:)/.freeze
|
5
|
+
|
4
6
|
def initialize(days_previous, start_date = nil)
|
5
7
|
@start_date = start_date || Time.now.utc.to_date
|
6
8
|
@end_date = @start_date - days_previous
|
@@ -29,7 +31,7 @@ module Sidekiq
|
|
29
31
|
conn
|
30
32
|
.hgetall(REDIS_HASH)
|
31
33
|
.each do |keys, value|
|
32
|
-
*keys, last = keys.split(
|
34
|
+
*keys, last = keys.split(KEY_SEPARATOR)
|
33
35
|
keys.inject(redis_hash, &key_or_empty_hash)[last.to_sym] = to_number(value)
|
34
36
|
end
|
35
37
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# elements like %{queue} are variables and should not be translated
|
2
|
+
de: # <---- change this to your locale code
|
3
|
+
Queue: Queue
|
4
|
+
Exclude: Ausblenden
|
5
|
+
Index: Übersicht
|
6
|
+
RealtimeStatistic: Echtzeitstatistik
|
7
|
+
Statistic: Statistik
|
8
|
+
Start: Beginn
|
9
|
+
End: Ende
|
10
|
+
Failed: Fehlgeschlagen
|
11
|
+
Passed: Erfolgreich
|
12
|
+
WorkersTable: Arbeiter-Tabelle
|
13
|
+
Worker: Arbeiter
|
14
|
+
Date: Datum
|
15
|
+
Success: Erfolg
|
16
|
+
Failure: Fehler
|
17
|
+
Total: Gesamt
|
18
|
+
TimeSec: Zeit(sek)
|
19
|
+
AverageSec: Durchschnitt(sek)
|
20
|
+
MinTimeSec: Min. Zeit(sek)
|
21
|
+
MaxTimeSec: Max. Zeit(sek)
|
22
|
+
LastJobStatus: Letzter Job Status
|
23
|
+
WorkerInformation: '%{worker} Information'
|
24
|
+
InformationTable: Info-Tabelle
|
25
|
+
WorkerLog: Arbeiter-Log
|
26
|
+
WorkerTablePerDay: Arbeiter-Tabelle (pro Tag)
|
27
|
+
LastRun: Letzte Ausführung
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# elements like %{queue} are variables and should not be translated
|
2
|
+
it: # <---- change this to your locale code
|
3
|
+
Queue: Fila
|
4
|
+
Exclude: Escludi
|
5
|
+
Index: Indice
|
6
|
+
RealtimeStatistic: Statistiche in Tempo Reale
|
7
|
+
Statistic: Statistiche
|
8
|
+
Start: Inizio
|
9
|
+
End: Fine
|
10
|
+
Failed: Fallito
|
11
|
+
Passed: Passato
|
12
|
+
WorkersTable: Tabella Worker
|
13
|
+
Worker: Worker
|
14
|
+
Date: Data
|
15
|
+
Success: Successo
|
16
|
+
Failure: Fallito
|
17
|
+
Total: Totale
|
18
|
+
TimeSec: Tempo (sec)
|
19
|
+
AverageSec: Media (sec)
|
20
|
+
MinTimeSec: Minimo (sec)
|
21
|
+
MaxTimeSec: Massimo (sec)
|
22
|
+
LastJobStatus: Stato Ultimo Job
|
23
|
+
WorkerInformation: 'Informazioni %{worker}'
|
24
|
+
InformationTable: Tabella Informazioni
|
25
|
+
WorkerLog: Worker log
|
26
|
+
WorkerTablePerDay: Tabella Worker (per giorno)
|
27
|
+
LastRun: Ultima Esecuzione
|
@@ -15,12 +15,27 @@ module Sidekiq
|
|
15
15
|
File
|
16
16
|
.readlines(@logfile)
|
17
17
|
.first(FILE_LINES_COUNT)
|
18
|
-
.map{ |line|
|
18
|
+
.map{ |line| sub_line(line) if line[/\W?#@worker_name\W?/] }
|
19
19
|
.compact
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
22
|
+
def sub_line(line)
|
23
|
+
line
|
24
|
+
.sub(/\n/, '')
|
25
|
+
.sub(/(JID-[\w]+)/) { jid_tag($1) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def jid_tag(jid)
|
29
|
+
"<span class=\"statistic__jid js-jid__#{jid[4..-1]}\""\
|
30
|
+
"data-target=\".js-jid__#{jid[4..-1]}\" #{jid_style jid}>#{jid}</span>"
|
31
|
+
end
|
32
|
+
|
33
|
+
def jid_style(worker_jid)
|
34
|
+
return unless worker_jid
|
35
|
+
color = Digest::MD5.hexdigest(worker_jid)[4..9]
|
36
|
+
.scan(/../).map{ |c| c.to_i(16) }.join ','
|
37
|
+
|
38
|
+
"style=\"background-color: rgba(#{color},0.2);\""
|
24
39
|
end
|
25
40
|
|
26
41
|
def color(line)
|
@@ -14,9 +14,13 @@ module Sidekiq
|
|
14
14
|
raise e
|
15
15
|
ensure
|
16
16
|
finish = Time.now
|
17
|
+
worker_status[:queue] = msg['queue'.freeze]
|
17
18
|
worker_status[:last_runtime] = finish.utc
|
18
19
|
worker_status[:time] = (finish - start).to_f.round(3)
|
19
20
|
worker_status[:class] = msg['wrapped'.freeze] || worker.class.to_s
|
21
|
+
if worker_status[:class] == 'ActionMailer::DeliveryJob'.freeze
|
22
|
+
worker_status[:class] = msg['args'.freeze].first['arguments'.freeze].first
|
23
|
+
end
|
20
24
|
|
21
25
|
save_entry_for_worker worker_status
|
22
26
|
end
|
@@ -31,7 +35,8 @@ module Sidekiq
|
|
31
35
|
redis.pipelined do
|
32
36
|
redis.hincrby REDIS_HASH, "#{worker_key}:#{status[:last_job_status]}", 1
|
33
37
|
redis.hmset REDIS_HASH, "#{worker_key}:last_job_status", status[:last_job_status],
|
34
|
-
"#{worker_key}:last_time", status[:last_runtime]
|
38
|
+
"#{worker_key}:last_time", status[:last_runtime],
|
39
|
+
"#{worker_key}:queue", status[:queue]
|
35
40
|
redis.lpush "#{worker_key}:timeslist", status[:time]
|
36
41
|
|
37
42
|
redis.hincrby realtime_hash, "#{status[:last_job_status]}:#{worker_status[:class]}", 1
|
@@ -20,7 +20,7 @@ module Sidekiq
|
|
20
20
|
conn
|
21
21
|
.hgetall("#{REDIS_HASH}:realtime:#{Time.now.sec - 1}")
|
22
22
|
.each do |keys, value|
|
23
|
-
*keys, last = keys.split(
|
23
|
+
*keys, last = keys.split(KEY_SEPARATOR)
|
24
24
|
keys.inject(redis_hash, &key_or_empty_hash)[last] = value.to_i
|
25
25
|
end
|
26
26
|
|
@@ -9,6 +9,7 @@ module Sidekiq
|
|
9
9
|
name: worker,
|
10
10
|
last_job_status: last_job_status_for(worker),
|
11
11
|
number_of_calls: number_of_calls(worker),
|
12
|
+
queue: last_queue(worker),
|
12
13
|
runtime: runtime_statistic(worker).values_hash
|
13
14
|
}
|
14
15
|
end
|
@@ -60,6 +61,10 @@ module Sidekiq
|
|
60
61
|
.last[:last_job_status]
|
61
62
|
end
|
62
63
|
|
64
|
+
def last_queue(worker)
|
65
|
+
statistic_for(worker).last[:queue]
|
66
|
+
end
|
67
|
+
|
63
68
|
def runtime_statistic(worker, values = nil)
|
64
69
|
Runtime.new(self, worker, values)
|
65
70
|
end
|
@@ -13,6 +13,7 @@ return d.pie(d.filterTargetsToShow(d.data.targets)).forEach(function(b){f||b.dat
|
|
13
13
|
}).call(C,function(){var a,d=[],e=[],f=[];if(w){for(a=0;w>a;a++)d.push("."+l.shape+"-"+(v+a)),e.push("."+l.text+"-"+(v+a)),f.push("."+l.eventRect+"-"+(v+a));b.svg.selectAll("."+l.shapes).selectAll(d).remove(),b.svg.selectAll("."+l.texts).selectAll(e).remove(),b.svg.selectAll("."+l.eventRects).selectAll(f).remove(),b.svg.select("."+l.xgrid).remove()}D.attr("transform",null).attr(b.xgridAttr),E.attr("transform",null),E.select("line").attr("x1",c.axis_rotated?0:p).attr("x2",c.axis_rotated?b.width:p),E.select("text").attr("x",c.axis_rotated?b.width:0).attr("y",p),H.attr("transform",null).attr("d",j),I.attr("transform",null).attr("d",k),J.attr("transform",null).attr("d",m),K.attr("transform",null).attr("cx",n).attr("cy",o),G.attr("transform",null).attr("x",q).attr("y",r).style("fill-opacity",b.opacityForText.bind(b)),F.attr("transform",null),F.select("rect").filter(b.isRegionOnX).attr("x",b.regionX.bind(b)).attr("width",b.regionWidth.bind(b)),c.interaction_enabled&&b.redrawEventRect(),B(),b.flowing=!1})}},h.selected=function(a){var b=this.internal,c=b.d3;return c.merge(b.main.selectAll("."+l.shapes+b.getTargetSelectorSuffix(a)).selectAll("."+l.shape).filter(function(){return c.select(this).classed(l.SELECTED)}).map(function(a){return a.map(function(a){var b=a.__data__;return b.data?b.data:b})}))},h.select=function(a,b,c){var d=this.internal,e=d.d3,f=d.config;f.data_selection_enabled&&d.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(g,h){var i=e.select(this),j=g.data?g.data.id:g.id,k=d.getToggle(this,g).bind(d),m=f.data_selection_grouped||!a||a.indexOf(j)>=0,n=!b||b.indexOf(h)>=0,o=i.classed(l.SELECTED);i.classed(l.line)||i.classed(l.area)||(m&&n?f.data_selection_isselectable(g)&&!o&&k(!0,i.classed(l.SELECTED,!0),g,h):q(c)&&c&&o&&k(!1,i.classed(l.SELECTED,!1),g,h))})},h.unselect=function(a,b){var c=this.internal,d=c.d3,e=c.config;e.data_selection_enabled&&c.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(f,g){var h=d.select(this),i=f.data?f.data.id:f.id,j=c.getToggle(this,f).bind(c),k=e.data_selection_grouped||!a||a.indexOf(i)>=0,m=!b||b.indexOf(g)>=0,n=h.classed(l.SELECTED);h.classed(l.line)||h.classed(l.area)||k&&m&&e.data_selection_isselectable(f)&&n&&j(!1,h.classed(l.SELECTED,!1),f,g)})},h.transform=function(a,b){var c=this.internal,d=["pie","donut"].indexOf(a)>=0?{withTransform:!0}:null;c.transformTo(b,a,d)},i.transformTo=function(a,b,c){var d=this,e=!d.hasArcType(),f=c||{withTransitionForAxis:e};f.withTransitionForTransform=!1,d.transiting=!1,d.setTargetType(a,b),d.updateTargets(d.data.targets),d.updateAndRedraw(f)},h.groups=function(a){var b=this.internal,c=b.config;return p(a)?c.data_groups:(c.data_groups=a,b.redraw(),c.data_groups)},h.xgrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_x_lines=a,b.redrawWithoutRescale(),c.grid_x_lines):c.grid_x_lines},h.xgrids.add=function(a){var b=this.internal;return this.xgrids(b.config.grid_x_lines.concat(a?a:[]))},h.xgrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!0)},h.ygrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_y_lines=a,b.redrawWithoutRescale(),c.grid_y_lines):c.grid_y_lines},h.ygrids.add=function(a){var b=this.internal;return this.ygrids(b.config.grid_y_lines.concat(a?a:[]))},h.ygrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!1)},h.regions=function(a){var b=this.internal,c=b.config;return a?(c.regions=a,b.redrawWithoutRescale(),c.regions):c.regions},h.regions.add=function(a){var b=this.internal,c=b.config;return a?(c.regions=c.regions.concat(a),b.redrawWithoutRescale(),c.regions):c.regions},h.regions.remove=function(a){var b,c,d,e=this.internal,f=e.config;return a=a||{},b=e.getOption(a,"duration",f.transition_duration),c=e.getOption(a,"classes",[l.region]),d=e.main.select("."+l.regions).selectAll(c.map(function(a){return"."+a})),(b?d.transition().duration(b):d).style("opacity",0).remove(),f.regions=f.regions.filter(function(a){var b=!1;return a["class"]?(a["class"].split(" ").forEach(function(a){c.indexOf(a)>=0&&(b=!0)}),!b):!0}),f.regions},h.data=function(a){var b=this.internal.data.targets;return"undefined"==typeof a?b:b.filter(function(b){return[].concat(a).indexOf(b.id)>=0})},h.data.shown=function(a){return this.internal.filterTargetsToShow(this.data(a))},h.data.values=function(a){var b,c=null;return a&&(b=this.data(a),c=b[0]?b[0].values.map(function(a){return a.value}):null),c},h.data.names=function(a){return this.internal.clearLegendItemTextBoxCache(),this.internal.updateDataAttributes("names",a)},h.data.colors=function(a){return this.internal.updateDataAttributes("colors",a)},h.data.axes=function(a){return this.internal.updateDataAttributes("axes",a)},h.category=function(a,b){var c=this.internal,d=c.config;return arguments.length>1&&(d.axis_x_categories[a]=b,c.redraw()),d.axis_x_categories[a]},h.categories=function(a){var b=this.internal,c=b.config;return arguments.length?(c.axis_x_categories=a,b.redraw(),c.axis_x_categories):c.axis_x_categories},h.color=function(a){var b=this.internal;return b.color(a)},h.x=function(a){var b=this.internal;return arguments.length&&(b.updateTargetX(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.xs=function(a){var b=this.internal;return arguments.length&&(b.updateTargetXs(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.axis=function(){},h.axis.labels=function(a){var b=this.internal;arguments.length&&(Object.keys(a).forEach(function(c){b.axis.setLabelText(c,a[c])}),b.axis.updateLabels())},h.axis.max=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_max=a.x),m(a.y)&&(c.axis_y_max=a.y),m(a.y2)&&(c.axis_y2_max=a.y2)):c.axis_y_max=c.axis_y2_max=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_max,y:c.axis_y_max,y2:c.axis_y2_max}},h.axis.min=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_min=a.x),m(a.y)&&(c.axis_y_min=a.y),m(a.y2)&&(c.axis_y2_min=a.y2)):c.axis_y_min=c.axis_y2_min=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_min,y:c.axis_y_min,y2:c.axis_y2_min}},h.axis.range=function(a){return arguments.length?(q(a.max)&&this.axis.max(a.max),void(q(a.min)&&this.axis.min(a.min))):{max:this.axis.max(),min:this.axis.min()}},h.legend=function(){},h.legend.show=function(a){var b=this.internal;b.showLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.legend.hide=function(a){var b=this.internal;b.hideLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.resize=function(a){var b=this.internal,c=b.config;c.size_width=a?a.width:null,c.size_height=a?a.height:null,this.flush()},h.flush=function(){var a=this.internal;a.updateAndRedraw({withLegend:!0,withTransition:!1,withTransitionForTransform:!1})},h.destroy=function(){var b=this.internal;return a.clearInterval(b.intervalForObserveInserted),a.onresize=null,b.selectChart.classed("c3",!1).html(""),Object.keys(b).forEach(function(a){b[a]=null}),null},h.tooltip=function(){},h.tooltip.show=function(a){var b,c,d=this.internal;a.mouse&&(c=a.mouse),a.data?d.isMultipleX()?(c=[d.x(a.data.x),d.getYScale(a.data.id)(a.data.value)],b=null):b=m(a.data.index)?a.data.index:d.getIndexByX(a.data.x):"undefined"!=typeof a.x?b=d.getIndexByX(a.x):"undefined"!=typeof a.index&&(b=a.index),d.dispatchEvent("mouseover",b,c),d.dispatchEvent("mousemove",b,c)},h.tooltip.hide=function(){this.internal.dispatchEvent("mouseout",0)};var z;i.isSafari=function(){var b=a.navigator.userAgent;return b.indexOf("Safari")>=0&&b.indexOf("Chrome")<0},i.isChrome=function(){var b=a.navigator.userAgent;return b.indexOf("Chrome")>=0},Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),"function"==typeof define&&define.amd?define("c3",["d3"],k):"undefined"!=typeof exports&&"undefined"!=typeof module?module.exports=k:a.c3=k}(window);
|
14
14
|
|
15
15
|
$(function () {
|
16
|
+
var path = window.location.pathname
|
16
17
|
var failedChart
|
17
18
|
var passedChart
|
18
19
|
var excludedWorkers = []
|
@@ -43,14 +44,15 @@ $(function () {
|
|
43
44
|
}
|
44
45
|
});
|
45
46
|
|
46
|
-
|
47
|
+
|
48
|
+
$.getJSON(path + '/charts_initializer.json', function (data) {
|
47
49
|
initializeChart['data']['columns'] = data
|
48
50
|
}).done(function () {
|
49
51
|
failedChart = c3.generate($.extend(initializeChart, { bindto: '.realtime__failed-chart' }))
|
50
52
|
passedChart = c3.generate($.extend(initializeChart, { bindto: '.realtime__passed-chart' }))
|
51
53
|
|
52
54
|
setInterval(function () {
|
53
|
-
$.getJSON('/
|
55
|
+
$.getJSON(path + '/charts.json', { excluded: excludedWorkers })
|
54
56
|
.done(function (data) {
|
55
57
|
failedChart.flow(data['failed'])
|
56
58
|
passedChart.flow(data['passed'])
|
@@ -35,6 +35,13 @@
|
|
35
35
|
.statistic__log {
|
36
36
|
display: none;
|
37
37
|
}
|
38
|
+
.statistic__jid {
|
39
|
+
cursor: pointer;
|
40
|
+
background-color: red;
|
41
|
+
}
|
42
|
+
.statistic__jid:hover {
|
43
|
+
background-color: inherit;
|
44
|
+
}
|
38
45
|
.statistic__table {
|
39
46
|
margin-top: 25px;
|
40
47
|
}
|
@@ -43,6 +50,30 @@
|
|
43
50
|
width: 300px;
|
44
51
|
}
|
45
52
|
|
53
|
+
#chartjs-tooltip {
|
54
|
+
opacity: 1;
|
55
|
+
position: absolute;
|
56
|
+
background: rgba(0, 0, 0, .7);
|
57
|
+
color: white;
|
58
|
+
padding: 3px;
|
59
|
+
border-radius: 3px;
|
60
|
+
-webkit-transition: all .1s ease;
|
61
|
+
transition: all .1s ease;
|
62
|
+
pointer-events: none;
|
63
|
+
-webkit-transform: translate(-50%, 0);
|
64
|
+
transform: translate(-50%, 0);
|
65
|
+
}
|
66
|
+
.chartjs-tooltip-title{
|
67
|
+
font-weight: 800;
|
68
|
+
margin-bottom: 5px;
|
69
|
+
}
|
70
|
+
.chartjs-tooltip-key{
|
71
|
+
display: inline-block;
|
72
|
+
width: 10px;
|
73
|
+
height: 10px;
|
74
|
+
margin: 0 2px 0 5px;
|
75
|
+
}
|
76
|
+
|
46
77
|
/*!
|
47
78
|
* jQuery UI Datepicker @VERSION
|
48
79
|
* http://jqueryui.com
|
@@ -23,6 +23,7 @@
|
|
23
23
|
<canvas id="js-failed-chart" width="800" height="200"></canvas>
|
24
24
|
<h2><%= t('Passed') %></h2>
|
25
25
|
<canvas id="js-passed-chart" width="800" height="200"></canvas>
|
26
|
+
<div id="chartjs-tooltip"></div>
|
26
27
|
</div>
|
27
28
|
|
28
29
|
<h2><%= t('WorkersTable') %></h2>
|
@@ -31,6 +32,7 @@
|
|
31
32
|
<thead>
|
32
33
|
<th><%= t('Worker') %></th>
|
33
34
|
<th><%= t('Date') %></th>
|
35
|
+
<th><%= t('Queue') %></th>
|
34
36
|
<th><%= t('Success') %></th>
|
35
37
|
<th><%= t('Failure') %></th>
|
36
38
|
<th><%= t('Total') %></th>
|
@@ -44,6 +46,7 @@
|
|
44
46
|
<tr>
|
45
47
|
<td class="worker"><a href="<%= root_path %>statistic/<%= worker[:name] %>"><%= worker[:name] %></a></td>
|
46
48
|
<td class="worker"><%= formate_date worker[:runtime][:last] %></td>
|
49
|
+
<td class="worker"><%= worker[:queue] %></td>
|
47
50
|
<td class="worker"><%= worker[:number_of_calls][:success] %></td>
|
48
51
|
<td class="worker"><%= worker[:number_of_calls][:failure] %></td>
|
49
52
|
<td class="worker"><%= worker[:number_of_calls][:total] %></td>
|
@@ -25,6 +25,39 @@ else{for(c=i&&i.getFullYear()===a,o=s&&s.getFullYear()===a,y+="<select class='ui
|
|
25
25
|
$(function () {
|
26
26
|
Chart.defaults.global.responsive = true
|
27
27
|
Chart.defaults.global.scaleLineColor = 'rgba(0,0,0,.4)'
|
28
|
+
Chart.defaults.global.customTooltips = function(tooltip) {
|
29
|
+
var tooltipEl = $('#chartjs-tooltip')
|
30
|
+
|
31
|
+
if (!tooltip) {
|
32
|
+
tooltipEl.css({
|
33
|
+
opacity: 0
|
34
|
+
});
|
35
|
+
return;
|
36
|
+
}
|
37
|
+
|
38
|
+
tooltipEl.removeClass('above below')
|
39
|
+
tooltipEl.addClass(tooltip.yAlign)
|
40
|
+
|
41
|
+
var innerHtml = '<div class="chartjs-tooltip-title">' + tooltip.title + ':</div>'
|
42
|
+
for (var i = tooltip.labels.length - 1; i >= 0; i--) {
|
43
|
+
innerHtml += [
|
44
|
+
'<div class="chartjs-tooltip-section">',
|
45
|
+
' <span class="chartjs-tooltip-key" style="background-color:' + tooltip.legendColors[i].fill.replace('0.2', '1.0') + '"></span>',
|
46
|
+
' <span class="chartjs-tooltip-value">' + tooltip.labels[i] + '</span>',
|
47
|
+
'</div>'
|
48
|
+
].join('')
|
49
|
+
}
|
50
|
+
tooltipEl.html(innerHtml)
|
51
|
+
|
52
|
+
tooltipEl.css({
|
53
|
+
opacity: 1,
|
54
|
+
left: tooltip.chart.canvas.offsetLeft + tooltip.x + 'px',
|
55
|
+
top: tooltip.chart.canvas.offsetTop + tooltip.y + 'px',
|
56
|
+
fontFamily: tooltip.fontFamily,
|
57
|
+
fontSize: tooltip.fontSize,
|
58
|
+
fontStyle: tooltip.fontStyle,
|
59
|
+
})
|
60
|
+
}
|
28
61
|
|
29
62
|
var datePickerFrom, datePickerTo
|
30
63
|
initializeDatePickers()
|
@@ -38,22 +71,27 @@ $(function () {
|
|
38
71
|
}, parseInt(localStorage.timeInterval) || 2000)
|
39
72
|
})
|
40
73
|
|
41
|
-
$(document).on('click', '.
|
74
|
+
$(document).on('click', '.statistic__tab', function (e) {
|
42
75
|
var $this = $(this)
|
43
76
|
$('.nav-tabs li').removeClass('active')
|
44
77
|
$this.parent().toggleClass('active')
|
45
78
|
|
46
|
-
$('.
|
79
|
+
$('.statistic__container').children().hide()
|
47
80
|
$($this.data('target')).show()
|
48
81
|
})
|
49
82
|
|
50
|
-
$('
|
83
|
+
$(document).on('click', '.statistic__jid', function (e) {
|
84
|
+
$('.statistic__i').toggle()
|
85
|
+
$($(this).data('target')).parent().show()
|
86
|
+
})
|
87
|
+
|
88
|
+
$('#statistic__search').keyup(function() {
|
51
89
|
var $this = $(this)
|
52
90
|
delay(function(){
|
53
91
|
if ($this.val().length) {
|
54
|
-
$('.
|
92
|
+
$('.statistic__i:not(:contains('+ $this.val() +'))').hide()
|
55
93
|
} else {
|
56
|
-
$('.
|
94
|
+
$('.statistic__i').show()
|
57
95
|
}
|
58
96
|
}, 200 )
|
59
97
|
});
|
@@ -67,7 +105,8 @@ $(function () {
|
|
67
105
|
})()
|
68
106
|
|
69
107
|
function initializeChars(data) {
|
70
|
-
|
108
|
+
var path = window.location.pathname
|
109
|
+
$.getJSON(path + '/charts.json', data, function (data) {
|
71
110
|
createChart('failed', data, data.failed_datasets)
|
72
111
|
createChart('passed', data, data.passed_datasets)
|
73
112
|
})
|
@@ -55,7 +55,7 @@
|
|
55
55
|
<div class="statistic__log">
|
56
56
|
<input type='text' name='' id='statistic__search' value='' placeholder='Search text in log file'/>
|
57
57
|
<% @worker_log.each do |line| %>
|
58
|
-
<p class="statistic__i
|
58
|
+
<p class="statistic__i"><%= line %></p>
|
59
59
|
<% end %>
|
60
60
|
</div>
|
61
61
|
</div>
|
@@ -49,14 +49,14 @@ module Sidekiq
|
|
49
49
|
render(:erb, File.read(File.join(view_path, 'realtime.erb')))
|
50
50
|
end
|
51
51
|
|
52
|
-
app.get '/statistic/
|
52
|
+
app.get '/statistic/realtime/charts.json' do
|
53
53
|
content_type :json
|
54
54
|
|
55
55
|
realtime = Sidekiq::Statistic::Realtime.new
|
56
56
|
Sidekiq.dump_json realtime.statistic(params)
|
57
57
|
end
|
58
58
|
|
59
|
-
app.get '/statistic/
|
59
|
+
app.get '/statistic/realtime/charts_initializer.json' do
|
60
60
|
content_type :json
|
61
61
|
Sidekiq.dump_json Sidekiq::Statistic::Realtime.charts_initializer
|
62
62
|
end
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-statistic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Davydov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -140,7 +140,9 @@ files:
|
|
140
140
|
- lib/sidekiq/statistic.rb
|
141
141
|
- lib/sidekiq/statistic/base.rb
|
142
142
|
- lib/sidekiq/statistic/configuration.rb
|
143
|
+
- lib/sidekiq/statistic/locales/de.yml
|
143
144
|
- lib/sidekiq/statistic/locales/en.yml
|
145
|
+
- lib/sidekiq/statistic/locales/it.yml
|
144
146
|
- lib/sidekiq/statistic/locales/ru.yml
|
145
147
|
- lib/sidekiq/statistic/log_parser.rb
|
146
148
|
- lib/sidekiq/statistic/middleware.rb
|
@@ -158,7 +160,7 @@ files:
|
|
158
160
|
- lib/sidekiq/statistic/web_api_extension.rb
|
159
161
|
- lib/sidekiq/statistic/web_extension.rb
|
160
162
|
- lib/sidekiq/statistic/web_extension_helper.rb
|
161
|
-
- sidekiq-
|
163
|
+
- sidekiq-statistic.gemspec
|
162
164
|
homepage: https://github.com/davydovanton/sidekiq-statistic
|
163
165
|
licenses:
|
164
166
|
- MIT
|