1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
# frozen_string_literal: true
require "set"
require_relative "template"
require_relative "structured"
module Dry
module Logger
module Formatters
# Basic string formatter.
#
# This formatter returns log entries in key=value format.
#
# @since 1.0.0
# @api public
class String < Structured
# @since 1.0.0
# @api private
HASH_SEPARATOR = ","
# @since 1.0.0
# @api private
EXCEPTION_SEPARATOR = ": "
# @since 1.2.0
# @api private
DEFAULT_SEVERITY_COLORS = {
DEBUG => :cyan,
INFO => :magenta,
WARN => :yellow,
ERROR => :red,
FATAL => :red,
UNKNOWN => :blue
}.freeze
# @since 1.0.0
# @api private
attr_reader :template
# @since 1.0.0
# @api private
def initialize(template: Logger.templates[:default], **options)
super(**options)
@template = Template[template]
end
# @since 1.0.0
# @api private
def colorize?
options[:colorize].equal?(true)
end
private
# @since 1.0.0
# @api private
def format_severity(value)
output = value.upcase
if colorize?
Colors.call(severity_colors[LEVELS[value]], output)
else
output
end
end
# @since 1.0.0
# @api private
def format(entry)
if entry.exception?
head = template % template_data(entry, exclude: %i[exception])
tail = format_exception(entry.exception)
"#{head}#{NEW_LINE}#{TAB}#{tail}"
else
template % template_data(entry)
end
end
# @since 1.0.0
# @api private
def format_tags(value)
Array(value)
.map { |tag|
case tag
when Hash then format_payload(tag)
else
tag.to_s
end
}
.join(SEPARATOR)
end
# @since 1.0.0
# @api private
def format_exception(value)
[
"#{value.message} (#{value.class})",
format_backtrace(value.backtrace || EMPTY_BACKTRACE)
].join(NEW_LINE)
end
# @since 1.0.0
# @api private
def format_payload(payload)
payload.map { |key, value| "#{key}=#{value.inspect}" }.join(SEPARATOR)
end
# @since 1.0.0
# @api private
def format_backtrace(value)
value.map { |line| "#{TAB}#{line}" }.join(NEW_LINE)
end
# @since 1.0.0
# @api private
def template_data(entry, exclude: EMPTY_ARRAY)
data = format_values(entry)
payload = data.except(:message, *entry.meta.keys, *template.tokens, *exclude)
data[:payload] = format_payload(payload)
if template.include?(:tags)
data[:tags] = format_tags(entry.tags)
end
if data[:message]
data.except(*payload.keys)
elsif template.include?(:message)
data[:message] = data.delete(:payload)
data[:payload] = nil
data
else
data
end
end
# @since 1.0.0
# @api private
def severity_colors
@severity_colors ||= DEFAULT_SEVERITY_COLORS.merge(
(options[:severity_colors] || EMPTY_HASH)
.to_h { |key, value| [LEVELS[key.to_s], value] }
)
end
end
end
end
end
|