You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
3.3 KiB

10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
  1. require_relative 'wrapper'
  2. require 'io/console'
  3. # Opinioned Rails custom formatter
  4. class BasicFormatter < SemanticLogger::Formatters::Color
  5. NAME_MAX_SIZE = 25
  6. FOREMAN_PREFIX = 15
  7. CONTENT_PREFIX = ' '.freeze
  8. WRAP_PREFIX = ' > '.freeze
  9. ANSI_DEBUG = "\e[90m".freeze
  10. ANSI_INFO = SemanticLogger::AnsiColors::GREEN
  11. ANSI_WARN = SemanticLogger::AnsiColors::YELLOW
  12. ANSI_ERROR = "\e[91m".freeze
  13. ANSI_NEUTRAL_INFO = SemanticLogger::AnsiColors::WHITE
  14. ANSI_REVERSED_WARNING = "\e[0;30;43m".freeze
  15. ANSI_REVERSED_ERROR = "\e[1;30;41m".freeze
  16. ANSI_REVERSED_FATAL = "\e[1;30;41m".freeze
  17. CONTENT_COLOR_MAP = ColorMap.new(
  18. debug: ANSI_DEBUG,
  19. info: ANSI_NEUTRAL_INFO,
  20. warn: ANSI_REVERSED_WARNING,
  21. error: ANSI_REVERSED_ERROR,
  22. fatal: ANSI_REVERSED_FATAL
  23. )
  24. EXCLUDE_LAMBDA = lambda { |log|
  25. if log.name == 'ActionView::Base'
  26. !log.message.starts_with?(' Rendering')
  27. elsif log.name == 'Rails' && !log.message.nil?
  28. log.message.exclude?('Started GET "/rails/live/reload')
  29. else
  30. true
  31. end
  32. }
  33. def initialize
  34. super(color_map: ColorMap.new(
  35. debug: ANSI_DEBUG,
  36. info: ANSI_INFO,
  37. warn: ANSI_WARN,
  38. error: ANSI_ERROR,
  39. fatal: ANSI_ERROR
  40. ))
  41. end
  42. def message
  43. return unless log.message
  44. message = log.message
  45. if log.name == 'Rails' && message.starts_with?('Completed')
  46. message.rstrip!
  47. message += "\n" unless message.starts_with?('Completed 5')
  48. end
  49. wrap_length = IO.console.winsize[1] - FOREMAN_PREFIX - before_message.length + CONTENT_PREFIX.length + 12
  50. space_prefix = message.match(/^\s*/)
  51. message = Wrapper.wrap("#{CONTENT_COLOR_MAP[log.level]}#{message}", before_message(true, space_prefix),
  52. wrap_length - space_prefix.length)
  53. "#{CONTENT_COLOR_MAP[log.level]}#{message}#{color_map.clear}"
  54. end
  55. def level
  56. level = log.level == :info ? ' ' : log.level.to_s.chr.upcase
  57. "#{color}#{level}#{color_map.clear}"
  58. end
  59. def name
  60. "#{ANSI_DEBUG}#{log.name.truncate(NAME_MAX_SIZE).center(NAME_MAX_SIZE)}#{color_map.clear}"
  61. end
  62. def exception # rubocop:disable Metrics/AbcSize
  63. return unless log.exception
  64. root_path = Rails.root.to_s
  65. stack = log.exception.backtrace.select { |line| line.starts_with?(root_path) }
  66. stack = stack.map { |line| line.delete_prefix("#{root_path}/") }
  67. "#{ANSI_REVERSED_ERROR}#{log.exception.class}#{color_map.clear}: #{color}#{log.exception.message}#{color_map.clear}#{backtrace(stack)}" # rubocop:disable Layout/LineLength
  68. end
  69. def call(log, logger)
  70. self.color = color_map[log.level]
  71. self.log = log
  72. self.logger = logger
  73. [before_message, message, payload, exception].compact.join(' ')
  74. end
  75. private
  76. def before_message(wrapped = false, prefix = '')
  77. result = [name, level, tags, named_tags, duration, CONTENT_PREFIX].compact.join(' ')
  78. if wrapped
  79. [name, level, tags, named_tags, duration,
  80. "#{color}#{WRAP_PREFIX}#{color_map.clear}#{prefix}"].compact.join(' ')
  81. else
  82. [name, level, tags, named_tags, duration,
  83. CONTENT_PREFIX].compact.join(' ')
  84. end
  85. end
  86. def backtrace(stack)
  87. nil unless stack.count.positive?
  88. "\n#{before_message} #{ANSI_ERROR}#{stack.join("\n#{before_message} #{ANSI_ERROR}")}#{color_map.clear}"
  89. end
  90. def color_content
  91. color
  92. end
  93. end