2010-02-04 5 views
27

Ich habe eine Rails-Anwendung, die eine Aktion hat, die häufig genug aufgerufen wird, um unbequem zu sein, wenn ich mich entwickle, da es in viel extra Protokollausgabe resultiert, die mich nicht interessiert. Wie kann ich Rails bekommen, die nichts protokollieren (Controller, Aktion, Parameter, Laufzeit usw.) für genau diese eine Aktion? Ich würde es gerne auch auf RAILS_ENV konditionieren, damit die Produktion abgeschlossen ist.Wie kann ich die Protokollierung in Ruby on Rails pro Aktion deaktivieren?

Danke!

+0

Wonder, wenn Sie Rack-Middleware irgendwie verwenden könnte - so könnte man die „Rails.logger werfen.Stille "Block um die komplette Anfrage-Antwort, wenn die Anfrage entspricht Ihrem Muster. – fig

+0

Ich schaute kurz auf das. Ich könnte etwas verpasst haben, aber es sah aus wie zu der Zeit Rack Middleware beteiligt ist, weiß es nicht, welche Controller/Aktion wird aufgerufen – archbishop

+0

http://edgeguides.rubyonrails.org/4_0_release_notes.html ActiveSupport :: Benchmarkable # silence ist aufgrund fehlender Threadsicherheit veraltet und wird in Rails 4.1 ersatzlos entfernt –

Antwort

7

Die Antwort stellt sich heraus, viel schwieriger zu sein, als ich erwartet hatte, da Schienen wirklich keinen Haken, dies zu tun bietet. Stattdessen müssen Sie einige der Eingeweide von ActionController :: Base einpacken. In der gemeinsamen Basisklasse für meinen Controller, ich

def silent?(action) 
    false 
end 

# this knows more than I'd like about the internals of process, but 
# the other options require knowing even more. It would have been 
# nice to be able to use logger.silence, but there isn't a good 
# method to hook that around, due to the way benchmarking logs. 

def log_processing_with_silence_logs 
    if logger && silent?(action_name) then 
    @old_logger_level, logger.level = logger.level, Logger::ERROR 
    end 

    log_processing_without_silence_logs 
end 

def process_with_silence_logs(request, response, method = :perform_action, *arguments) 
    ret = process_without_silence_logs(request, response, method, *arguments) 
    if logger && silent?(action_name) then 
    logger.level = @old_logger_level 
    end 
    ret 
end 

alias_method_chain :log_processing, :silence_logs 
alias_method_chain :process, :silence_logs 

dann in der Steuerung mit dem Verfahren möchte ich mich auf der Anmeldung zu unterdrücken:

def silent?(action) 
    RAILS_ENV == "development" && ['my_noisy_action'].include?(action) 
end 
13

Sie können die Rails-Logger-Objekt zum Schweigen bringen:

def action 
    Rails.logger.silence do 
    # Things within this block will not be logged... 
    end 
end 
+3

Das ist generell sinnvoll Muster, aber ActionController :: Base protokolliert Zeug vor und nach dem Ausführen der Aktionsmethode, so dass mein spezielles Problem nicht gelöst wird. – archbishop

+1

Dies wirft eine Verwarnungswarnung in Rails 3 aus. Sie können stattdessen 'silence do ... end' verwenden –

+0

Funktioniert nicht für mich (Rails 4) – Yarin

1

Die folgenden Arbeiten mit Rails 2.3.14:

eine benutzerdefinierte Logger Stellen, die zum Schweigen gebracht werden kann:

#selective_logger.rb 
require "active_support" 

class SelectiveLogger < ActiveSupport::BufferedLogger 

    attr_accessor :silent 

    def initialize path_to_log_file 
    super path_to_log_file 
    end 

    def add severity, message = nil, progname = nil, &block 
    super unless @silent 
    end 
end 

Tells Rails, es zu benutzen:

#environment.rb 
    config.logger = SelectiveLogger.new config.log_path 

Intercept die Protokollausgabe zu Beginn jeder Aktion und (Re-) Konfiguration des Loggers je nachdem, ob die Aktion still sein sollte oder nicht:

#application_controller.rb 
    # This method is invoked in order to log the lines that begin "Processing..." 
    # for each new request. 
    def log_processing 
    logger.silent = %w"ping time_zone_table".include? params[:action] 
    super 
    end 
6

folgende Arbeiten mit mindestens Rails 3.1 .0:

eine benutzerdefinierte Logger Stellen, die zum Schweigen gebracht werden kann:

# selective_logger.rb 
class SelectiveLogger < Rails::Rack::Logger 

    def initialize app, opts = {} 
    @app = app 
    @opts = opts 
    @opts[:silenced] ||= [] 
    end 

    def call env 
    if @opts[:silenced].include?(env['PATH_INFO']) || @opts[:silenced].any? {|silencer| silencer.is_a?(Regexp) && silencer.match(env['PATH_INFO']) } 
     Rails.logger.silence do 
     @app.call env 
     end 
    else 
     super env 
    end       
    end 

end 

Tells Rails, es zu benutzen:

# application.rb 
config.middleware.swap Rails::Rack::Logger, SelectiveLogger, :silenced => ["/remote/every_minute", %r"^/assets/"] 

Das obige Beispiel zeigt zum Schweigen zu bringen Asset dass Anforderungen, die in der Entwicklungsumgebung bedeutet weniger (und manchmal nicht) Scrollen erforderlich ist, wieder die aktuelle Anforderung zu sehen.

+0

Leider scheint dies mit dem Juwel von quiet_assets zu kollidieren (https: // gi thub.com/evrone/quiet_assets). Wenn beide aktiviert sind, bekomme ich Fehler wie '' 'NoMethodError: undefinierte Methode' collect 'für nil: NilClass''', die von logger.rb '' 'compute_tags''' kommt. – gmcnaughton

2

Sie können den Edelstein zum Gemfile silencer hinzufügen.

gem 'silencer', '>= 1.0.0.rc3' 

Und in Ihrer config/Umgebungen/production.rb:

require 'silencer/logger' 
    config.middleware.swap Rails::Rack::Logger, Silencer::Logger, :silence => ['/api/notifications'] 
+0

Aus irgendeinem Grund konnte ich dies in Rails 5.0.0.1 nicht ausführen. Ich bekomme: Keine solche Middleware einzufügen: Rails :: Rack :: Logger (RuntimeError) – Daniel

1

Verwenden lograge gem.

Gemfile:

gem 'lograge' 

config/application.rb