sidekiq-monitor 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Dimko
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ ## Sidekiq::Monitor
2
+
3
+ Jobs and queue stats for your Sidekiq.
4
+
5
+ ### Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'sidekiq-monitor'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install sidekiq-monitor
18
+
19
+ After you install Sidekiq monitor and add it to your Gemfile, you need to run the generator:
20
+
21
+ $ rails g sidekiq:monitor:migration
22
+
23
+ ### TODO
24
+
25
+ 1. Test it.
26
+
27
+ ### Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,27 @@
1
+ require 'rails/generators'
2
+
3
+ module Sidekiq
4
+ module Monitor
5
+ class MigrationGenerator < ::Rails::Generators::Base
6
+ include ::Rails::Generators::Migration
7
+
8
+ desc 'Generates migration for Sidekiq::Monitor::Event model'
9
+
10
+ def self.source_root
11
+ File.join(File.dirname(__FILE__), 'templates')
12
+ end
13
+
14
+ def self.next_migration_number(dirname)
15
+ if ActiveRecord::Base.timestamped_migrations
16
+ Time.now.utc.strftime('%Y%m%d%H%M%S').to_i.succ.to_s
17
+ else
18
+ '%.3d' % current_migration_number(dirname).succ
19
+ end
20
+ end
21
+
22
+ def create_migration_file
23
+ migration_template 'migration.rb', 'db/migrate/create_sidekiq_monitor_events.rb'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ class CreateSidekiqMonitorEvents < ActiveRecord::Migration
2
+ def change
3
+ create_table :sidekiq_monitor_events do |t|
4
+ t.string :revision, null: false
5
+ t.string :worker_class, null: false
6
+ t.string :queue, null: false
7
+ t.string :jid, null: false
8
+ t.integer :retry_count
9
+ t.text :args
10
+ t.text :exception
11
+ t.datetime :started_at
12
+ t.float :runtime
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ require 'sidekiq/monitor'
@@ -0,0 +1,40 @@
1
+ require 'sidekiq'
2
+ require 'sidekiq/web'
3
+ require 'will_paginate'
4
+ require 'will_paginate/view_helpers/sinatra'
5
+
6
+ require 'sidekiq/monitor/version'
7
+ require 'sidekiq/monitor/models/event'
8
+ require 'sidekiq/monitor/counters/base'
9
+ require 'sidekiq/monitor/counters/queue'
10
+ require 'sidekiq/monitor/counters/worker'
11
+ require 'sidekiq/monitor/middleware'
12
+ require 'sidekiq/monitor/railtie' if defined?(Rails)
13
+ require 'sidekiq/monitor/web/paginate_renderer'
14
+ require 'sidekiq/monitor/web'
15
+
16
+ module Sidekiq
17
+ module Monitor
18
+ extend self
19
+
20
+ include ActiveSupport::Configurable
21
+
22
+ config_accessor :events_ttl, :github_repo
23
+
24
+ def current_revision
25
+ @current_revision ||= begin
26
+ `git rev-parse HEAD`.strip
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ Sidekiq::Web.helpers WillPaginate::Sinatra::Helpers
33
+ Sidekiq::Web.register Sidekiq::Monitor::Web
34
+ Sidekiq::Web.tabs['Monitor'] = 'monitor'
35
+
36
+ Sidekiq.configure_server do |config|
37
+ config.server_middleware do |chain|
38
+ chain.add Sidekiq::Monitor::Middleware
39
+ end
40
+ end
@@ -0,0 +1,70 @@
1
+ module Sidekiq
2
+ module Monitor
3
+ module Counters
4
+ class Base
5
+ attr_reader :name, :enqueued, :runtime
6
+
7
+ def initialize(name, enqueued = nil, runtime = nil)
8
+ @name, @enqueued, @runtime = name, enqueued, runtime
9
+ end
10
+
11
+ def self.namespace
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def self.events_column
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def self.all(force = false)
20
+ update if force || update_needed?
21
+
22
+ Sidekiq.redis do |conn|
23
+ names.inject({}) do |memo, name|
24
+ memo[name] = conn.hgetall(new(name).key)
25
+ memo
26
+ end
27
+ end
28
+ end
29
+
30
+ def self.names
31
+ Sidekiq.redis do |conn|
32
+ conn.smembers(namespace).sort
33
+ end
34
+ end
35
+
36
+ def self.update
37
+ events = Sidekiq::Monitor::Event
38
+ Sidekiq.redis { |conn| conn.set("#{namespace}:updated_at", Time.now) }
39
+ events.connection.execute("SELECT #{events_column}, COUNT(id), AVG(runtime) FROM #{events.table_name} \
40
+ GROUP BY #{events_column}").values.each do |name, enqueued, runtime|
41
+
42
+ new(name, enqueued, runtime).save
43
+ end
44
+ end
45
+
46
+ def self.update_needed?
47
+ updated_at.nil? || updated_at.advance(seconds: 10).past?
48
+ end
49
+
50
+ def self.updated_at
51
+ Sidekiq.redis { |conn| Time.parse conn.get("#{namespace}:updated_at") }
52
+ rescue
53
+ end
54
+
55
+ def key
56
+ "#{self.class.namespace}:#{name}"
57
+ end
58
+
59
+ def save
60
+ Sidekiq.redis do |conn|
61
+ conn.pipelined do
62
+ conn.hmset(key, :enqueued, enqueued, :runtime, runtime)
63
+ conn.sadd(self.class.namespace, name)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,15 @@
1
+ module Sidekiq
2
+ module Monitor
3
+ module Counters
4
+ class Queue < Base
5
+ def self.namespace
6
+ 'monitor:queues'
7
+ end
8
+
9
+ def self.events_column
10
+ 'queue'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Sidekiq
2
+ module Monitor
3
+ module Counters
4
+ class Worker < Base
5
+ def self.namespace
6
+ 'monitor:workers'
7
+ end
8
+
9
+ def self.events_column
10
+ 'worker_class'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Sidekiq
2
+ module Monitor
3
+ class Middleware
4
+ def call(worker, message, queue)
5
+ event = Sidekiq::Monitor::Event.create_or_update_with(worker, message, queue)
6
+
7
+ begin
8
+ yield
9
+ event.finish
10
+ rescue Exception => e
11
+ event.error(e)
12
+ raise
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ module Sidekiq
3
+ module Monitor
4
+ class Event < ActiveRecord::Base
5
+ self.table_name = 'sidekiq_monitor_events'
6
+
7
+ serialize :exception, Hash
8
+ serialize :args, Array
9
+
10
+ scope :recent, lambda { order(:id).reverse_order }
11
+ scope :older_than, lambda { |time| where(arel_table[:created_at].lt(time)) }
12
+
13
+ before_save :assign_revision
14
+
15
+ class << self
16
+
17
+ def create_or_update_with(worker, message, queue)
18
+ transaction do
19
+ find_or_initialize_by_id(message['monitor_id']).tap do |e|
20
+ e.started_at = Time.now
21
+ e.retry_count = message['retry_count'].to_i + 1 if message.has_key?('retry_count')
22
+ e.worker_class = worker.class.name
23
+ e.args = message['args']
24
+ e.jid = message['jid']
25
+ e.queue = queue
26
+ e.save
27
+
28
+ message['monitor_id'] ||= e.id
29
+ end
30
+ end
31
+ end
32
+
33
+ def find_or_initialize_by_id(id, options = {}, &block)
34
+ id.nil? ? new(options, &block) : super
35
+ end
36
+
37
+ end
38
+
39
+ def finished?
40
+ !!finished_at
41
+ end
42
+
43
+ def finished_at
44
+ if runtime?
45
+ started_at + runtime.seconds
46
+ end
47
+ end
48
+
49
+ def finish
50
+ update_attribute(:runtime, Time.now - started_at)
51
+ end
52
+
53
+ def error(exception)
54
+ update_attribute(:exception, {
55
+ class: exception.class.name,
56
+ backtrace: exception.backtrace,
57
+ message: exception.message
58
+ })
59
+ end
60
+
61
+ protected
62
+
63
+ def assign_revision
64
+ self.revision = Sidekiq::Monitor.current_revision
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,9 @@
1
+ module Sidekiq
2
+ module Monitor
3
+ class Railtie < ::Rails::Railtie
4
+ rake_tasks do
5
+ require 'sidekiq/monitor/tasks'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ namespace :sidekiq do
2
+ namespace :monitor do
3
+ desc 'Sidekiq-monitor events cleanup'
4
+ task :cleanup => :environment do
5
+ ttl = Sidekiq::Monitor.events_ttl || 3.weeks
6
+ Sidekiq::Monitor::Event.older_than(ttl.ago).delete_all
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Sidekiq
2
+ module Monitor
3
+ VERSION = '0.0.2'
4
+ end
5
+ end
@@ -0,0 +1,47 @@
1
+ h3
2
+ ' Processed messages
3
+ - if @name
4
+ ' in
5
+ span.title= @name
6
+
7
+ - if @events.size > 0
8
+ table class="table table-striped table-bordered table-white" style="width: 100%; margin: 0; table-layout:fixed;"
9
+ thead
10
+ th style="width: 25%" Worker, args
11
+ th style="width: 50%" Runtime or Exception
12
+ th style="width: 15%" Started at
13
+ th style="width: 10%" Revision
14
+ tbody
15
+ - @events.each do |event|
16
+ tr
17
+ td style="overflow: hidden; text-overflow: ellipsis;"
18
+ = event.worker_class
19
+
20
+ div style="color: #999; font-size: 0.9em;"
21
+ = display_args event.args
22
+
23
+ td style="overflow: auto;"
24
+ - if event.finished?
25
+ = time_with_sec event.runtime
26
+
27
+ - if event.retry_count?
28
+ = " after #{event.retry_count} retries"
29
+
30
+ - elsif event.exception?
31
+ a.backtrace href="#" onclick="$(this).next().toggle(); return false"
32
+ = "#{event.exception[:class]}: #{event.exception[:message]}"
33
+ pre style="display: none; background: none; border: 0; width: 100%; max-height: 30em; font-size: 0.8em; white-space: nowrap;"
34
+ == event.exception[:backtrace].to_a.join('<br />')
35
+
36
+ - else
37
+ span style="color: #AAA;" performing ...
38
+ td
39
+ == relative_time(event.started_at)
40
+ td
41
+ == link_to_tree event.revision
42
+
43
+ == will_paginate @events, renderer: Sidekiq::Monitor::Web::PaginateRenderer, inner_window: 2
44
+ br
45
+
46
+ - else
47
+ .alert.alert-success No jobs found.
@@ -0,0 +1,47 @@
1
+ h3 Monitor
2
+
3
+ h5 Queues
4
+
5
+ - if @queues.size > 0
6
+ table class="table table-striped table-bordered table-white" style="width: 100%; margin: 0; table-layout:fixed;"
7
+ thead
8
+ th style="width: 55%" Name
9
+ / th style="width: 15%" Current
10
+ th style="width: 15%" Enqueued
11
+ th style="width: 15%" Average runtime
12
+ tbody
13
+ - @queues.each do |queue, counters|
14
+ tr
15
+ td
16
+ a href="#{root_path}monitor/queues/#{queue}" = queue
17
+ / td -
18
+ td= counters['enqueued']
19
+ td= time_with_sec counters['runtime']
20
+
21
+ - else
22
+ .alert.alert-success No queues found.
23
+
24
+ br
25
+
26
+ h5 Workers
27
+
28
+ - if @workers.size > 0
29
+ table class="table table-striped table-bordered table-white" style="width: 100%; margin: 0; table-layout:fixed;"
30
+ thead
31
+ th style="width: 55%" Name
32
+ / th style="width: 15%" Current
33
+ th style="width: 15%" Enqueued
34
+ th style="width: 15%" Average runtime
35
+ tbody
36
+ - @workers.each do |worker, counters|
37
+ tr
38
+ td
39
+ a href="#{root_path}monitor/workers/#{worker}" = worker
40
+ / td -
41
+ td= counters['enqueued']
42
+ td= time_with_sec counters['runtime']
43
+
44
+ - else
45
+ .alert.alert-success No workers found.
46
+
47
+ br
@@ -0,0 +1,63 @@
1
+ module Sidekiq
2
+ module Monitor
3
+ module Web
4
+ def self.registered(app)
5
+ app.instance_eval do
6
+ set :views, [ *views, File.expand_path('views', File.dirname(__FILE__)) ].flatten
7
+
8
+ helpers do
9
+ def time_with_sec(time)
10
+ "#{time.to_f.round(3)} sec"
11
+ end
12
+
13
+ def link_to_tree(revision)
14
+ if repo = Sidekiq::Monitor.github_repo
15
+ %(<a href="https://github.com/#{repo}/tree/#{revision}">#{revision[0..9]}</a>)
16
+ else
17
+ revision[0..9]
18
+ end
19
+ end
20
+
21
+ def find_template(views, name, engine, &block)
22
+ Array(views).each { |v| super(v, name, engine, &block) }
23
+ end
24
+ end
25
+
26
+ get '/monitor' do
27
+ @queues = Sidekiq::Monitor::Counters::Queue.all
28
+ @workers = Sidekiq::Monitor::Counters::Worker.all
29
+
30
+ slim :'monitor/index'
31
+ end
32
+
33
+ get '/monitor/events' do
34
+ @events = Sidekiq::Monitor::Event.recent.
35
+ paginate(page: params[:page])
36
+
37
+ slim :'monitor/events/index'
38
+ end
39
+
40
+ get '/monitor/queues/:name' do
41
+ halt 404 unless params[:name]
42
+
43
+ @name = params[:name]
44
+ @events = Sidekiq::Monitor::Event.where(queue: @name).recent.
45
+ paginate(page: params[:page])
46
+
47
+ slim :'monitor/events/index'
48
+ end
49
+
50
+ get '/monitor/workers/:name' do
51
+ halt 404 unless params[:name]
52
+
53
+ @name = params[:name]
54
+ @events = Sidekiq::Monitor::Event.where(worker_class: @name).recent.
55
+ paginate(page: params[:page])
56
+
57
+ slim :'monitor/events/index'
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ module Sidekiq
3
+ module Monitor
4
+ module Web
5
+ class PaginateRenderer < WillPaginate::Sinatra::LinkRenderer
6
+ protected
7
+
8
+ def html_container(html)
9
+ tag :div, tag(:ul, html), :class => 'pagination pagination-right'
10
+ end
11
+
12
+ def page_number(page)
13
+ tag :li, link(page, page, :rel => rel_value(page)), :class => ('active' if page == current_page)
14
+ end
15
+
16
+ def gap
17
+ tag :li, tag(:span, '&hellip;'), :class => 'gap'
18
+ end
19
+
20
+ def previous_page
21
+ num = @collection.current_page > 1 && @collection.current_page - 1
22
+ previous_or_next_page num, '«', 'previous_page'
23
+ end
24
+
25
+ def next_page
26
+ num = @collection.current_page < total_pages && @collection.current_page + 1
27
+ previous_or_next_page num, '»', 'next_page'
28
+ end
29
+
30
+ def previous_or_next_page(page, text, classname)
31
+ tag :li, link(text, page || '#'), :class => [classname[0..3], classname, ('disabled' unless page)].join(' ')
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sidekiq/monitor/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'sidekiq-monitor'
8
+ spec.version = Sidekiq::Monitor::VERSION
9
+ spec.authors = ['Dimko']
10
+ spec.email = ['deemox@gmail.com']
11
+ spec.description = %q{Tracks jobs enqueued, average duration and etc.}
12
+ spec.summary = %q{Jobs and queue stats for Sidekiq}
13
+ spec.homepage = 'https://github.com/dimko/sidekiq-monitor'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'sidekiq', '~> 2.6'
22
+ spec.add_dependency 'rails', '~> 3.2'
23
+ spec.add_dependency 'will_paginate', '~> 3.0'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.3'
26
+ spec.add_development_dependency 'rake'
27
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidekiq-monitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dimko
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sidekiq
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.6'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.6'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3.2'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.2'
46
+ - !ruby/object:Gem::Dependency
47
+ name: will_paginate
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.3'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Tracks jobs enqueued, average duration and etc.
95
+ email:
96
+ - deemox@gmail.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - lib/generators/sidekiq/monitor/migration_generator.rb
107
+ - lib/generators/sidekiq/monitor/templates/migration.rb
108
+ - lib/sidekiq-monitor.rb
109
+ - lib/sidekiq/monitor.rb
110
+ - lib/sidekiq/monitor/counters/base.rb
111
+ - lib/sidekiq/monitor/counters/queue.rb
112
+ - lib/sidekiq/monitor/counters/worker.rb
113
+ - lib/sidekiq/monitor/middleware.rb
114
+ - lib/sidekiq/monitor/models/event.rb
115
+ - lib/sidekiq/monitor/railtie.rb
116
+ - lib/sidekiq/monitor/tasks.rb
117
+ - lib/sidekiq/monitor/version.rb
118
+ - lib/sidekiq/monitor/views/monitor/events/index.slim
119
+ - lib/sidekiq/monitor/views/monitor/index.slim
120
+ - lib/sidekiq/monitor/web.rb
121
+ - lib/sidekiq/monitor/web/paginate_renderer.rb
122
+ - sidekiq-monitor.gemspec
123
+ homepage: https://github.com/dimko/sidekiq-monitor
124
+ licenses:
125
+ - MIT
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ! '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ segments:
137
+ - 0
138
+ hash: -45752073300806058
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ segments:
146
+ - 0
147
+ hash: -45752073300806058
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 1.8.25
151
+ signing_key:
152
+ specification_version: 3
153
+ summary: Jobs and queue stats for Sidekiq
154
+ test_files: []