{"id":14658237,"url":"https://github.com/rameerez/allgood","last_synced_at":"2025-04-07T21:12:00.660Z","repository":{"id":254308981,"uuid":"846096182","full_name":"rameerez/allgood","owner":"rameerez","description":"✅ Quickly set up a health check page for your Rails app","archived":false,"fork":false,"pushed_at":"2024-11-13T00:19:47.000Z","size":189,"stargazers_count":249,"open_issues_count":1,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-31T20:09:01.584Z","etag":null,"topics":["downtime","health-check","healthcheck","kamal","performance","performance-testing","rails","ruby","ruby-on-rails","smoke-test","smoke-tests","uptime","uptime-monitor","uptime-monitoring","uptimerobot"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rameerez.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-22T14:20:18.000Z","updated_at":"2025-03-25T07:20:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"e67cfa81-8f53-4cb1-a741-1ae2efee6015","html_url":"https://github.com/rameerez/allgood","commit_stats":{"total_commits":49,"total_committers":1,"mean_commits":49.0,"dds":0.0,"last_synced_commit":"d29b5954021e92c4cd2e139f26bbf38bf7100dc8"},"previous_names":["rameerez/allgood"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameerez%2Fallgood","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameerez%2Fallgood/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameerez%2Fallgood/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameerez%2Fallgood/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rameerez","download_url":"https://codeload.github.com/rameerez/allgood/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247730068,"owners_count":20986404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["downtime","health-check","healthcheck","kamal","performance","performance-testing","rails","ruby","ruby-on-rails","smoke-test","smoke-tests","uptime","uptime-monitor","uptime-monitoring","uptimerobot"],"created_at":"2024-09-11T18:00:56.058Z","updated_at":"2025-04-07T21:12:00.641Z","avatar_url":"https://github.com/rameerez.png","language":"Ruby","readme":"# ✅ Allgood - Rails gem for health checks\n\n[![Gem Version](https://badge.fury.io/rb/allgood.svg)](https://badge.fury.io/rb/allgood)\n\nAdd quick, simple, and beautiful health checks to your Rails application via a `/healthcheck` page.\n\nUse it for smoke testing, to make sure your app is healthy and functioning as expected.\n\n![Example dashboard of the Allgood health check page](allgood.jpeg)\n\n## How it works\n\n`allgood` allows you to define custom health checks / smoke tests (as in: can the Rails app connect to the DB, are there any new users in the past 24 hours, are they actually using the app, etc.) in a very intuitive way that reads just like English.\n\nIt provides a `/healthcheck` endpoint that displays the results in a beautiful page.\n\nYou can then [use that endpoint to monitor the health of your application via UptimeRobot](https://uptimerobot.com/?rid=854006b5fe82e4), Pingdom, etc. These services will load your `/healthcheck` page every few minutes, so all checks will be run when UptimeRobot fetches the page.\n\n`allgood` aims to provide developers with peace of mind by answering the question \"is production okay?\" at a glance.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n```ruby\ngem 'allgood'\n```\n\nThen run `bundle install`.\n\nAfter installing the gem, you need to mount the `/healthcheck` route and define your health checks in a `config/allgood.rb` file.\n\n\n## Mount the `/healthcheck` route\n\nIn your `config/routes.rb` file, mount the Allgood engine:\n```ruby\nmount Allgood::Engine =\u003e '/healthcheck'\n```\n\nYou can now navigate to `/healthcheck` to see the health check results.\n\nThe `/healthcheck` page returns HTTP codes:\n - `200 OK` if all checks are successful\n - `503 Service Unavailable` error otherwise\n\nServices like UptimeRobot pick up these HTTP codes, which makes monitoring easy.\n\n**Kamal**: `allgood` can also be used as a replacement for the default `/up` Rails action, to make [Kamal](https://github.com/basecamp/kamal) check things like if the database connection is healthy when deploying your app's containers. Just change `allgood`'s mounting route to `/up` instead of `/healthcheck`, or configure Kamal to use the `allgood` route.\n\n\u003e [!TIP]\n\u003e If you're using Kamal with `allgood`, container deployment will fail if any defined checks fail, [without feedback from Kamal](https://github.com/rameerez/allgood/issues/1) on what went wrong. Your containers will just not start, and you'll get a generic error message. To avoid this, you can either keep the `allgood.rb` file very minimal (e.g., only check for active DB connection, migrations up to date, etc.) so the app deployment is likely to succeed, or you can use the default `/up` route for Kamal, and then mount `allgood` on another route for more advanced business-oriented checks. What you want to avoid is your app deployment failing because of usage-dependent or business-oriented checks, like your app not deploying because it didn't get any users in the past hour, or something like that.\n\n## Configure your health checks\n\nCreate a file `config/allgood.rb` in your Rails application. This is where you'll define your health checks. Here's a simple example:\n```ruby\n# config/allgood.rb\n\ncheck \"We have an active database connection\" do\n  make_sure ActiveRecord::Base.connection.connect!.active?\nend\n```\n\n`allgood` will run all checks upon page load, and will show \"Check passed\" or \"Check failed\" next to it. That's it – add as many health checks as you want!\n\nHere's my default `config/allgood.rb` file that should work for most Rails applications, feel free to use it as a starting point:\n\n```ruby\n# config/allgood.rb\n\ncheck \"We have an active database connection\" do\n  make_sure ActiveRecord::Base.connection.connect!.active?\nend\n\ncheck \"Database can perform a simple query\" do\n  make_sure ActiveRecord::Base.connection.execute(\"SELECT 1\").any?\nend\n\ncheck \"Database migrations are up to date\" do\n  make_sure ActiveRecord::Migration.check_all_pending! == nil\nend\n\ncheck \"Disk space usage is below 90%\" do\n  usage = `df -h / | tail -1 | awk '{print $5}' | sed 's/%//'`.to_i\n  expect(usage).to_be_less_than(90)\nend\n\ncheck \"Memory usage is below 90%\" do\n  usage = `free | grep Mem | awk '{print $3/$2 * 100.0}' | cut -d. -f1`.to_i\n  expect(usage).to_be_less_than(90)\nend\n```\n\nI've also added an example [`config/allgood.rb`](examples/allgood.rb) file in the `examples` folder, with very comprehensive checks for a Rails 8+ app, that you can use as a starting point.\n\n\u003e [!IMPORTANT]\n\u003e Make sure you restart the Rails server (`bin/rails s`) every time you modify the `config/allgood.rb` file for the changes to apply – the `allgood` config is only loaded once when the Rails server starts.\n\n### The `allgood` DSL\n\nAs you can see, there's a very simple DSL (Domain-Specific Language) you can use to define health checks.\n\nIt reads almost like natural English, and allows you to define powerful yet simple checks to make sure your app is healthy.\n\nFor example, you can specify a custom human-readable success / error message for each check, so you don't go crazy when things fail and you can't figure out what the check expected output was:\n```ruby\ncheck \"Cache is accessible and functioning\" do\n  Rails.cache.write('allgood_test', 'ok')\n  make_sure Rails.cache.read('allgood_test') == 'ok', \"The `allgood_test` key in the cache should contain `'ok'`\"\nend\n```\n\nOther than checking for an active database connection, it's useful to check for business-oriented metrics, such as whether your app has gotten any new users in the past 24 hours (to make sure your signup flow is not broken), check whether there have been any new posts / records created recently (to make sure your users are performing the actions you'd expect them to do in your app), check for recent purchases, check for external API connections, check whether new records contain values within expected range, etc.\n\nSome business health check examples that you'd need to adapt to the specifics of your particular app:\n```ruby\n# Adapt these to your app specifics\n\ncheck \"There's been new signups in the past 24 hours\" do\n  count = User.where(created_at: 24.hours.ago..Time.now).count\n  expect(count).to_be_greater_than(0)\nend\n\ncheck \"The last created Purchase has a valid total\" do\n  last_purchase = Purchase.order(created_at: :desc).limit(1).first\n  make_sure last_purchase.total.is_a?(Numeric), \"Purchase total should be a number\"\n  expect(last_purchase.total).to_be_greater_than(0)\nend\n```\n\n### Available check methods\n\n- `make_sure(condition, message = nil)`: Ensures that the given condition is true.\n- `expect(actual).to_eq(expected)`: Checks if the actual value equals the expected value.\n- `expect(actual).to_be_greater_than(expected)`: Checks if the actual value is greater than the expected value.\n- `expect(actual).to_be_less_than(expected)`: Checks if the actual value is less than the expected value.\n\nPlease help us develop by adding more expectation methods in the `Expectation` class!\n\n### Run checks only in specific environments or under certain conditions\n\nYou can also make certain checks run only in specific environments or under certain conditions. Some examples:\n\n```ruby\n# Only run in production\ncheck \"There have been new user signups in the past hour\", only: :production do\n  make_sure User.where(created_at: 1.hour.ago..Time.now).count.positive?\nend\n\n# Run in both staging and production\ncheck \"External API is responsive\", only: [:staging, :production] do\n  # ...\nend\n\n# Run everywhere except development\ncheck \"A SolidCable connection is active and healthy\", except: :development do\n  # ...\nend\n\n# Using if with a direct boolean\ncheck \"Feature flag is enabled\", if: ENV['FEATURE_ENABLED'] == 'true' do\n  # ...\nend\n\n# Using if with a Proc for more complex conditions\ncheck \"Complex condition\", if: -\u003e { User.count \u003e 1000 \u0026\u0026 User.last.created_at \u003c 10.minutes.ago } do\n  # ...\nend\n\n# Override default timeout (in seconds) for specific checks\n# By default, each check has a timeout of 10 seconds\ncheck \"Slow external API\", timeout: 30 do\n  # ...\nend\n\n# Combine multiple conditions\ncheck \"Complex check\",\n      only: :production,\n      if: -\u003e { User.count \u003e 1000 },\n      timeout: 15 do\n  # ...\nend\n```\n\n### Rate Limiting Expensive Checks\n\nFor expensive operations (like testing paid APIs), you can limit how often checks run:\n\n```ruby\n# Run expensive checks a limited number of times\ncheck \"OpenAI is responding with a valid LLM message\", run: \"2 times per day\" do\n  # expensive API call\nend\n\ncheck \"Analytics can be processed\", run: \"4 times per hour\" do\n  # expensive operation\nend\n```\n\nImportant notes:\n- Rate limits reset at the start of each period (hour/day)\n- The error state persists between rate-limited runs\n- Rate-limited checks show clear feedback about remaining runs and next reset time\n\nWhen a check is skipped due to its conditions not being met, it will appear in the healthcheck page with a skip emoji (⏭️) and a clear explanation of why it was skipped.\n\n![Example dashboard of the Allgood health check page with skipped checks](allgood_skipped.webp)\n\n_Note: the `allgood` health check dashboard has an automatic dark mode, based on the system's appearance settings._\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/rameerez/allgood. Our code of conduct is: just be nice and make your mom proud of what you do and post online.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frameerez%2Fallgood","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frameerez%2Fallgood","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frameerez%2Fallgood/lists"}