makit 0.0.99 → 0.0.111
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/README.md +41 -0
- data/exe/makit +5 -0
- data/lib/makit/apache.rb +7 -11
- data/lib/makit/cli/build_commands.rb +500 -0
- data/lib/makit/cli/generators/base_generator.rb +74 -0
- data/lib/makit/cli/generators/dotnet_generator.rb +50 -0
- data/lib/makit/cli/generators/generator_factory.rb +49 -0
- data/lib/makit/cli/generators/node_generator.rb +50 -0
- data/lib/makit/cli/generators/ruby_generator.rb +77 -0
- data/lib/makit/cli/generators/rust_generator.rb +50 -0
- data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -0
- data/lib/makit/cli/generators/templates/node_templates.rb +161 -0
- data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -0
- data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -0
- data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -0
- data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -0
- data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -0
- data/lib/makit/cli/generators/templates/ruby/test.rb +39 -0
- data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -0
- data/lib/makit/cli/generators/templates/ruby/version.rb +29 -0
- data/lib/makit/cli/generators/templates/rust_templates.rb +128 -0
- data/lib/makit/cli/main.rb +48 -19
- data/lib/makit/cli/project_commands.rb +868 -0
- data/lib/makit/cli/repository_commands.rb +661 -0
- data/lib/makit/cli/utility_commands.rb +521 -0
- data/lib/makit/command_runner.rb +187 -128
- data/lib/makit/commands/compatibility.rb +365 -0
- data/lib/makit/commands/factory.rb +359 -0
- data/lib/makit/commands/middleware/base.rb +73 -0
- data/lib/makit/commands/middleware/cache.rb +248 -0
- data/lib/makit/commands/middleware/command_logger.rb +323 -0
- data/lib/makit/commands/middleware/unified_logger.rb +243 -0
- data/lib/makit/commands/middleware/validator.rb +269 -0
- data/lib/makit/commands/request.rb +254 -0
- data/lib/makit/commands/result.rb +323 -0
- data/lib/makit/commands/runner.rb +317 -0
- data/lib/makit/commands/strategies/base.rb +160 -0
- data/lib/makit/commands/strategies/synchronous.rb +134 -0
- data/lib/makit/commands.rb +24 -3
- data/lib/makit/configuration/gitlab_helper.rb +60 -0
- data/lib/makit/configuration/project.rb +127 -0
- data/lib/makit/configuration/rakefile_helper.rb +43 -0
- data/lib/makit/configuration/step.rb +34 -0
- data/lib/makit/configuration.rb +14 -0
- data/lib/makit/content/default_gitignore.rb +4 -2
- data/lib/makit/content/default_rakefile.rb +4 -2
- data/lib/makit/content/gem_rakefile.rb +4 -2
- data/lib/makit/context.rb +1 -0
- data/lib/makit/data.rb +9 -10
- data/lib/makit/directories.rb +48 -52
- data/lib/makit/directory.rb +38 -52
- data/lib/makit/docs/files.rb +5 -10
- data/lib/makit/docs/rake.rb +16 -20
- data/lib/makit/dotnet/cli.rb +65 -0
- data/lib/makit/dotnet/project.rb +153 -0
- data/lib/makit/dotnet/solution.rb +38 -0
- data/lib/makit/dotnet/solution_classlib.rb +239 -0
- data/lib/makit/dotnet/solution_console.rb +264 -0
- data/lib/makit/dotnet/solution_maui.rb +354 -0
- data/lib/makit/dotnet/solution_wasm.rb +275 -0
- data/lib/makit/dotnet/solution_wpf.rb +304 -0
- data/lib/makit/dotnet.rb +54 -171
- data/lib/makit/email.rb +46 -17
- data/lib/makit/environment.rb +22 -19
- data/lib/makit/examples/runner.rb +370 -0
- data/lib/makit/exceptions.rb +45 -0
- data/lib/makit/fileinfo.rb +3 -5
- data/lib/makit/files.rb +12 -16
- data/lib/makit/gems.rb +40 -39
- data/lib/makit/git/cli.rb +54 -0
- data/lib/makit/git/repository.rb +90 -0
- data/lib/makit/git.rb +44 -91
- data/lib/makit/gitlab_runner.rb +0 -1
- data/lib/makit/humanize.rb +31 -23
- data/lib/makit/indexer.rb +15 -24
- data/lib/makit/logging/configuration.rb +305 -0
- data/lib/makit/logging/format_registry.rb +84 -0
- data/lib/makit/logging/formatters/base.rb +39 -0
- data/lib/makit/logging/formatters/console_formatter.rb +127 -0
- data/lib/makit/logging/formatters/json_formatter.rb +65 -0
- data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -0
- data/lib/makit/logging/formatters/text_formatter.rb +64 -0
- data/lib/makit/logging/log_request.rb +115 -0
- data/lib/makit/logging/logger.rb +159 -0
- data/lib/makit/logging/sinks/base.rb +91 -0
- data/lib/makit/logging/sinks/console.rb +72 -0
- data/lib/makit/logging/sinks/file_sink.rb +92 -0
- data/lib/makit/logging/sinks/structured.rb +129 -0
- data/lib/makit/logging/sinks/unified_file_sink.rb +303 -0
- data/lib/makit/logging.rb +452 -37
- data/lib/makit/markdown.rb +18 -18
- data/lib/makit/mp/basic_object_mp.rb +5 -4
- data/lib/makit/mp/command_mp.rb +5 -5
- data/lib/makit/mp/command_request.mp.rb +3 -2
- data/lib/makit/mp/project_mp.rb +85 -96
- data/lib/makit/mp/string_mp.rb +245 -73
- data/lib/makit/nuget.rb +27 -25
- data/lib/makit/port.rb +25 -27
- data/lib/makit/process.rb +127 -29
- data/lib/makit/protoc.rb +27 -24
- data/lib/makit/rake/cli.rb +196 -0
- data/lib/makit/rake.rb +6 -6
- data/lib/makit/ruby/cli.rb +185 -0
- data/lib/makit/ruby.rb +25 -0
- data/lib/makit/secrets.rb +18 -18
- data/lib/makit/serializer.rb +29 -27
- data/lib/makit/services/builder.rb +186 -0
- data/lib/makit/services/error_handler.rb +226 -0
- data/lib/makit/services/repository_manager.rb +229 -0
- data/lib/makit/services/validator.rb +112 -0
- data/lib/makit/setup/classlib.rb +53 -0
- data/lib/makit/setup/gem.rb +250 -0
- data/lib/makit/setup/runner.rb +40 -0
- data/lib/makit/show.rb +16 -16
- data/lib/makit/storage.rb +32 -37
- data/lib/makit/symbols.rb +12 -0
- data/lib/makit/task_hooks.rb +125 -0
- data/lib/makit/task_info.rb +63 -21
- data/lib/makit/tasks/at_exit.rb +13 -0
- data/lib/makit/tasks/build.rb +18 -0
- data/lib/makit/tasks/clean.rb +11 -0
- data/lib/makit/tasks/hook_manager.rb +239 -0
- data/lib/makit/tasks/init.rb +47 -0
- data/lib/makit/tasks/integrate.rb +15 -0
- data/lib/makit/tasks/pull_incoming.rb +12 -0
- data/lib/makit/tasks/setup.rb +6 -0
- data/lib/makit/tasks/sync.rb +11 -0
- data/lib/makit/tasks/task_monkey_patch.rb +79 -0
- data/lib/makit/tasks.rb +5 -150
- data/lib/makit/test_cache.rb +239 -0
- data/lib/makit/v1/makit.v1_pb.rb +34 -35
- data/lib/makit/v1/makit.v1_services_pb.rb +2 -0
- data/lib/makit/version.rb +1 -57
- data/lib/makit/wix.rb +23 -23
- data/lib/makit/yaml.rb +18 -6
- data/lib/makit.rb +2 -261
- metadata +109 -145
- data/lib/makit/cli/clean.rb +0 -14
- data/lib/makit/cli/clone.rb +0 -59
- data/lib/makit/cli/init.rb +0 -38
- data/lib/makit/cli/make.rb +0 -54
- data/lib/makit/cli/new.rb +0 -37
- data/lib/makit/cli/nuget_cache.rb +0 -38
- data/lib/makit/cli/pull.rb +0 -31
- data/lib/makit/cli/setup.rb +0 -71
- data/lib/makit/cli/work.rb +0 -21
- data/lib/makit/content/default_gitignore.txt +0 -222
@@ -0,0 +1,305 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Makit
|
4
|
+
module Logging
|
5
|
+
# Configuration management for unified logging
|
6
|
+
#
|
7
|
+
# Provides schema validation, default configurations, and helper methods
|
8
|
+
# for setting up the unified file sink with various output configurations.
|
9
|
+
#
|
10
|
+
# @example Basic configuration
|
11
|
+
# config = Configuration.new(
|
12
|
+
# configurations: [
|
13
|
+
# { file: $stdout, format: :console },
|
14
|
+
# { file: "logs/app.log", format: :json }
|
15
|
+
# ]
|
16
|
+
# )
|
17
|
+
#
|
18
|
+
# @example YAML configuration
|
19
|
+
# config = Configuration.from_yaml("config/logging.yml")
|
20
|
+
#
|
21
|
+
# @example Environment-based configuration
|
22
|
+
# config = Configuration.for_environment(:production)
|
23
|
+
class Configuration
|
24
|
+
# @return [Array<Hash>] list of output configurations
|
25
|
+
attr_reader :configurations
|
26
|
+
|
27
|
+
# Initialize configuration
|
28
|
+
#
|
29
|
+
# @param configurations [Array<Hash>] list of output configurations
|
30
|
+
def initialize(configurations: [])
|
31
|
+
@configurations = configurations
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create configuration from YAML file
|
35
|
+
#
|
36
|
+
# @param yaml_file [String] path to YAML configuration file
|
37
|
+
# @return [Configuration] new configuration instance
|
38
|
+
def self.from_yaml(yaml_file)
|
39
|
+
require "yaml"
|
40
|
+
data = YAML.load_file(yaml_file)
|
41
|
+
configurations = data["logging"]["sinks"] || []
|
42
|
+
|
43
|
+
# Convert string keys to symbols
|
44
|
+
configurations = configurations.map do |config|
|
45
|
+
config.transform_keys(&:to_sym)
|
46
|
+
end
|
47
|
+
|
48
|
+
new(configurations: configurations)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Create configuration from JSON file
|
52
|
+
#
|
53
|
+
# @param json_file [String] path to JSON configuration file
|
54
|
+
# @return [Configuration] new configuration instance
|
55
|
+
def self.from_json(json_file)
|
56
|
+
require "json"
|
57
|
+
data = JSON.parse(File.read(json_file))
|
58
|
+
configurations = data["logging"]["sinks"] || []
|
59
|
+
|
60
|
+
# Convert string keys to symbols
|
61
|
+
configurations = configurations.map do |config|
|
62
|
+
config.transform_keys(&:to_sym)
|
63
|
+
end
|
64
|
+
|
65
|
+
new(configurations: configurations)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Create environment-specific configuration
|
69
|
+
#
|
70
|
+
# @param environment [Symbol] environment name (:development, :production, :test)
|
71
|
+
# @return [Configuration] new configuration instance
|
72
|
+
def self.for_environment(environment)
|
73
|
+
case environment
|
74
|
+
when :development
|
75
|
+
development_config
|
76
|
+
when :production
|
77
|
+
production_config
|
78
|
+
when :test
|
79
|
+
test_config
|
80
|
+
when :ci
|
81
|
+
ci_config
|
82
|
+
else
|
83
|
+
default_config
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get default configuration
|
88
|
+
#
|
89
|
+
# @return [Configuration] default configuration
|
90
|
+
def self.default_config
|
91
|
+
new(
|
92
|
+
configurations: [
|
93
|
+
{ file: $stdout, format: :console },
|
94
|
+
{ file: "artifacts/makit.log", format: :json, append: true },
|
95
|
+
],
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Get development configuration
|
100
|
+
#
|
101
|
+
# @return [Configuration] development configuration
|
102
|
+
def self.development_config
|
103
|
+
new(
|
104
|
+
configurations: [
|
105
|
+
{
|
106
|
+
file: $stdout,
|
107
|
+
format: :console,
|
108
|
+
show_timestamp: true,
|
109
|
+
show_level: true,
|
110
|
+
},
|
111
|
+
{
|
112
|
+
file: "logs/development.log",
|
113
|
+
format: :text,
|
114
|
+
append: true,
|
115
|
+
include_context: true,
|
116
|
+
},
|
117
|
+
{
|
118
|
+
file: "logs/debug.log",
|
119
|
+
format: :json,
|
120
|
+
append: true,
|
121
|
+
min_level: :debug,
|
122
|
+
},
|
123
|
+
],
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Get production configuration
|
128
|
+
#
|
129
|
+
# @return [Configuration] production configuration
|
130
|
+
def self.production_config
|
131
|
+
new(
|
132
|
+
configurations: [
|
133
|
+
{
|
134
|
+
file: "logs/application.log",
|
135
|
+
format: :json,
|
136
|
+
append: true,
|
137
|
+
include_metadata: true,
|
138
|
+
rotation: { max_size: "100MB", max_files: 10 },
|
139
|
+
},
|
140
|
+
{
|
141
|
+
file: "logs/errors.log",
|
142
|
+
format: :json,
|
143
|
+
append: true,
|
144
|
+
min_level: :error,
|
145
|
+
include_metadata: true,
|
146
|
+
},
|
147
|
+
],
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Get test configuration
|
152
|
+
#
|
153
|
+
# @return [Configuration] test configuration
|
154
|
+
def self.test_config
|
155
|
+
new(
|
156
|
+
configurations: [
|
157
|
+
{
|
158
|
+
file: "logs/test.log",
|
159
|
+
format: :text,
|
160
|
+
append: false,
|
161
|
+
include_context: true,
|
162
|
+
},
|
163
|
+
],
|
164
|
+
)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Get CI/CD configuration
|
168
|
+
#
|
169
|
+
# @return [Configuration] CI configuration
|
170
|
+
def self.ci_config
|
171
|
+
new(
|
172
|
+
configurations: [
|
173
|
+
{
|
174
|
+
file: $stdout,
|
175
|
+
format: :console,
|
176
|
+
show_level: true,
|
177
|
+
},
|
178
|
+
{
|
179
|
+
file: "artifacts/build.log",
|
180
|
+
format: :json,
|
181
|
+
append: true,
|
182
|
+
include_metadata: true,
|
183
|
+
},
|
184
|
+
],
|
185
|
+
)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Validate configuration
|
189
|
+
#
|
190
|
+
# @return [Boolean] true if valid
|
191
|
+
# @raise [ArgumentError] if configuration is invalid
|
192
|
+
def validate!
|
193
|
+
raise ArgumentError, "configurations must be an array" unless @configurations.is_a?(Array)
|
194
|
+
raise ArgumentError, "at least one configuration is required" if @configurations.empty?
|
195
|
+
|
196
|
+
@configurations.each_with_index do |config, index|
|
197
|
+
validate_single_configuration(config, index)
|
198
|
+
end
|
199
|
+
|
200
|
+
true
|
201
|
+
end
|
202
|
+
|
203
|
+
# Check if configuration is valid
|
204
|
+
#
|
205
|
+
# @return [Boolean] true if valid
|
206
|
+
def valid?
|
207
|
+
validate!
|
208
|
+
true
|
209
|
+
rescue ArgumentError
|
210
|
+
false
|
211
|
+
end
|
212
|
+
|
213
|
+
# Get configuration as hash
|
214
|
+
#
|
215
|
+
# @return [Hash] configuration as hash
|
216
|
+
def to_hash
|
217
|
+
{
|
218
|
+
logging: {
|
219
|
+
sinks: @configurations,
|
220
|
+
},
|
221
|
+
}
|
222
|
+
end
|
223
|
+
|
224
|
+
# Save configuration to YAML file
|
225
|
+
#
|
226
|
+
# @param yaml_file [String] path to YAML file
|
227
|
+
# @return [void]
|
228
|
+
def save_yaml(yaml_file)
|
229
|
+
require "yaml"
|
230
|
+
FileUtils.mkdir_p(File.dirname(yaml_file))
|
231
|
+
File.write(yaml_file, to_hash.to_yaml)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Save configuration to JSON file
|
235
|
+
#
|
236
|
+
# @param json_file [String] path to JSON file
|
237
|
+
# @return [void]
|
238
|
+
def save_json(json_file)
|
239
|
+
require "json"
|
240
|
+
FileUtils.mkdir_p(File.dirname(json_file))
|
241
|
+
File.write(json_file, JSON.pretty_generate(to_hash))
|
242
|
+
end
|
243
|
+
|
244
|
+
private
|
245
|
+
|
246
|
+
# Validate a single configuration
|
247
|
+
#
|
248
|
+
# @param config [Hash] configuration to validate
|
249
|
+
# @param index [Integer] configuration index for error messages
|
250
|
+
# @raise [ArgumentError] if configuration is invalid
|
251
|
+
def validate_single_configuration(config, index)
|
252
|
+
raise ArgumentError, "configuration #{index} must be a hash" unless config.is_a?(Hash)
|
253
|
+
|
254
|
+
required_keys = [:file, :format]
|
255
|
+
missing_keys = required_keys - config.keys
|
256
|
+
raise ArgumentError, "configuration #{index} missing required keys: #{missing_keys.join(", ")}" unless missing_keys.empty?
|
257
|
+
|
258
|
+
# Validate file
|
259
|
+
file = config[:file]
|
260
|
+
unless file.is_a?(String) || file.is_a?(IO) || file.respond_to?(:write)
|
261
|
+
raise ArgumentError, "configuration #{index} file must be a String path, IO object, or writable object"
|
262
|
+
end
|
263
|
+
|
264
|
+
# Validate format
|
265
|
+
format = config[:format]
|
266
|
+
unless format.is_a?(Symbol) || format.is_a?(String)
|
267
|
+
raise ArgumentError, "configuration #{index} format must be a Symbol or String"
|
268
|
+
end
|
269
|
+
|
270
|
+
# Validate log levels if specified
|
271
|
+
if config[:min_level] && !valid_log_level?(config[:min_level])
|
272
|
+
raise ArgumentError, "configuration #{index} min_level must be a valid log level"
|
273
|
+
end
|
274
|
+
|
275
|
+
if config[:max_level] && !valid_log_level?(config[:max_level])
|
276
|
+
raise ArgumentError, "configuration #{index} max_level must be a valid log level"
|
277
|
+
end
|
278
|
+
|
279
|
+
# Validate rotation if specified
|
280
|
+
if config[:rotation] && !valid_rotation_config?(config[:rotation])
|
281
|
+
raise ArgumentError, "configuration #{index} rotation must be a valid rotation configuration"
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Check if log level is valid
|
286
|
+
#
|
287
|
+
# @param level [Symbol] log level to check
|
288
|
+
# @return [Boolean] true if valid
|
289
|
+
def valid_log_level?(level)
|
290
|
+
%i[debug info warn error fatal success].include?(level)
|
291
|
+
end
|
292
|
+
|
293
|
+
# Check if rotation configuration is valid
|
294
|
+
#
|
295
|
+
# @param rotation [Hash] rotation configuration
|
296
|
+
# @return [Boolean] true if valid
|
297
|
+
def valid_rotation_config?(rotation)
|
298
|
+
return false unless rotation.is_a?(Hash)
|
299
|
+
|
300
|
+
valid_keys = [:max_size, :max_files, :compress, :pattern]
|
301
|
+
rotation.keys.all? { |key| valid_keys.include?(key) }
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Makit
|
4
|
+
module Logging
|
5
|
+
# Registry for managing available log formatters
|
6
|
+
#
|
7
|
+
# Provides a centralized way to register, retrieve, and manage formatters
|
8
|
+
# by name. This allows for easy extension and configuration of formatters.
|
9
|
+
#
|
10
|
+
# @example Registering a custom formatter
|
11
|
+
# FormatRegistry.register(:audit, AuditFormatter)
|
12
|
+
# formatter = FormatRegistry.get(:audit).new
|
13
|
+
#
|
14
|
+
# @example Using built-in formatters
|
15
|
+
# formatter = FormatRegistry.get(:json).new
|
16
|
+
# formatter = FormatRegistry.get(:text).new(timestamp_format: "%H:%M:%S")
|
17
|
+
class FormatRegistry
|
18
|
+
@formatters = {}
|
19
|
+
|
20
|
+
class << self
|
21
|
+
# @return [Hash] registered formatters
|
22
|
+
attr_reader :formatters
|
23
|
+
|
24
|
+
# Register a formatter class with a name
|
25
|
+
#
|
26
|
+
# @param name [Symbol, String] the name to register the formatter under
|
27
|
+
# @param formatter_class [Class] the formatter class to register
|
28
|
+
# @return [void]
|
29
|
+
def register(name, formatter_class)
|
30
|
+
@formatters[name.to_sym] = formatter_class
|
31
|
+
end
|
32
|
+
|
33
|
+
# Get a formatter class by name
|
34
|
+
#
|
35
|
+
# @param name [Symbol, String] the name of the formatter
|
36
|
+
# @return [Class] the formatter class
|
37
|
+
# @raise [ArgumentError] if formatter is not found
|
38
|
+
def get(name)
|
39
|
+
@formatters[name.to_sym] || raise(ArgumentError, "Unknown formatter: #{name}")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get all available formatter names
|
43
|
+
#
|
44
|
+
# @return [Array<Symbol>] list of registered formatter names
|
45
|
+
def available_formats
|
46
|
+
@formatters.keys
|
47
|
+
end
|
48
|
+
|
49
|
+
# Check if a formatter is registered
|
50
|
+
#
|
51
|
+
# @param name [Symbol, String] the name to check
|
52
|
+
# @return [Boolean] true if formatter is registered
|
53
|
+
def registered?(name)
|
54
|
+
@formatters.key?(name.to_sym)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Clear all registered formatters
|
58
|
+
#
|
59
|
+
# @return [void]
|
60
|
+
def clear
|
61
|
+
@formatters.clear
|
62
|
+
end
|
63
|
+
|
64
|
+
# Register built-in formatters
|
65
|
+
#
|
66
|
+
# @return [void]
|
67
|
+
def register_built_ins
|
68
|
+
require_relative "formatters/json_formatter"
|
69
|
+
require_relative "formatters/text_formatter"
|
70
|
+
require_relative "formatters/plain_text_formatter"
|
71
|
+
require_relative "formatters/console_formatter"
|
72
|
+
|
73
|
+
register(:json, Formatters::JsonFormatter)
|
74
|
+
register(:text, Formatters::TextFormatter)
|
75
|
+
register(:plain, Formatters::PlainTextFormatter)
|
76
|
+
register(:console, Formatters::ConsoleFormatter)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Initialize registry with built-in formatters
|
81
|
+
register_built_ins
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Makit
|
4
|
+
module Logging
|
5
|
+
module Formatters
|
6
|
+
# Base class for all logging formatters
|
7
|
+
#
|
8
|
+
# Formatters handle the conversion of log requests into formatted strings
|
9
|
+
# that can be written to various outputs (console, files, etc.).
|
10
|
+
# This separates formatting concerns from output routing concerns.
|
11
|
+
#
|
12
|
+
# @example Creating a custom formatter
|
13
|
+
# class CustomFormatter < Base
|
14
|
+
# def format(log_request)
|
15
|
+
# "#{log_request.level.upcase}: #{log_request.message}"
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
class Base
|
19
|
+
# Format a log request into a string
|
20
|
+
#
|
21
|
+
# @param log_request [LogRequest] the log request to format
|
22
|
+
# @return [String] the formatted log entry
|
23
|
+
def format(log_request)
|
24
|
+
raise NotImplementedError, "Subclasses must implement #format"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get formatter configuration
|
28
|
+
#
|
29
|
+
# @return [Hash] formatter configuration
|
30
|
+
def config
|
31
|
+
{
|
32
|
+
name: self.class.name.split("::").last,
|
33
|
+
type: self.class.name,
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "colorize"
|
4
|
+
require_relative "base"
|
5
|
+
|
6
|
+
module Makit
|
7
|
+
module Logging
|
8
|
+
module Formatters
|
9
|
+
# Console formatter for colored log output
|
10
|
+
#
|
11
|
+
# Formats log requests for console display with colors, symbols, and optional
|
12
|
+
# timestamps/levels. This is specifically designed for human-readable console output.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# formatter = ConsoleFormatter.new
|
16
|
+
# formatted = formatter.format(log_request)
|
17
|
+
# # => "→ Processing started" (with appropriate color)
|
18
|
+
class ConsoleFormatter < Base
|
19
|
+
# @return [Boolean] whether to show timestamps
|
20
|
+
attr_reader :show_timestamp
|
21
|
+
# @return [Boolean] whether to show log levels
|
22
|
+
attr_reader :show_level
|
23
|
+
|
24
|
+
# Initialize console formatter
|
25
|
+
#
|
26
|
+
# @param show_timestamp [Boolean] whether to show timestamps (default: false)
|
27
|
+
# @param show_level [Boolean] whether to show log levels (default: false)
|
28
|
+
def initialize(show_timestamp: false, show_level: false)
|
29
|
+
@show_timestamp = show_timestamp
|
30
|
+
@show_level = show_level
|
31
|
+
end
|
32
|
+
|
33
|
+
# Format log request for console display
|
34
|
+
#
|
35
|
+
# @param log_request [LogRequest] the log request to format
|
36
|
+
# @return [String] console formatted log entry with colors
|
37
|
+
def format(log_request)
|
38
|
+
parts = []
|
39
|
+
|
40
|
+
# Add timestamp if enabled
|
41
|
+
if @show_timestamp
|
42
|
+
timestamp = log_request.timestamp.strftime("%H:%M:%S")
|
43
|
+
parts << "[#{timestamp}]".colorize(:light_black)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Add log level if enabled
|
47
|
+
if @show_level
|
48
|
+
level_str = log_request.level.to_s.upcase
|
49
|
+
level_color = get_level_color(log_request.level)
|
50
|
+
parts << level_str.colorize(level_color)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Add symbol and message
|
54
|
+
symbol = get_level_symbol(log_request.level)
|
55
|
+
symbol_color = get_level_color(log_request.level)
|
56
|
+
message = log_request.message
|
57
|
+
|
58
|
+
# Add context if present
|
59
|
+
if !log_request.context.empty?
|
60
|
+
context_str = log_request.context.map { |k, v| "#{k}=#{v}" }.join(" ")
|
61
|
+
message += " #{context_str}".colorize(:light_black)
|
62
|
+
end
|
63
|
+
|
64
|
+
parts << "#{symbol} #{message}".colorize(symbol_color)
|
65
|
+
|
66
|
+
parts.join(" ")
|
67
|
+
end
|
68
|
+
|
69
|
+
# Get formatter configuration
|
70
|
+
#
|
71
|
+
# @return [Hash] formatter configuration
|
72
|
+
def config
|
73
|
+
super.merge(
|
74
|
+
show_timestamp: @show_timestamp,
|
75
|
+
show_level: @show_level,
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Get the color for a log level
|
82
|
+
#
|
83
|
+
# @param level [Symbol] the log level
|
84
|
+
# @return [Symbol] the color for the level
|
85
|
+
def get_level_color(level)
|
86
|
+
case level
|
87
|
+
when :debug
|
88
|
+
:grey
|
89
|
+
when :info
|
90
|
+
:grey
|
91
|
+
when :warn
|
92
|
+
:light_yellow
|
93
|
+
when :error, :fatal
|
94
|
+
:light_red
|
95
|
+
when :success
|
96
|
+
:green
|
97
|
+
else
|
98
|
+
:white
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Get the symbol for a log level
|
103
|
+
#
|
104
|
+
# @param level [Symbol] the log level
|
105
|
+
# @return [String] the symbol for the level
|
106
|
+
def get_level_symbol(level)
|
107
|
+
case level
|
108
|
+
when :debug
|
109
|
+
"•"
|
110
|
+
when :info
|
111
|
+
" " #"→"
|
112
|
+
when :warn
|
113
|
+
"!" #"⚠"
|
114
|
+
when :error
|
115
|
+
"✗"
|
116
|
+
when :fatal
|
117
|
+
"💀"
|
118
|
+
when :success
|
119
|
+
"✓"
|
120
|
+
else
|
121
|
+
"•"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require_relative "base"
|
5
|
+
|
6
|
+
module Makit
|
7
|
+
module Logging
|
8
|
+
module Formatters
|
9
|
+
# JSON formatter for structured logging
|
10
|
+
#
|
11
|
+
# Formats log requests as JSON objects with timestamp, level, message, and context.
|
12
|
+
# This is ideal for log aggregation systems and structured data analysis.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# formatter = JsonFormatter.new
|
16
|
+
# formatted = formatter.format(log_request)
|
17
|
+
# # => '{"timestamp":"2024-01-15T10:30:45Z","level":"INFO","message":"User logged in","context":{"user_id":123}}'
|
18
|
+
class JsonFormatter < Base
|
19
|
+
# @return [Hash] additional options for JSON formatting
|
20
|
+
attr_reader :options
|
21
|
+
|
22
|
+
# Initialize JSON formatter
|
23
|
+
#
|
24
|
+
# @param options [Hash] JSON generation options
|
25
|
+
def initialize(options: {})
|
26
|
+
@options = {
|
27
|
+
indent: nil,
|
28
|
+
space: nil,
|
29
|
+
space_before: nil,
|
30
|
+
object_nl: nil,
|
31
|
+
array_nl: nil,
|
32
|
+
allow_nan: false,
|
33
|
+
max_nesting: 100,
|
34
|
+
}.merge(options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Format log request as JSON
|
38
|
+
#
|
39
|
+
# @param log_request [LogRequest] the log request to format
|
40
|
+
# @return [String] JSON formatted log entry
|
41
|
+
def format(log_request)
|
42
|
+
log_data = {
|
43
|
+
timestamp: log_request.timestamp.iso8601,
|
44
|
+
level: log_request.level.to_s.upcase,
|
45
|
+
message: log_request.message,
|
46
|
+
}
|
47
|
+
|
48
|
+
# Add context if present
|
49
|
+
log_data[:context] = log_request.context unless log_request.context.empty?
|
50
|
+
|
51
|
+
JSON.generate(log_data, @options)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get formatter configuration
|
55
|
+
#
|
56
|
+
# @return [Hash] formatter configuration including JSON options
|
57
|
+
def config
|
58
|
+
super.merge(
|
59
|
+
json_options: @options,
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module Makit
|
6
|
+
module Logging
|
7
|
+
module Formatters
|
8
|
+
# Plain text formatter with just the message
|
9
|
+
#
|
10
|
+
# Formats log requests as plain text containing only the message content.
|
11
|
+
# This is useful for simple log files where only the message matters.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# formatter = PlainTextFormatter.new
|
15
|
+
# formatted = formatter.format(log_request)
|
16
|
+
# # => 'User logged in'
|
17
|
+
class PlainTextFormatter < Base
|
18
|
+
# @return [Boolean] whether to include context in output
|
19
|
+
attr_reader :include_context
|
20
|
+
|
21
|
+
# Initialize plain text formatter
|
22
|
+
#
|
23
|
+
# @param include_context [Boolean] whether to include context in output
|
24
|
+
def initialize(include_context: false)
|
25
|
+
@include_context = include_context
|
26
|
+
end
|
27
|
+
|
28
|
+
# Format log request as plain text
|
29
|
+
#
|
30
|
+
# @param log_request [LogRequest] the log request to format
|
31
|
+
# @return [String] plain text formatted log entry
|
32
|
+
def format(log_request)
|
33
|
+
message = log_request.message
|
34
|
+
|
35
|
+
# Add context if enabled and present
|
36
|
+
if @include_context && !log_request.context.empty?
|
37
|
+
# Create a more readable context representation
|
38
|
+
context_parts = log_request.context.map do |k, v|
|
39
|
+
# Format values nicely based on their type
|
40
|
+
formatted_value = case v
|
41
|
+
when String
|
42
|
+
v.include?(" ") ? "\"#{v}\"" : v
|
43
|
+
when Hash, Array
|
44
|
+
v.inspect
|
45
|
+
when Time
|
46
|
+
v.strftime("%Y-%m-%d %H:%M:%S")
|
47
|
+
else
|
48
|
+
v.to_s
|
49
|
+
end
|
50
|
+
"#{k}: #{formatted_value}"
|
51
|
+
end
|
52
|
+
|
53
|
+
context_str = context_parts.join(", ")
|
54
|
+
message += " (#{context_str})"
|
55
|
+
end
|
56
|
+
|
57
|
+
message
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get formatter configuration
|
61
|
+
#
|
62
|
+
# @return [Hash] formatter configuration
|
63
|
+
def config
|
64
|
+
super.merge(
|
65
|
+
include_context: @include_context,
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|