Skip to content

Commit

Permalink
add test of rack middleware in Rails
Browse files Browse the repository at this point in the history
  • Loading branch information
tsloughter-splunk committed May 25, 2022
1 parent e13b6af commit 86b20a5
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 2 deletions.
2 changes: 0 additions & 2 deletions lib/splunk/otel/instrumentation/action_pack/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ module ActionPack
# Install the Rack middleware for RUM responses
class Railtie < ::Rails::Railtie
config.before_initialize do |app|
OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.install({})

app.middleware.insert_before(
0,
Splunk::Otel::Rack::RumMiddleware
Expand Down
1 change: 1 addition & 0 deletions splunk-otel.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
# development dependencies
spec.add_development_dependency "rubocop-rake", "~> 0.6.0"
spec.add_development_dependency "simplecov", "~> 0.21.2"
spec.add_development_dependency "rails", "~> 7.0.0"

spec.metadata = {
"rubygems_mfa_required" => "true"
Expand Down
47 changes: 47 additions & 0 deletions test/splunk/instrumentation/rails_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

require 'rails'

require "test_helper"
require "opentelemetry/sdk"
require "opentelemetry/instrumentation/rack"
require "splunk/otel"
require "splunk/otel/instrumentation/rack"
require "rack/test"
require 'test_helpers/app_config.rb'

module Splunk
class RumRailsTest < Test::Unit::TestCase
include Rack::Test::Methods

DEFAULT_RAILS_APP = AppConfig.initialize_app
::Rails.application = DEFAULT_RAILS_APP

def setup
with_env("OTEL_SERVICE_NAME" => "test-service") do
Splunk::Otel.configure do |c|
c.use 'OpenTelemetry::Instrumentation::ActionPack'
end
end
end

def teardown
OpenTelemetry.tracer_provider.shutdown
end

def app
DEFAULT_RAILS_APP
end

test "RUM response from Rack middleware" do
get "/ok"

assert last_response.ok?
assert_equal "OK", last_response.body

response_headers = last_response.headers
assert_equal "Server-Timing", response_headers["Access-Control-Expose-Headers"]
assert_match(/traceparent;desc="00-\w{32}-\w{16}-01"/, response_headers["Server-Timing"])
end
end
end
96 changes: 96 additions & 0 deletions test/test_helpers/app_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

class Application < Rails::Application; end
require 'action_controller/railtie'
require_relative 'middlewares'
require_relative 'controllers'
require_relative 'routes'

module AppConfig
extend self

def initialize_app(use_exceptions_app: false, remove_rack_tracer_middleware: false)
new_app = Application.new
new_app.config.secret_key_base = 'secret_key_base'

# Ensure we don't see this Rails warning when testing
new_app.config.eager_load = false

# Prevent tests from creating log/*.log
new_app.config.logger = Logger.new(File::NULL)

new_app.config.filter_parameters = [:param_to_be_filtered]

case Rails.version
when /^6\.0/
apply_rails_6_0_configs(new_app)
when /^6\.1/
apply_rails_6_1_configs(new_app)
when /^7\./
apply_rails_7_configs(new_app)
end

remove_rack_middleware(new_app) if remove_rack_tracer_middleware
add_exceptions_app(new_app) if use_exceptions_app
add_middlewares(new_app)

new_app.initialize!

draw_routes(new_app)

new_app
end

private

def remove_rack_middleware(application)
application.middleware.delete(
OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware
)
end

def add_exceptions_app(application)
application.config.exceptions_app = lambda do |env|
ExceptionsController.action(:show).call(env)
end
end

def add_middlewares(application)
application.middleware.insert_after(
ActionDispatch::DebugExceptions,
ExceptionRaisingMiddleware
)

application.middleware.insert_after(
ActionDispatch::DebugExceptions,
RedirectMiddleware
)
end

def apply_rails_6_0_configs(application)
# Required in Rails 6
application.config.hosts << 'example.org'
# Creates a lot of deprecation warnings on subsequent app initializations if not explicitly set.
application.config.action_view.finalize_compiled_template_methods = ActionView::Railtie::NULL_OPTION
end

def apply_rails_6_1_configs(application)
# Required in Rails 6
application.config.hosts << 'example.org'
end

def apply_rails_7_configs(application)
# Required in Rails 7
application.config.hosts << 'example.org'

# Unfreeze values which may have been frozen on previous initializations.
ActiveSupport::Dependencies.autoload_paths =
ActiveSupport::Dependencies.autoload_paths.dup
ActiveSupport::Dependencies.autoload_once_paths =
ActiveSupport::Dependencies.autoload_once_paths.dup
end
end
8 changes: 8 additions & 0 deletions test/test_helpers/controllers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

require_relative 'controllers/example_controller'
require_relative 'controllers/exceptions_controller'
17 changes: 17 additions & 0 deletions test/test_helpers/controllers/example_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

class ExampleController < ActionController::Base
include ::Rails.application.routes.url_helpers

def ok
render plain: "OK"
end

def internal_server_error
raise :internal_server_error
end
end
11 changes: 11 additions & 0 deletions test/test_helpers/controllers/exceptions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

class ExceptionsController < ActionController::Base
def show
render plain: 'oops', status: :internal_server_error
end
end
8 changes: 8 additions & 0 deletions test/test_helpers/middlewares.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

require_relative 'middlewares/exception_raising_middleware'
require_relative 'middlewares/redirect_middleware'
23 changes: 23 additions & 0 deletions test/test_helpers/middlewares/exception_raising_middleware.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

class ExceptionRaisingMiddleware
def initialize(app, _options = {})
@app = app
end

def call(env)
raise 'a little hell' if should_raise?(env)

@app.call(env)
end

private

def should_raise?(env)
env['PATH_INFO'] == '/exception' || env['QUERY_STRING'].include?('raise_in_middleware')
end
end
23 changes: 23 additions & 0 deletions test/test_helpers/middlewares/redirect_middleware.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

class RedirectMiddleware
def initialize(app, _options = {})
@app = app
end

def call(env)
return [307, {}, 'Temporary Redirect'] if should_redirect?(env)

@app.call(env)
end

private

def should_redirect?(env)
env['PATH_INFO'] == '/redirection' || env['QUERY_STRING'].include?('redirect_in_middleware')
end
end
12 changes: 12 additions & 0 deletions test/test_helpers/routes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

def draw_routes(rails_app)
rails_app.routes.draw do
get '/ok', to: 'example#ok'
get '/internal_server_error', to: 'example#internal_server_error'
end
end

0 comments on commit 86b20a5

Please sign in to comment.