sidekiq-worker_stats 0.0.2 → 0.0.3

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
2
  SHA1:
3
- metadata.gz: dc301892db995ec508d5f9300d46fedece1bad94
4
- data.tar.gz: 689357440d58ff1d72a62f3dd59670dfec7f2063
3
+ metadata.gz: d1543112b4d14962857125dc3f4b1f87696fbf30
4
+ data.tar.gz: e1f94d3c2cde419a3ac7b0b791cdb78a548f5d71
5
5
  SHA512:
6
- metadata.gz: 64b8a35dfb4a99dfd7613a5dca0979875b7bb9731e01df922d648af8f6ad739add9c86f73b1f46db11e967f8adda2c8481dde0f1638d9db790daee9b4d17d514
7
- data.tar.gz: b7c1f6ae4c030359714f881e718080a315367fa5096aa24b5947e89f1bce609b0a9dedf1d66852e9d1cb4de38d9daa24105eda3e49c304996657314b28a5399b
6
+ metadata.gz: 29dd66f6095e0f074fa92e17591bde836e2ab2908c95bf0e173e4ba845c8b83fddf10a3f6fd88f8bda462bd5dc2aaad53a1062193f589728789602d4812b7a99
7
+ data.tar.gz: a49ec725dac939319000624e8eacd1f1522a36af6437ab2dc67d21c3e39c96ba706a1928c183b4a480451f1c3c975a619c4803f782a1dc0d5a13f0de93520748
data/README.md CHANGED
@@ -1,3 +1,28 @@
1
1
  # sidekiq-worker\_stats
2
+ **Statistics for sidekiq workers**
2
3
 
3
- Statistics for sidekiq workers.
4
+ Build status - TODO
5
+
6
+ The following statistics are saved for analysis:
7
+
8
+ * Start Time
9
+ * Stop Time
10
+ * Runtime
11
+ * Memory
12
+
13
+ ## Installation
14
+
15
+ Add `sidekiq-worker_stats` to your Gemfile
16
+
17
+ ```ruby
18
+ gem 'sidekiq-worker_stats'
19
+ ```
20
+
21
+ and install
22
+
23
+ ```bash
24
+ $ bundle install
25
+ ```
26
+
27
+ ## Configuration
28
+ We can configure
@@ -1,24 +1,11 @@
1
1
  require 'sidekiq'
2
2
 
3
- require 'sidekiq/worker_stats/configuration'
4
3
  require 'sidekiq/worker_stats/middleware'
5
4
  require 'sidekiq/worker_stats/web' if defined?(Sidekiq::Web)
6
5
 
7
6
  module Sidekiq
8
7
  module WorkerStats
9
8
  REDIS_HASH = 'sidekiq:worker_stats'.freeze
10
-
11
- class << self
12
- attr_writer :configuration
13
-
14
- def configuration
15
- @configuration ||= Configuration.new
16
- end
17
-
18
- def configure
19
- yield(configuration)
20
- end
21
- end
22
9
  end
23
10
  end
24
11
 
@@ -1,13 +1,23 @@
1
1
  module Sidekiq
2
2
  module WorkerStats
3
3
  class Configuration
4
- attr_accessor :log_file
5
- attr_accessor :time
4
+ DEFAULT_MEM_SLEEP = 5.freeze
5
+ DEFAULT_ENABLED = false.freeze
6
6
 
7
- def initialize
8
- @log_file = 'log/sidekiq.log'
9
- @time = 5
7
+ attr_reader :klass
8
+
9
+ def initialize(klass)
10
+ @klass = klass
11
+ end
12
+
13
+ def mem_sleep
14
+ @klass.get_sidekiq_options['worker_stats_mem_sleep'] || Sidekiq::WorkerStats::Configuration::DEFAULT_MEM_SLEEP
15
+ end
16
+
17
+ def enabled
18
+ @klass.get_sidekiq_options['worker_stats_enabled'] || Sidekiq::WorkerStats::Configuration::DEFAULT_ENABLED
10
19
  end
