복붙노트

[RUBY-ON-RAILS] 내가 어떻게 비활성화 당 액션 기준으로 루비 온 레일즈 로깅?

RUBY-ON-RAILS

내가 어떻게 비활성화 당 액션 기준으로 루비 온 레일즈 로깅?

내가 개발하고 때 나는 걱정하지 않는다 추가 로그 출력의 많은 결과로, 불편을로 충분히 자주 호출 작업이있는 레일 응용 프로그램이 있습니다. 어떻게 레일 그냥이 한 행동에 대한 어떤 (컨트롤러, 액션, 매개 변수, complection 시간 등)을 기록하지받을 수 있나요? 내가 생산에 로그가 완료 있도록,뿐만 아니라 RAILS_ENV에 그것을 조건화하고 싶습니다.

감사!

해결법

  1. ==============================

    1.당신은 레일을 로거 객체를 침묵 수 있습니다 :

    당신은 레일을 로거 객체를 침묵 수 있습니다 :

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

    2.3.1.0 레일 적어도 다음과 같은 작품 :

    3.1.0 레일 적어도 다음과 같은 작품 :

    침묵 할 수있는 사용자 정의 로거를 확인 :

    # 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
    

    그것을 사용하는 레일 알려주기 :

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

    개발 환경 수단 이하 (때로는 아니오) 위로 스크롤 실제 요구를 볼 필요 방송 사일런 저작물 게재 요청, 위의 예.

  3. ==============================

    3.lograge 보석을 사용합니다.

    lograge 보석을 사용합니다.

    Gemfile :

    gem 'lograge'
    

    설정 / application.rb :

    config.lograge.enabled = true
    config.lograge.ignore_actions = ['StatusController#nginx', ...]
    
  4. ==============================

    4.대답은 레일 정말이 작업을 수행 할 후크를 제공하지 않기 때문에, 많은 어렵게 생각보다 것으로 밝혀졌습니다. 대신, ActionController :: 자료의 내장의 일부를 포장해야합니다. 내 컨트롤러에 대한 공통 기본 클래스에서 내가 할

    대답은 레일 정말이 작업을 수행 할 후크를 제공하지 않기 때문에, 많은 어렵게 생각보다 것으로 밝혀졌습니다. 대신, ActionController :: 자료의 내장의 일부를 포장해야합니다. 내 컨트롤러에 대한 공통 기본 클래스에서 내가 할

    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
    

    다음 방법에 컨트롤러에서 나는 억제 로깅에 원하는 :

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

    5.당신은 Gemfile 소음기에 보석을 추가 할 수 있습니다.

    당신은 Gemfile 소음기에 보석을 추가 할 수 있습니다.

    gem 'silencer', '>= 1.0.1'
    

    그리고 당신의 설정 / 초기화 / silencer.rb에서 :

      require 'silencer/logger'
    
      Rails.application.configure do
        config.middleware.swap Rails::Rack::Logger, Silencer::Logger, silence: ['/api/notifications']
      end
    
  6. ==============================

    6.레일 2.3.14와 다음 작품 :

    레일 2.3.14와 다음 작품 :

    침묵 할 수있는 사용자 정의 로거를 확인 :

    #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
    

    그것을 사용하는 레일 알려주기 :

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

    각 작업 및 (재)의 시작 부분에 로그 출력 절편 작업이 침묵해야하는지 여부에 따라 로거를 구성 :

    #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
    
  7. ==============================

    7.레일 5는 더 복잡한 요청 처리는 여러 클래스에 기록됩니다 가져옵니다. 첫째로 우리는 Logger 클래스에 call_app를 오버라이드 (override) 할 필요가하자가이 파일을 lib 디렉토리 / logger.rb 전화 :

    레일 5는 더 복잡한 요청 처리는 여러 클래스에 기록됩니다 가져옵니다. 첫째로 우리는 Logger 클래스에 call_app를 오버라이드 (override) 할 필요가하자가이 파일을 lib 디렉토리 / logger.rb 전화 :

    # original class:
    # https://github.com/rails/rails/blob/master/railties/lib/rails/rack/logger.rb
    require 'rails/rack/logger'
    module Rails
      module Rack
        class Logger < ActiveSupport::LogSubscriber
    
          def call_app(request, env) # :doc:
            unless Rails.configuration.logger_exclude.call(request.filtered_path)
              instrumenter = ActiveSupport::Notifications.instrumenter
              instrumenter.start "request.action_dispatch", request: request
              logger.info { started_request_message(request) }
            end
            status, headers, body = @app.call(env)
            body = ::Rack::BodyProxy.new(body) { finish(request) }
            [status, headers, body]
          rescue Exception
            finish(request)
            raise
          ensure
            ActiveSupport::LogSubscriber.flush_all!
          end
    
        end
      end
    end
    

    그리고 lib 디렉토리 / silent_log_subscriber.rb에 따라 :

    require 'active_support/log_subscriber'
    require 'action_view/log_subscriber'
    require 'action_controller/log_subscriber'
    # original class:
    # https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/log_subscriber.rb
    class SilentLogSubscriber < ActiveSupport::LogSubscriber
    
      def start_processing(event)
        return unless logger.info?
    
        payload = event.payload
        return if Rails.configuration.logger_exclude.call(payload[:path])
    
        params  = payload[:params].except(*ActionController::LogSubscriber::INTERNAL_PARAMS)
        format  = payload[:format]
        format  = format.to_s.upcase if format.is_a?(Symbol)
        info "Processing by #{payload[:controller]}##{payload[:action]} as #{format}"
        info "  Parameters: #{params.inspect}" unless params.empty?
      end
    
      def process_action(event)
        return if Rails.configuration.logger_exclude.call(event.payload[:path])
    
        info do
          payload = event.payload
          additions = ActionController::Base.log_process_action(payload)
          status = payload[:status]
    
          if status.nil? && payload[:exception].present?
            exception_class_name = payload[:exception].first
            status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
          end
    
          additions << "Allocations: #{event.allocations}" if event.respond_to? :allocations
    
          message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
          message << " (#{additions.join(" | ")})" unless additions.empty?
          message << "\n\n" if defined?(Rails.env) && Rails.env.development?
    
          message
        end
      end
    
      def self.setup
        # unsubscribe default processors
        ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
          case subscriber
          when ActionView::LogSubscriber
            self.unsubscribe(:action_view, subscriber)
          when ActionController::LogSubscriber
            self.unsubscribe(:action_controller, subscriber)
          end
        end
      end
    
      def self.unsubscribe(component, subscriber)
        events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
        events.each do |event|
          ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
            if listener.instance_variable_get('@delegate') == subscriber
              ActiveSupport::Notifications.unsubscribe listener
            end
          end
        end
      end
    end
    # subscribe this class
    SilentLogSubscriber.attach_to :action_controller
    SilentLogSubscriber.setup
    

    확인 수정 부하에 모듈 예를 들어, 에서 설정 / application.rb 로딩 레일 후 :

    require_relative '../lib/logger'
    require_relative '../lib/silent_log_subscriber'
    

    마지막으로 구성 제외 경로 :

    Rails.application.configure do
      config.logger_exclude = ->(path) { path == "/health" }
    end
    

    우리는 레일의 핵심 코드를 수정하고 그것은 당신이 사용하고 레일 버전에서 원래의 클래스를 확인하는 것이 좋습니다 항상.

    이 모습이 너무 많은 수정을 좋아한다면, 당신은 단순히 꽤 많이 다른 몇 가지 수정과 같은 일 lograge 보석을 사용할 수 있습니다. 랙 :: Loggger 코드, 레일 3 이후 변경된 있지만 일부 기능을 잃어버린 될 수 있도록.

  8. ==============================

    8.조용한 자산의 버전 3.1.0을 소개합니다 구현부터 보석을 톱니가-레일. 불행하게도이 순간에 유연 아니지만, 쉽게 충분히 확장 할 수 있습니다.

    조용한 자산의 버전 3.1.0을 소개합니다 구현부터 보석을 톱니가-레일. 불행하게도이 순간에 유연 아니지만, 쉽게 충분히 확장 할 수 있습니다.

    설정 / 초기화 / custom_quiet_assets.rb 파일을 만듭니다

    class CustomQuietAssets < ::Sprockets::Rails::QuietAssets
      def initialize(app)
        super
        @assets_regex = %r(\A/{0,2}#{quiet_paths})
      end
    
      def quiet_paths
        [
          ::Rails.application.config.assets.prefix, # remove if you don't need to quiet assets
          '/ping',
        ].join('|')
      end
    end
    

    추가 미들웨어의 구성 / application.rb :

    # NOTE: that config.assets.quiet must be set to false (its default value).
    initializer :quiet_assets do |app|
      app.middleware.insert_before ::Rails::Rack::Logger, CustomQuietAssets
    end
    

    레일 4.2 테스트

  9. from https://stackoverflow.com/questions/2196828/how-can-i-disable-logging-in-ruby-on-rails-on-a-per-action-basis by cc-by-sa and MIT license