听老歌 发表于 2011-10-24 11:07

RUBY中保存异常现场

RUBY中保存异常现场


无法接触到服务器,但有些问题需要异常的数据,虽然可以在抛出异常时把数据给手动打印到日记,感觉太麻烦了

记得有看豆瓣的架构时,有提到他们在发生异常时,会把当时的所有变量都打印到日记里,方便调试.

在RUBY中实现这个也不难,稍微有点难的是本地变量的保存

实例变量已经在RAILS已经有现在的实现了

引用
http://apidock.com/rails/Object/instance_values


Ruby代码1.# File activesupport/lib/active_support/core_ext/object/instance_variables.rb, line 12   
2.def instance_values #:nodoc:   
3.    Hash, instance_variable_get(name)] }]   
4.end
# File activesupport/lib/active_support/core_ext/object/instance_variables.rb, line 12
def instance_values #:nodoc:
    Hash, instance_variable_get(name)] }]
end但没有找到local_values这个方法,好吧,我们自己来实现一个

Ruby代码1.def local_values(context, black_list = [])   
2.black_list.concat(%w)   
3.context.eval <<-EOS   
4. local_value_hashs = {}   
5. local_variables.each do |var_name|   
6.   next if [#{black_list.map{|b|"'#{b}'"}.join ','}].include? var_name   
7.   local_value_hashs = eval(var_name)   
8. end
9. local_value_hashs   
10.EOS   
11.end
    def local_values(context, black_list = [])
      black_list.concat(%w)
      context.eval <<-EOS
   local_value_hashs = {}
   local_variables.each do |var_name|
       next if [#{black_list.map{|b|"'#{b}'"}.join ','}].include? var_name
       local_value_hashs = eval(var_name)
   end
   local_value_hashs
      EOSend


这个方法默认只需要一个参数,context参数在发生异常的rescue语句里调用binding方法,black_list参数是一个数组,当你不需要把某些本地变量给打印出来的,把它的名字写到这个数组就行了

小demo

Ruby代码1.require 'pp'
2.class Kitty   
3.def hello   
4.    str = "hello kitty"
5.    raise 'test kitty'
6.rescue   
7.    pp local_values(binding)   
8.end
9.
10.def local_values(context, black_list = [])   
11.    black_list.concat(%w)   
12.    context.eval <<-EOS   
13.   local_value_hashs = {}   
14.   local_variables.each do |var_name|   
15.       next if [#{black_list.map{|b|"'#{b}'"}.join ','}].include? var_name   
16.       local_value_hashs = eval(var_name)   
17.   end
18.   local_value_hashs   
19.    EOS   
20.end
21.end
22.
23.Kitty.new.hello
require 'pp'
class Kitty
def hello
    str = "hello kitty"
    raise 'test kitty'
rescue
    pp local_values(binding)
end

def local_values(context, black_list = [])
    black_list.concat(%w)
    context.eval <<-EOS
   local_value_hashs = {}
   local_variables.each do |var_name|
       next if [#{black_list.map{|b|"'#{b}'"}.join ','}].include? var_name
       local_value_hashs = eval(var_name)
   end
   local_value_hashs
    EOS
end
end

Kitty.new.hello

输出结果

引用
{"str"=>"hello kitty"}思路

•通过binding方法获取异常发生的上下文
•调用上下文的eval方法,在eval里通过ruby自带的local_variables,获取所有本地变量的名称
•通过eval获取本地变量的值,把它存起来,返回结果

2gua 发表于 2011-10-25 00:49

好好好,很好啊。
页: [1]
查看完整版本: RUBY中保存异常现场