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.

111 lines
3.2 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
  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. message = Wrapper.wrap("#{CONTENT_COLOR_MAP[log.level]}#{message.lstrip}", before_message(true), wrap_length)
  51. "#{CONTENT_COLOR_MAP[log.level]}#{message}#{color_map.clear}"
  52. end
  53. def level
  54. level = log.level == :info ? ' ' : log.level.to_s.chr.upcase
  55. "#{color}#{level}#{color_map.clear}"
  56. end
  57. def name
  58. "#{ANSI_DEBUG}#{log.name.truncate(NAME_MAX_SIZE).center(NAME_MAX_SIZE)}#{color_map.clear}"
  59. end
  60. def exception # rubocop:disable Metrics/AbcSize
  61. return unless log.exception
  62. root_path = Rails.root.to_s
  63. stack = log.exception.backtrace.select { |line| line.starts_with?(root_path) }
  64. stack = stack.map { |line| line.delete_prefix("#{root_path}/") }
  65. "#{ANSI_REVERSED_ERROR}#{log.exception.class}#{color_map.clear}: #{color}#{log.exception.message}#{color_map.clear}#{backtrace(stack)}" # rubocop:disable Layout/LineLength
  66. end
  67. def call(log, logger)
  68. self.color = color_map[log.level]
  69. self.log = log
  70. self.logger = logger
  71. [before_message, message, payload, exception].compact.join(' ')
  72. end
  73. private
  74. def before_message(wrapped = false)
  75. result = [name, level, tags, named_tags, duration, CONTENT_PREFIX].compact.join(' ')
  76. if wrapped
  77. [name, level, tags, named_tags, duration,
  78. "#{color}#{WRAP_PREFIX}#{color_map.clear}"].compact.join(' ')
  79. else
  80. [name, level, tags, named_tags, duration,
  81. CONTENT_PREFIX].compact.join(' ')
  82. end
  83. end
  84. def backtrace(stack)
  85. nil unless stack.count.positive?
  86. "\n#{before_message} #{ANSI_ERROR}#{stack.join("\n#{before_message} #{ANSI_ERROR}")}#{color_map.clear}"
  87. end
  88. def color_content
  89. color
  90. end
  91. end