kubernetes-health 3.4.1 → 3.6.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
2
  SHA256:
3
- metadata.gz: e002184325d2c508f38c8fc4c73532d748046664fcc65764e345d0119734d066
4
- data.tar.gz: 85419dad18b1fe9df0d0fcdcbbf1686f0e7233497bc1685f2a1182baba7cceb8
3
+ metadata.gz: 6f0b091b68d3acd2e69b0e2e259ad841eef9b5030ae7f7a8a404f7d0535722c7
4
+ data.tar.gz: 2ab614dc570e2b8202533101566a4eb0f6aca71ad2490d27ac10d4739e9cc322
5
5
  SHA512:
6
- metadata.gz: 5b3cc913270ba83fda812e464bbcd3469e6949778059e707b6de62f4b2391747ade9f957c12062c0f98c42fbd0beb421403caed4c0bd6c15acc553edb917f560
7
- data.tar.gz: b147c8e17cee0c3648116ac10eb1e9e6cfa89d1f78a5d03815629d2aa0d27b8b066fb4abcf70b6ea3b0595de36828911b8959c1cf2a0bd9f3077c0f9d1d8a6af
6
+ metadata.gz: 26068d438952f640c22b9e7ce3d416aeec53fd32bec73013de08c4037ad1183619dd13cd8f23fe1561d2a57f191272a895138b9cb0279bc90fa41cba309d8d2a
7
+ data.tar.gz: 5c89c1531a8f10b858ba3bcd7626fe7d34fc308bde57bb0ba56fbd26e45e85b50caa72332186e4ce2e04c4e50a17c26226dabb0a7d13738eea02acdd9805491f
data/README.md CHANGED
@@ -1,21 +1,22 @@
1
1
  # Kubernetes::Health
2
-
3
- This gem allows kubernetes monitoring your app while it is running migrates and after it starts.
2
+ This gem open a HTTP port for monitoring your rails app while it is running Migrates, Sidekiq and Puma.
4
3
 
5
4
  # Features
