Skip to content

Commit 1c08eeb

Browse files
author
Arne De Herdt
committed
[CIOPS-1085] Silence log requests
This pull request introduces the silencing of the Rack and Rails logger for the endpoint. By default we will not log any of the requests to not spam the output and log files with repeated simple checks. There is an option to enable to when desired.
1 parent 9dbf155 commit 1c08eeb

File tree

9 files changed

+141
-2
lines changed

9 files changed

+141
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Is It Ready? CHANGELOG
22

3+
## 0.0.5
4+
* Silence Rails and the Rack middleware by default
5+
* Add an option to allow logging of requests
6+
37
## 0.0.4
48
* Add support for HTTP Authorization Bearer tokens
59

lib/is_it_ready.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# frozen_string_literal: true
22

3+
require 'is_it_ready/log_silencer'
34
require "is_it_ready/engine"
45

56
# The namespace holding everything related to our Gem.
@@ -19,4 +20,9 @@ module IsItReady
1920
# When enabled however, the request will need to provide the required token as a Bearer value
2021
# in the AUTHORIZATION header of the request.
2122
mattr_accessor :bearer_token
23+
24+
# Silences the logging of the request against the endpoint. Defaults to true.
25+
# When disabled, the entire request will appear in the Rails logs.
26+
mattr_accessor :silence_logs
27+
@@silence_logs = true
2228
end

lib/is_it_ready/engine.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,11 @@ class Engine < ::Rails::Engine
1414
mount ::IsItReady::Engine => ::IsItReady.endpoint
1515
end
1616
end
17+
18+
# If the user has enabled the silencing of the loggers, we will mount the middleware
19+
# to do so, otherwise skip the process entirely.
20+
initializer 'is_it_ready.add_middleware' do |app|
21+
app.middleware.insert_before(::Rails::Rack::Logger, ::IsItReady::LogSilencer, silenced: ::IsItReady.endpoint)
22+
end
1723
end
1824
end

lib/is_it_ready/log_silencer.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# frozen_string_literal: true
2+
3+
module IsItReady
4+
# This class is a Rack::Middleware implementation that will support us in silencing the
5+
# logging of calls for incoming requests against the endpoint. Otherwise the app would be
6+
# writing all requests in the Rails logs, causing an overload of information to be reported
7+
# that's simply not relevant. The usage of this Middleware can be controlled through the Engine's
8+
# configuration on whether to silence logging or not.
9+
class LogSilencer
10+
# Creates a new instance of the Middleware and initializes it using the Rack standard approach
11+
# for setting up the required values in a Rack::Middleware.
12+
def initialize(app, opts = {})
13+
@silenced = opts.delete(:silenced)
14+
@app = app
15+
end
16+
17+
# Executes the Middleware.
18+
# If the environment contains the special X-SILENCE-LOGGER header to globally silence the request,
19+
# or the path matches the provided silence configuration, the middleware will silence Rails for the
20+
# request, otherwise pass the request along.
21+
def call(env)
22+
if ::IsItReady.silence_logs && silence_path?(env['PATH_INFO'])
23+
::Rails.logger.silence do
24+
@app.call(env)
25+
end
26+
else
27+
@app.call(env)
28+
end
29+
end
30+
31+
private
32+
33+
# Returns true when the given path needs to be silenced.
34+
# This uses a manual Regex check, since the .match? method might not exist depending on the Ruby
35+
# version that's being used for this gem. So we perform a manual match and return true if there's
36+
# a 0 response.
37+
def silence_path?(path)
38+
(path =~ /#{@silenced}/).present?
39+
end
40+
end
41+
end

lib/is_it_ready/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module IsItReady
4-
VERSION = '0.0.4'
4+
VERSION = '0.0.5'
55
end

test/integration/custom_navigation_test.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
require 'test_helper'
22

33
module IsItReady
4+
# This test verifies whether the Engine respects the dynamic configuration of the endpoint,
5+
# allowing it to be dynamically loaded when Rails loads the configuration, ensuring that we can
6+
# mount the engine using a custom path when required.
47
class CustomNavigationTest < ActionDispatch::IntegrationTest
58
include Engine.routes.url_helpers
69

710
setup do
811
::IsItReady.endpoint = '/something_else'
9-
Rails.application.reload_routes!
12+
::Rails.application.reload_routes!
13+
end
14+
15+
teardown do
16+
::IsItReady.endpoint = ::IsItReady::DEFAULT_PATH
17+
::Rails.application.reload_routes!
1018
end
1119

1220
test('it returns the correct response status on the root') do

test/integration/logging_test.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
module IsItReady
6+
# This class tests whether the ::Rails.logger is properly enabled during the execution of the Rails.engine.
7+
# By default silencing of the incoming requests on the health check is disabled to avoid the Rails logs
8+
# from being spammed with the repeated health checks. With this test, we check whether the Engine
9+
# respects the configuration at runtime.
10+
class SilentLoggingTest < ::ActionDispatch::IntegrationTest
11+
include Engine.routes.url_helpers
12+
include ::LoggerIntrospection
13+
14+
setup do
15+
::IsItReady.endpoint = ::IsItReady::DEFAULT_PATH
16+
::IsItReady.silence_logs = false
17+
end
18+
19+
teardown do
20+
::IsItReady.silence_logs = true
21+
end
22+
23+
test('it writes the request to the standard Rails logger') do
24+
with_logger_introspection do |logger_output|
25+
get root_url
26+
27+
assert_match(/Started GET "#{::IsItReady.endpoint}\/" for 127.0.0.1 at */, logger_output.string)
28+
end
29+
end
30+
end
31+
end
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 'test_helper'
4+
5+
module IsItReady
6+
# This class tests whether the ::Rails.logger is properly silenced during the execution of the Rails.engine.
7+
# By default silencing of the incoming requests on the health check is disabled to avoid the Rails logs
8+
# from being spammed with the repeated health checks.
9+
class SilentLoggingTest < ::ActionDispatch::IntegrationTest
10+
include Engine.routes.url_helpers
11+
include ::LoggerIntrospection
12+
13+
test('it does not write anything to the standard Rails logger') do
14+
with_logger_introspection do |logger_output|
15+
get root_url
16+
17+
refute_match(/Started GET "#{::IsItReady.endpoint}" for 127.0.0.1 at */, logger_output.string)
18+
end
19+
end
20+
end
21+
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
# This module contains methods that can be used in tests to perform introspection on the Rails logger.
4+
# This allows us to wrap some support functionality inside our tests and check whether certain behavior
5+
# is implemented correctly without overloading the test itself.
6+
module LoggerIntrospection
7+
# Performs introspection on the ::Rails.logger with the given block inside the test.
8+
# The method will duplicate the original logger, and replace the logger with a simple StringIO object.
9+
# All log entries are then made available in the object, and after the test the logger is restored
10+
# to the original functionality to not affect other tests.
11+
def with_logger_introspection(&block)
12+
original_logger = ::Rails.logger.dup
13+
@logger_output = ::StringIO.new
14+
15+
begin
16+
::Rails.logger = ::ActiveSupport::Logger.new(@logger_output)
17+
block.call(@logger_output)
18+
ensure
19+
::Rails.logger = original_logger
20+
end
21+
end
22+
end

0 commit comments

Comments
 (0)