sidekiq-err 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/exe/sidekiq-err +27 -0
- data/lib/sidekiq-err/alive.rb +10 -0
- data/lib/sidekiq-err/error.rb +6 -0
- data/lib/sidekiq-err/version.rb +5 -0
- data/lib/sidekiq-err/view.rb +144 -0
- data/lib/sidekiq-err.rb +38 -0
- metadata +108 -0
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,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
|
data/lib/sidekiq-err.rb
ADDED
@@ -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: []
|