diff --git a/app/controllers/scores_controller.rb b/app/controllers/scores_controller.rb index 5ff2bf7..8a9a8fc 100644 --- a/app/controllers/scores_controller.rb +++ b/app/controllers/scores_controller.rb @@ -90,7 +90,7 @@ class ScoresController < ApplicationController private def do_an_exception - raise 'Unable to destroy this score' * 5 + raise 'Unable to destroy this score. ' * 5 end # Use callbacks to share common setup or constraints between actions. diff --git a/config/environments/development.rb b/config/environments/development.rb index 9ac1764..2f7548c 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -81,12 +81,13 @@ Rails.application.configure do # rubocop:disable Metrics/BlockLength config.rails_semantic_logger.rendered = true config.rails_semantic_logger.add_file_appender = false - require Rails.root.join('lib', 'formatters', 'basic_formatter') require Rails.root.join('lib', 'formatters', 'ansi_formatter') - + require Rails.root.join('lib', 'formatters', 'ansi_filter') config.semantic_logger.add_appender(io: $stdout, - formatter: AnsiFormatter.new) + formatter: AnsiFormatter.new, + filter: ->(log) { !AnsiFilter.reject(log) }) + # require Rails.root.join('lib', 'formatters', 'basic_formatter') # config.semantic_logger.add_appender(io: $stdout, # formatter: BasicFormatter.new, # filter: BasicFormatter::EXCLUDE_LAMBDA) diff --git a/lib/formatters/ansi_dimensions.rb b/lib/formatters/ansi_dimensions.rb new file mode 100644 index 0000000..e478ace --- /dev/null +++ b/lib/formatters/ansi_dimensions.rb @@ -0,0 +1,6 @@ +# extra dimensions to customize ansi_loggingg +module AnsiDimensions + def self.new(rails: '╣x╠', before: 0, after: 0) + OpenStruct.new(rails:, before:, after:) + end +end diff --git a/lib/formatters/ansi_filter.rb b/lib/formatters/ansi_filter.rb new file mode 100644 index 0000000..f313821 --- /dev/null +++ b/lib/formatters/ansi_filter.rb @@ -0,0 +1,21 @@ +require_relative 'ansi_dimensions' + +# filter log message +module AnsiFilter + def self.reject(log) + # log.name == 'ScoresController' || false + false + end + + def self.alter(log) + if log.name == 'Rails' && log.message + log.dimensions = AnsiDimensions.new(rails: '╓─╖', before: 1) if log.message.starts_with?('Started') + + if log.message.starts_with?('Completed 200 OK') + log.dimensions = AnsiDimensions.new(rails: '╙─╜', after: 1) + log.message.chomp!('') + end + end + log + end +end diff --git a/lib/formatters/ansi_formatter.rb b/lib/formatters/ansi_formatter.rb index 3762aa4..0870685 100644 --- a/lib/formatters/ansi_formatter.rb +++ b/lib/formatters/ansi_formatter.rb @@ -9,72 +9,68 @@ require 'json' class AnsiFormatter < SemanticLogger::Formatters::Color include AnsiColors - ANSI_DEBUG = CLEAR + TEXT_GRAY_400 - ANSI_INFO = CLEAR + TEXT_GRAY_100 - ANSI_WARN = CLEAR + BG_YELLOW + TEXT_BLACK - ANSI_ERROR = CLEAR + BG_RED + TEXT_WHITE - ANSI_FATAL = CLEAR + BG_MAGENTA + BOLD + TEXT_WHITE - NAME_MAX_SIZE = 20 + CENTER_SIZE = 20 FOREMAN_PREFIX_LENGTH = 18 - DEFAULT_UNDETECTED_WRAP = 80 + FAILOVER_WRAP = 80 def initialize - super(color_map: ColorMap.new( - debug: ANSI_DEBUG, - info: ANSI_INFO, - warn: ANSI_WARN, - error: ANSI_ERROR, - fatal: ANSI_FATAL - )) + super(color_map: + ColorMap.new( + debug: CLEAR + TEXT_GRAY_400, + info: CLEAR + TEXT_GRAY_100, + warn: CLEAR + BG_YELLOW + TEXT_BLACK, + error: CLEAR + BG_RED + TEXT_WHITE, + fatal: CLEAR + BG_MAGENTA + BOLD + TEXT_WHITE + )) end def call(log, logger) + log = AnsiFilter.alter(log) + self.log = log self.logger = logger self.color = color_map[log.level] - wrap_length = compute_useful_length - wrap_level(wrap_length, message, payload, exception) - end - def origin - origin = log.name.truncate(NAME_MAX_SIZE).center(NAME_MAX_SIZE) - colorize(origin, AnsiColors::TEXT_CYAN) + wrap_level(compute_useful_length, message, payload, exception) end - def message - return unless log.message + private - colorize(log.message) - end + def origin = colorize(centerize(log.name), TEXT_CYAN) + def build_prefix(char) = "#{origin} ╣#{colorize(char)}╠ " + def centerize(text) = text.truncate(CENTER_SIZE).center(CENTER_SIZE) + def colorize(text, tint = color) = "#{tint}#{text}#{CLEAR}" + def stackisize(items) = items.length.positive? ? "\n#{items.join("\n")}" : '' - def exception - return unless log.exception + def build_dimensions(dimensions) + "#{origin} #{dimensions.rails} " + end - clazz = "#{log.exception.class}\n" - message = log.exception.message.chomp('') - backtrace = clean_backtrace(log.exception.backtrace) + def compute_useful_length + IO.console.winsize[1] - FOREMAN_PREFIX_LENGTH + rescue StandardError + FAILOVER_WRAP + end - "#{colorize(clazz, ANSI_FATAL)}#{colorize(message, ANSI_ERROR)}#{backtrace}" + def message + colorize(log.message) if log.message end - private + def exception + return unless log.exception - def colorize(text, tint = color) = "#{tint}#{text}#{AnsiColors::CLEAR}" - def build_prefix = "#{origin} #{colorize(draw_rails(level_char))} " - def build_continuation = "#{origin} #{colorize(draw_rails('┆'))} " - def draw_rails(char) = "╣#{char}╠" + exc = log.exception + clazz = colorize("#{exc.class}\n", color_map[:fatal]) + message = colorize(exc.message.chomp(''), color_map[:error]) + backtrace = stackisize(clean_backtrace(exc.backtrace)) - def compute_useful_length - IO.console.winsize[1] - FOREMAN_PREFIX_LENGTH - rescue StandardError - DEFAULT_UNDETECTED_WRAP + "#{clazz}#{message}#{backtrace}" end def clean_backtrace(backtrace) root_path = Rails.root.to_s backtrace = backtrace.select { |line| line.starts_with?(root_path) } - backtrace = backtrace.map { |line| line.delete_prefix("#{root_path}/") } - backtrace.compact.join("\n") + backtrace.map { |line| line.delete_prefix("#{root_path}/") } end def level_char @@ -85,8 +81,11 @@ class AnsiFormatter < SemanticLogger::Formatters::Color end def wrap_level(length, *items) - prefix = build_prefix - continuation = build_continuation + prefix = log.dimensions ? build_dimensions(log.dimensions) : build_prefix(level_char) + continuation = build_prefix('┆') + + log.dimensions&.before&.times { items.unshift('') } + log.dimensions&.after&.times { items << '' } items.map do |item| AnsiWrapper.wrap(item, length, prefix, continuation) end.compact.join("\n") diff --git a/lib/formatters/symbols.txt b/lib/formatters/symbols.txt index 1613cd9..79397b3 100644 --- a/lib/formatters/symbols.txt +++ b/lib/formatters/symbols.txt @@ -1,15 +1,16 @@ ╣ ╠ ╣ǁ╠ ╣▹╠ -╣▥╠ ╣◉╠ -╙─╜ +╣◼╠ ╙╨╜ -╣☉╠ +╙─╜ ╙─╜ -╣◼╠ +╣▥╠ +╣☉╠ ╙─╜ + ╣☀╠ ╙─╜ 🛑 @@ -43,7 +44,35 @@ ☇ -╙╨╜ +╙─╜ 200 OK + +╙ ╜ 300 redirect +╙⸾╜ 300 redirect +╙ǁ╜ +╙⍑╜ +╙─╜ + +╓─╖ +╣⸾╠ +╙─╜ + + + +╙╨╜ 400 client error +╙ǁ╜ 400 client error + +╙⍑╜ 500 servererror +╙⯶╜ 500 servererror +╙ ╜ 500 servererror + +╣ ╠ +╣⍑╠ +╣⍑╠ +╣⯶╠ +╣⸾╠ +╙─╜ + +╣┻╠ ╓─╖ ╣║╠ ╣║╠ @@ -51,22 +80,25 @@ ╣┊╠ ╣┆╠ ╣│╠ -╣┻╠ + +╣⇰╠ +╣⭪╠ +╣⥱╠ +╣⇴╠ +╣⇲╠ +╣⇥╠ +╣⇄╠ +╣⇣╠ ╙╨╜ ╙─╜ - -╣⇰╠⭪⬸⥱⇴⇲⇥⇄⇣ -╣⎇╠ - - -╣⍾╠ ╙─╜ - +╣⍾╠ +╣⬸╠ ╣☐╠ -╙─╜ - ╣☑╠ ╙─╜ +╙─╜ + ╣☒╠ ╙─╜ @@ -85,23 +117,31 @@ ⦹ ╣⦾╠ -╙─╜ -╣ ╠ ⨈ ⦾ ⦿ ⮾ -⯶ -ⵙⵞ⸾ + +ⵙⵞ +⸾ +╣⫨╠ +╣⤫╠ ╣⫫╠ -⫫⫨⮓⮱⮾⇤ + +⫫ +⫨ +⮓ +⮱ +⮾ +⇤ ⛭ -➾➟⬎ -⤫ +➾ +➟ +⬎ + -╙ ╜ - ⍑ + diff --git a/lib/monkey_patches/rails_semantic_logger/debug_exceptions.rb b/lib/monkey_patches/action_dispatch/debug_exceptions.rb similarity index 100% rename from lib/monkey_patches/rails_semantic_logger/debug_exceptions.rb rename to lib/monkey_patches/action_dispatch/debug_exceptions.rb diff --git a/lib/formatters/base.rb b/lib/monkey_patches/rails_semantic_logger/base.rb similarity index 100% rename from lib/formatters/base.rb rename to lib/monkey_patches/rails_semantic_logger/base.rb