2017-04-17 4 views
1

私はたくさんログを記録したいです。機能性と方法のログを分離する方法ルビメソッドの機能とログを切り離す方法

def my_method(argument1:, argument2:) 
    logger.info "Starting my_method with arguments: #{argument1} and #{argument2}" 
    result = argument1 + argument2 
    logger.info "Finished my_method with result: #{result}" 
end 

:私のRailsアプリでは私のようなメソッドをたくさん持っていますか?。 (それは、より読みやすいですが、私はこれはコードの行の点ではあまり効率的である知っている

before_method: :my_method_log_start, only: :my_method 
after_method: :my_method_log_end, only: :my_method 

def my_method(argument1:, argument2:) 
    result = argument1 + argument2 
end 

private 

def my_method_log_start 
    logger.info "Starting my_method with arguments: #{argument1} and #{argument2}" 
end 

def my_method_log_end 
    logger.info "Finished my_method with result: #{result}" 
end 

理想的には、結果はこのようなもの(単なる一例としてのRailsからのコールバックの概念を借用し)になります私の考えでは)。

私はAspect Orient ProgrammingとAquariusのようないくつかの宝石について読んだことがありますが、ロギングのためだけに新しいパラダイムを追加するには余計に思えます。

+4

ある[パフォーマンス・オーバーヘッド](http://guides.rubyonrails.org/debugging_rails_applications.html#impact-of-logs-on-performance):だから、そのような何かを書くことができますログステートメントの束 - 私はあなたがデバッガを使用する方法や、貧弱なテクニックのための松葉杖としてログに頼る代わりにテストを書く方法を学ぶことをお勧めします。 – max

答えて

3

私はAvdi Grimmにあなたが使用できる技術の良い説明があると思います。アイデアは

class Task 
    # ... 
    def add_listener(listener) 
    (@listeners ||= []) << listener 
    end 
    # ... 

    def notify_listeners(event_name, *args) 
    @listeners && @listeners.each do |listener| 
     if listener.respond_to?(event_name) 
     listener.public_send(event_name, self, *args) 
     end 
    end 
    end 
end 

なり、これが唯一のローカル用の場合

task = Task.new 
task.add_lestener(YourLoggerClass.new) 
task.notify_listeners(:start_logging) 
task.notify_listeners(:end_logging) 
+0

これは基本的に[Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern)です。 – max

2

ようSTHを行うだろうリスナークラスへのロギング(または何か他)を抽出し、そのリスナーにイベントを発行し、基本的な例ですデバッグ、それはTracePointクラスの良いユースケースです。ここにコードです:

tp1 = TracePoint.new do |tp| 
    if tp.event == :call 
    method = tp.defined_class.method(tp.method_id) 
    arguments = method.parameters.map do |param| 
     "#{param[1]}: #{tp.binding.local_variable_get(param[1])}" 
    end.join(", ") 
    puts "Starting #{tp.method_id} with arguments #{arguments}" 
    elsif tp.event.to_s == "return" 
    puts "Finished #{tp.method_id} with result: #{tp.return_value}" 
    end 
end 

tp1.enable 

def my_method1(a, b) 
    a + b 
end 

puts my_method1(2, 3) 

私はこのクラスのドキュメントを読むことをお勧めします、それは本当に素晴らしい機能があります。もちろん、いくつかのエッジケースを処理するためにこのコードを少し磨く必要があります。気付いているメソッドに対してのみ、トレースブロックを呼び出すためのフィルタをいくつか追加できます。または、コードの一部に基づいてこれを有効/無効にすることができます。

0

メソッドをその名前で呼び出すか、procにして別のメソッドに渡すことができます。追加に

def foo(a, b) 
    a + b 
end 

def call_with_logging(method_name, *args) 
    args_as_string = args.map(&:to_s).join(' ') 
    puts "Starting my_method with arguments #{args_as_string}" 
    result = Object.send(method_name, *args) 
    puts "Finished my_method with result: #{result}" 
end 

call_with_logging :foo, 1, 2 
関連する問題