11
20
  end
12
21
  end
13
22
  end
23
+
@@ -1,53 +1,26 @@
1
- require 'json'
1
+ require 'sidekiq/worker_stats/configuration'
2
+ require 'sidekiq/worker_stats/stats'
2
3
 
3
4
  module Sidekiq
4
5
  module WorkerStats
5
6
  class Middleware
6
7
  def call(worker, msg, queue)
7
- worker_stats = {}
8
- worker_stats[:start] = Time.now.to_i
9
- worker_stats[:status] = 'started'
8
+ c = Sidekiq::WorkerStats::Configuration.new(worker.class)
10
9
 
11
- worker_stats[:pid] = Process.pid
12
- worker_stats[:jid] = worker.jid
13
-
14
- worker_stats[:page_size] = `getconf PAGESIZE`.to_i
15
- worker_stats[:mem] = {}
16
- worker_stats[:mem][Time.now.to_i] = `awk '{ print $2 }' /proc/#{worker_stats[:pid]}/statm`.strip.to_i * worker_stats[:page_size]
17
-
18
- thr = Thread.new do
19
- while true do
20
- sleep Sidekiq::WorkerStats.configuration.time
21
- worker_stats[:mem][Time.now.to_i] = `awk '{ print $2 }' /proc/#{worker_stats[:pid]}/statm`.strip.to_i * worker_stats[:page_size]
22
- end
10
+ unless c.enabled
11
+ yield
12
+ return
23
13
  end
24
14
 
25
- yield
26
-
27
- worker_stats[:status] = 'completed'
28
- rescue => e
29
- worker_stats[:status] = 'failed'
30
-
31
- raise e
32
- ensure
33
- worker_stats[:stop] = Time.now.to_i
34
- worker_stats[:runtime] = worker_stats[:stop] - worker_stats[:start]
35
-
36
- worker_stats[:queue] = queue
37
- worker_stats[:class] = worker.class.to_s
38
-
39
- thr.exit if thr != nil
40
-
41
- worker_key = "#{worker_stats[:class]}:#{worker_stats[:start]}:#{worker_stats[:jid]}"
42
-
43
- save_worker_stats worker_key, worker_stats
44
- end
45
-
46
- private
47
-
48
- def save_worker_stats(key, worker_stats)
49
- Sidekiq.redis do |redis|
50
- redis.hset REDIS_HASH, key, JSON.generate(worker_stats)
15
+ begin
16
+ s = Sidekiq::WorkerStats::Stats.new(worker, msg, queue, c)
17
+ yield
18
+ s.stop('completed')
19
+ rescue => e
20
+ s.stop('failed')
21
+ raise e
22
+ ensure
23
+ s.save
51
24
  end
52
25
  end
53
26
  end
