sidekiq-monitoring 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3dca02fdd9b9ccd8a481dcceceaa7eb8508c147f
4
- data.tar.gz: d937018ee6e611209451eb5e283591348feea379
2
+ SHA256:
3
+ metadata.gz: 867752e2b644a7a48f415b6e37d3eef5122c37d03b1a44da1633c2be1aa02bf3
4
+ data.tar.gz: 1af6cb2ba71889e9abb16c0993f8e03f10eff68b02d3d51c1a1753df1c990073
5
5
  SHA512:
6
- metadata.gz: 13cb2b57e1081d036dd83f0d5812dfac815429bcfb95fc7aa2a1ae5a6b3be98f68820fe3f334a797b0776289617d2144ae57b39c9e2ad680af6ccb0fb98c9ccb
7
- data.tar.gz: 27663efcfb2e3aedf3119b2683bc543729a5e94e13232421c249dcc97153831c8040b998de0d9dafe69e1fd43d28c24d005aace7a5e15cb6ac7d5ce9731fe298
6
+ metadata.gz: 63b53cfe4cc6bcf800735ee049d5f88d7305a9b06ebc7268b88c22f404f1fdb132887bb4879282e2bde104bbe03108ebcd3c92eb0014cb7ed4a6c4c0d16e7d07
7
+ data.tar.gz: 655dd710850b528576fdb163335b45765d27838501736c1c9bfadf50e459e6083db7b9211a0b4f249c49d0ffb096e937c203f1e28fe1fd945e09e424e7e31661
data/Gemfile CHANGED
@@ -1,3 +1,10 @@
1
- source "https://rubygems.org"
2
-
1
+ source 'https://rubygems.org'
3
2
  gemspec
3
+
4
+ group :test do
5
+ gem 'mock_redis'
6
+ gem 'pry'
7
+ gem 'rack-test'
8
+ gem 'rspec'
9
+ gem 'timecop'
10
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Rails 3 and 4
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.thresholds = {
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.latency_thresholds = {
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
- Or if you want to override the default threshold in case of the queue name
40
- isn't specified in your thresholds:
41
-
42
- ```ruby
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
 
@@ -2,66 +2,85 @@ require 'sinatra/base'
2
2
  require 'multi_json'
3
3
 
4
4
  class SidekiqMonitoring < Sinatra::Base
5
- VERSION = "1.2.0"
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
- def self.thresholds=(thresholds)
9
- @@thresholds = thresholds
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
- @@thresholds = {}
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(@@thresholds, @@latency_thresholds)
37
+ MultiJson.dump SidekiqMonitoring::Global.new(@@queue_size_thresholds, @@latency_thresholds, @@elapsed_thresholds)
21
38
  end
22
39
 
23
- module Monitorable
24
- ALERT_STATUS = {
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
- ALERT_STATUS[status] <=> ALERT_STATUS[other.status]
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
- include Monitorable
57
+ DEFAULT_ELAPSED_THRESHOLD = [ 60, 120 ]
41
58
 
42
- DEFAULT_THRESHOLD = [ 60, 120 ]
59
+ include StatusMixin
43
60
 
44
- attr_accessor :process_id, :jid, :run_at, :queue, :worker_class
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, thresholds = nil)
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
- @warning_threshold, @critical_threshold = thresholds ? thresholds : DEFAULT_THRESHOLD
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
- 'process_id' => process_id
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 status
73
- return 'CRITICAL' if elapsed_time >= critical_threshold
74
- return 'WARNING' if elapsed_time >= warning_threshold
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
- attr_accessor :name, :size, :latency, :warning_latency_threshold, :critical_latency_threshold
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, thresholds = nil, latency_thresholds = nil)
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
- @warning_threshold, @critical_threshold = (thresholds ? thresholds : DEFAULT_THRESHOLD)
93
- @warning_latency_threshold, @critical_latency_threshold = (latency_thresholds ? latency_thresholds : DEFAULT_LATENCY_THRESHOLD)
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
- 'warning_threshold' => warning_threshold,
102
- 'critical_threshold' => critical_threshold,
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
- 'status' => status
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 >= critical_threshold || latency >= critical_latency_threshold
112
- return 'WARNING' if size >= warning_threshold || latency >= warning_latency_threshold
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 :thresholds, :latency_thresholds
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
- status = if worker_status != 'UNKNOWN' && Monitorable::ALERT_STATUS[worker_status] > Monitorable::ALERT_STATUS[queue_status]
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(thresholds = {}, latency_thresholds = {})
146
- @thresholds = thresholds
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, thresholds_from_queue(queue.name), latency_thresholds_from_queue(queue.name))
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'], latency_thresholds_from_queue(work['queue']))
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
@@ -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 = "sidekiq-monitoring"
8
+ spec.name = 'sidekiq-monitoring'
8
9
  spec.version = SidekiqMonitoring::VERSION
9
- spec.authors = ["Jeremy Carlier"]
10
- spec.email = ["jeremy.carlier@dimelo.com"]
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 = "http://github.com/dimelo/sidekiq-monitoring"
15
- spec.license = "MIT"
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.add_runtime_dependency "sinatra", ">= 1.3"
25
- spec.add_runtime_dependency "multi_json"
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 "rack-test"
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.2.0
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: 2017-10-25 00:00:00.000000000 Z
11
+ date: 2018-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: sinatra
14
+ name: sidekiq
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
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.3'
26
+ version: '3.1'
27
27
  - !ruby/object:Gem::Dependency
28
- name: multi_json
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: rack-test
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: :development
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.14'
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.14'
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.13
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