Custom rails errors logs

0. Mở đầu

Trong các ứng dụng web, logs là rất cần thiết để chúng ta theo dõi tình trạng của server.

Tuy nhiên, rails ghi toàn bộ log vào staging.log, production.log

Điều này sẽ gây khó khăn cho chúng ta nếu như muốn biết hiện tại server có đang hoạt động ổn định không, có lỗi gì không, log lỗi là gì...

Hôm nay mình xin hướng dẫn các bạn cách ghi các log lỗi ra riêng 1 file staging_special.log, production_special.log

1. Setup

Tạo 1 Custom logger /lib/distinct_file_logger.rb

require "logger"
class DistinctFileLogger < Logger
 LOG_LEVEL = %i(debug info warn error fatal unknown).freeze
 LOG_LEVEL_SPECIAL = %i(error fatal unknown).freeze

 def initialize path
   @logger_file = {}
   @special_log = {}
   @logger_stdout = {}

   LOG_LEVEL.each do |level|
     @logger_file[level] = Logger.new "#{path}/#{Rails.env}.log"
     @logger_stdout[level] = ActiveSupport::Logger.new STDOUT
   end
   LOG_LEVEL_SPECIAL.each do |level_special|
     @special_log[level_special] = Logger.new "#{path}/#{Rails.env}_special.log"
   end
 end

 LOG_LEVEL.each do |level|
   define_method(level) do |message="", &block|
     @logger_file[level].send level, message, &block
     @logger_stdout[level].send level, message, &block
     
     if LOG_LEVEL_SPECIAL.include? level
       @special_log[level].send level, message, &block
     end
   end
 end
end

config logger config/environments/staging.rb config/environments/production.rb

  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger = ActiveSupport::TaggedLogging.new(logger)
  else
    config.logger = DistinctFileLogger.new Rails.root.join "log"
  end

Source code: @TranQuanTrung

2. Cách sử dụng

cd /usr/local/rails_apps/APP_NAME/current

Theo dõi toàn bộ log

tail -100f log/staging.log

Theo dõi riêng các logs errors

tail -100f log/staging_special.log

Kết quả:

F, [2017-09-29T08:37:06.914243 #18030] FATAL -- :   
F, [2017-09-29T08:37:06.914854 #18030] FATAL -- : ActionController::RoutingError (No route matches [GET] "/favicon.ico"):
F, [2017-09-29T08:37:06.915192 #18030] FATAL -- :   
F, [2017-09-29T08:37:06.915442 #18030] FATAL -- : actionpack (5.1.2) lib/action_dispatch/middleware/debug_exceptions.rb:63:in `call'
actionpack (5.1.2) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.1.2) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.1.2) lib/rails/rack/logger.rb:26:in `call'
actionpack (5.1.2) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
request_store (1.3.2) lib/request_store/middleware.rb:9:in `call'
actionpack (5.1.2) lib/action_dispatch/middleware/request_id.rb:25:in `call'
rack (2.0.3) lib/rack/method_override.rb:22:in `call'
rack (2.0.3) lib/rack/runtime.rb:22:in `call'
activesupport (5.1.2) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in `call'
actionpack (5.1.2) lib/action_dispatch/middleware/executor.rb:12:in `call'
rack (2.0.3) lib/rack/sendfile.rb:111:in `call'
railties (5.1.2) lib/rails/engine.rb:522:in `call'
/usr/lib/ruby/vendor_ruby/phusion_passenger/rack/thread_handler_extension.rb:97:in `process_request'
/usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler/thread_handler.rb:152:in `accept_and_process_next_request'
/usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler/thread_handler.rb:113:in `main_loop'
/usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler.rb:416:in `block (3 levels) in start_threads'
/usr/lib/ruby/vendor_ruby/phusion_passenger/utils.rb:113:in `block in create_thread_and_abort_on_exception'

3. Kết luận

Chỉ với 1 vài dòng code đơn giản. Chúng ta đã có thể kiểm theo dõi hoạt động của server, phát hiện ra các lỗi code trong quá trình server hoạt động để tìm ra đoạn code lỗi và nhanh chóng gửi pull request xử lý.

Hi vọng bài viết này hữu ích. ❤️