lumberjack 1.4.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ARCHITECTURE.md +524 -176
- data/CHANGELOG.md +89 -0
- data/README.md +604 -211
- data/UPGRADE_GUIDE.md +80 -0
- data/VERSION +1 -1
- data/lib/lumberjack/attribute_formatter.rb +451 -0
- data/lib/lumberjack/attributes_helper.rb +100 -0
- data/lib/lumberjack/context.rb +120 -23
- data/lib/lumberjack/context_logger.rb +620 -0
- data/lib/lumberjack/device/buffer.rb +209 -0
- data/lib/lumberjack/device/date_rolling_log_file.rb +10 -62
- data/lib/lumberjack/device/log_file.rb +76 -29
- data/lib/lumberjack/device/logger_wrapper.rb +137 -0
- data/lib/lumberjack/device/multi.rb +92 -30
- data/lib/lumberjack/device/null.rb +26 -8
- data/lib/lumberjack/device/size_rolling_log_file.rb +13 -54
- data/lib/lumberjack/device/test.rb +337 -0
- data/lib/lumberjack/device/writer.rb +184 -176
- data/lib/lumberjack/device.rb +134 -15
- data/lib/lumberjack/device_registry.rb +90 -0
- data/lib/lumberjack/entry_formatter.rb +357 -0
- data/lib/lumberjack/fiber_locals.rb +55 -0
- data/lib/lumberjack/forked_logger.rb +143 -0
- data/lib/lumberjack/formatter/date_time_formatter.rb +14 -3
- data/lib/lumberjack/formatter/exception_formatter.rb +12 -2
- data/lib/lumberjack/formatter/id_formatter.rb +13 -1
- data/lib/lumberjack/formatter/inspect_formatter.rb +14 -1
- data/lib/lumberjack/formatter/multiply_formatter.rb +10 -0
- data/lib/lumberjack/formatter/object_formatter.rb +13 -1
- data/lib/lumberjack/formatter/pretty_print_formatter.rb +15 -2
- data/lib/lumberjack/formatter/redact_formatter.rb +18 -3
- data/lib/lumberjack/formatter/round_formatter.rb +12 -0
- data/lib/lumberjack/formatter/string_formatter.rb +9 -1
- data/lib/lumberjack/formatter/strip_formatter.rb +13 -1
- data/lib/lumberjack/formatter/structured_formatter.rb +18 -2
- data/lib/lumberjack/formatter/tagged_message.rb +10 -32
- data/lib/lumberjack/formatter/tags_formatter.rb +32 -0
- data/lib/lumberjack/formatter/truncate_formatter.rb +8 -1
- data/lib/lumberjack/formatter.rb +271 -141
- data/lib/lumberjack/formatter_registry.rb +84 -0
- data/lib/lumberjack/io_compatibility.rb +133 -0
- data/lib/lumberjack/local_log_template.rb +209 -0
- data/lib/lumberjack/log_entry.rb +154 -79
- data/lib/lumberjack/log_entry_matcher/score.rb +276 -0
- data/lib/lumberjack/log_entry_matcher.rb +126 -0
- data/lib/lumberjack/logger.rb +328 -556
- data/lib/lumberjack/message_attributes.rb +38 -0
- data/lib/lumberjack/rack/context.rb +66 -15
- data/lib/lumberjack/rack.rb +0 -2
- data/lib/lumberjack/remap_attribute.rb +24 -0
- data/lib/lumberjack/severity.rb +52 -15
- data/lib/lumberjack/tag_context.rb +8 -71
- data/lib/lumberjack/tag_formatter.rb +22 -188
- data/lib/lumberjack/tags.rb +15 -21
- data/lib/lumberjack/template.rb +252 -62
- data/lib/lumberjack/template_registry.rb +60 -0
- data/lib/lumberjack/utils.rb +198 -48
- data/lib/lumberjack.rb +167 -59
- data/lumberjack.gemspec +4 -2
- metadata +41 -15
- data/lib/lumberjack/device/rolling_log_file.rb +0 -145
- data/lib/lumberjack/rack/request_id.rb +0 -31
- data/lib/lumberjack/rack/unit_of_work.rb +0 -21
- data/lib/lumberjack/tagged_logger_support.rb +0 -81
- data/lib/lumberjack/tagged_logging.rb +0 -29
data/lib/lumberjack/template.rb
CHANGED
@@ -1,50 +1,175 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Lumberjack
|
4
|
-
# A template
|
5
|
-
#
|
4
|
+
# A flexible template system for converting log entries into formatted strings.
|
5
|
+
# Templates use mustache style placeholders to create customizable log output formats.
|
6
6
|
#
|
7
|
-
#
|
8
|
-
# * :severity
|
9
|
-
# * :progname
|
10
|
-
# * :tags
|
11
|
-
# * :message
|
7
|
+
# The template system supports the following built-in placeholders:
|
12
8
|
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# with
|
9
|
+
# - <code>{{time}}</code> - The log entry timestamp
|
10
|
+
# - <code>{{severity}}</code> - The severity level (DEBUG, INFO, WARN, ERROR, FATAL). The severity
|
11
|
+
# can also be formatted in a variety of ways with an optional format specifier.
|
12
|
+
# Supported formats include:
|
13
|
+
# - <code>{{severity(padded)}}</code> - Right padded so that all values are five characters
|
14
|
+
# - <code>{{severity(char)}}</code> - Single character representation (D, I, W, E, F)
|
15
|
+
# - <code>{{severity(emoji)}}</code> - Emoji representation
|
16
|
+
# - <code>{{severity(level)}}</code> - Numeric level representation
|
17
|
+
# - <code>{{progname}}</code> - The program name that generated the entry
|
18
|
+
# - <code>{{pid}}</code> - The process ID
|
19
|
+
# - <code>{{message}}</code> - The main log message content
|
20
|
+
# - <code>{{attributes}}</code> - All custom attributes formatted as key:value pairs
|
21
|
+
#
|
22
|
+
# Custom attribute placeholders can also be put in the double bracket placeholders.
|
23
|
+
# Any attributes explicitly added to the template in their own placeholder will be removed
|
24
|
+
# from the general list of attributes.
|
25
|
+
#
|
26
|
+
# @example Basic template usage
|
27
|
+
# template = Lumberjack::Template.new("[{{time}} {{severity}}] {{message}}")
|
28
|
+
# # Output: [2023-08-21T10:30:15.123 INFO] User logged in
|
29
|
+
#
|
30
|
+
# @example Multi-line message formatting
|
31
|
+
# template = Lumberjack::Template.new(
|
32
|
+
# "[{{time}} {{severity}}] {{message}}",
|
33
|
+
# additional_lines: "\n | {{message}}"
|
34
|
+
# )
|
35
|
+
# # Output:
|
36
|
+
# # [2023-08-21T10:30:15.123 INFO] First line
|
37
|
+
# # | Second line
|
38
|
+
# # | Third line
|
39
|
+
#
|
40
|
+
# @example Custom attribute placeholders
|
41
|
+
# # The user_id attribute will be put before the message instead of with the rest of the attributes.
|
42
|
+
# template = Lumberjack::Template.new("[{{time}} {{severity}}] (usr:{{user_id}} {{message}} -- {{attributes}})")
|
16
43
|
class Template
|
17
|
-
|
44
|
+
DEFAULT_FIRST_LINE_TEMPLATE = "[{{time}} {{severity(padded)}} {{progname}}({{pid}})] {{message}} {{attributes}}"
|
45
|
+
STDLIB_FIRST_LINE_TEMPLATE = "{{severity(char)}}, [{{time}} {{pid}}] {{severity(padded)}} -- {{progname}}: {{message}} {{attributes}}"
|
46
|
+
DEFAULT_ADDITIONAL_LINES_TEMPLATE = "#{Lumberjack::LINE_SEPARATOR}> {{message}}"
|
47
|
+
DEFAULT_ATTRIBUTE_FORMAT = "[%s:%s]"
|
48
|
+
|
49
|
+
TemplateRegistry.add(:default, DEFAULT_FIRST_LINE_TEMPLATE)
|
50
|
+
TemplateRegistry.add(:stdlib, STDLIB_FIRST_LINE_TEMPLATE)
|
51
|
+
TemplateRegistry.add(:message, "{{message}}")
|
52
|
+
|
53
|
+
# A wrapper template that delegates formatting to a standard Ruby Logger formatter.
|
54
|
+
# This provides compatibility with existing Logger::Formatter implementations while
|
55
|
+
# maintaining the Template interface for consistent usage within Lumberjack.
|
56
|
+
class StandardFormatterTemplate < Template
|
57
|
+
# Create a new wrapper for a standard Ruby Logger formatter.
|
58
|
+
#
|
59
|
+
# @param formatter [Logger::Formatter] The formatter to wrap
|
60
|
+
def initialize(formatter)
|
61
|
+
@formatter = formatter
|
62
|
+
end
|
63
|
+
|
64
|
+
# Format a log entry using the wrapped formatter.
|
65
|
+
#
|
66
|
+
# @param entry [Lumberjack::LogEntry] The log entry to format
|
67
|
+
# @return [String] The formatted log entry
|
68
|
+
def call(entry)
|
69
|
+
@formatter.call(entry.severity_label, entry.time, entry.progname, entry.message)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Set the datetime format on the wrapped formatter if supported.
|
73
|
+
#
|
74
|
+
# @param value [String] The datetime format string
|
75
|
+
# @return [void]
|
76
|
+
def datetime_format=(value)
|
77
|
+
@formatter.datetime_format = value if @formatter.respond_to?(:datetime_format=)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get the datetime format from the wrapped formatter if supported.
|
81
|
+
#
|
82
|
+
# @return [String, nil] The datetime format string, or nil if not supported
|
83
|
+
def datetime_format
|
84
|
+
@formatter.datetime_format if @formatter.respond_to?(:datetime_format)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
TEMPLATE_ARGUMENT_ORDER = %w[
|
89
|
+
time
|
90
|
+
severity
|
91
|
+
severity(padded)
|
92
|
+
severity(char)
|
93
|
+
severity(emoji)
|
94
|
+
severity(level)
|
95
|
+
progname
|
96
|
+
pid
|
97
|
+
message
|
98
|
+
attributes
|
99
|
+
].freeze
|
100
|
+
|
18
101
|
MILLISECOND_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%3N"
|
19
102
|
MICROSECOND_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%6N"
|
20
|
-
PLACEHOLDER_PATTERN =
|
103
|
+
PLACEHOLDER_PATTERN = /{{ *((?:[^}]|}(?!}))*) *}}/i
|
104
|
+
V1_PLACEHOLDER_PATTERN = /:[a-z0-9_.-]+/i
|
105
|
+
RESET_CHAR = "\e[0m"
|
106
|
+
private_constant :TEMPLATE_ARGUMENT_ORDER, :MILLISECOND_TIME_FORMAT, :MICROSECOND_TIME_FORMAT, :PLACEHOLDER_PATTERN, :V1_PLACEHOLDER_PATTERN, :RESET_CHAR
|
21
107
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
#
|
108
|
+
class << self
|
109
|
+
def colorize_entry(formatted_string, entry)
|
110
|
+
color_start = entry.severity_data.terminal_color
|
111
|
+
formatted_string.split(Lumberjack::LINE_SEPARATOR).collect do |line|
|
112
|
+
"\e7#{color_start}#{line}\e8"
|
113
|
+
end.join(Lumberjack::LINE_SEPARATOR)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Create a new template with customizable formatting options. The template
|
118
|
+
# supports different formatting for single-line and multi-line messages,
|
119
|
+
# custom time formatting, and configurable attribute display.
|
33
120
|
#
|
34
|
-
# @param [String]
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
121
|
+
# @param first_line [String, nil] Template for formatting the first line of messages.
|
122
|
+
# Defaults to <code>[{{ time }} {{ severity(padded) }} {{ progname }}({{ pid }})] {{ message }} {{ attributes }}</code>
|
123
|
+
# @param additional_lines [String, nil] Template for formatting additional lines
|
124
|
+
# in multi-line messages. Defaults to <code>\\n> {{ message }}</code>
|
125
|
+
# @param time_format [String, Symbol, nil] Time formatting specification. Can be:
|
126
|
+
# - A strftime format string (e.g., "%Y-%m-%d %H:%M:%S")
|
127
|
+
# - +:milliseconds+ for ISO format with millisecond precision (default)
|
128
|
+
# - +:microseconds+ for ISO format with microsecond precision
|
129
|
+
# @param attribute_format [String, nil] Printf-style format for individual attributes.
|
130
|
+
# Must contain exactly two %s placeholders for name and value. Defaults to "[%s:%s]"
|
131
|
+
# @param colorize [Boolean] Whether to colorize the log entry based on severity (default: false)
|
132
|
+
# @raise [ArgumentError] If attribute_format doesn't contain exactly two %s placeholders
|
133
|
+
def initialize(first_line = nil, additional_lines: nil, time_format: nil, attribute_format: nil, colorize: false)
|
134
|
+
first_line ||= DEFAULT_FIRST_LINE_TEMPLATE
|
135
|
+
first_line = "#{first_line.chomp}#{Lumberjack::LINE_SEPARATOR}"
|
136
|
+
if !first_line.include?("{{") && first_line.match?(V1_PLACEHOLDER_PATTERN)
|
137
|
+
Utils.deprecated("Template.v1", "Templates now use {{placeholder}} instead of :placeholder and :tags has been replaced with {{attributes}}.") do
|
138
|
+
@first_line_template, @first_line_attributes = compile_v1(first_line)
|
139
|
+
end
|
140
|
+
else
|
141
|
+
@first_line_template, @first_line_attributes = compile(first_line)
|
142
|
+
end
|
143
|
+
|
144
|
+
additional_lines ||= DEFAULT_ADDITIONAL_LINES_TEMPLATE
|
145
|
+
if !additional_lines.include?("{{") && additional_lines.match?(V1_PLACEHOLDER_PATTERN)
|
146
|
+
Utils.deprecated("Template.v1", "Templates now use {{placeholder}} instead of :placeholder and :tags has been replaced with {{attributes}}.") do
|
147
|
+
@additional_line_template, @additional_line_attributes = compile_v1(additional_lines)
|
148
|
+
end
|
149
|
+
else
|
150
|
+
@additional_line_template, @additional_line_attributes = compile(additional_lines)
|
151
|
+
end
|
152
|
+
|
153
|
+
@attribute_template = attribute_format || DEFAULT_ATTRIBUTE_FORMAT
|
154
|
+
unless @attribute_template.scan("%s").size == 2
|
155
|
+
raise ArgumentError.new("attribute_format must be a printf template with exactly two '%s' placeholders")
|
156
|
+
end
|
157
|
+
|
40
158
|
# Formatting the time is relatively expensive, so only do it if it will be used
|
41
|
-
@template_include_time =
|
42
|
-
self.datetime_format = (
|
159
|
+
@template_include_time = "#{@first_line_template} #{@additional_line_template}".include?("%1$s")
|
160
|
+
self.datetime_format = (time_format || :milliseconds)
|
161
|
+
|
162
|
+
@colorize = colorize
|
43
163
|
end
|
44
164
|
|
45
|
-
# Set the format used
|
165
|
+
# Set the datetime format used for timestamp formatting in the template.
|
166
|
+
# This method accepts both strftime format strings and symbolic shortcuts.
|
46
167
|
#
|
47
|
-
# @param [String]
|
168
|
+
# @param format [String, Symbol] The datetime format specification:
|
169
|
+
# - String: A strftime format pattern (e.g., "%Y-%m-%d %H:%M:%S")
|
170
|
+
# - +:milliseconds+: ISO format with millisecond precision (YYYY-MM-DDTHH:MM:SS.sss)
|
171
|
+
# - +:microseconds+: ISO format with microsecond precision (YYYY-MM-DDTHH:MM:SS.ssssss)
|
172
|
+
# @return [void]
|
48
173
|
def datetime_format=(format)
|
49
174
|
if format == :milliseconds
|
50
175
|
format = MILLISECOND_TIME_FORMAT
|
@@ -54,17 +179,19 @@ module Lumberjack
|
|
54
179
|
@time_formatter = Formatter::DateTimeFormatter.new(format)
|
55
180
|
end
|
56
181
|
|
57
|
-
# Get the format used
|
182
|
+
# Get the current datetime format string used for timestamp formatting.
|
58
183
|
#
|
59
|
-
# @return [String]
|
184
|
+
# @return [String] The strftime format string currently in use
|
60
185
|
def datetime_format
|
61
186
|
@time_formatter.format
|
62
187
|
end
|
63
188
|
|
64
|
-
# Convert
|
189
|
+
# Convert a log entry into a formatted string using the template. This method
|
190
|
+
# handles both single-line and multi-line messages, applying the appropriate
|
191
|
+
# templates and performing placeholder substitution.
|
65
192
|
#
|
66
|
-
# @param [Lumberjack::LogEntry]
|
67
|
-
# @return [String] The
|
193
|
+
# @param entry [Lumberjack::LogEntry] The log entry to format
|
194
|
+
# @return [String] The formatted log entry string
|
68
195
|
def call(entry)
|
69
196
|
return entry unless entry.is_a?(LogEntry)
|
70
197
|
|
@@ -76,58 +203,121 @@ module Lumberjack
|
|
76
203
|
end
|
77
204
|
|
78
205
|
formatted_time = @time_formatter.call(entry.time) if @template_include_time
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
206
|
+
severity = entry.severity_data
|
207
|
+
format_args = [
|
208
|
+
formatted_time,
|
209
|
+
severity.label,
|
210
|
+
severity.padded_label,
|
211
|
+
severity.char,
|
212
|
+
severity.emoji,
|
213
|
+
severity.level,
|
214
|
+
entry.progname,
|
215
|
+
entry.pid,
|
216
|
+
first_line
|
217
|
+
]
|
218
|
+
append_attribute_args!(format_args, entry.attributes, @first_line_attributes)
|
219
|
+
message = (@first_line_template % format_args)
|
83
220
|
|
84
221
|
if additional_lines && !additional_lines.empty?
|
85
|
-
|
222
|
+
format_args.slice!(9, format_args.size)
|
223
|
+
append_attribute_args!(format_args, entry.attributes, @additional_line_attributes)
|
224
|
+
|
225
|
+
message_length = message.length
|
226
|
+
message.chomp!(Lumberjack::LINE_SEPARATOR)
|
227
|
+
chomped = message.length != message_length
|
228
|
+
|
86
229
|
additional_lines.each do |line|
|
87
|
-
format_args[
|
88
|
-
line_message =
|
89
|
-
line_message.rstrip! if line_message.end_with?(" ")
|
230
|
+
format_args[8] = line
|
231
|
+
line_message = @additional_line_template % format_args
|
90
232
|
message << line_message
|
91
233
|
end
|
234
|
+
|
235
|
+
message << Lumberjack::LINE_SEPARATOR if chomped
|
92
236
|
end
|
237
|
+
|
238
|
+
message = Template.colorize_entry(message, entry) if @colorize
|
239
|
+
|
93
240
|
message
|
94
241
|
end
|
95
242
|
|
96
243
|
private
|
97
244
|
|
98
|
-
|
99
|
-
|
245
|
+
# Build the arguments array for sprintf formatting by appending attribute values.
|
246
|
+
# This method handles both the general :attributes placeholder and specific
|
247
|
+
# attribute placeholders defined in the template.
|
248
|
+
#
|
249
|
+
# @param args [Array] The existing format arguments array to modify
|
250
|
+
# @param attributes [Hash, nil] The log entry attributes hash
|
251
|
+
# @param attribute_vars [Array<String>] List of specific attribute names used in template
|
252
|
+
# @return [void]
|
253
|
+
def append_attribute_args!(args, attributes, attribute_vars)
|
254
|
+
if attributes.nil? || attributes.size == 0
|
255
|
+
(attribute_vars.length + 1).times { args << nil }
|
256
|
+
return
|
257
|
+
end
|
100
258
|
|
101
|
-
|
102
|
-
|
103
|
-
unless value.nil? ||
|
259
|
+
attributes_string = +""
|
260
|
+
attributes.each do |name, value|
|
261
|
+
unless value.nil? || attribute_vars.include?(name)
|
104
262
|
value = value.to_s
|
105
263
|
value = value.gsub(Lumberjack::LINE_SEPARATOR, " ") if value.include?(Lumberjack::LINE_SEPARATOR)
|
106
|
-
|
264
|
+
attributes_string << " "
|
265
|
+
attributes_string << @attribute_template % [name, value]
|
107
266
|
end
|
108
267
|
end
|
109
268
|
|
110
|
-
args
|
111
|
-
|
112
|
-
args <<
|
269
|
+
args << attributes_string
|
270
|
+
attribute_vars.each do |name|
|
271
|
+
args << attributes[name]
|
113
272
|
end
|
114
|
-
args
|
115
273
|
end
|
116
274
|
|
117
|
-
#
|
275
|
+
# Parse and compile a template string into a sprintf-compatible format string
|
276
|
+
# and extract attribute variable names. This method handles placeholder
|
277
|
+
# substitution and escape sequence processing.
|
278
|
+
#
|
279
|
+
# @param template [String] The raw template string with placeholders
|
280
|
+
# @return [Array<String, Array<String>>] A tuple of [compiled_template, attribute_vars]
|
118
281
|
def compile(template) # :nodoc:
|
119
|
-
|
282
|
+
template = template.gsub(/ ({{ *)attributes( *}})/, "\\1attributes\\2")
|
283
|
+
template = template.gsub(/%(?!%)/, "%%")
|
284
|
+
|
285
|
+
attribute_vars = []
|
120
286
|
template = template.gsub(PLACEHOLDER_PATTERN) do |match|
|
121
|
-
var_name = match.sub(
|
287
|
+
var_name = match.sub(/{{ */, "").sub(/ *}}/, "")
|
288
|
+
position = TEMPLATE_ARGUMENT_ORDER.index(var_name)
|
289
|
+
if position
|
290
|
+
"%#{position + 1}$s"
|
291
|
+
else
|
292
|
+
attribute_vars << var_name
|
293
|
+
"%#{TEMPLATE_ARGUMENT_ORDER.size + attribute_vars.size}$s"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
[template, attribute_vars]
|
297
|
+
end
|
298
|
+
|
299
|
+
# Parse and compile a template string into a sprintf-compatible format string
|
300
|
+
# and extract attribute variable names. This method handles placeholder
|
301
|
+
# substitution and escape sequence processing.
|
302
|
+
#
|
303
|
+
# @param template [String] The raw template string with placeholders
|
304
|
+
# @return [Array<String, Array<String>>] A tuple of [compiled_template, attribute_vars]
|
305
|
+
def compile_v1(template) # :nodoc:
|
306
|
+
template = template.gsub(":tags", ":attributes").gsub(/ ?:attributes/, ":attributes")
|
307
|
+
template = template.gsub(/%(?!%)/, "%%")
|
308
|
+
|
309
|
+
attribute_vars = []
|
310
|
+
template = template.gsub(V1_PLACEHOLDER_PATTERN) do |match|
|
311
|
+
var_name = match[1, match.length]
|
122
312
|
position = TEMPLATE_ARGUMENT_ORDER.index(var_name)
|
123
313
|
if position
|
124
314
|
"%#{position + 1}$s"
|
125
315
|
else
|
126
|
-
|
127
|
-
"%#{TEMPLATE_ARGUMENT_ORDER.size +
|
316
|
+
attribute_vars << var_name
|
317
|
+
"%#{TEMPLATE_ARGUMENT_ORDER.size + attribute_vars.size}$s"
|
128
318
|
end
|
129
319
|
end
|
130
|
-
[template,
|
320
|
+
[template, attribute_vars]
|
131
321
|
end
|
132
322
|
end
|
133
323
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lumberjack
|
4
|
+
class TemplateRegistry
|
5
|
+
@templates = {}
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Register a log template class with a symbol.
|
9
|
+
#
|
10
|
+
# @param name [Symbol] The name of the template.
|
11
|
+
# @param template [String, Class, #call] The log template to register.
|
12
|
+
def add(name, template)
|
13
|
+
unless template.is_a?(String) || template.is_a?(Class) || template.respond_to?(:call)
|
14
|
+
raise ArgumentError.new("template must be a String, Class, or respond to :call")
|
15
|
+
end
|
16
|
+
|
17
|
+
@templates[name.to_sym] = template
|
18
|
+
end
|
19
|
+
|
20
|
+
# Remove a template from the registry. raise ArgumentError.new("template must be a String, Class, or respond to :call")
|
21
|
+
#
|
22
|
+
# @param name [Symbol] The name of the template to remove.
|
23
|
+
# @return [void]
|
24
|
+
def remove(name)
|
25
|
+
@templates.delete(name.to_sym)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if a template is registered.
|
29
|
+
#
|
30
|
+
# @param name [Symbol] The name of the template.
|
31
|
+
# @return [Boolean] True if the template is registered, false otherwise.
|
32
|
+
def registered?(name)
|
33
|
+
@templates.include(name.to_sym)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get a registered log template class by its symbol.
|
37
|
+
#
|
38
|
+
# @param name [Symbol] The symbol of the registered log template class.
|
39
|
+
# @return [Class, nil] The registered log template class, or nil if not found.
|
40
|
+
def template(name, options = {})
|
41
|
+
template = @templates[name.to_sym]
|
42
|
+
if template.is_a?(Class)
|
43
|
+
template.new(options)
|
44
|
+
elsif template.is_a?(String)
|
45
|
+
template_options = options.slice(:additional_lines, :time_format, :attribute_format, :colorize)
|
46
|
+
Template.new(template, **template_options)
|
47
|
+
else
|
48
|
+
template
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# List all registered log template symbols.
|
53
|
+
#
|
54
|
+
# @return [Array<Symbol>] An array of all registered log template symbols.
|
55
|
+
def registered_templates
|
56
|
+
@templates.dup
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|