# Phusion Passenger - http://www.modrails.com/# Copyright (c) 2010 Phusion## "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.## Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to deal# in the Software without restriction, including without limitation the rights# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:## The above copyright notice and this permission notice shall be included in# all copies or substantial portions of the Software.## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN# THE SOFTWARE.require'phusion_passenger/constants'require'digest/md5'modulePhusionPassengermoduleRails3Extensionsdefself.init!(options)if!AnalyticsLogging.install!(options)# Remove code to save memory.PhusionPassenger::Rails3Extensions.send(:remove_const,:AnalyticsLogging)PhusionPassenger.send(:remove_const,:Rails3Extensions)endendendmoduleRails3ExtensionsclassAnalyticsLogging<ActiveSupport::LogSubscriberdefself.install!(options)analytics_logger=options["analytics_logger"]returnfalseif!analytics_logger||!options["analytics"]# If the Ruby interpreter supports GC statistics then turn it on# so that the info can be logged.GC.enable_statsifGC.respond_to?(:enable_stats)subscriber=self.newAnalyticsLogging.attach_to(:action_controller,subscriber)AnalyticsLogging.attach_to(:active_record,subscriber)ifdefined?(ActiveSupport::Cache::Store)ActiveSupport::Cache::Store.instrument=trueAnalyticsLogging.attach_to(:active_support,subscriber)endifdefined?(ActionDispatch::ShowExceptions)Rails.application.middleware.insert_after(ActionDispatch::ShowExceptions,ExceptionLogger,analytics_logger)endifdefined?(ActionController::Base)ActionController::Base.class_evaldoincludeACExtensionendendifdefined?(ActiveSupport::Benchmarkable)ActiveSupport::Benchmarkable.class_evaldoincludeASBenchmarkableExtensionalias_method_chain:benchmark,:passengerendendreturntrueenddefprocess_action(event)log=Thread.current[PASSENGER_ANALYTICS_WEB_LOG]iflogview_runtime=event.payload[:view_runtime]log.message("View rendering time: #{(view_runtime*1000).to_i}")ifview_runtimeendenddefsql(event)log=Thread.current[PASSENGER_ANALYTICS_WEB_LOG]iflogname=event.payload[:name]sql=event.payload[:sql]digest=Digest::MD5.hexdigest("#{name}\0#{sql}\0#{rand}")log.measured_time_points("DB BENCHMARK: #{digest}",event.time,event.end,"#{name}\n#{sql}")endenddefcache_read(event)ifevent.payload[:hit]PhusionPassenger.log_cache_hit(nil,event.payload[:key])elsePhusionPassenger.log_cache_miss(nil,event.payload[:key])endenddefcache_fetch_hit(event)PhusionPassenger.log_cache_hit(nil,event.payload[:key])enddefcache_generate(event)PhusionPassenger.log_cache_miss(nil,event.payload[:key],event.duration*1000)endclassExceptionLoggerdefinitialize(app,analytics_logger)@app=app@analytics_logger=analytics_loggerenddefcall(env)@app.call(env)rescueException=>elog_analytics_exception(env,e)ifenv[PASSENGER_TXN_ID]raiseeendprivatedeflog_analytics_exception(env,exception)log=@analytics_logger.new_transaction(env[PASSENGER_GROUP_NAME],:exceptions,env[PASSENGER_UNION_STATION_KEY])beginrequest=ActionDispatch::Request.new(env)ifrequest.parameters['controller']controller=request.parameters['controller'].humanize+"Controller"action=request.parameters['action']endrequest_txn_id=env[PASSENGER_TXN_ID]message=exception.messagemessage=exception.to_sifmessage.empty?message=[message].pack('m')message.gsub!("\n","")backtrace_string=[exception.backtrace.join("\n")].pack('m')backtrace_string.gsub!("\n","")ifaction&&controllercontroller_action="#{controller}##{action}"elsecontroller_action=controllerendlog.message("Request transaction ID: #{request_txn_id}")log.message("Message: #{message}")log.message("Class: #{exception.class.name}")log.message("Backtrace: #{backtrace_string}")log.message("Controller action: #{controller_action}")ifcontroller_actionensurelog.closeendendendmoduleACExtensiondefprocess_action(action,*args)log=request.env[PASSENGER_ANALYTICS_WEB_LOG]ifloglog.message("Controller action: #{self.class.name}##{action_name}")log.measure("framework request processing")dosuperendelsesuperendenddefrender(*args)log=request.env[PASSENGER_ANALYTICS_WEB_LOG]ifloglog.measure("view rendering")dosuperendelsesuperendendendmoduleASBenchmarkableExtensiondefbenchmark_with_passenger(message="Benchmarking",*args)log=Thread.current[PASSENGER_ANALYTICS_WEB_LOG]ifloglog.measure("BENCHMARK: #{message}")dobenchmark_without_passenger(message,*args)doyieldendendelsebenchmark_without_passenger(message,*args)doyieldendendendendend# class AnalyticsLoggingend# module Rails3Extensionsend# module PhusionPassenger