healthier 0.1.71 → 0.2.4
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 +4 -4
- data/README.md +55 -5
- data/app/controllers/healthier/application_controller.rb +0 -1
- data/app/controllers/healthier/{checks_controller.rb → healthier_controller.rb} +12 -3
- data/config/routes.rb +3 -1
- data/lib/connectors/elastic_search.rb +36 -0
- data/lib/connectors/mongodb.rb +25 -0
- data/lib/connectors/postgresql.rb +22 -0
- data/lib/connectors/rabbitmq.rb +30 -0
- data/lib/connectors/redis.rb +24 -0
- data/lib/connectors/sidekiq.rb +21 -0
- data/lib/generators/healthier/config_generator.rb +5 -0
- data/lib/healthier/api_authenticator.rb +5 -5
- data/lib/healthier/doctor.rb +98 -0
- data/lib/healthier/engine.rb +16 -23
- data/lib/healthier/version.rb +1 -1
- metadata +24 -19
- data/app/lib/errors/api_errors.rb +0 -33
- data/lib/checkers/mongodb_checker.rb +0 -26
- data/lib/checkers/postgresql_checker.rb +0 -23
- data/lib/checkers/rabbitmq_checker.rb +0 -25
- data/lib/checkers/redis_checker.rb +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 79b6e112a7ffa5ea29b9d6d2e8448d15ffc07f435b509ca0fc1bbbb4110bd2e8
|
|
4
|
+
data.tar.gz: b6a5c3673cebc007cc71f94fd02d0a0e5fe7c1ddbd7dd664a5025cfa7e97d85e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5fd0ab542308dc0fad393d1e3dd4ef0e3fe13643631f3270138c2fd22b3a438456ada91a85af844f1e19ad3c7afd89c1b4609a41826c9f85ed333e7d2765785d
|
|
7
|
+
data.tar.gz: e568f145d560f227d0423239c186b88d15540df3459fb1fff6b76830b48857c3694ed407406d1f0cc4d5dc7e3058eee1a75a4442337c74f80497c73bd0fa6d6f
|
data/README.md
CHANGED
|
@@ -72,8 +72,8 @@ mount Healthier::Engine => '/healthier'
|
|
|
72
72
|
ENVs for basic authentication:
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
HEALTHIER_USERNAME: 'demouser'
|
|
76
|
+
HEALTHIER_PASSWORD: 'demouser@2023'
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
ENVs for Bearer token authentication:
|
|
@@ -88,9 +88,59 @@ However, if you want to leave the API open, just set:
|
|
|
88
88
|
Healthier.auth_mechanism = :none
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
## Health Check Endpoints
|
|
92
|
+
|
|
93
|
+
Healthier provides three distinct health check endpoints for monitoring your application:
|
|
94
|
+
|
|
95
|
+
### 1. Ping Endpoint (`GET /healthier/ping`)
|
|
96
|
+
Returns detailed health status of all configured services.
|
|
97
|
+
|
|
98
|
+
**Response:** JSON object with service health statuses
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"postgresql": {
|
|
102
|
+
"status": "success",
|
|
103
|
+
"message": "PostgreSQL service is healthy"
|
|
104
|
+
},
|
|
105
|
+
"redis": {
|
|
106
|
+
"status": "success",
|
|
107
|
+
"message": "Redis service is healthy"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 2. Live Endpoint (`GET /healthier/live`)
|
|
113
|
+
Basic liveness check that verifies if the application is running.
|
|
114
|
+
|
|
115
|
+
**Response:** Boolean value
|
|
116
|
+
```json
|
|
117
|
+
true
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3. Ready Endpoint (`GET /healthier/ready`)
|
|
121
|
+
Readiness check that verifies if all configured services are healthy and the application is ready to serve requests.
|
|
122
|
+
|
|
123
|
+
**Response:** Boolean value
|
|
124
|
+
```json
|
|
125
|
+
true
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Example Usage
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Ping - detailed service health
|
|
132
|
+
curl http://localhost:3000/healthier/ping
|
|
133
|
+
|
|
134
|
+
# Live - basic liveness check
|
|
135
|
+
curl http://localhost:3000/healthier/live
|
|
136
|
+
|
|
137
|
+
# Ready - service readiness check
|
|
138
|
+
curl http://localhost:3000/healthier/ready
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Example Curl with authentication:
|
|
142
|
+
```bash
|
|
143
|
+
curl -H "Bearer your_token_here" -H "Content-Type: application/json" 'http://localhost:3000/healthier/ping'
|
|
94
144
|
```
|
|
95
145
|
|
|
96
146
|
## Contributing
|
|
@@ -2,13 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
module Healthier
|
|
4
4
|
# Controller for performing health checks
|
|
5
|
-
class
|
|
5
|
+
class HealthierController < ApplicationController
|
|
6
6
|
include ActionController::HttpAuthentication::Basic::ControllerMethods
|
|
7
7
|
|
|
8
|
-
before_action :authenticate_request
|
|
8
|
+
before_action :authenticate_request, except: [:live]
|
|
9
9
|
|
|
10
10
|
def ping
|
|
11
|
-
render json: Healthier::
|
|
11
|
+
render json: Healthier::Doctor.ping!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# NOTE: Just return 200
|
|
15
|
+
def live
|
|
16
|
+
render json: Healthier::Doctor.up?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def ready
|
|
20
|
+
render json: Healthier::Doctor.ping!
|
|
12
21
|
end
|
|
13
22
|
|
|
14
23
|
protected
|
data/config/routes.rb
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Connectors
|
|
4
|
+
# ElasticSearch health checker
|
|
5
|
+
class ElasticSearch
|
|
6
|
+
def connect
|
|
7
|
+
url = ENV.fetch('ELASTICSEARCH_URL', 'http://localhost:9200')
|
|
8
|
+
|
|
9
|
+
require 'net/http'
|
|
10
|
+
require 'uri'
|
|
11
|
+
require 'json'
|
|
12
|
+
|
|
13
|
+
uri = URI.parse(url)
|
|
14
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
15
|
+
http.read_timeout = 2
|
|
16
|
+
http.open_timeout = 2
|
|
17
|
+
|
|
18
|
+
response = http.get('/_cluster/health')
|
|
19
|
+
if response.code.to_i == 200
|
|
20
|
+
health_data = JSON.parse(response.body)
|
|
21
|
+
health_data['status'] != 'red'
|
|
22
|
+
else
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
rescue StandardError => e
|
|
26
|
+
puts "ElasticSearch Connection Error: #{e.message}"
|
|
27
|
+
false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.configured? # rubocop:disable Naming/PredicateMethod
|
|
31
|
+
raise StandardError, 'Please make sure you have Elasticsearch installed' unless defined?(::Elasticsearch::Client)
|
|
32
|
+
|
|
33
|
+
'configured'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Connectors
|
|
4
|
+
# Mongodb health checker
|
|
5
|
+
class Mongodb
|
|
6
|
+
def connect
|
|
7
|
+
@client = Mongo::Client.new(
|
|
8
|
+
ENV.fetch('MONGO_DB_URI', nil) || ['localhost:27017']
|
|
9
|
+
)
|
|
10
|
+
@client.command(ping: 1)
|
|
11
|
+
true
|
|
12
|
+
rescue Mongo::Error::SocketError, Mongo::Error::NoServerAvailable
|
|
13
|
+
puts "Mongodb Connection Error: #{e.message}"
|
|
14
|
+
false
|
|
15
|
+
ensure
|
|
16
|
+
@client&.close
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.configured?
|
|
20
|
+
raise StandardError, 'Please make sure you have MongoDB installed' unless defined?(::Mongo::Client)
|
|
21
|
+
|
|
22
|
+
'configured'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Connectors
|
|
4
|
+
# Postgres health checker
|
|
5
|
+
class Postgresql
|
|
6
|
+
def connect
|
|
7
|
+
@conn = ActiveRecord::Base.connection
|
|
8
|
+
true
|
|
9
|
+
rescue ::PG::ConnectionBad
|
|
10
|
+
puts "Postgres Connection Error: #{e.message}"
|
|
11
|
+
false
|
|
12
|
+
ensure
|
|
13
|
+
@conn&.close
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.configured?
|
|
17
|
+
raise StandardError, 'Please make sure you have Postgres installed' unless defined?(::ActiveRecord::Base)
|
|
18
|
+
|
|
19
|
+
'configured'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Connectors
|
|
4
|
+
# Rabbitmq health checker
|
|
5
|
+
class Rabbitmq
|
|
6
|
+
def connect
|
|
7
|
+
@conn = ::Bunny.new
|
|
8
|
+
@conn.start
|
|
9
|
+
@channel = @conn.create_channel
|
|
10
|
+
@queue = @channel.queue('health_check', auto_delete: true)
|
|
11
|
+
@queue.publish('ping')
|
|
12
|
+
true
|
|
13
|
+
rescue ::Bunny::Exception, ::Bunny::TCPConnectionFailed, ::Bunny::PossibleAuthenticationFailureError => e
|
|
14
|
+
puts "RabbitMQ Connection Error: #{e.message}"
|
|
15
|
+
false
|
|
16
|
+
ensure
|
|
17
|
+
# Queue with auto_delete: true will be automatically deleted when connection closes.
|
|
18
|
+
@queue&.delete
|
|
19
|
+
@queue&.purge
|
|
20
|
+
@channel&.close
|
|
21
|
+
@conn&.close
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.configured?
|
|
25
|
+
raise StandardError, 'Please make sure you have RabbitMQ installed' unless defined?(::Bunny)
|
|
26
|
+
|
|
27
|
+
'configured'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Connectors
|
|
4
|
+
# Redis health checker
|
|
5
|
+
class Redis
|
|
6
|
+
def connect
|
|
7
|
+
begin
|
|
8
|
+
@redis = ::Redis.new
|
|
9
|
+
@redis.ping == 'PONG'
|
|
10
|
+
rescue Redis::CannotConnectError
|
|
11
|
+
puts "Redis Connection Error: #{e.message}"
|
|
12
|
+
false
|
|
13
|
+
ensure
|
|
14
|
+
@redis&.close
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.configured?
|
|
19
|
+
raise StandardError, 'Please make sure you have Redis installed' unless defined?(::Redis)
|
|
20
|
+
|
|
21
|
+
'configured'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Connectors
|
|
4
|
+
# Sidekiq health checker
|
|
5
|
+
class Sidekiq
|
|
6
|
+
def connect
|
|
7
|
+
::Sidekiq.redis do |r|
|
|
8
|
+
r.ping == 'PONG'
|
|
9
|
+
end
|
|
10
|
+
rescue StandardError => e
|
|
11
|
+
puts "Sidekiq Connection Error: #{e.message}"
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.configured?
|
|
16
|
+
raise StandardError, 'Please make sure you have Sidekiq installed' unless defined?(::Sidekiq)
|
|
17
|
+
|
|
18
|
+
'configured'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
module Healthier
|
|
4
4
|
# Engine
|
|
5
5
|
class ApiAuthenticator
|
|
6
|
-
attr_accessor :controller
|
|
6
|
+
attr_accessor :controller
|
|
7
7
|
|
|
8
8
|
def initialize(controller)
|
|
9
9
|
@controller = controller
|
|
10
|
-
@request = controller.request
|
|
11
10
|
end
|
|
12
11
|
|
|
13
12
|
def authenticate
|
|
@@ -17,13 +16,14 @@ module Healthier
|
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def authenticate_with_bearer_token
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
controller.authenticate_with_http_token do |token, _options|
|
|
20
|
+
ENV['HEALTHIER_BEARER_TOKEN'] == token
|
|
21
|
+
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def authenticate_with_basic_auth
|
|
25
25
|
controller.authenticate_or_request_with_http_basic do |username, password|
|
|
26
|
-
|
|
26
|
+
username == ENV['HEALTHIER_USERNAME'] && password == ENV['HEALTHIER_PASSWORD']
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Healthier
|
|
4
|
+
# Health Checker Doctor
|
|
5
|
+
class Doctor
|
|
6
|
+
SUCCESS = :success
|
|
7
|
+
FAILURE = :failure
|
|
8
|
+
|
|
9
|
+
def initialize(config = nil)
|
|
10
|
+
@config = config || Healthier.depends_on['healthier'] || {}
|
|
11
|
+
@connectors = load_connectors
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.ping!
|
|
15
|
+
new.ping
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.up?
|
|
19
|
+
new.up?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.running?
|
|
23
|
+
new.running?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def up?
|
|
27
|
+
# Basic health check - just return true for now
|
|
28
|
+
# Could be extended to check basic application health
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def running?
|
|
33
|
+
# Check if all configured services are running
|
|
34
|
+
ping.values.all? { |service_result| service_result[:status] == SUCCESS }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def ping
|
|
38
|
+
@config.fetch('depends_on', []).each_with_object({}) do |service_config, result|
|
|
39
|
+
result[service_config['name']] = diagnose(service_config)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def load_connectors
|
|
46
|
+
@config.fetch('depends_on', []).to_h do |service_config|
|
|
47
|
+
[
|
|
48
|
+
service_config['name'],
|
|
49
|
+
"::Connectors::#{service_config['name'].camelize}".constantize
|
|
50
|
+
]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def diagnose(service_config)
|
|
55
|
+
connector_class = @connectors[service_config['name']]
|
|
56
|
+
|
|
57
|
+
return custom_diagnosis(service_config) if service_config['custom_checker']
|
|
58
|
+
|
|
59
|
+
begin
|
|
60
|
+
connector = connector_class.new
|
|
61
|
+
connection_result = connector.connect
|
|
62
|
+
|
|
63
|
+
if connection_result == true
|
|
64
|
+
{
|
|
65
|
+
status: SUCCESS,
|
|
66
|
+
message: "#{service_config['name'].camelize} service is healthy"
|
|
67
|
+
}
|
|
68
|
+
else
|
|
69
|
+
{
|
|
70
|
+
status: FAILURE,
|
|
71
|
+
message: "#{service_config['name'].camelize} service is not responding"
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
rescue StandardError => e
|
|
75
|
+
{
|
|
76
|
+
status: FAILURE,
|
|
77
|
+
message: "Diagnosis failed for #{service_config['name']}: #{e.message}"
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def custom_diagnosis(service_config)
|
|
83
|
+
custom_checker = service_config['custom_checker']
|
|
84
|
+
|
|
85
|
+
if custom_checker.respond_to?(:call)
|
|
86
|
+
custom_checker.call
|
|
87
|
+
elsif custom_checker.is_a?(String)
|
|
88
|
+
connector_class = @connectors[service_config['name']]
|
|
89
|
+
connector_class.send(custom_checker)
|
|
90
|
+
else
|
|
91
|
+
{
|
|
92
|
+
status: FAILURE,
|
|
93
|
+
message: "Invalid diagnosis method for #{service_config['name']}"
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
data/lib/healthier/engine.rb
CHANGED
|
@@ -1,35 +1,28 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '
|
|
4
|
-
require_relative '../
|
|
5
|
-
require_relative '../
|
|
6
|
-
require_relative '../
|
|
3
|
+
require_relative 'doctor'
|
|
4
|
+
require_relative '../connectors/mongodb'
|
|
5
|
+
require_relative '../connectors/postgresql'
|
|
6
|
+
require_relative '../connectors/rabbitmq'
|
|
7
|
+
require_relative '../connectors/redis'
|
|
8
|
+
require_relative '../connectors/sidekiq'
|
|
9
|
+
require_relative '../connectors/elastic_search'
|
|
7
10
|
|
|
8
11
|
module Healthier
|
|
9
12
|
# Engine
|
|
10
13
|
class Engine < ::Rails::Engine
|
|
11
14
|
isolate_namespace Healthier
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def conf
|
|
20
|
-
@conf ||= Healthier.depends_on['healthier']
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def ping_it(service)
|
|
24
|
-
checked = checker(service).check
|
|
16
|
+
initializer 'healthier.after_initialize' do
|
|
17
|
+
ActiveSupport.on_load(:after_initialize) do
|
|
18
|
+
dependent_services = Healthier.depends_on.dig('healthier', 'depends_on')
|
|
19
|
+
next unless dependent_services
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def checker(service)
|
|
32
|
-
"::Checkers::#{service.camelize}Checker".constantize
|
|
21
|
+
dependent_services.each do |service_conf|
|
|
22
|
+
connector_class = "::Connectors::#{service_conf['name'].camelize}".constantize
|
|
23
|
+
connector_class.configured?
|
|
24
|
+
end
|
|
25
|
+
end
|
|
33
26
|
end
|
|
34
27
|
end
|
|
35
28
|
end
|
data/lib/healthier/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: healthier
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nima Yonten
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-12-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '6.0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '6.0'
|
|
27
|
-
description:
|
|
27
|
+
description: Healthier provides comprehensive health check endpoints (live, ready,
|
|
28
|
+
ping) for Rails applications with support for monitoring multiple backing services
|
|
29
|
+
including PostgreSQL, MongoDB, Redis, RabbitMQ, Sidekiq, and ElasticSearch. It includes
|
|
30
|
+
built-in authentication and flexible configuration options.
|
|
28
31
|
email:
|
|
29
|
-
-
|
|
32
|
+
- bugloper@hey.com
|
|
30
33
|
executables: []
|
|
31
34
|
extensions: []
|
|
32
35
|
extra_rdoc_files: []
|
|
@@ -35,28 +38,30 @@ files:
|
|
|
35
38
|
- README.md
|
|
36
39
|
- Rakefile
|
|
37
40
|
- app/controllers/healthier/application_controller.rb
|
|
38
|
-
- app/controllers/healthier/
|
|
39
|
-
- app/lib/errors/api_errors.rb
|
|
41
|
+
- app/controllers/healthier/healthier_controller.rb
|
|
40
42
|
- config/routes.rb
|
|
41
|
-
- lib/
|
|
42
|
-
- lib/
|
|
43
|
-
- lib/
|
|
44
|
-
- lib/
|
|
43
|
+
- lib/connectors/elastic_search.rb
|
|
44
|
+
- lib/connectors/mongodb.rb
|
|
45
|
+
- lib/connectors/postgresql.rb
|
|
46
|
+
- lib/connectors/rabbitmq.rb
|
|
47
|
+
- lib/connectors/redis.rb
|
|
48
|
+
- lib/connectors/sidekiq.rb
|
|
45
49
|
- lib/generators/healthier/config_generator.rb
|
|
46
50
|
- lib/healthier.rb
|
|
47
51
|
- lib/healthier/api_authenticator.rb
|
|
52
|
+
- lib/healthier/doctor.rb
|
|
48
53
|
- lib/healthier/engine.rb
|
|
49
54
|
- lib/healthier/version.rb
|
|
50
55
|
- lib/tasks/healthier_tasks.rake
|
|
51
|
-
homepage: https://github.com/
|
|
56
|
+
homepage: https://github.com/SELISEdigitalplatforms/healthier
|
|
52
57
|
licenses:
|
|
53
58
|
- MIT
|
|
54
59
|
metadata:
|
|
55
60
|
allowed_push_host: https://rubygems.org
|
|
56
|
-
homepage_uri: https://github.com/
|
|
57
|
-
source_code_uri: https://github.com/
|
|
58
|
-
changelog_uri: https://github.com/
|
|
59
|
-
rubygems_mfa_required: '
|
|
61
|
+
homepage_uri: https://github.com/SELISEdigitalplatforms/healthier
|
|
62
|
+
source_code_uri: https://github.com/SELISEdigitalplatforms/healthier
|
|
63
|
+
changelog_uri: https://github.com/SELISEdigitalplatforms/healthier
|
|
64
|
+
rubygems_mfa_required: 'false'
|
|
60
65
|
post_install_message:
|
|
61
66
|
rdoc_options: []
|
|
62
67
|
require_paths:
|
|
@@ -72,8 +77,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
72
77
|
- !ruby/object:Gem::Version
|
|
73
78
|
version: '0'
|
|
74
79
|
requirements: []
|
|
75
|
-
rubygems_version: 3.4.
|
|
80
|
+
rubygems_version: 3.4.1
|
|
76
81
|
signing_key:
|
|
77
82
|
specification_version: 4
|
|
78
|
-
summary:
|
|
83
|
+
summary: Healthier is a gem that provides a health check endpoint for your Rails application.
|
|
79
84
|
test_files: []
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Errors
|
|
4
|
-
module ApiErrors
|
|
5
|
-
def self.included(base)
|
|
6
|
-
base.class_eval do
|
|
7
|
-
rescue_from StandardError, with: :bad_request
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def bad_request(error)
|
|
12
|
-
render_error(:bad_request, error: { message: error.message })
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def render_success(status, options = {})
|
|
16
|
-
options[:success] = true
|
|
17
|
-
render json: options, status: status
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def render_error(status, options = {})
|
|
21
|
-
options[:error] = { message: I18n.t("api_errors.#{status}") } if options[:error].blank?
|
|
22
|
-
options[:success] = false
|
|
23
|
-
Rollbar.error(options[:error])
|
|
24
|
-
render json: options, status: status
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def render_silent_error(status, options = {})
|
|
28
|
-
options[:error] = { message: I18n.t("api_errors.#{status}") } if options[:error].blank?
|
|
29
|
-
options[:success] = false
|
|
30
|
-
render json: options, status: status
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Checkers
|
|
4
|
-
# Mongodb health checker
|
|
5
|
-
class MongodbChecker
|
|
6
|
-
class << self
|
|
7
|
-
def check
|
|
8
|
-
raise 'Please make sure you have Mongodb installed' unless defined?(::Mongo::Client)
|
|
9
|
-
|
|
10
|
-
begin
|
|
11
|
-
@client = Mongo::Client.new(
|
|
12
|
-
ENV.fetch('MONGO_DB_URI', nil) || ['localhost:27017'],
|
|
13
|
-
max_retries: 2,
|
|
14
|
-
retry_interval: 1
|
|
15
|
-
)
|
|
16
|
-
@client.command(ping: 1)
|
|
17
|
-
true
|
|
18
|
-
rescue Mongo::Error::SocketError, Mongo::Error::NoServerAvailable
|
|
19
|
-
false
|
|
20
|
-
ensure
|
|
21
|
-
@client&.close
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Checkers
|
|
4
|
-
# Postgres health checker
|
|
5
|
-
class PostgresqlChecker
|
|
6
|
-
class << self
|
|
7
|
-
def check
|
|
8
|
-
raise 'Please make sure you have Postgres installed' unless defined?(::ActiveRecord::Base)
|
|
9
|
-
|
|
10
|
-
begin
|
|
11
|
-
# @conn = ::PG.connect(dbname: ENV['DATABASE_NAME'])
|
|
12
|
-
# @conn.exec('SELECT 1')
|
|
13
|
-
@conn = ActiveRecord::Base.connection
|
|
14
|
-
true
|
|
15
|
-
rescue ::PG::ConnectionBad
|
|
16
|
-
false
|
|
17
|
-
ensure
|
|
18
|
-
@conn&.close
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Checkers
|
|
4
|
-
# Rabbitmq health checker
|
|
5
|
-
class RabbitmqChecker
|
|
6
|
-
class << self
|
|
7
|
-
def check
|
|
8
|
-
raise 'Please make sure you have RabbitMQ installed' unless defined?(::Bunny)
|
|
9
|
-
|
|
10
|
-
begin
|
|
11
|
-
@conn = ::Bunny.new
|
|
12
|
-
@conn.start
|
|
13
|
-
channel = @conn.create_channel
|
|
14
|
-
queue = channel.queue('health_check')
|
|
15
|
-
queue.publish('ping')
|
|
16
|
-
true
|
|
17
|
-
rescue ::Bunny::Exception, ::Bunny::TCPConnectionFailed, ::Bunny::PossibleAuthenticationFailureError
|
|
18
|
-
false
|
|
19
|
-
ensure
|
|
20
|
-
@conn&.close
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Checkers
|
|
4
|
-
# Redis health checker
|
|
5
|
-
class RedisChecker
|
|
6
|
-
class << self
|
|
7
|
-
def check
|
|
8
|
-
raise 'Please make sure you have Redis installed' unless defined?(::Redis)
|
|
9
|
-
|
|
10
|
-
begin
|
|
11
|
-
@redis = Redis.new
|
|
12
|
-
@redis.ping == 'PONG'
|
|
13
|
-
rescue Redis::CannotConnectError
|
|
14
|
-
false
|
|
15
|
-
ensure
|
|
16
|
-
@redis&.close
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|