6
- - add routes `/_readiness`, `/_liveness` on rails stack.
7
- - add routes `/_readiness`, `/_liveness` and `/_metrics` as a puma plugin.
8
- - metrics are prometheus compatible (code copied from `puma-metrics` gem) or json.
9
- - allow custom checks for `/_readiness` and `/_liveness`.
5
+ - Puma and Sidekiq metrics for autoscaling.
6
+ - Prometheus and JSON metrics (tested using https://github.com/zalando-incubator/kube-metrics-adapter and JSON format).
7
+ - add routes `/_readiness`, `/_liveness` on Rails Stack.
8
+ - add routes `/_readiness`, `/_liveness` and `/_metrics` as a puma plugin at another port to avoid problems when your app get busy. (code copied from `puma-metrics` gem).
10
9
  - add routes `/_readiness` and `/_liveness` while `rake db:migrate` runs. (optional)
11
- - add support to avoid parallel running of `rake db:migrate` while keep kubernetes waiting. (optional)
12
-
10
+ - add routes `/_readiness` and `/_liveness` while `sidekiq` runs. (optional)
11
+ - add support to avoid parallel running of `rake db:migrate` while keep kubernetes waiting (PostgreSQL required).
12
+ - allow custom checks for `/_readiness` and `/_liveness`.
13
+
13
14
  ## Installation
14
15
 
15
16
  Add this line to your application's Gemfile:
16
17
 
17
18
  ```ruby
18
- gem 'kubernetes-health', '~> 3.4'
19
+ gem 'kubernetes-health', '~> 3.6'
19
20
  ```
20
21
 
21
22
  ## Enabling puma plugin
@@ -48,6 +49,7 @@ In Kubernetes you need to configure your deployment `readinessProbe` and `livene
48
49
  ```
49
50
 
50
51
  Setting `failureThreshold` is import to avoid problems when app finish migrates and is starting the web process.
52
+
51
53
  ## Enabling monitoring while `rake db:migrate` runs
52
54
 
53
55
  Your Dockerfile's entry script needs to run migrates before start your web app.
@@ -60,9 +62,22 @@ or add in your `application.rb`.
60
62
  # default: false
61
63
  Kubernetes::Health::Config.enable_rack_on_migrate = true
62
64
  ```
65
+ The defined port at `config/puma.rb` will be used.
66
+
67
+ ## Enabling monitoring for `sidekiq`
68
+
69
+ Add `KUBERNETES_HEALTH_ENABLE_RACK_ON_SIDEKIQ=true` environment variable.
70
+
71
+ or add in your `application.rb`.
72
+
73
+ ```
74
+ # default: false
75
+ Kubernetes::Health::Config.enable_rack_on_sidekiq = true
76
+ ```
77
+ The defined port at `config/puma.rb` will be used.
63
78
 
64
- ### How `rake db:migrate` monitoring works
65
- It will run a RACK server for `/_readiness` and `/_liveness` routes while `rake db:migrate` is running.
79
+ ### How `rake db:migrate` and `sidekiq` monitoring works
80
+ It will run a RACK server for `/_readiness`, `/_liveness` and `/_metrics`.
66
81
 
67
82
  ## Avoiding migrations running in parallel and making kubernetes happy.
68
83
  Rails already avoid migrations running in parallel, but it raise exceptions. This gem will just wait for other migrations without exit.
@@ -128,7 +143,7 @@ Kubernetes::Health::Config.response_format = 'json'
128
143
  ## Customizing requests logs
129
144
 
130
145
  ```
131
- Kubernetes::Health::Config.request_log_callback = lambda { |req, http_code|
132
- Rails.logger.debug "Kubernetes Health: Rack on Migrate - Request: Path: #{req.path_info} / Params: #{req.params} / HTTP Code: #{http_code}" rescue nil
146
+ Kubernetes::Health::Config.request_log_callback = lambda { |req, http_code, content|
147
+ Rails.logger.debug "Kubernetes Health: Rack on Migrate - Request: Path: #{req.path_info} / Params: #{req.params} / HTTP Code: #{http_code}\n#{content}" rescue nil
133
148
  }
134
149
  ```
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ task :server do
12
12
  require 'puma'
13
13
  require 'puma/configuration'
14
14
  require 'puma/events'
15
- require 'puma/plugin/kubernetes.rb'
15
+ require 'puma/plugin/kubernetes'
16
16
 
17
17
  configuration = Puma::Configuration.new do |config|
18
18
  config.bind 'tcp://127.0.0.1:0'
@@ -0,0 +1,7 @@
1
+ require 'kubernetes/health/rack_on_sidekiq'
2
+
3
+ if Kubernetes::Health::Config.enable_rack_on_sidekiq && Sidekiq.options[:concurrency].positive?
4
+ Thread.new do
5
+ Rack::Handler.default.run Kubernetes::Health::RackOnSidekiq.new
6
+ end
7
+ end
@@ -5,6 +5,7 @@ module Kubernetes
5
5
  @@ready_if = lambda { true }
6
6
  @@enable_lock_on_migrate = [true, 'true'].include? ENV['KUBERNETES_HEALTH_ENABLE_LOCK_ON_MIGRATE']
7
7
  @@enable_rack_on_migrate = [true, 'true'].include? ENV['KUBERNETES_HEALTH_ENABLE_RACK_ON_MIGRATE']
8
+ @@enable_rack_on_sidekiq = [true, 'true'].include? ENV['KUBERNETES_HEALTH_ENABLE_RACK_ON_SIDEKIQ']
8
9
  @@route_liveness = '/_liveness'
9
10
  @@route_readiness = '/_readiness'
10
11
  @@route_metrics = '/_metrics'
@@ -57,6 +58,14 @@ module Kubernetes
57
58
  @@enable_rack_on_migrate = value
58
59
  end
59
60
 
61
+ def self.enable_rack_on_sidekiq
62
+ @@enable_rack_on_sidekiq
63
+ end
64
+
65
+ def self.enable_rack_on_sidekiq=(value)
66
+ @@enable_rack_on_sidekiq = value
67
+ end
68
+
60
69
  def self.route_metrics
61
70
  @@route_metrics
62
71
  end
@@ -1,10 +1,11 @@
1
1
  require 'rack'
2
2
  require "kubernetes/health/rack_on_migrate"
3
+
3
4
  namespace :kubernetes_health do
4
5
  task :rack_on_migrate do
5
- Thread.new {
6
+ Thread.new do
6
7
  Rack::Handler.default.run Kubernetes::Health::RackOnMigrate.new
7
- }
8
+ end
8
9
  end
9
10
  end
10
11
  Rake::Task['db:migrate'].enhance(['kubernetes_health:rack_on_migrate'])
@@ -0,0 +1,57 @@
1
+ require 'rack'
2
+ require 'prometheus/client'
3
+ require 'prometheus/client/formats/text'
4
+
5
+ module Kubernetes
6
+ module Health
7
+ class RackOnSidekiq
8
+ def call(env)
9
+ req = ::Rack::Request.new(env)
10
+ content = ''
11
+ type = ::Kubernetes::Health::Config.response_format == 'json' ? { 'Content-Type' => 'application/json' } : { 'Content-Type' => 'text/plain' }
12
+ case req.path_info
13
+ when Kubernetes::Health::Config.route_metrics
14
+ http_code = 200
15
+
16
+ @sidekiq_metrics = sidekiq_metrics
17
+
18
+ if ::Kubernetes::Health::Config.response_format == 'json'
19
+ content = @sidekiq_metrics.to_json
20
+ else
21
+ prometheus_registry.get(:sidekiq_capacity).set({}, @sidekiq_metrics[:sidekiq_capacity])
22
+ prometheus_registry.get(:sidekiq_busy).set({}, @sidekiq_metrics[:sidekiq_busy])
23
+ prometheus_registry.get(:sidekiq_usage).set({}, @sidekiq_metrics[:sidekiq_usage])
24
+ content = Prometheus::Client::Formats::Text.marshal(prometheus_registry)
25
+ end
26
+ else
27
+ http_code = 404
28
+ end
29
+ ::Kubernetes::Health::Config.request_log_callback.call(req, http_code, content)
30
+
31
+ [http_code, type, [content]]
32
+ end
33
+
34
+ def prometheus_registry
35
+ return @prometheus_registry if @prometheus_registry
36
+
37
+ @prometheus_registry = Prometheus::Client.registry
38
+ @prometheus_registry.gauge(:sidekiq_capacity, 'Sidekiq Threads Number', index: 0)
39
+ @prometheus_registry.gauge(:sidekiq_busy, 'Sidekiq Busy Threads', index: 0)
40
+ @prometheus_registry.gauge(:sidekiq_usage, 'Result of sidekiq_busy/sidekiq_capacity', index: 0)
41
+ @prometheus_registry
42
+ end
43
+
44
+ def sidekiq_metrics
45
+ sidekiq_info = Sidekiq::ProcessSet.new.to_a.filter { |p| p.identity == Sidekiq.options[:identity] }
46
+
47
+ stats = {
48
+ sidekiq_capacity: Sidekiq.options[:concurrency],
49
+ sidekiq_busy: sidekiq_info.size.zero? ? 0 : sidekiq_info[0]['busy']
50
+ }
51
+
52
+ stats[:sidekiq_usage] = (stats[:sidekiq_busy] / stats[:sidekiq_capacity].to_f).round(2)
53
+ stats
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,5 +1,5 @@
1
1
  module Kubernetes
2
2
  module Health
3
- VERSION = "3.4.1"
3
+ VERSION = '3.6.0'.freeze
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- require "kubernetes/health/config"
1
+ require 'kubernetes/health/config'
2
2
  require 'prometheus/client/formats/text'
3
3
  require 'puma/kubernetes/parser'
4
4
  require 'rack'
@@ -28,15 +28,17 @@ module Puma
28
28
  when ::Kubernetes::Health::Config.route_metrics
29
29
  http_code = 200
30
30
  if ::Kubernetes::Health::Config.response_format == 'json'
31
- content = include_puma_key_prefix(include_usage(JSON.parse(@launcher.stats))).to_json
31
+ content = include_puma_key_prefix(include_usage(merge_worker_status_if_needed(@launcher.stats))).to_json
32
32
  else
33
- @parser.parse include_usage(JSON.parse(@launcher.stats))
33
+ @parser.parse include_usage(merge_worker_status_if_needed(@launcher.stats))
34
34
  content = Prometheus::Client::Formats::Text.marshal(Prometheus::Client.registry)
35
35
  end
36
36
  else
37
37
  http_code = 404
38
38
  end
39
- rescue
39
+ rescue => e
40
+ puts e.message
41
+ puts e.backtrace.join("\n")
40
42
  http_code = 500
41
43
  content = ''
42
44
  end
@@ -44,7 +46,23 @@ module Puma
44
46
  [http_code, type, [content]]
45
47
  end
46
48
 
49
+ def merge_worker_status_if_needed(stats)
50
+ return stats unless stats[:worker_status]
51
+
52
+ merded_stats = stats[:worker_status].map { |ws| ws[:last_status] }.inject({}) { |sum, hash| sum.merge(hash) { |_key, val1, val2| val1+val2 } }
53
+ merded_stats[:puma_started_at] = stats[:puma_started_at]
54
+ merded_stats[:worker_status] = stats[:worker_status]
55
+ merded_stats
56
+ end
57
+
47
58
  def include_usage(stats)
59
+ if stats.is_a?(String)
60
+ # puma <= 4.
61
+ stats = JSON.parse(stats)
62
+ else
63
+ # Puma >=5 uses symbol.
64
+ stats = JSON.parse(stats.to_json)
65
+ end
48
66
  stats['usage'] = (1 - stats['pool_capacity'].to_f / stats['max_threads']).round(2)
49
67
  stats
50
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kubernetes-health
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.1
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wagner Caixeta
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-29 00:00:00.000000000 Z
11
+ date: 2022-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -128,6 +128,7 @@ files:
128
128
  - app/controllers/kubernetes/health_controller.rb
129
129
  - bin/console
130
130
  - bin/setup
131
+ - config/initializers/enable_rack_on_sidekiq.rb
131
132
  - config/routes.rb
132
133
  - kubernetes-health.gemspec
133
134
  - lib/kubernetes/health.rb
@@ -136,6 +137,7 @@ files:
136
137
  - lib/kubernetes/health/lock_on_migrate.rake
137
138
  - lib/kubernetes/health/rack_on_migrate.rake
138
139
  - lib/kubernetes/health/rack_on_migrate.rb
140
+ - lib/kubernetes/health/rack_on_sidekiq.rb
139
141
  - lib/kubernetes/health/railtie.rb
140
142
  - lib/kubernetes/health/version.rb
141
143
  - lib/puma/kubernetes/app.rb
@@ -145,7 +147,7 @@ files:
145
147
  homepage: https://github.com/platbr/kubernetes-health
146
148
  licenses: []
147
149
  metadata: {}
148
- post_install_message:
150
+ post_install_message:
149
151
  rdoc_options: []
150
152
  require_paths:
151
153
  - lib
@@ -160,8 +162,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
162
  - !ruby/object:Gem::Version
161
163
  version: '0'
162
164
  requirements: []
163
- rubygems_version: 3.2.17
164
- signing_key:
165
+ rubygems_version: 3.1.4
166
+ signing_key:
165
167
  specification_version: 4
166
168
  summary: This gem allows kubernetes monitoring your app while it is running migrates
167
169
  and after it started.