hey_doctor 1.0.0

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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +97 -0
  4. data/Rakefile +10 -0
  5. data/app/services/hey_doctor/check_application_health_service.rb +29 -0
  6. data/app/services/hey_doctor/check_database_health_service.rb +43 -0
  7. data/app/services/hey_doctor/check_redis_health_service.rb +31 -0
  8. data/lib/hey_doctor.rb +22 -0
  9. data/lib/hey_doctor/engine.rb +10 -0
  10. data/lib/hey_doctor/version.rb +5 -0
  11. data/lib/tasks/hey_doctor_tasks.rake +5 -0
  12. data/spec/dummy/Rakefile +6 -0
  13. data/spec/dummy/app/assets/config/manifest.js +1 -0
  14. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  15. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  16. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  17. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  18. data/spec/dummy/app/controllers/home_controller.rb +5 -0
  19. data/spec/dummy/app/javascript/packs/application.js +15 -0
  20. data/spec/dummy/app/jobs/application_job.rb +7 -0
  21. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  22. data/spec/dummy/app/models/application_record.rb +3 -0
  23. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  24. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  25. data/spec/dummy/bin/rails +4 -0
  26. data/spec/dummy/bin/rake +4 -0
  27. data/spec/dummy/bin/setup +33 -0
  28. data/spec/dummy/config.ru +11 -0
  29. data/spec/dummy/config/application.rb +42 -0
  30. data/spec/dummy/config/boot.rb +5 -0
  31. data/spec/dummy/config/cable.yml +10 -0
  32. data/spec/dummy/config/database.yml +21 -0
  33. data/spec/dummy/config/environment.rb +5 -0
  34. data/spec/dummy/config/environments/development.rb +66 -0
  35. data/spec/dummy/config/environments/production.rb +113 -0
  36. data/spec/dummy/config/environments/test.rb +59 -0
  37. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  38. data/spec/dummy/config/initializers/backtrace_silencers.rb +8 -0
  39. data/spec/dummy/config/initializers/cors.rb +16 -0
  40. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  41. data/spec/dummy/config/initializers/inflections.rb +16 -0
  42. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  43. data/spec/dummy/config/initializers/redis.rb +1 -0
  44. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  45. data/spec/dummy/config/locales/en.yml +33 -0
  46. data/spec/dummy/config/puma.rb +43 -0
  47. data/spec/dummy/config/routes.rb +3 -0
  48. data/spec/dummy/config/storage.yml +34 -0
  49. data/spec/dummy/db/schema.rb +18 -0
  50. data/spec/dummy/log/development.log +1693 -0
  51. data/spec/dummy/log/test.log +1258 -0
  52. data/spec/dummy/tmp/development_secret.txt +1 -0
  53. data/spec/dummy/tmp/pids/server.pid +1 -0
  54. data/spec/lib/hey_doctor/hey_doctor_spec.rb +42 -0
  55. data/spec/rails_helper.rb +27 -0
  56. data/spec/requests/health_check_spec.rb +28 -0
  57. data/spec/services/hey_doctor/check_application_health_service_spec.rb +46 -0
  58. data/spec/services/hey_doctor/check_database_health_service_spec.rb +91 -0
  59. data/spec/services/hey_doctor/check_redis_health_service_spec.rb +56 -0
  60. data/spec/spec_helper.rb +25 -0
  61. metadata +240 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '0824d2e802a96ba8586c63f1ee7a193ca8675ce69b35d73f0dcdaeebf7c5e082'
