sidekiq-monitoring 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +9 -2
- data/README.md +7 -11
- data/lib/sidekiq-monitoring.rb +70 -69
- data/sidekiq-monitoring.gemspec +14 -15
- metadata +13 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 867752e2b644a7a48f415b6e37d3eef5122c37d03b1a44da1633c2be1aa02bf3
|
4
|
+
data.tar.gz: 1af6cb2ba71889e9abb16c0993f8e03f10eff68b02d3d51c1a1753df1c990073
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63b53cfe4cc6bcf800735ee049d5f88d7305a9b06ebc7268b88c22f404f1fdb132887bb4879282e2bde104bbe03108ebcd3c92eb0014cb7ed4a6c4c0d16e7d07
|
7
|
+
data.tar.gz: 655dd710850b528576fdb163335b45765d27838501736c1c9bfadf50e459e6083db7b9211a0b4f249c49d0ffb096e937c203f1e28fe1fd945e09e424e7e31661
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Rails 3 and
|
1
|
+
# Rails 3, 4 and 5
|
2
2
|
|
3
3
|
Add `sinatra` (and `sprockets` if you are on Rails 3.0) to your Gemfile
|
4
4
|
|
@@ -23,26 +23,22 @@ Please remember to mount the route before going to this URL
|
|
23
23
|
Add the following to an initializer:
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
SidekiqMonitoring.
|
26
|
+
SidekiqMonitoring.elapsed_thresholds = {
|
27
27
|
'queue_name_1' => [warning, critical],
|
28
28
|
'queue_name_2' => [warning, critical],
|
29
29
|
'queue_name_3' => [warning, critical]
|
30
30
|
}
|
31
31
|
|
32
|
-
SidekiqMonitoring.
|
32
|
+
SidekiqMonitoring.queue_size_thresholds = {
|
33
33
|
'queue_name_1' => [warning, critical],
|
34
34
|
'queue_name_2' => [warning, critical],
|
35
35
|
'queue_name_3' => [warning, critical]
|
36
36
|
}
|
37
|
-
```
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
SidekiqMonitoring.thresholds = {
|
44
|
-
'default' => [warning, critical],
|
45
|
-
'queue_name' => [warning, critical],
|
38
|
+
SidekiqMonitoring.latency_thresholds = {
|
39
|
+
'queue_name_1' => [warning, critical],
|
40
|
+
'queue_name_2' => [warning, critical],
|
41
|
+
'queue_name_3' => [warning, critical]
|
46
42
|
}
|
47
43
|
```
|
48
44
|
|
data/lib/sidekiq-monitoring.rb
CHANGED
@@ -2,66 +2,85 @@ require 'sinatra/base'
|
|
2
2
|
require 'multi_json'
|
3
3
|
|
4
4
|
class SidekiqMonitoring < Sinatra::Base
|
5
|
-
VERSION = "1.
|
5
|
+
VERSION = "1.3.0"
|
6
6
|
# Set your down thresholds configuration
|
7
7
|
# {'default' => [ 1_000, 2_000 ], 'low' => [ 10_000, 20_000 ] }
|
8
|
-
|
9
|
-
|
8
|
+
#
|
9
|
+
# NOTE: « queue_size_thresholds » are the thresholds about the number of job in a queue
|
10
|
+
def self.queue_size_thresholds=(queue_size_thresholds)
|
11
|
+
@queue_size_thresholds = queue_size_thresholds
|
10
12
|
end
|
11
|
-
@@
|
13
|
+
@@queue_size_thresholds = {}
|
12
14
|
|
15
|
+
# NOTE: « latency_thresholds » are the thresholds about the latency, difference of time between job pushed/enqueued
|
16
|
+
# (field 'enqueued_at') and job pulled/processed by the queue
|
13
17
|
def self.latency_thresholds=(latency_thresholds)
|
14
18
|
@@latency_thresholds = latency_thresholds
|
15
19
|
end
|
16
20
|
@@latency_thresholds = {}
|
17
21
|
|
22
|
+
# NOTE: « elapsed_thresholds » are the thresholds about the elapsed time of a job in a queue (while processing)
|
23
|
+
def self.elapsed_thresholds=(elapsed_thresholds)
|
24
|
+
@@elapsed_thresholds = elapsed_thresholds
|
25
|
+
end
|
26
|
+
@@elapsed_thresholds = {}
|
27
|
+
|
28
|
+
STATUS_LIST = {
|
29
|
+
'OK' => 0,
|
30
|
+
'WARNING' => 1,
|
31
|
+
'CRITICAL' => 2,
|
32
|
+
'UNKNOWN' => 3
|
33
|
+
}
|
34
|
+
|
18
35
|
get '/sidekiq_queues' do
|
19
36
|
content_type :json
|
20
|
-
MultiJson.dump SidekiqMonitoring::Global.new(@@
|
37
|
+
MultiJson.dump SidekiqMonitoring::Global.new(@@queue_size_thresholds, @@latency_thresholds, @@elapsed_thresholds)
|
21
38
|
end
|
22
39
|
|
23
|
-
module
|
24
|
-
|
25
|
-
'OK' => 0,
|
26
|
-
'WARNING' => 1,
|
27
|
-
'CRITICAL' => 2,
|
28
|
-
'UNKNOWN' => 3
|
29
|
-
}
|
30
|
-
|
31
|
-
attr_accessor :warning_threshold, :critical_threshold, :status
|
40
|
+
module StatusMixin
|
41
|
+
attr_reader :status
|
32
42
|
|
33
43
|
def <=>(other)
|
34
|
-
|
44
|
+
STATUS_LIST[status] <=> STATUS_LIST[other.status]
|
35
45
|
end
|
36
46
|
|
47
|
+
def criticality(status = monitoring_status)
|
48
|
+
STATUS_LIST[status]
|
49
|
+
end
|
50
|
+
|
51
|
+
def monitoring_status
|
52
|
+
raise NotImplementedError.new "#{self.class}#monitoring_status"
|
53
|
+
end
|
37
54
|
end
|
38
55
|
|
39
56
|
class Worker
|
40
|
-
|
57
|
+
DEFAULT_ELAPSED_THRESHOLD = [ 60, 120 ]
|
41
58
|
|
42
|
-
|
59
|
+
include StatusMixin
|
43
60
|
|
44
|
-
|
61
|
+
attr_reader :process_id, :jid, :run_at, :queue, :worker_class
|
62
|
+
attr_accessor :elapsed_warning_threshold, :elapsed_critical_threshold
|
45
63
|
|
46
|
-
def initialize(process_id, jid, run_at, queue, worker_class,
|
64
|
+
def initialize(process_id, jid, run_at, queue, worker_class, elapsed_thresholds = nil)
|
47
65
|
@process_id = process_id
|
48
66
|
@jid = jid
|
49
67
|
@run_at = run_at
|
50
68
|
@queue = queue
|
51
69
|
@worker_class = worker_class
|
52
|
-
@
|
70
|
+
@elapsed_warning_threshold, @elapsed_critical_threshold = elapsed_thresholds ? elapsed_thresholds : DEFAULT_ELAPSED_THRESHOLD
|
71
|
+
@status = monitoring_status
|
53
72
|
end
|
54
73
|
|
55
74
|
def as_json
|
56
75
|
{
|
57
76
|
'queue' => queue,
|
58
77
|
'jid' => jid,
|
78
|
+
'process_id' => process_id,
|
59
79
|
'worker_class' => worker_class,
|
60
|
-
'elapsed_time' => elapsed_time,
|
61
|
-
'warning_threshold' => warning_threshold,
|
62
|
-
'critical_threshold' => critical_threshold,
|
63
80
|
'status' => status,
|
64
|
-
'
|
81
|
+
'elapsed_time' => elapsed_time,
|
82
|
+
'elapsed_warning_threshold' => elapsed_warning_threshold,
|
83
|
+
'elapsed_critical_threshold' => elapsed_critical_threshold
|
65
84
|
}
|
66
85
|
end
|
67
86
|
|
@@ -69,105 +88,87 @@ class SidekiqMonitoring < Sinatra::Base
|
|
69
88
|
@elapsed_time ||= Time.now.to_i - run_at
|
70
89
|
end
|
71
90
|
|
72
|
-
def
|
73
|
-
return 'CRITICAL' if elapsed_time >=
|
74
|
-
return 'WARNING' if elapsed_time >=
|
91
|
+
def monitoring_status
|
92
|
+
return 'CRITICAL' if elapsed_time >= elapsed_critical_threshold
|
93
|
+
return 'WARNING' if elapsed_time >= elapsed_warning_threshold
|
75
94
|
'OK'
|
76
95
|
end
|
77
|
-
|
78
96
|
end
|
79
97
|
|
80
98
|
class Queue
|
81
|
-
include Monitorable
|
82
|
-
|
83
99
|
DEFAULT_THRESHOLD = [ 1_000, 2_000 ]
|
84
100
|
DEFAULT_LATENCY_THRESHOLD = [ 300, 900 ]
|
85
101
|
|
86
|
-
|
102
|
+
include StatusMixin
|
103
|
+
|
104
|
+
attr_reader :name, :size
|
105
|
+
attr_accessor :queue_size_warning_threshold, :queue_size_critical_threshold, :latency, :latency_warning_threshold, :latency_critical_threshold
|
87
106
|
|
88
|
-
def initialize(name, size, latency,
|
107
|
+
def initialize(name, size, latency, queue_size_thresholds = nil, latency_thresholds = nil)
|
89
108
|
@name = name
|
90
109
|
@size = size
|
91
110
|
@latency = latency
|
92
|
-
@
|
93
|
-
@
|
111
|
+
@queue_size_warning_threshold, @queue_size_critical_threshold = (queue_size_thresholds ? queue_size_thresholds : DEFAULT_THRESHOLD)
|
112
|
+
@latency_warning_threshold, @latency_critical_threshold = (latency_thresholds ? latency_thresholds : DEFAULT_LATENCY_THRESHOLD)
|
94
113
|
@status = monitoring_status
|
95
114
|
end
|
96
115
|
|
97
116
|
def as_json
|
98
117
|
{
|
99
118
|
'name' => name,
|
119
|
+
'status' => status,
|
100
120
|
'size' => size,
|
101
|
-
'
|
102
|
-
'
|
103
|
-
'latency_warning_threshold' => warning_latency_threshold,
|
104
|
-
'latency_critical_threshold' => critical_latency_threshold,
|
121
|
+
'queue_size_warning_threshold' => queue_size_warning_threshold,
|
122
|
+
'queue_size_critical_threshold' => queue_size_critical_threshold,
|
105
123
|
'latency' => latency,
|
106
|
-
'
|
124
|
+
'latency_warning_threshold' => latency_warning_threshold,
|
125
|
+
'latency_critical_threshold' => latency_critical_threshold
|
107
126
|
}
|
108
127
|
end
|
109
128
|
|
110
129
|
def monitoring_status
|
111
|
-
return 'CRITICAL' if size >=
|
112
|
-
return 'WARNING' if size >=
|
130
|
+
return 'CRITICAL' if size >= queue_size_critical_threshold || latency >= latency_critical_threshold
|
131
|
+
return 'WARNING' if size >= queue_size_warning_threshold || latency >= latency_warning_threshold
|
113
132
|
'OK'
|
114
133
|
end
|
115
|
-
|
116
|
-
def criticality
|
117
|
-
ALERT_STATUS[monitoring_status]
|
118
|
-
end
|
119
|
-
|
120
134
|
end
|
121
135
|
|
122
136
|
class Global
|
137
|
+
include StatusMixin
|
123
138
|
|
124
|
-
attr_accessor :
|
139
|
+
attr_accessor :queue_size_thresholds, :latency_thresholds, :elapsed_thresholds
|
125
140
|
|
126
141
|
def as_json(options = {})
|
127
142
|
{
|
128
143
|
'global_status' => global_status,
|
129
144
|
'queues' => queues.select { |q| q.size > 0 }.sort_by(&:criticality).reverse!.map!(&:as_json),
|
130
|
-
'workers' => workers.map(&:as_json)
|
145
|
+
'workers' => workers.sort_by(&:criticality).reverse!.map!(&:as_json),
|
131
146
|
}
|
132
147
|
end
|
133
148
|
|
134
149
|
def global_status
|
135
150
|
queue_status = (queues.sort.last && queues.sort.last.status) || 'UNKNOWN'
|
136
151
|
worker_status = (workers.sort.last && workers.sort.last.status) || 'UNKNOWN'
|
137
|
-
|
138
|
-
worker_status
|
139
|
-
else
|
140
|
-
queue_status
|
141
|
-
end
|
142
|
-
@global_status ||= status
|
152
|
+
@global_status ||= (worker_status != 'UNKNOWN' && criticality(worker_status) > criticality(queue_status)) ? worker_status : queue_status
|
143
153
|
end
|
144
154
|
|
145
|
-
def initialize(
|
146
|
-
@
|
147
|
-
@latency_thresholds = latency_thresholds
|
155
|
+
def initialize(queue_size_thresholds = nil, latency_thresholds = nil, elapsed_thresholds = nil)
|
156
|
+
@queue_size_thresholds = queue_size_thresholds || {}
|
157
|
+
@latency_thresholds = latency_thresholds || {}
|
158
|
+
@elapsed_thresholds = elapsed_thresholds || {}
|
148
159
|
end
|
149
160
|
|
150
161
|
def queues
|
151
162
|
@queues ||= Sidekiq::Queue.all.map do |queue|
|
152
|
-
Queue.new(queue.name, queue.size, queue.latency,
|
163
|
+
Queue.new(queue.name, queue.size, queue.latency, queue_size_thresholds[queue.name], latency_thresholds[queue.name])
|
153
164
|
end
|
154
165
|
end
|
155
166
|
|
156
167
|
def workers
|
157
168
|
@workers ||= Sidekiq::Workers.new.map do |process_id, thread_id, work|
|
158
169
|
payload = work['payload']
|
159
|
-
Worker.new(process_id, payload['jid'], work['run_at'], work['queue'], payload['class'],
|
170
|
+
Worker.new(process_id, payload['jid'], work['run_at'], work['queue'], payload['class'], elapsed_thresholds[work['queue']])
|
160
171
|
end
|
161
172
|
end
|
162
|
-
|
163
|
-
def thresholds_from_queue(queue_name)
|
164
|
-
(thresholds || {})[queue_name]
|
165
|
-
end
|
166
|
-
|
167
|
-
def latency_thresholds_from_queue(queue_name)
|
168
|
-
(latency_thresholds || {})[queue_name]
|
169
|
-
end
|
170
|
-
|
171
173
|
end
|
172
|
-
|
173
174
|
end
|
data/sidekiq-monitoring.gemspec
CHANGED
@@ -1,32 +1,31 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
4
5
|
require 'sidekiq-monitoring'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'sidekiq-monitoring'
|
8
9
|
spec.version = SidekiqMonitoring::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ['Jeremy Carlier']
|
11
|
+
spec.email = ['jeremy.carlier@dimelo.com']
|
11
12
|
|
12
13
|
spec.summary = %q{Addons to provide a monitoring API for Sidekiq}
|
13
14
|
spec.description = %q{Give a state of sidekiq available queues}
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
15
|
+
spec.homepage = 'http://github.com/dimelo/sidekiq-monitoring'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
16
20
|
|
17
21
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
22
|
f.match(%r{^(test|spec|features)/})
|
19
23
|
end
|
20
|
-
spec.bindir = "exe"
|
21
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
-
spec.require_paths = ["lib"]
|
23
24
|
|
24
|
-
spec.
|
25
|
-
spec.
|
25
|
+
spec.require_paths = ['lib']
|
26
|
+
spec.add_dependency 'sidekiq', '~> 3.1'
|
27
|
+
spec.add_dependency 'sinatra'
|
28
|
+
spec.add_dependency 'multi_json'
|
26
29
|
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency "bundler", "~> 1.14"
|
29
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
31
|
-
spec.add_development_dependency "sidekiq", "~> 3.1"
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
32
31
|
end
|
metadata
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-monitoring
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Carlier
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: sidekiq
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1
|
19
|
+
version: '3.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1
|
26
|
+
version: '3.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: sinatra
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,13 +39,13 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: multi_json
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
|
-
type: :
|
48
|
+
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
@@ -58,56 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '1.
|
61
|
+
version: '1.16'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '1.
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rake
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '10.0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '10.0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rspec
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '3.0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '3.0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: sidekiq
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '3.1'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '3.1'
|
68
|
+
version: '1.16'
|
111
69
|
description: Give a state of sidekiq available queues
|
112
70
|
email:
|
113
71
|
- jeremy.carlier@dimelo.com
|
@@ -146,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
104
|
version: '0'
|
147
105
|
requirements: []
|
148
106
|
rubyforge_project:
|
149
|
-
rubygems_version: 2.6
|
107
|
+
rubygems_version: 2.7.6
|
150
108
|
signing_key:
|
151
109
|
specification_version: 4
|
152
110
|
summary: Addons to provide a monitoring API for Sidekiq
|