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 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