mirror of
https://github.com/samsonjs/grape_logging.git
synced 2026-03-25 08:55:47 +00:00
152 lines
3.6 KiB
Ruby
152 lines
3.6 KiB
Ruby
require 'grape'
|
|
|
|
module GrapeLogging
|
|
module Middleware
|
|
class RequestLogger < Grape::Middleware::Base
|
|
|
|
ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
|
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
GrapeLogging::Timings.append_db_runtime(event)
|
|
end if defined?(ActiveRecord)
|
|
|
|
# Persist response status & response (body)
|
|
# to use int in parameters
|
|
attr_accessor :response_status, :response_body
|
|
|
|
def initialize(app, options = {})
|
|
super
|
|
|
|
@included_loggers = @options[:include] || []
|
|
@reporter = if options[:instrumentation_key]
|
|
Reporters::ActiveSupportReporter.new(@options[:instrumentation_key])
|
|
else
|
|
Reporters::LoggerReporter.new(@options[:logger], @options[:formatter], @options[:log_level])
|
|
end
|
|
end
|
|
|
|
def before
|
|
reset_db_runtime
|
|
start_time
|
|
invoke_included_loggers(:before)
|
|
end
|
|
|
|
def after(status, response)
|
|
stop_time
|
|
|
|
# Response status
|
|
@response_status = status
|
|
@response_body = response
|
|
|
|
# Perform reporters
|
|
@reporter.perform(collect_parameters)
|
|
|
|
# Invoke loggers
|
|
invoke_included_loggers(:after)
|
|
nil
|
|
end
|
|
|
|
# Call stack and parse responses & status.
|
|
#
|
|
# @note Exceptions are logged as 500 status & re-raised.
|
|
def call!(env)
|
|
@env = env
|
|
|
|
# Before hook
|
|
before
|
|
|
|
# Catch error
|
|
error = catch(:error) do
|
|
@app_response = @app.call(@env)
|
|
nil
|
|
rescue StandardError => e
|
|
# Log as 500 + message
|
|
after(e.respond_to?(:status) ? e.status : 500, e.message)
|
|
|
|
# Re-raise exception
|
|
raise e
|
|
end
|
|
|
|
# Get status & response from app_response
|
|
# when no error occurs.
|
|
if error
|
|
# Call with error & response
|
|
after(error[:status], error[:message])
|
|
|
|
# Throw again
|
|
throw(:error, error)
|
|
else
|
|
status, _, resp = *@app_response
|
|
|
|
# Call after hook properly
|
|
after(status, resp)
|
|
end
|
|
|
|
# Otherwise return original response
|
|
@app_response
|
|
end
|
|
|
|
protected
|
|
|
|
def parameters
|
|
{
|
|
status: response_status,
|
|
time: {
|
|
total: total_runtime,
|
|
db: db_runtime,
|
|
view: view_runtime
|
|
},
|
|
method: request.request_method,
|
|
path: request.path,
|
|
params: request.params,
|
|
host: request.host
|
|
}
|
|
end
|
|
|
|
private
|
|
|
|
def request
|
|
@request ||= ::Rack::Request.new(@env)
|
|
end
|
|
|
|
def total_runtime
|
|
((stop_time - start_time) * 1000).round(2)
|
|
end
|
|
|
|
def view_runtime
|
|
(total_runtime - db_runtime).round(2)
|
|
end
|
|
|
|
def db_runtime
|
|
GrapeLogging::Timings.db_runtime.round(2)
|
|
end
|
|
|
|
def reset_db_runtime
|
|
GrapeLogging::Timings.reset_db_runtime
|
|
end
|
|
|
|
def start_time
|
|
@start_time ||= Time.now
|
|
end
|
|
|
|
def stop_time
|
|
@stop_time ||= Time.now
|
|
end
|
|
|
|
def collect_parameters
|
|
parameters.tap do |params|
|
|
@included_loggers.each do |logger|
|
|
params.merge! logger.parameters(request, response_body) do |_, oldval, newval|
|
|
oldval.respond_to?(:merge) ? oldval.merge(newval) : newval
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def invoke_included_loggers(method_name)
|
|
@included_loggers.each do |logger|
|
|
logger.send(method_name) if logger.respond_to?(method_name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|