Skip to content

Rails Health Endpoint Setup #89

@schmijos

Description

@schmijos

Quick guidance on how to setup a custom health probe would be nice, because otherwise the uptime monitoring is not continuous. This is measurement cosmetics.

Default behaviour without custom health probe
Image

Reason explained by Nick:

I checked the raw underlying metrics and it seems it happens due to the query. For memory based metrics you don’t need any fancy query functions actually. One basically requests the underlying metric container_memory_working_set_bytes and the reporting of this metric stops as soon as the container/pod was marked as ‘Terminating’. That is why there is no overlapping in the graph.

Fixed behaviour with custom health probe
Image

Change

Make code changes

# app/controllers/health_controller.rb
class HealthController < Rails::HealthController
  def up
    ActiveRecord::Base.connection.execute("SELECT 1") # Test if database is here
    render json: { status: "ok" }, status: :ok
  rescue StandardError => e
    render json: { status: "error", error: e.message }, status: :internal_server_error
  end
end

# config/routes.rb
get "/up" => "health#up"

# config/environments/production.rb
# Opt out of SSL redirection for health endpoint
config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }

# spec/requests/health_spec.rb
require "rails_helper"

RSpec.describe "Health" do
  describe "GET /up" do
    context "when the database is healthy" do
      before do
        expect(ActiveRecord::Base.connection).to receive(:execute).and_return(nil)
      end

      it "returns http success" do
        get up_path
        expect(response).to have_http_status(:ok)
        expect(response.parsed_body).to eq({ "status" => "ok" })
      end
    end

    context "when the database is unhealthy" do
      before do
        allow(ActiveRecord::Base.connection).to receive(:execute).and_raise(ActiveRecord::ConnectionNotEstablished)
      end

      it "returns http internal server error" do
        get up_path
        expect(response).to have_http_status(:internal_server_error)
        expect(response.parsed_body).to include({ "status" => "error" })
      end
    end
  end
end

Test

Deploy and visit page: example.com/up

Configure Deploio

Then setup the healthprobe (like described in https://docs.nine.ch/de/docs/deplo-io/configuration/deploio-health-probe/ )

nctl update app APP_NAME --health-probe-path="/up" --health-probe-period-seconds=5

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions