Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
elixir_pay-logger / lib / elixir_pay / logger / elixir_logger.rb
Size: Mime:
# frozen_string_literal: true

module ElixirPay
  # Logger
  module Logger
    # ElixirLogger
    class ElixirLogger < ::Logger # rubocop:disable Metrics/ClassLength
      def initialize(io_devices_and_loggers,
                     app_name: nil,
                     class_name: nil,
                     filter: nil)

        SemanticLogger.default_level = :debug

        io_devices_and_loggers.each do |item|
          case item.dig(:appender)
          when :elasticsearch
            SemanticLogger.add_appender(appender: item.dig(:appender),
                                        index: item.dig(:index),
                                        url: item.dig(:url),
                                        level: item.dig(:level))
          when :stdout
            STDOUT.sync = true
            SemanticLogger.add_appender(io: STDOUT,
                                        formatter: item.dig(:formatter),
                                        level: item.dig(:level))
          end
        end

        @app_name = app_name || ''
        @class_name = class_name
        @filter = Filter.new(filter)
        @logger = SemanticLogger[app_name]
      end

      def info(message,
               class_name: nil,
               options: nil)

        user = RequestStore.store[:current_user]

        return if !message.is_a?(Hash) && !message.index('s) SELECT').nil?

        msg = log('INFO', message, class_name)
        if user.nil?
          @logger.info msg, options
        else
          @logger.tagged(user: user_context(user)) do
            @logger.info info, options
          end
        end
      end

      def error(message,
                class_name: nil,
                options: nil)
        user = RequestStore.store[:current_user]

        msg = log('ERROR', message, class_name)

        if user.nil?
          @logger.error msg, options
        else
          @logger.tagged(user: user_context(user)) do
            @logger.error msg, options
          end
        end
      end

      def warn(message,
               class_name: nil,
               options: nil)
        user = RequestStore.store[:current_user]

        msg = log('WARN', message, class_name)

        if user.nil?
          @logger.warn msg, options
        else
          @logger.tagged(user: user_context(user)) do
            @logger.warn msg, options
          end
        end
      end

      def debug(message,
                class_name: nil,
                options: nil)
        user = RequestStore.store[:current_user]

        msg = log('DEBUG', message, class_name)

        if user.nil?
          @logger.debug msg, options
        else
          Timber.with_context(user_context(user)) do
            @logger.debug msg, options
          end
        end
      end

      private

      LEVEL = {
        INFO: :magenta,
        WARN: :yellow,
        ERROR: :red,
        DEBUG: :magenta
      }.freeze

      def log(level, msg, class_name) # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
        request_id = RequestStore.store[:request_id]
        user = RequestStore.store[:user]

        Thread.current.name = if user.nil?
                                request_id
                              else
                                "#{request_id}:#{user_context(user)}"
                              end

        @class_name ||= class_name
        msg = if msg.is_a?(Hash)
                params = @filter.call(msg[:params])
                {
                  class_name: @class_name.nil? ? nil : "[#{Paint[@class_name, :blue]}]",
                  level: "[#{Paint[level, LEVEL[level.to_sym]]}]",
                  user: user.nil? ? nil : "[#{Paint["#{user.email}(#{user.username})", :yellow]}]",
                  msg: "#{msg[:http]} #{msg[:verb]} #{msg[:status]} #{msg[:ip]} #{msg[:path]} #{msg[:length]} #{params}"
                }
              else
                {
                  class_name: @class_name.nil? ? nil : "[#{Paint[@class_name, :blue]}]",
                  level: "[#{Paint[level, LEVEL[level.to_sym]]}]",
                  user: user.nil? ? nil : "[#{Paint["#{user.email}(#{user.username})", :yellow]}]",
                  msg: msg
                }
              end

        msg.reject { |_, v| v.nil? }.map { |_, v| v }.join(' ')
      end

      def user_context(user)
        "#{user.email}(#{user.username})"
      end
    end
  end
end