Skip to content

Commit 66a9d11

Browse files
authored
Silence healthcheck requests from the log (rails#52789)
* Add SilenceRequest middleware * Make config.silence_healthcheck a way to quiet "/up"
1 parent 937ae86 commit 66a9d11

File tree

9 files changed

+81
-4
lines changed

9 files changed

+81
-4
lines changed

guides/source/configuring.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,14 @@ config.session_store :my_custom_store
593593

594594
The default store is a cookie store with the application name as the session key.
595595

596+
#### `config.silence_healthcheck_path`
597+
598+
Specifies the path of the healthcheck that should be silenced in the logs. Uses `Rails::Rack::SilenceRequest` to implement the silencing. All in service of keeping healthchecks from clogging the production logs, especially for early-stage applications.
599+
600+
```
601+
config.silence_healthcheck_path = "/up"
602+
```
603+
596604
#### `config.ssl_options`
597605

598606
Configuration options for the [`ActionDispatch::SSL`](https://api.rubyonrails.org/classes/ActionDispatch/SSL.html) middleware.

railties/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
* Add Rails::Rack::SilenceRequest middleware and use it via `config.silence_healthcheck_path = path`
2+
to silence requests to "/up". This prevents the Kamal-required healthchecks from clogging up
3+
the production logs.
4+
5+
*DHH*
6+
17
* Introduce `mariadb-mysql` and `mariadb-trilogy` database options for `rails new`
28

39
When used with the `--devcontainer` flag, these options will use `mariadb` as the database for the

railties/lib/rails.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
require "rails/deprecator"
1313
require "rails/application"
1414
require "rails/backtrace_cleaner"
15+
require "rails/rack/silence_request"
1516

1617
require "active_support/railtie"
1718
require "action_dispatch/railtie"

railties/lib/rails/application/configuration.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class Configuration < ::Rails::Engine::Configuration
1515
:cache_classes, :cache_store, :consider_all_requests_local, :console,
1616
:eager_load, :exceptions_app, :file_watcher, :filter_parameters, :precompile_filter_parameters,
1717
:force_ssl, :helpers_paths, :hosts, :host_authorization, :logger, :log_formatter,
18-
:log_tags, :railties_order, :relative_url_root,
18+
:log_tags, :silence_healthcheck_path, :railties_order, :relative_url_root,
1919
:ssl_options, :public_file_server,
2020
:session_options, :time_zone, :reload_classes_only_on_change,
2121
:beginning_of_week, :filter_redirect, :x,
@@ -62,6 +62,7 @@ def initialize(*)
6262
@exceptions_app = nil
6363
@autoflush_log = true
6464
@log_formatter = ActiveSupport::Logger::SimpleFormatter.new
65+
@silence_healthcheck_path = nil
6566
@eager_load = nil
6667
@secret_key_base = nil
6768
@api_only = false

railties/lib/rails/application/default_middleware_stack.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ def build_stack
5454
middleware.use ::ActionDispatch::RequestId, header: config.action_dispatch.request_id_header
5555
middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies
5656

57+
if path = config.silence_healthcheck_path
58+
middleware.use ::Rails::Rack::SilenceRequest, path: path
59+
end
60+
5761
middleware.use ::Rails::Rack::Logger, config.log_tags
5862
middleware.use ::ActionDispatch::ShowExceptions, show_exceptions_app
5963
middleware.use ::ActionDispatch::DebugExceptions, app, config.debug_exception_response_format

railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ Rails.application.configure do
6060
# Skip http-to-https redirect for the default health check endpoint.
6161
# config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }
6262

63+
# Prevent healthchecks from clogging up the logs
64+
config.silence_healthcheck_path = "/up"
65+
6366
# Log to STDOUT by default
6467
config.logger = ActiveSupport::Logger.new(STDOUT)
6568
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
# :markup: markdown
4+
5+
require "active_support/logger_silence"
6+
7+
module Rails
8+
module Rack
9+
# Allows you to silence requests made to a specific path.
10+
# This is useful for preventing recurring requests like healthchecks from clogging the logging.
11+
# This middleware is used to do just that against the path /up in production by default.
12+
#
13+
# Example:
14+
#
15+
# config.middleware.insert_before \
16+
# Rails::Rack::Logger, Rails::Rack::SilenceRequest, path: "/up"
17+
#
18+
# This middleware can also be configured using `config.silence_healthcheck = "/up"` in Rails.
19+
class SilenceRequest
20+
def initialize(app, path:)
21+
@app, @path = app, path
22+
end
23+
24+
def call(env)
25+
if env["PATH_INFO"] == @path
26+
Rails.logger.silence { @app.call(env) }
27+
else
28+
@app.call(env)
29+
end
30+
end
31+
end
32+
end
33+
end

railties/test/commands/middleware_test.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,10 @@ def app
196196
assert_includes middleware, "ActionDispatch::AssumeSSL"
197197
end
198198

199-
test "ActionDispatch::SSL is present when force_ssl is set" do
200-
add_to_config "config.force_ssl = true"
199+
test "silence healthcheck" do
200+
add_to_config "config.silence_healthcheck_path = '/up'"
201201
boot!
202-
assert_includes middleware, "ActionDispatch::SSL"
202+
assert_includes middleware, "Rails::Rack::SilenceRequest"
203203
end
204204

205205
test "ActionDispatch::SSL is configured with options when given" do
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
require "abstract_unit"
4+
require "rack/test"
5+
require "minitest/mock"
6+
7+
class RackSilenceRequestTest < ActiveSupport::TestCase
8+
test "silence request only to specific path" do
9+
mock_logger = Minitest::Mock.new
10+
mock_logger.expect :silence, nil
11+
12+
app = Rails::Rack::SilenceRequest.new(lambda { |env| [200, env, "app"] }, path: "/up")
13+
14+
Rails.stub(:logger, mock_logger) do
15+
app.call(Rack::MockRequest.env_for("http://example.com/up"))
16+
app.call(Rack::MockRequest.env_for("http://example.com/down"))
17+
end
18+
19+
assert mock_logger.verify
20+
end
21+
end

0 commit comments

Comments
 (0)