health_check 2.5.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +162 -111
- data/CHANGELOG +36 -0
- data/README.rdoc +109 -43
- data/Rakefile +1 -1
- data/Vagrantfile +32 -0
- data/config/routes.rb +1 -1
- data/health_check.gemspec +7 -6
- data/lib/health_check.rb +51 -6
- data/lib/health_check/elasticsearch_health_check.rb +15 -0
- data/lib/health_check/health_check_controller.rb +32 -25
- data/lib/health_check/health_check_routes.rb +1 -1
- data/lib/health_check/middleware_health_check.rb +6 -1
- data/lib/health_check/rabbitmq_health_check.rb +16 -0
- data/lib/health_check/redis_health_check.rb +20 -7
- data/lib/health_check/s3_health_check.rb +9 -14
- data/lib/health_check/utils.rb +55 -33
- data/lib/health_check/version.rb +1 -1
- data/test/fake_smtp_server +143 -24
- data/test/init_variables +19 -1
- data/test/migrate/nine/9_create_countries.rb +1 -1
- data/test/migrate/twelve/011_create_roles.roles.rb +1 -1
- data/test/migrate/twelve/012_create_users.rb +2 -2
- data/test/migrate/twelve/9_create_countries.rb +1 -1
- data/test/provision_vagrant +103 -0
- data/test/rails_5.0.gemfile +10 -7
- data/test/rails_5.1.gemfile +34 -0
- data/test/rails_5.2.gemfile +34 -0
- data/test/rails_6.0.gemfile +30 -0
- data/test/rails_6.1.gemfile +29 -0
- data/test/rails_6.2.gemfile +30 -0
- data/test/rails_edge.gemfile +14 -9
- data/test/setup_railsapp +175 -95
- data/test/test_with_railsapp +152 -46
- data/test/testurl +9 -0
- metadata +45 -22
- data/test/rails_4.0.gemfile +0 -33
- data/test/rails_4.1.gemfile +0 -33
- data/test/rails_4.2.gemfile +0 -30
data/Rakefile
CHANGED
data/Vagrantfile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
Vagrant.configure("2") do |config|
|
5
|
+
# For a complete reference, please see the online documentation at
|
6
|
+
# https://docs.vagrantup.com.
|
7
|
+
|
8
|
+
config.vm.box = "ubuntu/focal64"
|
9
|
+
|
10
|
+
# set auto_update to false, if you do NOT want to check the correct
|
11
|
+
# additions version when booting this machine
|
12
|
+
config.vbguest.auto_update = false
|
13
|
+
|
14
|
+
# do NOT download the iso file from a webserver
|
15
|
+
config.vbguest.no_remote = true
|
16
|
+
|
17
|
+
# provision with a shell script.
|
18
|
+
config.vm.provision "shell", path: "./test/provision_vagrant"
|
19
|
+
|
20
|
+
config.vm.provider "virtualbox" do |v|
|
21
|
+
# travis allocates 7.5 GB, but this is sufficient
|
22
|
+
v.memory = 2048
|
23
|
+
v.cpus = 2
|
24
|
+
end
|
25
|
+
|
26
|
+
# if File.file?('.git') && IO.read('.git') =~ %r{\Agitdir: (.+)/.git/worktrees.*}
|
27
|
+
# # Handle git worktrees ...
|
28
|
+
# path = $1
|
29
|
+
# config.vm.synced_folder path, path
|
30
|
+
# end
|
31
|
+
|
32
|
+
end
|
data/config/routes.rb
CHANGED
data/health_check.gemspec
CHANGED
@@ -9,20 +9,21 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.required_rubygems_version = Gem::Requirement.new(">= 0") if gem.respond_to? :required_rubygems_version=
|
10
10
|
gem.authors = ["Ian Heggie"]
|
11
11
|
gem.email = ["ian@heggie.biz"]
|
12
|
-
gem.summary = %q{Simple health check of Rails app for uptime monitoring with Pingdom, NewRelic, EngineYard
|
12
|
+
gem.summary = %q{Simple health check of Rails app for uptime monitoring with Pingdom, NewRelic, EngineYard etc.}
|
13
13
|
gem.description = <<-EOF
|
14
|
-
Simple health check of Rails app for uptime monitoring with Pingdom, NewRelic, EngineYard
|
14
|
+
Simple health check of Rails app for uptime monitoring with Pingdom, NewRelic, EngineYard etc.
|
15
15
|
EOF
|
16
16
|
gem.homepage = "https://github.com/ianheggie/health_check"
|
17
|
+
gem.license = "MIT"
|
17
18
|
|
18
19
|
gem.files = `git ls-files`.split($/)
|
19
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
20
20
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
21
21
|
gem.extra_rdoc_files = [ "README.rdoc" ]
|
22
22
|
gem.require_paths = ["lib"]
|
23
|
-
gem.required_ruby_version = '>=
|
24
|
-
gem.add_dependency(%q<
|
23
|
+
gem.required_ruby_version = '>= 2.2.2'
|
24
|
+
gem.add_dependency(%q<railties>, [">= 5.0"])
|
25
|
+
gem.add_development_dependency(%q<smarter_bundler>, [">= 0.1.0"])
|
25
26
|
gem.add_development_dependency(%q<rake>, [">= 0.8.3"])
|
26
27
|
gem.add_development_dependency(%q<shoulda>, ["~> 2.11.0"])
|
27
|
-
gem.add_development_dependency(%q<bundler>, ["
|
28
|
+
gem.add_development_dependency(%q<bundler>, [">= 1.2"])
|
28
29
|
end
|
data/lib/health_check.rb
CHANGED
@@ -3,14 +3,22 @@
|
|
3
3
|
|
4
4
|
module HealthCheck
|
5
5
|
|
6
|
-
class Engine < Rails::Engine
|
7
|
-
cattr_accessor :routes_explicitly_defined
|
6
|
+
class Engine < ::Rails::Engine
|
7
|
+
cattr_accessor :routes_explicitly_defined
|
8
8
|
end
|
9
9
|
|
10
|
+
# Log level
|
11
|
+
mattr_accessor :log_level
|
12
|
+
self.log_level = 'info'
|
13
|
+
|
10
14
|
# Text output upon success
|
11
15
|
mattr_accessor :success
|
12
16
|
self.success = "success"
|
13
17
|
|
18
|
+
# Text output upon failure
|
19
|
+
mattr_accessor :failure
|
20
|
+
self.failure = "health_check failed"
|
21
|
+
|
14
22
|
# Timeout in seconds used when checking smtp server
|
15
23
|
mattr_accessor :smtp_timeout
|
16
24
|
self.smtp_timeout = 30.0
|
@@ -27,6 +35,10 @@ module HealthCheck
|
|
27
35
|
mattr_accessor :http_status_for_ip_whitelist_error
|
28
36
|
self.http_status_for_ip_whitelist_error = 403
|
29
37
|
|
38
|
+
# check remote_ip rather than ip for ip whitelist
|
39
|
+
mattr_accessor :accept_proxied_requests
|
40
|
+
self.accept_proxied_requests = false
|
41
|
+
|
30
42
|
# ips allowed to perform requests
|
31
43
|
mattr_accessor :origin_ip_whitelist
|
32
44
|
self.origin_ip_whitelist = []
|
@@ -40,6 +52,10 @@ module HealthCheck
|
|
40
52
|
mattr_accessor :buckets
|
41
53
|
self.buckets = {}
|
42
54
|
|
55
|
+
# rabbitmq
|
56
|
+
mattr_accessor :rabbitmq_config
|
57
|
+
self.rabbitmq_config = {}
|
58
|
+
|
43
59
|
# health check uri path
|
44
60
|
mattr_accessor :uri
|
45
61
|
self.uri = 'health_check'
|
@@ -53,8 +69,8 @@ module HealthCheck
|
|
53
69
|
mattr_accessor :custom_checks
|
54
70
|
mattr_accessor :full_checks
|
55
71
|
mattr_accessor :standard_checks
|
56
|
-
self.custom_checks =
|
57
|
-
self.full_checks = ['database', 'migrations', 'custom', 'email', 'cache', 'redis-if-present', 'sidekiq-redis-if-present', 'resque-redis-if-present', 's3-if-present']
|
72
|
+
self.custom_checks = { }
|
73
|
+
self.full_checks = ['database', 'migrations', 'custom', 'email', 'cache', 'redis-if-present', 'sidekiq-redis-if-present', 'resque-redis-if-present', 's3-if-present', 'elasticsearch-if-present']
|
58
74
|
self.standard_checks = [ 'database', 'migrations', 'custom', 'emailconf' ]
|
59
75
|
|
60
76
|
# Middleware based checks
|
@@ -63,8 +79,35 @@ module HealthCheck
|
|
63
79
|
|
64
80
|
mattr_accessor :installed_as_middleware
|
65
81
|
|
66
|
-
|
67
|
-
|
82
|
+
# Allow non-standard redis url and password
|
83
|
+
mattr_accessor :redis_url
|
84
|
+
self.redis_url = ENV['REDIS_URL']
|
85
|
+
|
86
|
+
mattr_accessor :redis_password
|
87
|
+
self.redis_password = 'some-password'
|
88
|
+
|
89
|
+
# Include the error in the response body.
|
90
|
+
# You should only do this where your /health_check endpoint is NOT open to the public internet
|
91
|
+
mattr_accessor :include_error_in_response_body
|
92
|
+
self.include_error_in_response_body = false
|
93
|
+
|
94
|
+
# used for on_failure and on_success
|
95
|
+
mattr_accessor :success_callbacks
|
96
|
+
mattr_accessor :failure_callbacks
|
97
|
+
|
98
|
+
def self.add_custom_check(name = 'custom', &block)
|
99
|
+
custom_checks[name] ||= [ ]
|
100
|
+
custom_checks[name] << block
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.on_success(&block)
|
104
|
+
success_callbacks ||= [ ]
|
105
|
+
success_callbacks << block
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.on_failure(&block)
|
109
|
+
failure_callbacks ||= [ ]
|
110
|
+
failure_callbacks << block
|
68
111
|
end
|
69
112
|
|
70
113
|
def self.setup
|
@@ -78,10 +121,12 @@ require 'health_check/base_health_check'
|
|
78
121
|
require 'health_check/resque_health_check'
|
79
122
|
require 'health_check/s3_health_check'
|
80
123
|
require 'health_check/redis_health_check'
|
124
|
+
require 'health_check/elasticsearch_health_check'
|
81
125
|
require 'health_check/sidekiq_health_check'
|
82
126
|
require 'health_check/utils'
|
83
127
|
require 'health_check/health_check_controller'
|
84
128
|
require 'health_check/health_check_routes'
|
85
129
|
require 'health_check/middleware_health_check'
|
130
|
+
require 'health_check/rabbitmq_health_check'
|
86
131
|
|
87
132
|
# vi: sw=2 sm ai:
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module HealthCheck
|
2
|
+
class ElasticsearchHealthCheck
|
3
|
+
extend BaseHealthCheck
|
4
|
+
|
5
|
+
def self.check
|
6
|
+
unless defined?(::Elasticsearch)
|
7
|
+
raise "Wrong configuration. Missing 'elasticsearch' gem"
|
8
|
+
end
|
9
|
+
res = ::Elasticsearch::Client.new.ping
|
10
|
+
res == true ? '' : "Elasticsearch returned #{res.inspect} instead of true"
|
11
|
+
rescue Exception => e
|
12
|
+
create_error 'elasticsearch', e.message
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
# Copyright (c) 2010-
|
1
|
+
# Copyright (c) 2010-2021 Ian Heggie, released under the MIT license.
|
2
2
|
# See MIT-LICENSE for details.
|
3
|
+
require "ipaddr"
|
3
4
|
|
4
5
|
module HealthCheck
|
5
6
|
class HealthCheckController < ActionController::Base
|
@@ -14,8 +15,8 @@ module HealthCheck
|
|
14
15
|
if max_age > 1
|
15
16
|
last_modified = Time.at((last_modified.to_f / max_age).floor * max_age).utc
|
16
17
|
end
|
17
|
-
|
18
|
-
if stale?(:
|
18
|
+
is_public = (max_age > 1) && ! HealthCheck.basic_auth_username
|
19
|
+
if stale?(last_modified: last_modified, public: is_public)
|
19
20
|
checks = params[:checks] ? params[:checks].split('_') : ['standard']
|
20
21
|
checks -= HealthCheck.middleware_checks if HealthCheck.installed_as_middleware
|
21
22
|
begin
|
@@ -23,15 +24,25 @@ module HealthCheck
|
|
23
24
|
rescue Exception => e
|
24
25
|
errors = e.message.blank? ? e.class.to_s : e.message.to_s
|
25
26
|
end
|
26
|
-
response.headers['Cache-
|
27
|
+
response.headers['Cache-Control'] = "must-revalidate, max-age=#{max_age}"
|
27
28
|
if errors.blank?
|
28
|
-
send_response nil, :ok, :ok
|
29
|
+
send_response true, nil, :ok, :ok
|
30
|
+
if HealthCheck.success_callbacks
|
31
|
+
HealthCheck.success_callbacks.each do |callback|
|
32
|
+
callback.call(checks)
|
33
|
+
end
|
34
|
+
end
|
29
35
|
else
|
30
|
-
msg = "
|
31
|
-
send_response msg, HealthCheck.http_status_for_error_text, HealthCheck.http_status_for_error_object
|
36
|
+
msg = HealthCheck.include_error_in_response_body ? "#{HealthCheck.failure}: #{errors}" : nil
|
37
|
+
send_response false, msg, HealthCheck.http_status_for_error_text, HealthCheck.http_status_for_error_object
|
38
|
+
|
32
39
|
# Log a single line as some uptime checkers only record that it failed, not the text returned
|
33
|
-
|
34
|
-
|
40
|
+
msg = "#{HealthCheck.failure}: #{errors}"
|
41
|
+
logger.send(HealthCheck.log_level, msg) if logger && HealthCheck.log_level
|
42
|
+
if HealthCheck.failure_callbacks
|
43
|
+
HealthCheck.failure_callbacks.each do |callback|
|
44
|
+
callback.call(checks, msg)
|
45
|
+
end
|
35
46
|
end
|
36
47
|
end
|
37
48
|
end
|
@@ -39,15 +50,14 @@ module HealthCheck
|
|
39
50
|
|
40
51
|
protected
|
41
52
|
|
42
|
-
def send_response(msg, text_status, obj_status)
|
43
|
-
healthy
|
44
|
-
|
45
|
-
obj = { :healthy => healthy, :message => msg}
|
53
|
+
def send_response(healthy, msg, text_status, obj_status)
|
54
|
+
msg ||= healthy ? HealthCheck.success : HealthCheck.failure
|
55
|
+
obj = { healthy: healthy, message: msg}
|
46
56
|
respond_to do |format|
|
47
|
-
format.html { render
|
48
|
-
format.json { render :
|
49
|
-
format.xml { render :
|
50
|
-
format.any { render
|
57
|
+
format.html { render plain: msg, status: text_status, content_type: 'text/plain' }
|
58
|
+
format.json { render json: obj, status: obj_status }
|
59
|
+
format.xml { render xml: obj, status: obj_status }
|
60
|
+
format.any { render plain: msg, status: text_status, content_type: 'text/plain' }
|
51
61
|
end
|
52
62
|
end
|
53
63
|
|
@@ -59,11 +69,12 @@ module HealthCheck
|
|
59
69
|
end
|
60
70
|
|
61
71
|
def check_origin_ip
|
72
|
+
request_ipaddr = IPAddr.new(HealthCheck.accept_proxied_requests ? request.remote_ip : request.ip)
|
62
73
|
unless HealthCheck.origin_ip_whitelist.blank? ||
|
63
|
-
HealthCheck.origin_ip_whitelist.
|
64
|
-
render
|
65
|
-
:
|
66
|
-
:
|
74
|
+
HealthCheck.origin_ip_whitelist.any? { |addr| IPAddr.new(addr).include? request_ipaddr }
|
75
|
+
render plain: 'Health check is not allowed for the requesting IP',
|
76
|
+
status: HealthCheck.http_status_for_ip_whitelist_error,
|
77
|
+
content_type: 'text/plain'
|
67
78
|
end
|
68
79
|
end
|
69
80
|
|
@@ -72,9 +83,5 @@ module HealthCheck
|
|
72
83
|
false
|
73
84
|
end
|
74
85
|
|
75
|
-
def plain_key
|
76
|
-
# Rails 4.0 doesn't have :plain, but it is deprecated later on
|
77
|
-
Rails.version < '4.1' ? :text : :plain
|
78
|
-
end
|
79
86
|
end
|
80
87
|
end
|
@@ -8,7 +8,7 @@ module ActionDispatch::Routing
|
|
8
8
|
|
9
9
|
def add_health_check_routes(prefix = nil)
|
10
10
|
HealthCheck.uri = prefix if prefix
|
11
|
-
match "#{HealthCheck.uri}(/:checks)(.:format)", :
|
11
|
+
match "#{HealthCheck.uri}(/:checks)(.:format)", controller: 'health_check/health_check', action: :index, via: [:get, :post], defaults: { format: 'txt' }
|
12
12
|
end
|
13
13
|
|
14
14
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# Copyright (c) 2010-2021 Ian Heggie, released under the MIT license.
|
2
|
+
# See MIT-LICENSE for details.
|
3
|
+
require 'ipaddr'
|
4
|
+
|
1
5
|
module HealthCheck
|
2
6
|
class MiddlewareHealthcheck
|
3
7
|
|
@@ -59,7 +63,8 @@ module HealthCheck
|
|
59
63
|
def ip_blocked(env)
|
60
64
|
return false if HealthCheck.origin_ip_whitelist.blank?
|
61
65
|
req = Rack::Request.new(env)
|
62
|
-
|
66
|
+
request_ipaddr = IPAddr.new(req.ip)
|
67
|
+
unless HealthCheck.origin_ip_whitelist.any? { |addr| IPAddr.new(addr).include? request_ipaddr }
|
63
68
|
[ HealthCheck.http_status_for_ip_whitelist_error,
|
64
69
|
{ 'Content-Type' => 'text/plain' },
|
65
70
|
[ 'Health check is not allowed for the requesting IP' ]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HealthCheck
|
2
|
+
class RabbitMQHealthCheck
|
3
|
+
extend BaseHealthCheck
|
4
|
+
def self.check
|
5
|
+
unless defined?(::Bunny)
|
6
|
+
raise "Wrong configuration. Missing 'bunny' gem"
|
7
|
+
end
|
8
|
+
connection = Bunny.new(HealthCheck.rabbitmq_config)
|
9
|
+
connection.start
|
10
|
+
connection.close
|
11
|
+
''
|
12
|
+
rescue Exception => e
|
13
|
+
create_error 'rabbitmq', e.message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,15 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HealthCheck
|
2
4
|
class RedisHealthCheck
|
3
5
|
extend BaseHealthCheck
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
raise "Wrong configuration. Missing 'redis' gem"
|
7
|
+
class << self
|
8
|
+
def check
|
9
|
+
raise "Wrong configuration. Missing 'redis' gem" unless defined?(::Redis)
|
10
|
+
|
11
|
+
client.ping == 'PONG' ? '' : "Redis.ping returned #{res.inspect} instead of PONG"
|
12
|
+
rescue Exception => err
|
13
|
+
create_error 'redis', err.message
|
14
|
+
ensure
|
15
|
+
client.close if client.connected?
|
16
|
+
end
|
17
|
+
|
18
|
+
def client
|
19
|
+
@client ||= Redis.new(
|
20
|
+
{
|
21
|
+
url: HealthCheck.redis_url,
|
22
|
+
password: HealthCheck.redis_password
|
23
|
+
}.reject { |k, v| v.nil? }
|
24
|
+
)
|
8
25
|
end
|
9
|
-
res = ::Redis.new.ping
|
10
|
-
res == 'PONG' ? '' : "Redis.ping returned #{res.inspect} instead of PONG"
|
11
|
-
rescue Exception => e
|
12
|
-
create_error 'redis', e.message
|
13
26
|
end
|
14
27
|
end
|
15
28
|
end
|
@@ -5,7 +5,7 @@ module HealthCheck
|
|
5
5
|
class << self
|
6
6
|
def check
|
7
7
|
unless defined?(::Aws)
|
8
|
-
raise "Wrong configuration. Missing 'aws-sdk' gem"
|
8
|
+
raise "Wrong configuration. Missing 'aws-sdk' or 'aws-sdk-s3' gem"
|
9
9
|
end
|
10
10
|
return create_error 's3', 'Could not connect to aws' if aws_s3_client.nil?
|
11
11
|
HealthCheck.buckets.each do |bucket_name, permissions|
|
@@ -27,19 +27,14 @@ module HealthCheck
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
+
# We already assume you are using Rails. Let's also assume you have an initializer
|
31
|
+
# created for your Aws config. We will set the region here so you can use an
|
32
|
+
# instance profile and simply set the region in your environment.
|
30
33
|
def configure_client
|
31
|
-
|
34
|
+
::Aws.config[:s3] = { force_path_style: true }
|
35
|
+
::Aws.config[:region] ||= ENV['AWS_REGION'] || ENV['DEFAULT_AWS_REGION']
|
32
36
|
|
33
|
-
|
34
|
-
region: Rails.application.secrets.aws_default_region,
|
35
|
-
credentials: ::Aws::Credentials.new(
|
36
|
-
Rails.application.secrets.aws_access_key_id,
|
37
|
-
Rails.application.secrets.aws_secret_access_key
|
38
|
-
),
|
39
|
-
force_path_style: true
|
40
|
-
}
|
41
|
-
|
42
|
-
::Aws::S3::Client.new aws_configuration
|
37
|
+
::Aws::S3::Client.new
|
43
38
|
end
|
44
39
|
|
45
40
|
def aws_s3_client
|
@@ -52,13 +47,13 @@ module HealthCheck
|
|
52
47
|
|
53
48
|
def W(bucket)
|
54
49
|
aws_s3_client.put_object(bucket: bucket,
|
55
|
-
key: "healthcheck_#{Rails.application.class.parent_name}",
|
50
|
+
key: "healthcheck_#{::Rails.application.class.parent_name}",
|
56
51
|
body: Time.new.to_s)
|
57
52
|
end
|
58
53
|
|
59
54
|
def D(bucket)
|
60
55
|
aws_s3_client.delete_object(bucket: bucket,
|
61
|
-
key: "healthcheck_#{Rails.application.class.parent_name}")
|
56
|
+
key: "healthcheck_#{::Rails.application.class.parent_name}")
|
62
57
|
end
|
63
58
|
end
|
64
59
|
end
|
data/lib/health_check/utils.rb
CHANGED
@@ -6,13 +6,13 @@ module HealthCheck
|
|
6
6
|
|
7
7
|
@@default_smtp_settings =
|
8
8
|
{
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
9
|
+
address: "localhost",
|
10
|
+
port: 25,
|
11
|
+
domain: 'localhost.localdomain',
|
12
|
+
user_name: nil,
|
13
|
+
password: nil,
|
14
|
+
authentication: nil,
|
15
|
+
enable_starttls_auto: true
|
16
16
|
}
|
17
17
|
|
18
18
|
cattr_accessor :default_smtp_settings
|
@@ -55,6 +55,8 @@ module HealthCheck
|
|
55
55
|
errors << HealthCheck::RedisHealthCheck.check if defined?(::Redis)
|
56
56
|
when 's3-if-present'
|
57
57
|
errors << HealthCheck::S3HealthCheck.check if defined?(::Aws)
|
58
|
+
when 'elasticsearch-if-present'
|
59
|
+
errors << HealthCheck::ElasticsearchHealthCheck.check if defined?(::Elasticsearch)
|
58
60
|
when 'resque-redis'
|
59
61
|
errors << HealthCheck::ResqueHealthCheck.check
|
60
62
|
when 'sidekiq-redis'
|
@@ -63,28 +65,41 @@ module HealthCheck
|
|
63
65
|
errors << HealthCheck::RedisHealthCheck.check
|
64
66
|
when 's3'
|
65
67
|
errors << HealthCheck::S3HealthCheck.check
|
68
|
+
when 'elasticsearch'
|
69
|
+
errors << HealthCheck::ElasticsearchHealthCheck.check
|
70
|
+
when 'rabbitmq'
|
71
|
+
errors << HealthCheck::RabbitMQHealthCheck.check
|
66
72
|
when "standard"
|
67
73
|
errors << HealthCheck::Utils.process_checks(HealthCheck.standard_checks, called_from_middleware)
|
68
74
|
when "middleware"
|
69
75
|
errors << "Health check not called from middleware - probably not installed as middleware." unless called_from_middleware
|
70
76
|
when "custom"
|
71
|
-
HealthCheck.custom_checks.each do |
|
72
|
-
|
77
|
+
HealthCheck.custom_checks.each do |name, list|
|
78
|
+
list.each do |custom_check|
|
79
|
+
errors << custom_check.call(self)
|
80
|
+
end
|
73
81
|
end
|
74
82
|
when "all", "full"
|
75
83
|
errors << HealthCheck::Utils.process_checks(HealthCheck.full_checks, called_from_middleware)
|
76
84
|
else
|
77
|
-
|
85
|
+
if HealthCheck.custom_checks.include? check
|
86
|
+
HealthCheck.custom_checks[check].each do |custom_check|
|
87
|
+
errors << custom_check.call(self)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
return "invalid argument to health_test."
|
91
|
+
end
|
78
92
|
end
|
93
|
+
errors << '. ' unless errors == '' || errors.end_with?('. ')
|
79
94
|
end
|
80
|
-
return errors
|
95
|
+
return errors.strip
|
81
96
|
rescue => e
|
82
97
|
return e.message
|
83
98
|
end
|
84
99
|
|
85
100
|
def self.db_migrate_path
|
86
101
|
# Lazy initialisation so Rails.root will be defined
|
87
|
-
@@db_migrate_path ||= File.join(Rails.root, 'db', 'migrate')
|
102
|
+
@@db_migrate_path ||= File.join(::Rails.root, 'db', 'migrate')
|
88
103
|
end
|
89
104
|
|
90
105
|
def self.db_migrate_path=(value)
|
@@ -127,36 +142,43 @@ module HealthCheck
|
|
127
142
|
status = ''
|
128
143
|
begin
|
129
144
|
if @skip_external_checks
|
130
|
-
status = '
|
145
|
+
status = '250'
|
131
146
|
else
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
139
|
-
t.puts "HELO #{settings[:domain]}\r"
|
140
|
-
while status != nil && status !~ /^250/
|
141
|
-
status = t.gets
|
142
|
-
end
|
143
|
-
t.puts "QUIT\r"
|
144
|
-
status = t.gets
|
145
|
-
ensure
|
146
|
-
t.close
|
147
|
-
end
|
147
|
+
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
148
|
+
smtp.enable_starttls if settings[:enable_starttls_auto]
|
149
|
+
smtp.open_timeout = timeout
|
150
|
+
smtp.read_timeout = timeout
|
151
|
+
smtp.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do
|
152
|
+
status = smtp.helo(settings[:domain]).status
|
148
153
|
end
|
149
154
|
end
|
150
|
-
rescue Errno::EBADF => ex
|
151
|
-
status = "Unable to connect to service"
|
152
155
|
rescue Exception => ex
|
153
156
|
status = ex.to_s
|
154
157
|
end
|
155
|
-
(status =~ /^
|
158
|
+
(status =~ /^250/) ? '' : "SMTP: #{status || 'unexpected error'}. "
|
156
159
|
end
|
157
160
|
|
158
161
|
def self.check_cache
|
159
|
-
|
162
|
+
t = Time.now.to_i
|
163
|
+
value = "ok #{t}"
|
164
|
+
ret = ::Rails.cache.read('__health_check_cache_test__')
|
165
|
+
if ret.to_s =~ /^ok (\d+)$/
|
166
|
+
diff = ($1.to_i - t).abs
|
167
|
+
return('Cache expiry is broken. ') if diff > 30
|
168
|
+
elsif ret
|
169
|
+
return 'Cache is returning garbage. '
|
170
|
+
end
|
171
|
+
if ::Rails.cache.write('__health_check_cache_test__', value, expires_in: 2.seconds)
|
172
|
+
ret = ::Rails.cache.read('__health_check_cache_test__')
|
173
|
+
if ret =~ /^ok (\d+)$/
|
174
|
+
diff = ($1.to_i - t).abs
|
175
|
+
(diff < 2 ? '' : 'Out of date cache or time is skewed. ')
|
176
|
+
else
|
177
|
+
'Unable to read from cache. '
|
178
|
+
end
|
179
|
+
else
|
180
|
+
'Unable to write to cache. '
|
181
|
+
end
|
160
182
|
end
|
161
183
|
|
162
184
|
end
|