DEV Community

Sohair Ahmad
Sohair Ahmad

Posted on

Use Simple Custom Logger in Rails Application

Using ActiveSupport::TaggedLogging in the code with the following way was not so simple for me

logger.tagged('SOME_TAG') { logger.info 'Stuff' } 
Enter fullscreen mode Exit fullscreen mode

So I come up with the solution with other team members so we only have to call a simple method to log everything we required.

This is how we did it...

We created a file with the following content on lib/logging/custom_logger.rb in library.

# lib/logging/custom_logger.rb

module Logging
  class CustomLogger
    DEFAULTS = {
      level: :info
    }

    LEVELS = %w(debug info warn error fatal unknown).map(&:to_sym)

    def self.log(*tags, **params)
      level = determine_log_level(**params)
      params.delete(:level)
      message = build_message(*tags, **params)

      Rails.logger.send(level, message)
    end

    private

    def self.determine_log_level(**params)
      params.has_key?(:level) && params[:level].to_sym.in?(LEVELS) ? params[:level].to_sym : :info
    end

    def self.build_message(*tags, **params)
      tags.map!{ |tag| format_tag(tag) }
      params = params.map{ |args| format_param(args[0], args[1]) }


      tags.join(' ') + ' ' + params.join(' ')
    end

    def self.format_tag(tag)
      tag = tag.to_s.gsub(/[^\w]/i, '').upcase
      "[#{tag}]"
    end

    def self.format_param(key, value)
      key = key.to_s.gsub(/[^\w]/i, '').downcase
      value = value.to_s.gsub('"','')

      "#{key}=\"#{value}\""
    end
  end
end

# Can be used in conjunction with Rails.logger.tagged and Rails.logger.silence
def log(*tags, **params)
  Logging::CustomLogger.log(*tags, **params)
end

Enter fullscreen mode Exit fullscreen mode

def log(*tags, **params) is a public method which used in the full app directory. We can call this method with the combinations of TAGS and parameters to help track the logs.

# Can be used in conjunction with Rails.logger.tagged and Rails.logger.silence
def log(*tags, **params)
  Logging::CustomLogger.log(*tags, **params)
end
Enter fullscreen mode Exit fullscreen mode

require logging/custom_logger added in some initializer or at the end of application.rb so that log can be accessed anywhere in the application.

module APP_NAME
  class Application < Rails::Application

  end
end

require 'logging/custom_logger'
Enter fullscreen mode Exit fullscreen mode

class constant LEVELS defining all the logging level supported. Whereas the default logging level is info as defined in the DEFAULTS constant.

logging lib will upcase the tags either we pass in a different case.

Example Usage:

log('MAIN_TAG', 'SUB_TAG', key1: "value1", key2: "value2", error_message: e.message)

# Out put:
#[MAIN_TAG] [SUB_TAG] key1=value1 key2=value2
Enter fullscreen mode Exit fullscreen mode

The following exception handling will output the log:


begin
  user = User.find(params[:id]) # id = 100
rescue StandardError => e
  log('ERROR', 'USER', error: e.message)
end


[ERROR] [USER] error="ActiveRecord::RecordNotFound (Couldn't find User with 'id'=1000)"
Enter fullscreen mode Exit fullscreen mode

The following is the gist of the above described lib https://gist.github.com/Sohair63/106dd168af3bc5f8f37f82c05947ce0f

Top comments (0)