@@ -0,0 +1,86 @@
1
+ require 'sidekiq'
2
+ require 'json'
3
+
4
+ module Sidekiq
5
+ module WorkerStats
6
+ class Stats
7
+ attr_reader :pid
8
+ attr_reader :jid
9
+ attr_reader :queue
10
+ attr_reader :klass
11
+
12
+ attr_reader :start
13
+ attr_reader :stop
14
+ attr_reader :walltime
15
+ attr_reader :status
16
+ attr_reader :page_size
17
+ attr_reader :mem
18
+
19
+ attr_reader :mem_thr
20
+ attr_reader :config
21
+
22
+ def initialize(worker, msg, queue, config)
23
+ @config = config
24
+ @queue = queue
25
+ @klass = worker.class
26
+ @pid = Process.pid
27
+ @jid = worker.jid
28
+ @page_size = `getconf PAGESIZE`.to_i
29
+ start
30
+ end
31
+
32
+ def start
33
+ @status = 'started'
34
+ @start = Time.now.to_f
35
+ memory_measurement
36
+ end
37
+
38
+ def stop(status)
39
+ @stop = Time.now.to_f
40
+ @walltime = @stop - @start
41
+ @status = status
42
+
43
+ mem_thr.exit if mem_thr != nil
44
+ @mem[Time.now.to_f] = current_memory
45
+ end
46
+
47
+ def save
48
+ worker_key = "#{@klass}:#{@start}:#{@jid}"
49
+ data = {
50
+ pid: @pid,
51
+ jid: @jid,
52
+ queue: @queue,
53
+ class: @klass,
54
+ start: @start,
55
+ stop: @stop,
56
+ walltime: @walltime,
57
+ status: @status,
58
+ page_size: @page_size,
59
+ mem: @mem
60
+ }
61
+
62
+ Sidekiq.redis do |redis|
63
+ redis.hset Sidekiq::WorkerStats::REDIS_HASH, worker_key, JSON.generate(data)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def memory_measurement
70
+ @mem = {}
71
+ mem_sleep = @config.mem_sleep
72
+ puts mem_sleep
73
+ @mem_thr = Thread.new do
74
+ while true do
75
+ @mem[Time.now.to_f] = current_memory
76
+ sleep mem_sleep
77
+ end
78
+ end
79
+ end
80
+
81
+ def current_memory
82
+ `awk '{ print $2 }' /proc/#{@pid}/statm`.strip.to_i * @page_size
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,5 +1,5 @@
1
1
  module Sidekiq
2
2
  module WorkerStats
3
- VERSION = '0.0.2'.freeze
3
+ VERSION = '0.0.3'.freeze
4
4
  end
5
5
  end
@@ -19,7 +19,7 @@
19
19
  <td><a href="<%= root_path %>worker_stats/<%= key.to_s %>"><%= worker["class"].to_s %></a></td>
20
20
  <td><%= Time.at(worker["start"]).strftime "%Y-%m-%d %H:%M:%S" %></td>
21
21
  <td><%= Time.at(worker["stop"]).strftime "%Y-%m-%d %H:%M:%S" %></td>
22
- <td><%= "#{worker["runtime"]} s" %></td>
22
+ <td><%= "#{worker["walltime"]} s" %></td>
23
23
  <td><%= "#{(worker["mem"].values.inject(:+) / worker["mem"].count) / 1024 / 1024} Mb" %></td>
24
24
  <td><%= "#{(worker["mem"].values.max / 1024 / 1024)} Mb" %></td>
25
25
  </tr>
@@ -38,7 +38,7 @@
38
38
  </tr>
39
39
  <tr>
40
40
  <td>Runtime</td>
41
- <td><%= @worker["runtime"] %> seconds</td>
41
+ <td><%= @worker["walltime"] %> seconds</td>
42
42
  </tr>
43
43
  </tbody>
44
44
  </table>
@@ -57,7 +57,7 @@
57
57
  <tbody>
58
58
  <% @worker["mem"].each do |time, mem| %>
59
59
  <tr>
60
- <td><%= (time.to_i - @worker["start"]).to_s %> seconds</td>
60
+ <td><%= (time.to_f - @worker["start"]).round(2).to_s %> seconds</td>
61
61
  <td><%= "#{mem / 1024 / 1024} Mb" %></td>
62
62
  </tr>
63
63
  <% end %>
@@ -13,7 +13,8 @@ module Sidekiq
13
13
  Sidekiq.redis do |redis|
14
14
  keys = redis.hkeys REDIS_HASH
15
15
  keys.each do |key|
16
- @workers[key] = JSON.parse(redis.hget(REDIS_HASH, key))
16
+ worker_stats = redis.hget(REDIS_HASH, key)
17
+ @workers[key] = JSON.parse(worker_stats) if worker_stats != nil
17
18
  end
18
19
  end
19
20
 
