middleware_healthcheck 0.2.1

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: 38b91fef5d4a3905b2813f39042c793f360204d0b9c628f4f924d659ff192a2d
4
+ data.tar.gz: e147717615b025caeea300ad09aaf6d340018b28a740f61cd818a7f38e7fdfd1
5
+ SHA512:
6
+ metadata.gz: bffd5928ca999c46a20c7d6af18302899818b0b91aad1e6a2d5040bb02c28bb3d94d191febdf20376e820407b3785d22d03b63177275c1614c7265d8bdff5f24
7
+ data.tar.gz: b5798095104d400611081987408e5e4b19f1f2f4c3f13de21ab010c71d0746fe20d77497f434562d7280fec3adc449ae03d2ff4839a1302a36db7d34093480cc
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Adam Wieczorkowski
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # MiddlewareHealthcheck
2
+
3
+ ## Installation
4
+ Add this line to your application's Gemfile:
5
+ ```ruby
6
+ gem 'middleware_healthcheck'
7
+ ```
8
+
9
+ And then execute:
10
+ ```bash
11
+ $ bundle
12
+ ```
13
+
14
+ Or install it yourself as:
15
+ ```bash
16
+ $ gem install middleware_healthcheck
17
+ ```
18
+
19
+ ## Usage
20
+ Run basic check (without running any advanced checkers):
21
+ ```
22
+ /healthcheck
23
+ ```
24
+
25
+ To run all available checkers, add `full` parameter:
26
+ ```
27
+ /healthcheck?full=1
28
+ ```
29
+
30
+ To run selected checkers, add `checks` parameter, where the value is the name of checkers separated by a comma:
31
+ ```
32
+ /healthcheck?checks=active_record,second_checker,another_checker
33
+ ```
34
+
35
+ To change default path and parameters see Configuration section
36
+
37
+ ## Configuration
38
+ Create ``config/initializers/middleware_healthcheck.rb`` file
39
+ ```ruby
40
+ MiddlewareHealthcheck.configure do |config|
41
+ config.healthcheck_path = "my_custom_path"
42
+ ...
43
+ end
44
+ ```
45
+ Available options:
46
+ ```
47
+ healthcheck_path
48
+ full_check_param_name
49
+ selected_check_param_name
50
+ error_response_status
51
+ success_response_status
52
+ success_response_body
53
+ errors_delimiter
54
+ selected_check_param_split_delimiter
55
+ ```
56
+
57
+ ## Custom Checkers
58
+ Your Custom Checker class should look like this:
59
+ ```ruby
60
+ class MyCustomChecker
61
+ attr_accessor :error
62
+
63
+ def initialize(_app, _env)
64
+ end
65
+
66
+ def healthy?
67
+ if everything_ok?
68
+ true
69
+ else
70
+ self.error = 'Error message'
71
+ false
72
+ end
73
+ end
74
+ end
75
+ ```
76
+
77
+ To include Custom Checker, just add
78
+ ```ruby
79
+ HealthcheckMiddleware.configure do |config|
80
+ config.checkers << MyCustomChecker
81
+ end
82
+ ```
83
+ in initializer.
84
+
85
+ ## Development
86
+
87
+ ```
88
+ # build the docker containers
89
+ docker-compose build
90
+
91
+ # run the specs
92
+ docker-compose run --rm app bundle exec rspec
93
+
94
+ ```
95
+
96
+ ## License
97
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'MiddlewareHealthcheck'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
@@ -0,0 +1,19 @@
1
+ require "middleware_healthcheck/rails" if defined? Rails::Railtie
2
+ require "middleware_healthcheck/default_checkers"
3
+ require "middleware_healthcheck/configuration"
4
+ require "middleware_healthcheck/main_checker"
5
+ require "middleware_healthcheck/middleware"
6
+
7
+ module MiddlewareHealthcheck
8
+ class << self
9
+ attr_accessor :configuration
10
+
11
+ def configuration
12
+ @configuration ||= Configuration.new
13
+ end
14
+
15
+ def configure
16
+ yield configuration
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module MiddlewareHealthcheck
2
+ class Configuration
3
+ DEFAULT_HEALTHCHECK_PATH = '/healthcheck'.freeze
4
+ DEFAULT_FULL_CHECK_PARAM_NAME = 'full'.freeze
5
+ DEFAULT_SELECTED_CHECK_PARAM_NAME = 'checks'.freeze
6
+ DEFAULT_ERROR_RESPONSE_STATUS = 422
7
+ DEFAULT_SUCCESS_RESPONSE_STATUS = 200
8
+ DEFAULT_SUCCESS_RESPONSE_BODY = "It's alive!".freeze
9
+ DEFAULT_ERRORS_DELIMITER = '; '.freeze
10
+ DEFAULT_SELECTED_CHECK_PARAM_SPLIT_DELIMITER = ','.freeze
11
+
12
+ attr_accessor :healthcheck_path, :full_check_param_name, :selected_check_param_name,
13
+ :error_response_status, :success_response_status, :success_response_body,
14
+ :errors_delimiter, :selected_check_param_split_delimiter, :checkers
15
+
16
+ def initialize
17
+ self.healthcheck_path = DEFAULT_HEALTHCHECK_PATH
18
+ self.full_check_param_name = DEFAULT_FULL_CHECK_PARAM_NAME
19
+ self.selected_check_param_name = DEFAULT_SELECTED_CHECK_PARAM_NAME
20
+ self.error_response_status = DEFAULT_ERROR_RESPONSE_STATUS
21
+ self.success_response_status = DEFAULT_SUCCESS_RESPONSE_STATUS
22
+ self.success_response_body = DEFAULT_SUCCESS_RESPONSE_BODY
23
+ self.errors_delimiter = DEFAULT_ERRORS_DELIMITER
24
+ self.selected_check_param_split_delimiter = DEFAULT_SELECTED_CHECK_PARAM_SPLIT_DELIMITER
25
+ self.checkers = MiddlewareHealthcheck::DefaultCheckers.constants.map do |const|
26
+ klass = MiddlewareHealthcheck::DefaultCheckers.const_get(const)
27
+ klass if klass.is_a? Class
28
+ end.compact
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ if defined? ActiveRecord::Railtie
2
+ require "middleware_healthcheck/default_checkers/active_record_checker"
3
+ end
4
+
5
+ module MiddlewareHealthcheck
6
+ module DefaultCheckers
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ module MiddlewareHealthcheck
2
+ module DefaultCheckers
3
+ class ActiveRecordChecker
4
+ NOT_CONNECTED_ERROR = "Can't connect to database.".freeze
5
+ EXCEPTION_REGEXP = /^ActiveRecord::/.freeze
6
+
7
+ attr_accessor :error
8
+
9
+ def initialize(_app, _env)
10
+ end
11
+
12
+ def healthy?
13
+ ActiveRecord::Base.establish_connection
14
+ ActiveRecord::Base.connection
15
+ if ActiveRecord::Base.connected?
16
+ true
17
+ else
18
+ self.error = NOT_CONNECTED_ERROR
19
+ false
20
+ end
21
+ rescue => e
22
+ if e.class.to_s.match EXCEPTION_REGEXP
23
+ self.error = e.message
24
+ false
25
+ else
26
+ raise e
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,103 @@
1
+ module MiddlewareHealthcheck
2
+ class MainChecker
3
+ QUERY_STRING_KEY = "QUERY_STRING".freeze
4
+ UNDEFINED_CHECKER_ERROR = "Can't find checker: ".freeze
5
+
6
+ attr_accessor :app, :env
7
+
8
+ def initialize(app, env)
9
+ self.app = app
10
+ self.env = env
11
+ end
12
+
13
+ def check_health
14
+ if full_check?
15
+ run_all_checkers
16
+ elsif selected_check?
17
+ run_selected_checkers
18
+ end
19
+
20
+ build_response
21
+ end
22
+
23
+ def build_response
24
+ if errors.present?
25
+ build_error_response
26
+ else
27
+ build_success_response
28
+ end
29
+ end
30
+
31
+ def build_success_response
32
+ build_text_response(
33
+ configuration.success_response_status,
34
+ configuration.success_response_body
35
+ )
36
+ end
37
+
38
+ def build_error_response
39
+ build_text_response(
40
+ configuration.error_response_status,
41
+ errors.join(configuration.errors_delimiter)
42
+ )
43
+ end
44
+
45
+ def build_text_response(status, body)
46
+ [ status, { "Content-Type" => "text/plain" }, [body] ]
47
+ end
48
+
49
+ def run_all_checkers
50
+ run_checkers(configuration.checkers)
51
+ end
52
+
53
+ def run_selected_checkers
54
+ run_checkers(selected_checkers)
55
+ end
56
+
57
+
58
+ def run_checkers(checkers)
59
+ checkers.each do |checker|
60
+ checker_instance = checker.new(@app, @env)
61
+ errors.push(checker_instance.error) unless checker_instance.healthy?
62
+ end
63
+ end
64
+
65
+ def selected_checkers
66
+ selected_checkers_names.map do |checker_name|
67
+ find_checker_by_name(checker_name)
68
+ end.compact
69
+ end
70
+
71
+ def find_checker_by_name(name)
72
+ configuration.checkers.each do |checker|
73
+ return checker if checker.to_s.demodulize.underscore.gsub(/_checker$/, '') == name
74
+ end
75
+ errors.push(UNDEFINED_CHECKER_ERROR + name.camelize)
76
+ nil
77
+ end
78
+
79
+ def selected_checkers_names
80
+ @selected_check_param_names ||= params[configuration.selected_check_param_name]
81
+ .split(configuration.selected_check_param_split_delimiter)
82
+ end
83
+
84
+ def params
85
+ @params ||= Rack::Utils.parse_nested_query(@env[QUERY_STRING_KEY])
86
+ end
87
+
88
+ def errors
89
+ @errors ||= []
90
+ end
91
+
92
+ def full_check?
93
+ params[configuration.full_check_param_name].present?
94
+ end
95
+ def selected_check?
96
+ params[configuration.selected_check_param_name].present?
97
+ end
98
+
99
+ def configuration
100
+ @configuration ||= MiddlewareHealthcheck.configuration
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,17 @@
1
+ module MiddlewareHealthcheck
2
+ class Middleware
3
+ PATH_INFO_KEY = "PATH_INFO".freeze
4
+
5
+ def initialize(app)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ if env[PATH_INFO_KEY] == MiddlewareHealthcheck.configuration.healthcheck_path
11
+ MainChecker.new(@app, env).check_health
12
+ else
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module MiddlewareHealthcheck
2
+ class Railtie < Rails::Railtie
3
+ initializer "middleware_healthcheck.configure_rails_initialization" do
4
+ app.middleware.insert_after Rails::Rack::Logger, MiddlewareHealthcheck::Middleware
5
+ end
6
+
7
+ def app
8
+ Rails.application
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module MiddlewareHealthcheck
2
+ VERSION = '0.2.1'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :middleware_healthcheck do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleware_healthcheck
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Adam Wieczorkowski
8
+ - Claudio Perez Gamayo
9
+ - Jan Wieczorkowski
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2019-03-21 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '4.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '4.0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: sqlite3
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rspec-rails
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: pry-byebug
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ description: Rack middleware to provide a healthcheck endpoint, useful for load balancers
72
+ health checks.
73
+ email:
74
+ - adam.wieczorkowski@naturaily.com
75
+ - claudio@firefield.com
76
+ - jan.wieczorkowski@naturaily.com
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - MIT-LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - lib/middleware_healthcheck.rb
85
+ - lib/middleware_healthcheck/configuration.rb
86
+ - lib/middleware_healthcheck/default_checkers.rb
87
+ - lib/middleware_healthcheck/default_checkers/active_record_checker.rb
88
+ - lib/middleware_healthcheck/main_checker.rb
89
+ - lib/middleware_healthcheck/middleware.rb
90
+ - lib/middleware_healthcheck/rails.rb
91
+ - lib/middleware_healthcheck/version.rb
92
+ - lib/tasks/middleware_healthcheck_tasks.rake
93
+ homepage: ''
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 3.0.1
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Rack middleware to provide a healthcheck endpoint.
116
+ test_files: []