509082bafb
Generating the following tags Grape#GET /projects/:id/archive from Grape::Route objects like { :path => /:version/projects/:id/archive(.:format) :version => “v3”, :method => “GET” } Use an instance variable to cache raw_path transformations. This variable is only going to growth to the number of endpoints of the API, not with exact different requests We can store this cache as an instance variable because middleware are initialised only once
70 lines
1.8 KiB
Ruby
70 lines
1.8 KiB
Ruby
module Gitlab
|
|
module Metrics
|
|
# Rack middleware for tracking Rails and Grape requests.
|
|
class RackMiddleware
|
|
CONTROLLER_KEY = 'action_controller.instance'
|
|
ENDPOINT_KEY = 'api.endpoint'
|
|
|
|
def initialize(app)
|
|
@app = app
|
|
end
|
|
|
|
# env - A Hash containing Rack environment details.
|
|
def call(env)
|
|
trans = transaction_from_env(env)
|
|
retval = nil
|
|
|
|
begin
|
|
retval = trans.run { @app.call(env) }
|
|
|
|
# Even in the event of an error we want to submit any metrics we
|
|
# might've gathered up to this point.
|
|
ensure
|
|
if env[CONTROLLER_KEY]
|
|
tag_controller(trans, env)
|
|
elsif env[ENDPOINT_KEY]
|
|
tag_endpoint(trans, env)
|
|
end
|
|
|
|
trans.finish
|
|
end
|
|
|
|
retval
|
|
end
|
|
|
|
def transaction_from_env(env)
|
|
trans = Transaction.new
|
|
|
|
trans.set(:request_uri, env['REQUEST_URI'])
|
|
trans.set(:request_method, env['REQUEST_METHOD'])
|
|
|
|
trans
|
|
end
|
|
|
|
def tag_controller(trans, env)
|
|
controller = env[CONTROLLER_KEY]
|
|
trans.action = "#{controller.class.name}##{controller.action_name}"
|
|
end
|
|
|
|
def tag_endpoint(trans, env)
|
|
endpoint = env[ENDPOINT_KEY]
|
|
path = endpoint_paths_cache[endpoint.route.route_method][endpoint.route.route_path]
|
|
trans.action = "Grape##{endpoint.route.route_method} #{path}"
|
|
end
|
|
|
|
private
|
|
|
|
def endpoint_paths_cache
|
|
@endpoint_paths_cache ||= Hash.new do |hash, http_method|
|
|
hash[http_method] = Hash.new do |inner_hash, raw_path|
|
|
inner_hash[raw_path] = endpoint_instrumentable_path(raw_path)
|
|
end
|
|
end
|
|
end
|
|
|
|
def endpoint_instrumentable_path(raw_path)
|
|
raw_path.sub('(.:format)', '').sub('/:version', '')
|
|
end
|
|
end
|
|
end
|
|
end
|