Skip to content

Use as Rails logger

Toshimitsu Takahashi edited this page Jan 25, 2022 · 4 revisions

Define a custom logger

Add following code to lib/your_app/logger.rb A custom logger includes LoggerSilence because Rails logger must support silence feature.

module YourApp
  class Logger < Ougai::Logger
    include ActiveSupport::LoggerThreadSafeLevel
    include LoggerSilence

    def initialize(*args)
      super
      after_initialize if respond_to?(:after_initialize) && ActiveSupport::VERSION::MAJOR < 6
    end

    def create_formatter
      if Rails.env.development? || Rails.env.test?
        Ougai::Formatters::Readable.new
      else
        Ougai::Formatters::Bunyan.new
      end
    end
  end
end

for Development

Add following code to config/environments/development.rb

Rails.application.configure do
  ...

  config.logger = YourApp::Logger.new(STDOUT)
end

for Production

Add following code to the end block of config/environments/production.rb

Rails.application.configure do
  ...

  if ENV["RAILS_LOG_TO_STDOUT"].present?
    config.logger = YourApp::Logger.new(STDOUT)
  else
    config.logger = YourApp::Logger.new(config.paths['log'].first)
  end
end

With Lograge

You must modify lograge formatter like Raw. The following code set request data to request field of JSON.

Rails.application.configure do
  config.lograge.enabled = true
  config.lograge.formatter = Class.new do |fmt|
    def fmt.call(data)
      { msg: 'Request', request: data }
    end
  end
end

Output example on development

If you modify application_controller.rb as

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def hello
    logger.debug 'Call action', somefield: 'somevalue'
    render plain: 'Hello!'
  end
end

logger outputs following:

[2016-11-03T15:11:24.847+09:00] DEBUG: Call action
{
    :somefield => "somevalue"
}
[2016-11-03T15:11:24.872+09:00] INFO: Request
{
    :request => {
            :method => "GET",
              :path => "/",
            :format => :html,
        :controller => "ApplicationController",
            :action => "hello",
            :status => 200,
          :duration => 30.14,
              :view => 3.35,
                :db => 0.0
    }
}

With ActiveSupport::TaggedLogging

Apply the monkey patch as below and embed the tags as a field on output

Rails.application.configure do
  ...

  module ActiveSupport::TaggedLogging::Formatter
    def call(severity, time, progname, data)
      data = { msg: data.to_s } unless data.is_a?(Hash)
      tags = current_tags
      data[:tags] = tags if tags.present?
      _call(severity, time, progname, data)
    end
  end

  config.logger = ActiveSupport::TaggedLogging.new(YourApp::Logger.new(STDOUT))
end