Skip to content

Commit

Permalink
Move the Grape middleware to the rack directory
Browse files Browse the repository at this point in the history
Move the Appsignal::Grape::Middleware constant to
Appsignal::Rack::GrapeMiddleware so it matches the format of some of the
other middleware we have.

Move it to the `rack/` directory as well so all the middleware are in
one place. People can still require the `appsignal/integrations/grape`
file like previously, same as we support for
`appsignal/integrations/sinatra`. The integrations file can stay to
automate or include any other things we need.
  • Loading branch information
tombruijn committed Jun 26, 2024
1 parent 519b4f4 commit 844aa0a
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 49 deletions.
18 changes: 18 additions & 0 deletions .changesets/deprecate-appsignal--grape--middleware.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
bump: patch
type: deprecate
---

Deprecate `Appsignal::Grape::Middleware` constant in favor of `Appsignal::Rack::GrapeMiddleware` constant.

To fix this deprecation warning, update the usage of `Appsignal::Grape::Middleware` like this:

```ruby
# Grape only apps
insert_before Grape::Middleware::Error, Appsignal::Rack::GrapeMiddleware
# or
use Appsignal::Rack::GrapeMiddleware

# Grape on Rails app
use Appsignal::Rack::GrapeMiddleware
```
63 changes: 16 additions & 47 deletions lib/appsignal/integrations/grape.rb
Original file line number Diff line number Diff line change
@@ -1,55 +1,24 @@
# frozen_string_literal: true

require "appsignal/rack/grape_middleware"

module Appsignal
# @todo Move to sub-namespace
# @api private
module Grape
class Middleware < ::Grape::Middleware::Base
def call(env)
if Appsignal.active?
call_with_appsignal_monitoring(env)
else
app.call(env)
end
end

def call_with_appsignal_monitoring(env)
request = ::Rack::Request.new(env)
transaction = Appsignal::Transaction.create(
SecureRandom.uuid,
Appsignal::Transaction::HTTP_REQUEST,
request
)
begin
app.call(env)
rescue Exception => error # rubocop:disable Lint/RescueException
# Do not set error if "grape.skip_appsignal_error" is set to `true`.
transaction.set_error(error) unless env["grape.skip_appsignal_error"]
raise error
ensure
request_method = request.request_method.to_s.upcase
path = request.path # Path without namespaces
endpoint = env["api.endpoint"]

if endpoint&.options
options = endpoint.options
request_method = options[:method].first.to_s.upcase
klass = options[:for]
namespace = endpoint.namespace
namespace = "" if namespace == "/"

path = options[:path].first.to_s
path = "/#{path}" if path[0] != "/"
path = "#{namespace}#{path}"

transaction.set_action_if_nil("#{request_method}::#{klass}##{path}")
end

transaction.set_http_or_background_queue_start
transaction.set_metadata("path", path)
transaction.set_metadata("method", request_method)
Appsignal::Transaction.complete_current!
end
# Alias constants that have moved with a warning message that points to the
# place to update the reference.
def self.const_missing(name)
case name
when :Middleware
callers = caller
Appsignal::Utils::StdoutAndLoggerMessage.warning \
"The constant Appsignal::Grape::Middleware has been deprecated. " \
"Please update the constant name to " \
"Appsignal::Rack::GrapeMiddleware in the following file to " \
"remove this message.\n#{callers.first}"
Appsignal::Rack::GrapeMiddleware
else
super
end
end
end
Expand Down
55 changes: 55 additions & 0 deletions lib/appsignal/rack/grape_middleware.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

module Appsignal
module Rack
# @api private
class GrapeMiddleware < ::Grape::Middleware::Base
def call(env)
if Appsignal.active?
call_with_appsignal_monitoring(env)
else
app.call(env)
end
end

def call_with_appsignal_monitoring(env)
request = ::Rack::Request.new(env)
transaction = Appsignal::Transaction.create(
SecureRandom.uuid,
Appsignal::Transaction::HTTP_REQUEST,
request
)
begin
app.call(env)
rescue Exception => error # rubocop:disable Lint/RescueException
# Do not set error if "grape.skip_appsignal_error" is set to `true`.
transaction.set_error(error) unless env["grape.skip_appsignal_error"]
raise error
ensure
request_method = request.request_method.to_s.upcase
path = request.path # Path without namespaces
endpoint = env["api.endpoint"]

if endpoint&.options
options = endpoint.options
request_method = options[:method].first.to_s.upcase
klass = options[:for]
namespace = endpoint.namespace
namespace = "" if namespace == "/"

path = options[:path].first.to_s
path = "/#{path}" if path[0] != "/"
path = "#{namespace}#{path}"

transaction.set_action_if_nil("#{request_method}::#{klass}##{path}")
end

transaction.set_http_or_background_queue_start
transaction.set_metadata("path", path)
transaction.set_metadata("method", request_method)
Appsignal::Transaction.complete_current!
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,40 @@
if DependencyHelper.grape_present?
require "appsignal/integrations/grape"

describe Appsignal::Grape::Middleware do
context "Appsignal::Grape::Middleware constant" do
let(:err_stream) { std_stream }
let(:stderr) { err_stream.read }

it "returns the Probes constant calling the Minutely constant" do
silence { expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware) }
end

it "prints a deprecation warning to STDERR" do
capture_std_streams(std_stream, err_stream) do
expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware)
end

expect(stderr).to include(
"appsignal WARNING: The constant Appsignal::Grape::Middleware has been deprecated."
)
end

it "logs a warning" do
logs =
capture_logs do
silence do
expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware)
end
end

expect(logs).to contains_log(
:warn,
"The constant Appsignal::Grape::Middleware has been deprecated."
)
end
end

describe Appsignal::Rack::GrapeMiddleware do
let(:app) do
Class.new(::Grape::API) do
format :json
Expand All @@ -17,7 +50,7 @@
"REQUEST_METHOD" => "POST",
:path => "/ping"
end
let(:middleware) { Appsignal::Grape::Middleware.new(api_endpoint) }
let(:middleware) { Appsignal::Rack::GrapeMiddleware.new(api_endpoint) }
around do |example|
GrapeExample = Module.new
GrapeExample.send(:const_set, :Api, app)
Expand Down

0 comments on commit 844aa0a

Please sign in to comment.