lib/tty/logger/handlers/console.rb
# frozen_string_literal: true require "pastel" require_relative "base" module TTY class Logger module Handlers class Console include Base ARROW = "›" STYLES = { debug: { label: "debug", symbol: "•", color: :cyan, levelpad: 2 }, info: { label: "info", symbol: "ℹ", color: :green, levelpad: 3 }, warn: { label: "warning", symbol: "⚠", color: :yellow, levelpad: 0 }, error: { label: "error", symbol: "⨯", color: :red, levelpad: 2 }, fatal: { label: "fatal", symbol: "!", color: :red, levelpad: 2 }, success: { label: "success", symbol: "✔", color: :green, levelpad: 0 }, wait: { label: "waiting", symbol: "…", color: :cyan, levelpad: 0 } }.freeze TEXT_REGEXP = /([{}()\[\]])?(["']?)(\S+?)(["']?=)/.freeze JSON_REGEXP = /\"([^,]+?)\"(?=:)/.freeze COLOR_PATTERNS = { text: [TEXT_REGEXP, ->(c) { "\\1\\2" + c.("\\3") + "\\4" }], json: [JSON_REGEXP, ->(c) { "\"" + c.("\\1") + "\"" }] }.freeze # The output stream # @api private attr_reader :output # The configuration options # @api private attr_reader :config # The logging level # @api private attr_reader :level # The format for the message # @api private attr_reader :message_format def initialize(output: $stderr, formatter: nil, config: nil, level: nil, styles: {}, enable_color: nil, message_format: "%-25s") @output = Array[output].flatten @formatter = coerce_formatter(formatter || config.formatter).new @formatter_name = @formatter.class.name.split("::").last.downcase @color_pattern = COLOR_PATTERNS[@formatter_name.to_sym] @config = config @styles = styles @level = level || @config.level @mutex = Mutex.new @pastel = Pastel.new(enabled: enable_color) @message_format = message_format end # Handle log event output in format # # @param [Event] event # the current event logged # # @api publicMethod `call` has 38 lines of code (exceeds 25 allowed). Consider refactoring.
Method `call` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring. def call(event) @mutex.lock style = configure_styles(event) color = configure_color(style) fmt = [] metadata.each do |meta| case meta when :date fmt << @pastel.white("[" + event.metadata[:time]. strftime(config.date_format) + "]") when :time fmt << @pastel.white("[" + event.metadata[:time]. strftime(config.time_format) + "]") when :file fmt << @pastel.white("[#{format_filepath(event)}]") when :pid fmt << @pastel.white("[%d]" % event.metadata[:pid]) else raise "Unknown metadata `#{meta}`" end end fmt << ARROW unless config.metadata.empty? unless style.empty? fmt << color.(style[:symbol]) fmt << color.(style[:label]) + (" " * style[:levelpad]) end fmt << message_format % event.message.join(" ") unless event.fields.empty? pattern, replacement = *@color_pattern fmt << @formatter.dump(event.fields, max_bytes: config.max_bytes, max_depth: config.max_depth) .gsub(pattern, replacement.(color)) end unless event.backtrace.empty? fmt << "\n" + format_backtrace(event) end output.each { |out| out.puts fmt.join(" ") } ensure @mutex.unlock end private def format_backtrace(event) indent = " " * 4 event.backtrace.map do |bktrace| indent + bktrace.to_s end.join("\n") end # Merge default styles with custom style overrides # # @return [Hash[String]] # the style matching log type # # @api private def configure_styles(event) return {} if event.metadata[:name].nil? STYLES.fetch(event.metadata[:name].to_sym, {}) .dup .merge!(@styles[event.metadata[:name].to_sym] || {}) end def configure_color(style) color = style.fetch(:color) { :cyan } @pastel.send(color).detach end end # Console end # Handlers end # Loggerend # TTY