@@ -34,5 +35,7 @@ module Sidekiq
34
35
  end
35
36
  end
36
37
 
37
- Sidekiq::Web.register Sidekiq::WorkerStats::Web
38
- Sidekiq::Web.tabs['Worker Stats'] = 'worker_stats'
38
+ if defined?(Sidekiq::Web)
39
+ Sidekiq::Web.register Sidekiq::WorkerStats::Web
40
+ Sidekiq::Web.tabs['Worker Stats'] = 'worker_stats'
41
+ end
@@ -6,55 +6,76 @@ require 'sidekiq'
6
6
  require 'sidekiq/testing'
7
7
  require 'sidekiq/worker_stats'
8
8
 
9
-
10
- class WorkerHelper
9
+ class BasicWorker
11
10
  include Sidekiq::Worker
12
11
 
12
+ sidekiq_options({
13
+ worker_stats_enabled: true,
14
+ worker_stats_mem_sleep: 1
15
+ })
16
+
13
17
  def perform
14
18
  # Let's use some memory
15
19
  a = []
16
- for i in 1..10000000
20
+ for i in 1..5000000
17
21
  a << i.to_s * 10
18
22
  end
19
23
  end
20
24
  end
21
25
 
22
- class ErrorWorkerHelper
26
+ class NoStatsWorker
23
27
  include Sidekiq::Worker
24
28
 
29
+ sidekiq_options({
30
+ worker_stats_enabled: false
31
+ })
32
+
25
33
  def perform
26
- raise StandardError.new("Error")
27
34
  end
28
35
  end
29
36
 
30
- class TestMiddleware < Minitest::Test
31
- include Rack::Test::Methods
37
+ class ErrorWorker
38
+ include Sidekiq::Worker
39
+
40
+ sidekiq_options({
41
+ worker_stats_enabled: true,
42
+ worker_stats_mem_sleep: 1
43
+ })
32
44
 
33
- def app
34
- Sidekiq::Web
45
+ def perform
46
+ raise StandardError.new("Error")
35
47
  end
48
+ end
36
49
 
50
+ class TestMiddleware < Minitest::Test
37
51
  def setup
38
52
  Sidekiq::Testing.server_middleware do |chain|
39
53
  chain.add Sidekiq::WorkerStats::Middleware
40
54
  end
41
55
  end
42
56
 
43
- def test_that_middleware_reports_start
57
+ def test_basic_worker_stats_are_saved
44
58
  Sidekiq::Testing.inline! do
45
- WorkerHelper.perform_async
59
+ BasicWorker.perform_async
46
60
  end
47
61
  end
48
62
 
49
- def test_that_middleware_reports_end
50
- skip 'todo'
63
+ def test_no_stats_worker
64
+ Sidekiq::Testing.inline! do
65
+ NoStatsWorker.perform_async
66
+ end
51
67
  end
52
68
 
53
69
  def test_that_middleware_raises_error
54
70
  Sidekiq::Testing.inline! do
55
71
  assert_raises StandardError do
56
- ErrorWorkerHelper.perform_async
72
+ ErrorWorker.perform_async
57
73
  end
58
74
  end
59
75
  end
76
+
77
+ def test_that_middleware_reports_end
78
+ skip 'todo'
79
+ end
80
+
60
81
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-worker_stats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Jesus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-07 00:00:00.000000000 Z
11
+ date: 2016-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq
@@ -99,6 +99,7 @@ files:
99
99
  - lib/sidekiq/worker_stats.rb
100
100
  - lib/sidekiq/worker_stats/configuration.rb
101
101
  - lib/sidekiq/worker_stats/middleware.rb
102
+ - lib/sidekiq/worker_stats/stats.rb
102
103
  - lib/sidekiq/worker_stats/version.rb
103
104
  - lib/sidekiq/worker_stats/views/worker_stats.erb
104
105
  - lib/sidekiq/worker_stats/views/worker_stats_single.erb