sidekiq-err 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 540a25393182c06c16aa1133a3eb97a382a4e7918d37564ab48ea1f5244b3bad
4
+ data.tar.gz: 1780bcba830dc7332e999381ade9e86f0480d4386727aef14f7f680ea1e0efd6
5
+ SHA512:
6
+ metadata.gz: 0d40784c25269602e7b9698583f27a0cc0a6c760693bc0947a5a816789b4a29ee79dc16fe6d5e8598a5efd090e84aba1123c3ea5080681664a9e76e7469d5418
7
+ data.tar.gz: 12b25794cdb14be82e0a048037596d897764f3b56bb2b875904cd8909c1266f67f9475725fbecae9bf2ca7bf0aa4d584fcc9caa06c6c30b78cddba74f033cd6a
data/exe/sidekiq-err ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'sidekiq-err'
6
+
7
+ require 'pry' if ENV.fetch('USE_PRY', false)
8
+
9
+ # main entry point
10
+ begin
11
+ case ARGV[0]
12
+ when '-a', '--alive'
13
+ SidekiqErr.alive?
14
+ when '-r', '--report'
15
+ SidekiqErr.status(ARGV[1])
16
+ when '-h', '--help'
17
+ SidekiqErr.print_usage
18
+ else
19
+ puts
20
+ puts 'Uknown command, use --help for usage details'
21
+ puts
22
+ end
23
+ rescue SidekiqErr::Error, Redis::CannotConnectError, Redis::TimeoutError => e
24
+ puts "Error: #{e.message}"
25
+ puts
26
+ exit(1)
27
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqErr
4
+ class Alive
5
+ def self.check?
6
+ process_set = Sidekiq::ProcessSet.new
7
+ raise(NoProcessFound, 'No sidekiq process running!') if process_set.size.zero?
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqErr
4
+ class Error < StandardError; end
5
+ class NoProcessFound < Error; end
6
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqErr
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqErr
4
+ class View
5
+ class InvalidSection < SidekiqErr::Error; end
6
+
7
+ attr_reader :section
8
+
9
+ def self.valid_sections
10
+ @valid_sections ||= %w[all version overview processes queues].freeze
11
+ end
12
+
13
+ def initialize(section)
14
+ @section = section
15
+ end
16
+
17
+ def display
18
+ if invalid_section?(section)
19
+ msg = "Invalid section for status check: '#{section}'"
20
+ msg += "\nTry one of these: #{self.class.valid_sections.join(', ')}"
21
+ raise(InvalidSection, msg)
22
+ end
23
+
24
+ send(section)
25
+ end
26
+
27
+ def all
28
+ version
29
+ puts
30
+ overview
31
+ puts
32
+ processes
33
+ puts
34
+ queues
35
+ end
36
+
37
+ def version
38
+ puts "Sidekiq #{Sidekiq::VERSION}"
39
+ puts Time.now.utc
40
+ end
41
+
42
+ def overview
43
+ puts '---- Overview ----'
44
+ puts " Processed: #{delimit stats.processed}"
45
+ puts " Failed: #{delimit stats.failed}"
46
+ puts " Busy: #{delimit stats.workers_size}"
47
+ puts " Enqueued: #{delimit stats.enqueued}"
48
+ puts " Retries: #{delimit stats.retry_size}"
49
+ puts " Scheduled: #{delimit stats.scheduled_size}"
50
+ puts " Dead: #{delimit stats.dead_size}"
51
+ end
52
+
53
+ def processes
54
+ puts "---- Processes (#{process_set.size}) ----"
55
+ process_set.each_with_index do |process, index|
56
+ puts "#{process['identity']} #{tags_for(process)}"
57
+ puts " Started: #{Time.at(process['started_at'])} (#{time_ago(process['started_at'])})"
58
+ puts " Threads: #{process['concurrency']} (#{process['busy']} busy)"
59
+ puts " Queues: #{split_multiline(process['queues'].sort, pad: 11)}"
60
+ puts '' unless (index+1) == process_set.size
61
+ end
62
+ end
63
+
64
+ COL_PAD = 2
65
+ def queues
66
+ puts "---- Queues (#{queue_data.size}) ----"
67
+ columns = {
68
+ name: [:ljust, (['name'] + queue_data.map(&:name)).map(&:length).max + COL_PAD],
69
+ size: [:rjust, (['size'] + queue_data.map(&:size)).map(&:length).max + COL_PAD],
70
+ latency: [:rjust, (['latency'] + queue_data.map(&:latency)).map(&:length).max + COL_PAD]
71
+ }
72
+ columns.each { |col, (dir, width)| print col.to_s.upcase.public_send(dir, width) }
73
+ puts
74
+ queue_data.each do |q|
75
+ columns.each do |col, (dir, width)|
76
+ print q.send(col).public_send(dir, width)
77
+ end
78
+ puts
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ def delimit(number)
85
+ number.to_s.reverse.scan(/.{1,3}/).join(',').reverse
86
+ end
87
+
88
+ def split_multiline(values, opts = {})
89
+ return 'none' unless values
90
+
91
+ pad = opts[:pad] || 0
92
+ max_length = opts[:max_length] || (80 - pad)
93
+ out = []
94
+ line = ''.dup
95
+ values.each do |value|
96
+ if (line.length + value.length) > max_length
97
+ out += line
98
+ line = ' ' * pad
99
+ end
100
+ line += "#{value}, "
101
+ end
102
+ out << line[0..-3]
103
+ out.join("\n")
104
+ end
105
+
106
+ def tags_for(process)
107
+ tags = [
108
+ process['tag'],
109
+ process['labels'],
110
+ (process['quiet'] == 'true' ? 'quiet' : nil)
111
+ ].flatten.compact
112
+ tags.any? ? "[#{tags.join('] [')}]" : nil
113
+ end
114
+
115
+ def time_ago(timestamp)
116
+ seconds = Time.now - Time.at(timestamp)
117
+ return 'just now' if seconds < 60
118
+ return 'a minute ago' if seconds < 120
119
+ return "#{seconds.floor / 60} minutes ago" if seconds < 3600
120
+ return 'an hour ago' if seconds < 7200
121
+
122
+ "#{seconds.floor / 60 / 60} hours ago"
123
+ end
124
+
125
+ QUEUE_STRUCT = Struct.new(:name, :size, :latency)
126
+ def queue_data
127
+ @queue_data ||= Sidekiq::Queue.all.map do |q|
128
+ QUEUE_STRUCT.new(q.name, q.size.to_s, sprintf('%#.2f', q.latency))
129
+ end
130
+ end
131
+
132
+ def process_set
133
+ @process_set ||= Sidekiq::ProcessSet.new
134
+ end
135
+
136
+ def stats
137
+ @stats ||= Sidekiq::Stats.new
138
+ end
139
+
140
+ def invalid_section?(section)
141
+ !self.class.valid_sections.include?(section)
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sidekiq-err/version'
4
+ require 'sidekiq-err/error'
5
+ require 'sidekiq-err/alive'
6
+ require 'sidekiq-err/view'
7
+ require 'fileutils'
8
+ require 'sidekiq/api'
9
+
10
+ module SidekiqErr
11
+ CMD = File.basename($PROGRAM_NAME)
12
+
13
+ def self.print_usage
14
+ puts "#{CMD} - Sidekiq process reporting."
15
+ puts
16
+ puts "Usage: #{CMD}"
17
+ puts
18
+ puts ' -a, --alive'
19
+ puts ' check if at least 1 Sidekiq process is running'
20
+ puts ' sets the exit code to 1 if no process if found'
21
+ puts
22
+ puts ' -r, --report [SECTION_NAME]'
23
+ puts ' view the status report'
24
+ puts ' SECTION_NAME is optional and filters the report to a specific section'
25
+ puts " Valid sections are: #{View.valid_sections.join(', ')}"
26
+ puts " Default is 'all'"
27
+ puts
28
+ end
29
+
30
+ def self.status(section = nil)
31
+ section ||= 'all'
32
+ SidekiqErr::View.new(section).display
33
+ end
34
+
35
+ def self.alive?
36
+ SidekiqErr::Alive.check?
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidekiq-err
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Campbell Allen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-12-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sidekiq
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Status of your sidekiq system - useful for Kubernetes liveness probes
70
+ email:
71
+ - campbell.allen@gmail.com
72
+ executables:
73
+ - sidekiq-err
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - exe/sidekiq-err
78
+ - lib/sidekiq-err.rb
79
+ - lib/sidekiq-err/alive.rb
80
+ - lib/sidekiq-err/error.rb
81
+ - lib/sidekiq-err/version.rb
82
+ - lib/sidekiq-err/view.rb
83
+ homepage: https://github.com/camallen/sidekiq-err
84
+ licenses:
85
+ - MIT
86
+ metadata:
87
+ homepage_uri: https://github.com/camallen/sidekiq-err
88
+ source_code_uri: https://github.com/camallen/sidekiq-err
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '2.4'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.0.1
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Status of your sidekiq system - useful for Kubernetes liveness probes
108
+ test_files: []