1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00
puma--puma/lib/mongrel/debug.rb
zedshaw e1d9c729c1 Finally a solution to the damn memory leak. It's a leak in ruby http://pastie.caboo.se/10194 which is fixed with http://pastie.caboo.se/10317
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@335 19e92222-5c0b-0410-8929-a290d50e31e9
2006-08-26 03:05:05 +00:00

201 lines
5 KiB
Ruby

# Copyright (c) 2005 Zed A. Shaw
# You can redistribute it and/or modify it under the same terms as Ruby.
#
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
# for more information.
require 'logger'
require 'set'
require 'socket'
$mongrel_debugging=true
module MongrelDbg
SETTINGS = { :tracing => {}}
LOGGING = { }
def MongrelDbg::configure(log_dir = File.join("log","mongrel_debug"))
Dir.mkdir(log_dir) if not File.exist?(log_dir)
@log_dir = log_dir
$objects_out=open(File.join("log","mongrel_debug","objects.log"),"w")
$objects_out.puts "run,classname,last,count,delta,lenmean,lensd,lenmax"
$objects_out.sync = true
$last_stat = nil
$run_count = 0
end
def MongrelDbg::trace(target, message)
if SETTINGS[:tracing][target] and LOGGING[target]
LOGGING[target].log(Logger::DEBUG, message)
end
end
def MongrelDbg::begin_trace(target)
SETTINGS[:tracing][target] = true
if not LOGGING[target]
LOGGING[target] = Logger.new(File.join(@log_dir, "#{target.to_s}.log"))
end
MongrelDbg::trace(target, "TRACING ON #{Time.now}")
end
def MongrelDbg::end_trace(target)
SETTINGS[:tracing][target] = false
MongrelDbg::trace(target, "TRACING OFF #{Time.now}")
LOGGING[target].close
LOGGING[target] = nil
end
def MongrelDbg::tracing?(target)
SETTINGS[:tracing][target]
end
end
$open_files = {}
class IO
alias_method :orig_open, :open
alias_method :orig_close, :close
def open(*arg, &blk)
$open_files[self] = args.inspect
orig_open(*arg,&blk)
end
def close(*arg,&blk)
$open_files.delete self
orig_close(*arg,&blk)
end
end
module Kernel
alias_method :orig_open, :open
def open(*arg, &blk)
$open_files[self] = arg[0]
orig_open(*arg,&blk)
end
def log_open_files
open_counts = {}
$open_files.each do |f,args|
open_counts[args] ||= 0
open_counts[args] += 1
end
MongrelDbg::trace(:files, open_counts.to_yaml)
end
end
module RequestLog
# Just logs whatever requests it gets to STDERR (which ends up in the mongrel
# log when daemonized).
class Access < GemPlugin::Plugin "/handlers"
include Mongrel::HttpHandlerPlugin
def process(request,response)
p = request.params
STDERR.puts "#{p['REMOTE_ADDR']} - [#{Time.now.httpdate}] \"#{p['REQUEST_METHOD']} #{p["REQUEST_URI"]} HTTP/1.1\""
end
end
class Files < GemPlugin::Plugin "/handlers"
include Mongrel::HttpHandlerPlugin
def process(request, response)
MongrelDbg::trace(:files, "#{Time.now} FILES OPEN BEFORE REQUEST #{request.params['PATH_INFO']}")
log_open_files
end
end
# stolen from Robert Klemme
class Objects < GemPlugin::Plugin "/handlers"
include Mongrel::HttpHandlerPlugin
def process(request,response)
begin
stats = Hash.new(0)
lengths = {}
ObjectSpace.each_object do |o|
begin
if o.respond_to? :length
len = o.length
lengths[o.class] ||= Stats.new(o.class)
lengths[o.class].sample(len)
end
rescue Object
end
stats[o.class] += 1
end
stats.sort {|(k1,v1),(k2,v2)| v2 <=> v1}.each do |k,v|
if $last_stat
delta = v - $last_stat[k]
if v > 10 and delta != 0
if lengths[k]
$objects_out.printf "%d,%s,%d,%d,%d,%f,%f,%f\n", $run_count, k, $last_stat[k], v, delta,lengths[k].mean,lengths[k].sd,lengths[k].max
else
$objects_out.printf "%d,%s,%d,%d,%d,,,\n", $run_count, k, $last_stat[k], v, delta
end
end
end
end
$run_count += 1
$last_stat = stats
rescue Object
STDERR.puts "object.log ERROR: #$!"
end
end
end
class Params < GemPlugin::Plugin "/handlers"
include Mongrel::HttpHandlerPlugin
def process(request, response)
MongrelDbg::trace(:rails, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
MongrelDbg::trace(:rails, request.params.to_yaml)
end
end
class Threads < GemPlugin::Plugin "/handlers"
include Mongrel::HttpHandlerPlugin
def process(request, response)
MongrelDbg::trace(:threads, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
ObjectSpace.each_object do |obj|
begin
if obj.class == Mongrel::HttpServer
worker_list = obj.workers.list
if worker_list.length > 0
keys = "-----\n\tKEYS:"
worker_list.each {|t| keys << "\n\t\t-- #{t}: #{t.keys.inspect}" }
end
MongrelDbg::trace(:threads, "#{obj.host}:#{obj.port} -- THREADS: #{worker_list.length} #{keys}")
end
rescue Object
# ignore since obj.class can sometimes take parameters
end
end
end
end
end
END {
MongrelDbg::trace(:files, "FILES OPEN AT EXIT")
log_open_files
}