4
+ data.tar.gz: 567451703ce9ead34d72691ba51071e8c11e39c9086d5cf9cec63b5e04feca38
5
+ SHA512:
6
+ metadata.gz: f5add1a4598b39cc55c0f5b50855e1089caf5e3f5728a08988a75e98b0e4cf1fa1a98a4eeb43e286cf1234cd818ea33f0e91c8e6aed596d6cbf52dd84a4b91c9
7
+ data.tar.gz: f022c57f63cfa656aea89af82e0d85d8c57349634c73fd45a9f4c109a520774159d1f92b0d26c39ac24e414a9aeb2c990bddd317d313685457c08257691069b2
@@ -0,0 +1,20 @@
1
+ Copyright 2021 Matheus A Martins
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.
@@ -0,0 +1,97 @@
1
+ # HeyDoctor - doc c'mon man!
2
+
3
+ ![banner](banner.png)
4
+
5
+ This is a simple stack health check for rails based applications, it mounts a endpoint with the current status of database, application and redis.
6
+
7
+ ## Usage
8
+
9
+ After installing this gem it will mount a endpoint in `/_ah/health`, this will bring a response like this:
10
+
11
+ `curl localhost:8000/_ah/health`
12
+
13
+ ```json
14
+ {
15
+ "app":{
16
+ "message":"Application is running",
17
+ "success":true
18
+ },
19
+ "database":{
20
+ "message":"Database is connected",
21
+ "success":true
22
+ },
23
+ "redis":{
24
+ "message":"Redis is connected",
25
+ "success":true
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Installation
31
+
32
+ If you have a redis instance in you application add the following initializer to create a `Redis.current`, so it don't need to use global vars, or create a new connection each request:
33
+
34
+ ```ruby
35
+ # config/initializers/redis.rb
36
+
37
+ Redis.current ||= Redis.new(url: ENV['REDIS_URL'])
38
+ ```
39
+
40
+ Add this line to your application's Gemfile:
41
+
42
+ ```ruby
43
+ gem 'hey_doctor'
44
+ ```
45
+
46
+ And then execute:
47
+ ```bash
48
+ bundle install
49
+ ```
50
+
51
+ After installing the gem just mount the HealthCheck endpoint inside config.ru:
52
+
53
+ ```ruby
54
+ # config.ru
55
+
56
+ # bunch of requires here
57
+ require "hey_doctor"
58
+
59
+ map '/_ah/health' do
60
+ run HeyDoctor::Rack::HealthCheck.new
61
+ end
62
+
63
+ ...
64
+ ```
65
+
66
+ ## Developing
67
+
68
+ ```bash
69
+ docker-compose build && docker-compose up
70
+
71
+ docker-compose exec web bash
72
+
73
+ rails db:setup
74
+
75
+ rubocop -A && rspec
76
+ ```
77
+
78
+ Minimum coverage is set to 95%.
79
+
80
+ ## Releasing
81
+
82
+ Change the tag in `lib/hey_doctor/version.rb` each release using [SEMVER](https://semver.org/lang/pt-BR/).
83
+
84
+ ```bash
85
+ bundle exec rake build
86
+ # build gem in pkg/hey_doctor-TAG.gem
87
+
88
+ bundle exec rake release
89
+ # Ask for rubygems credentials and makes the release
90
+ ```
91
+ ## Contributing
92
+
93
+ Fell free to send a PR.
94
+
95
+ ## License
96
+
97
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+
5
+ APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
6
+ load 'rails/tasks/engine.rake'
7
+
8
+ load 'rails/tasks/statistics.rake'
9
+
10
+ require 'bundler/gem_tasks'
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HeyDoctor::CheckApplicationHealthService
4
+ class << self
5
+ SUCCESS = {
6
+ message: 'Application is running',
7
+ success: true
8
+ }.freeze
9
+
10
+ ERROR = {
11
+ message: 'Application down, call the firefighters',
12
+ success: false
13
+ }.freeze
14
+
15
+ def call
16
+ return SUCCESS if responding?
17
+
18
+ ERROR
19
+ end
20
+
21
+ private
22
+
23
+ def responding?
24
+ Net::HTTP.start('localhost', 8000) { |http| http.head('/') }.code == '200'
25
+ rescue StandardError
26
+ false
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HeyDoctor::CheckDatabaseHealthService
4
+ class << self
5
+ SUCCESS = {
6
+ message: 'Database is connected',
7
+ success: true
8
+ }.freeze
9
+
10
+ MIGRATION_PENDING = {
11
+ message: 'Pending migrations detected',
12
+ success: true
13
+ }.freeze
14
+
15
+ ERROR = {
16
+ message: 'Error connecting to database',
17
+ success: false
18
+ }.freeze
19
+
20
+ def call
21
+ return ERROR unless connected?
22
+ return MIGRATION_PENDING if needs_migration?
23
+
24
+ SUCCESS
25
+ end
26
+
27
+ private
28
+
29
+ def connected?
30
+ ActiveRecord::Base.connection.execute('select 1')
31
+
32
+ true
33
+ rescue ActiveRecord::StatementInvalid, ActiveRecord::NoDatabaseError
34
+ false
35
+ end
36
+
37
+ def needs_migration?
38
+ return false unless connected?
39
+
40
+ ActiveRecord::Base.connection.migration_context.needs_migration?
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HeyDoctor::CheckRedisHealthService
4
+ class << self
5
+ SUCCESS = {
6
+ message: 'Redis is connected',
7
+ success: true
8
+ }.freeze
9
+
10
+ ERROR = {
11
+ message: 'Error connecting to redis',
12
+ success: false
13
+ }.freeze
14
+
15
+ def call
16
+ return SUCCESS if connected?
17
+
18
+ ERROR
19
+ end
20
+
21
+ private
22
+
23
+ def connected?
24
+ Redis.current.get('viva_a_sociedade_alternativa')
25
+
26
+ true
27
+ rescue Redis::CannotConnectError, NameError
28
+ false
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hey_doctor/version'
4
+ require 'hey_doctor/engine'
5
+
6
+ module HeyDoctor::Rack
7
+ class HealthCheck
8
+ def call(_env)
9
+ [200, {}, [status]]
10
+ end
11
+
12
+ private
13
+
14
+ def status
15
+ {
16
+ app: ::HeyDoctor::CheckApplicationHealthService.call,
17
+ database: ::HeyDoctor::CheckDatabaseHealthService.call,
18
+ redis: ::HeyDoctor::CheckRedisHealthService.call
19
+ }.to_json
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HeyDoctor::Engine < ::Rails::Engine
4
+ isolate_namespace HeyDoctor
5
+ config.generators.api_only = true
6
+
7
+ config.generators do |generators|
8
+ generators.test_framework :rspec
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HeyDoctor
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # desc "Explaining what the task does"
3
+ # task :hey_doctor do
4
+ # # Task goes here
5
+ # end
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative "config/application"
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module ApplicationCable
2
+ class Channel < ActionCable::Channel::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ApplicationCable
2
+ class Connection < ActionCable::Connection::Base
3
+ end
4
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::API
2
+ end
@@ -0,0 +1,5 @@
1
+ class HomeController < ApplicationController
2
+ def index
3
+ render :ok, json: { funfa: 'sim' }
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require rails-ujs
14
+ //= require activestorage
15
+ //= require_tree .
@@ -0,0 +1,7 @@
1
+ class ApplicationJob < ActiveJob::Base
2
+ # Automatically retry jobs that encountered a deadlock
3
+ # retry_on ActiveRecord::Deadlocked
4
+
5
+ # Most jobs are safe to ignore if the underlying records are no longer available
6
+ # discard_on ActiveJob::DeserializationError
7
+ end
@@ -0,0 +1,4 @@
1
+ class ApplicationMailer < ActionMailer::Base
2
+ default from: 'from@example.com'
3
+ layout 'mailer'
4
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+ <style>
6
+ /* Email styles need to be inline */
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <%= yield %>
12
+ </body>
13
+ </html>
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../config/application', __dir__)
3
+ require_relative "../config/boot"
4
+ require "rails/commands"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../config/boot"
3
+ require "rake"
4
+ Rake.application.run
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ require "fileutils"
3
+
4
+ # path to your application root.
5
+ APP_ROOT = File.expand_path('..', __dir__)
6
+
7
+ def system!(*args)
8
+ system(*args) || abort("\n== Command #{args} failed ==")
9
+ end
10
+
11
+ FileUtils.chdir APP_ROOT do
12
+ # This script is a way to set up or update your development environment automatically.
13
+ # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14
+ # Add necessary setup steps to this file.
15
+
16
+ puts '== Installing dependencies =='
17
+ system! 'gem install bundler --conservative'
18
+ system('bundle check') || system!('bundle install')
19
+
20
+ # puts "\n== Copying sample files =="
21
+ # unless File.exist?('config/database.yml')
22
+ # FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
23
+ # end
24
+
25
+ puts "\n== Preparing database =="
26
+ system! 'bin/rails db:prepare'
27
+
28
+ puts "\n== Removing old logs and tempfiles =="
29
+ system! 'bin/rails log:clear tmp:clear'
30
+
31
+ puts "\n== Restarting application server =="
32
+ system! 'bin/rails restart'
33
+ end