require 'sinatra' require 'logger' require 'logjam_agent' require 'logjam_agent/middleware' require 'logjam_agent/rack/sinatra_request' require 'logjam_agent/rack/logger' require 'time_bandits' module LogjamAgent module Sinatra class Middleware def initialize(app) app_with_logging = LogjamAgent::Rack::Logger.new(app) @app = LogjamAgent::Middleware.new(app_with_logging, :sinatra) end def call(env) @app.call(env) end end module Helpers def action_name(action_name) LogjamAgent.request.fields[:action] = action_name end def logger LogjamAgent.logger end end def setup_logjam_logger log_path = ENV["APP_LOG_TO_STDOUT"].present? ? STDOUT : "#{settings.root}/log/#{LogjamAgent.environment_name}.log" logger = LogjamAgent::BufferedLogger.new(log_path) rescue LogjamAgent::BufferedLogger.new(STDERR) loglevel = settings.respond_to?(:loglevel) ? settings.loglevel : :info logger.level = ::Logger.const_get(loglevel.to_s.upcase) LogjamAgent.log_device_log_level = logger.level LogjamAgent.log_device_log_level = ::Logger::ERROR unless %i[test development].include?(settings.environment.to_sym) logger.formatter = settings.respond_to?(:logformatter) ? settings.logformatter : Logger::Formatter.new logger = ActiveSupport::TaggedLogging.new(logger) LogjamAgent.logger = logger ActiveSupport::LogSubscriber.logger = logger log_path = ENV["APP_LOG_TO_STDOUT"].present? ? STDOUT : "#{settings.root}/log/logjam_agent_error.log" forwarding_error_logger = ::Logger.new(log_path) rescue ::Logger.new(STDERR) forwarding_error_logger.level = ::Logger::ERROR forwarding_error_logger.formatter = ::Logger::Formatter.new LogjamAgent.forwarding_error_logger = forwarding_error_logger truncate_overlong_params = lambda { |key, value| max_size = LogjamAgent.max_logged_size_for(key) if value.is_a?(String) && value.size > max_size value[max_size..-1] = " ... [TRUNCATED]" end } LogjamAgent.parameter_filters << truncate_overlong_params end def self.registered(app) app.helpers Helpers LogjamAgent.environment_name = ENV['LOGJAM_ENV'] || app.settings.environment.to_s LogjamAgent.auto_detect_logged_exceptions LogjamAgent.disable! if app.settings.environment.to_sym == :test end end end # For classic apps. Sinatra.register LogjamAgent::Sinatra # We already supply a logger. Sinatra::Base.class_eval do class << self def setup_logging(builder); end end end # Patch Sinatra's render logic to compute corrected view times. module LogjamAgent module ComputeRenderTimes def render(engine, data, options = {}, locals = {}, &block) consumed_before_rendering = TimeBandits.consumed result = exception = nil duration = Benchmark.ms do begin result = super rescue => exception end end consumed_during_rendering = TimeBandits.consumed - consumed_before_rendering duration -= consumed_during_rendering raise exception if exception result ensure Thread.current.thread_variable_set( :time_bandits_completed_info, [ duration, ["Views: %.3fms" % duration.to_f], duration, "" ] ) end end end Sinatra::Base.prepend LogjamAgent::ComputeRenderTimes # Define exception, but don't do anything about it. Sneaky! module ActionDispatch module RemoteIp class IpSpoofAttackError < StandardError; end end end # Add GC time bandit TimeBandits.reset TimeBandits.add TimeBandits::TimeConsumers::GarbageCollection.instance if GC.respond_to? :enable_stats