health_check Gem

repository·master·Indexed 19 days ago

https://github.com/purple-devs/health_check

A gem for Rails 5.x and 6.x applications that provides monitoring URIs for uptime services like Pingdom, NewRelic, or Nagios. It verifies application health by checking critical resources including databases, caches, email gateways, background workers, Redis, and Elasticsearch. It supports custom health checks, IP whitelisting, Basic Authentication, and multiple response formats including plain text, JSON, and XML.

Tokens
5.8K
Snippets
22
Records
30
Agent score
66%

What's inside health_check

  1. Install the health_check gem

    master

    To add health_check to your Rails application, add the following line to your Gemfile (ideally after your Rails gems are listed):

    gem 'health_check'

    Then run bundle. Alternatively, you can install it manually via gem install health_check.

  2. How Resque health check works

    master

    The HealthCheck::ResqueHealthCheck.check method verifies the connectivity of the Resque worker system by performing a ping on the underlying Redis instance used by Resque.

    It performs the following logic:

    1. Verifies that the Resque constant is defined (requires the resque gem to be loaded).
    2. Executes ::Resque.redis.ping.
    3. Returns an empty string '' if the response is 'PONG' (indicating success).
    4. Returns an error message if the response is not 'PONG'.
    5. Catches any exceptions and reports them using create_error with the identifier 'resque-redis'.
    HealthCheck::ResqueHealthCheck.check
  3. How the Redis health check works

    master

    The HealthCheck::RedisHealthCheck.check method verifies Redis connectivity by attempting a PING command.

    • Success: If the client receives 'PONG', the check returns an empty string (indicating success).
    • Failure: If the response is not 'PONG', or if an exception is raised during the connection or ping, the check records an error associated with the 'redis' key.
    • Cleanup: The check ensures the Redis client connection is closed if it was connected, preventing connection leaks.

    Prerequisites:

    • The redis gem must be defined in the environment. If the gem is missing, the check raises a "Wrong configuration. Missing 'redis' gem" error.
    # Example of how the check is invoked internally or via the health check runner
    HealthCheck::RedisHealthCheck.check
  4. How the HealthCheck Rack middleware processes requests

    master

    The HealthCheck::MiddlewareHealthcheck middleware intercepts requests based on the configured HealthCheck.uri.

    When a matching URI is requested, the middleware performs the following logic:

    1. Security Checks: It verifies if the request IP is in the HealthCheck.origin_ip_whitelist (if configured) and checks for Basic Auth credentials if HealthCheck.basic_auth_username and HealthCheck.basic_auth_password are set.
    2. Check Categorization: It parses the URI to determine which checks to run. Checks are split into two groups:
      • Middleware Checks: These are executed immediately within the middleware using HealthCheck::Utils.process_checks.
      • Full Stack Checks: If any checks are requested that are not in the HealthCheck.middleware_checks list, the middleware passes the request down the rest of the application stack (@app.call(env)).
    3. Response Generation: Based on the file extension in the URI (e.g., .json, .xml), it returns a response containing the health status and error messages in the requested format.
  5. Configure HealthCheck URI and response formats

    master

    The middleware identifies health check requests by matching the PATH_INFO against HealthCheck.uri. You can specify the response format by adding a file extension to the URI.

    Supported Formats:

    • Plain Text: Default format (no extension).
    • JSON: Use .json extension (e.g., /health_check.json). Returns application/json.
    • XML: Use .xml extension (e.g., /health_check.xml). Returns text/xml.

    Check Selection via URI: The URI pattern follows: /{uri}(/{checks})?(.{extension})?.

    • checks are underscore-separated strings (e.g., /health_check/smtp_server_and_database).
    • The keyword and is used as a separator in the URI but is stripped before processing.
  6. Install health_check as Middleware

    master

    To ensure health_check can detect exceptions from earlier parts of the Rails middleware stack (such as database connection errors from QueryCache), install it as middleware.

    Add the following to config/application.rb:

    config.middleware.insert_after Rails::Rack::Logger, HealthCheck::MiddlewareHealthcheck

    Note: The gem is still installed as a full Rails engine even when added as middleware so that full-stack checks continue to function. You can control which checks run from the middleware layer using config.middleware_checks.

  7. Mount health check endpoints in Rails routes

    master

    To expose the health check endpoints in your Rails application, use the health_check_routes method within your config/routes.rb file. You can optionally provide a prefix to define the URI path for the health check.

    Note: The prefix should not have a leading slash. If a prefix is provided, it is assigned to HealthCheck.uri.

    Rails.application.routes.draw do
      # Mount health check routes at the root
      health_check_routes
    
      # OR mount health check routes with a specific prefix (no leading slash)
      health_check_routes 'my-app-health'
    end
  8. Configure routes for health_check

    master

    If your application uses a catch-all route, you must add the health_check_routes method above that route in config/routes.rb to ensure the health check endpoints are reachable.

    # config/routes.rb
    health_check_routes
    # ... catch-all route follows ...
  9. Configure health_check via initializer

    master

    Create a file at config/initializers/health_check.rb to customize the gem's behavior. You can configure the URI prefix, success/failure messages, log levels, authentication, and specific checks to run.

    HealthCheck.setup do |config|
      config.uri = 'health_check'
      config.success = 'success'
      config.failure = 'health_check failed'
      config.include_error_in_response_body = false
      config.log_level = 'info'
      config.smtp_timeout = 30.0
      config.http_status_for_error_text = 500
      config.http_status_for_error_object = 500
      config.buckets = {'bucket_name' => [:R, :W, :D]}
      config.standard_checks = [ 'database', 'migrations', 'custom' ]
      config.full_checks = ['database', 'migrations', 'custom', 'email', 'cache', 'redis', 'resque-redis', 'sidekiq-redis', 's3']
      config.max_age = 1
      config.basic_auth_username = 'my_username'
      config.basic_auth_password = 'my_password'
      config.origin_ip_whitelist = %w(123.123.123.123 10.11.12.0/24 2400:cb00::/32)
      config.accept_proxied_requests = false
      config.http_status_for_ip_whitelist_error = 403
      config.rabbitmq_config = {}
      config.redis_url = 'redis_url'
      config.redis_password = 'redis_password'
      config.on_failure do |checks, msg|
        # log msg somewhere
      end
      config.on_success do |checks|
        # flag that everything is well
      end
    end
  10. Configure AWS S3 for HealthCheck

    master

    The S3HealthCheck requires the aws-sdk or aws-sdk-s3 gem to be present. It relies on your existing AWS configuration. To ensure the health check works correctly, you should set the AWS region in your environment variables so the client can be initialized.

    Supported environment variables for the region:

    • AWS_REGION
    • DEFAULT_AWS_REGION

    Additionally, the implementation automatically sets force_path_style: true in the Aws.config[:s3] settings.

    # Ensure these are set in your environment
    export AWS_REGION='us-east-1'
  11. Secure HealthCheck with IP Whitelisting and Basic Auth

    master

    To prevent leaking sensitive health information or allowing unauthorized access, you can configure security constraints on the HealthCheck module:

    IP Whitelisting

    If HealthCheck.origin_ip_whitelist is configured, only requests from IPs within these ranges are permitted. If an IP is not whitelisted, the middleware returns a specific error status defined by HealthCheck.http_status_for_ip_whitelist_error.

    Basic Authentication

    If HealthCheck.basic_auth_username and HealthCheck.basic_auth_password are set, the middleware requires Basic Authentication.

    • If credentials are provided and match, env['REMOTE_USER'] is populated.
    • If credentials are missing or incorrect, the middleware returns a 401 Unauthorized response with a WWW-Authenticate header.