makit 0.0.112 → 0.0.128

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.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -41
  3. data/exe/makit +5 -5
  4. data/lib/makit/apache.rb +28 -28
  5. data/lib/makit/cli/build_commands.rb +500 -500
  6. data/lib/makit/cli/generators/base_generator.rb +74 -74
  7. data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
  8. data/lib/makit/cli/generators/generator_factory.rb +49 -49
  9. data/lib/makit/cli/generators/node_generator.rb +50 -50
  10. data/lib/makit/cli/generators/ruby_generator.rb +77 -77
  11. data/lib/makit/cli/generators/rust_generator.rb +50 -50
  12. data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
  13. data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
  14. data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
  15. data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -40
  16. data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
  17. data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
  18. data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
  19. data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
  20. data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
  21. data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
  22. data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
  23. data/lib/makit/cli/main.rb +62 -62
  24. data/lib/makit/cli/project_commands.rb +868 -868
  25. data/lib/makit/cli/repository_commands.rb +661 -661
  26. data/lib/makit/cli/utility_commands.rb +521 -521
  27. data/lib/makit/commands/factory.rb +359 -359
  28. data/lib/makit/commands/middleware/base.rb +73 -73
  29. data/lib/makit/commands/middleware/cache.rb +248 -248
  30. data/lib/makit/commands/middleware/command_logger.rb +311 -320
  31. data/lib/makit/commands/middleware/validator.rb +269 -269
  32. data/lib/makit/commands/request.rb +316 -254
  33. data/lib/makit/commands/result.rb +323 -323
  34. data/lib/makit/commands/runner.rb +368 -337
  35. data/lib/makit/commands/strategies/base.rb +171 -160
  36. data/lib/makit/commands/strategies/synchronous.rb +139 -134
  37. data/lib/makit/commands.rb +50 -51
  38. data/lib/makit/configuration/gitlab_helper.rb +58 -60
  39. data/lib/makit/configuration/project.rb +167 -127
  40. data/lib/makit/configuration/rakefile_helper.rb +43 -43
  41. data/lib/makit/configuration/step.rb +34 -34
  42. data/lib/makit/configuration.rb +14 -14
  43. data/lib/makit/content/default_gitignore.rb +7 -7
  44. data/lib/makit/content/default_gitignore.txt +226 -0
  45. data/lib/makit/content/default_rakefile.rb +13 -13
  46. data/lib/makit/content/gem_rakefile.rb +16 -16
  47. data/lib/makit/context.rb +1 -1
  48. data/lib/makit/data.rb +49 -49
  49. data/lib/makit/directories.rb +140 -141
  50. data/lib/makit/directory.rb +262 -262
  51. data/lib/makit/docs/files.rb +89 -89
  52. data/lib/makit/docs/rake.rb +102 -102
  53. data/lib/makit/dotnet/cli.rb +69 -65
  54. data/lib/makit/dotnet/project.rb +217 -153
  55. data/lib/makit/dotnet/solution.rb +38 -38
  56. data/lib/makit/dotnet/solution_classlib.rb +239 -239
  57. data/lib/makit/dotnet/solution_console.rb +264 -264
  58. data/lib/makit/dotnet/solution_maui.rb +354 -354
  59. data/lib/makit/dotnet/solution_wasm.rb +275 -275
  60. data/lib/makit/dotnet/solution_wpf.rb +304 -304
  61. data/lib/makit/dotnet.rb +102 -102
  62. data/lib/makit/email.rb +90 -90
  63. data/lib/makit/environment.rb +142 -142
  64. data/lib/makit/examples/runner.rb +370 -370
  65. data/lib/makit/exceptions.rb +45 -45
  66. data/lib/makit/fileinfo.rb +24 -24
  67. data/lib/makit/files.rb +43 -43
  68. data/lib/makit/gems.rb +40 -40
  69. data/lib/makit/git/cli.rb +54 -54
  70. data/lib/makit/git/repository.rb +90 -90
  71. data/lib/makit/git.rb +98 -98
  72. data/lib/makit/gitlab_runner.rb +59 -59
  73. data/lib/makit/humanize.rb +137 -137
  74. data/lib/makit/indexer.rb +47 -47
  75. data/lib/makit/logging/configuration.rb +308 -305
  76. data/lib/makit/logging/format_registry.rb +84 -84
  77. data/lib/makit/logging/formatters/base.rb +39 -39
  78. data/lib/makit/logging/formatters/console_formatter.rb +140 -140
  79. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  80. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  81. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  82. data/lib/makit/logging/log_request.rb +119 -115
  83. data/lib/makit/logging/logger.rb +199 -163
  84. data/lib/makit/logging/sinks/base.rb +91 -91
  85. data/lib/makit/logging/sinks/console.rb +72 -72
  86. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  87. data/lib/makit/logging/sinks/structured.rb +123 -129
  88. data/lib/makit/logging/sinks/unified_file_sink.rb +296 -303
  89. data/lib/makit/logging.rb +565 -530
  90. data/lib/makit/markdown.rb +75 -75
  91. data/lib/makit/mp/basic_object_mp.rb +17 -17
  92. data/lib/makit/mp/command_mp.rb +13 -13
  93. data/lib/makit/mp/command_request.mp.rb +17 -17
  94. data/lib/makit/mp/project_mp.rb +199 -199
  95. data/lib/makit/mp/string_mp.rb +191 -193
  96. data/lib/makit/nuget.rb +74 -74
  97. data/lib/makit/port.rb +32 -32
  98. data/lib/makit/process.rb +163 -163
  99. data/lib/makit/protoc.rb +107 -107
  100. data/lib/makit/rake/cli.rb +196 -196
  101. data/lib/makit/rake.rb +25 -25
  102. data/lib/makit/ruby/cli.rb +185 -185
  103. data/lib/makit/ruby.rb +25 -25
  104. data/lib/makit/secrets.rb +51 -51
  105. data/lib/makit/serializer.rb +130 -130
  106. data/lib/makit/services/builder.rb +186 -186
  107. data/lib/makit/services/error_handler.rb +226 -226
  108. data/lib/makit/services/repository_manager.rb +231 -229
  109. data/lib/makit/services/validator.rb +112 -112
  110. data/lib/makit/setup/classlib.rb +94 -53
  111. data/lib/makit/setup/gem.rb +268 -263
  112. data/lib/makit/setup/razorclasslib.rb +91 -0
  113. data/lib/makit/setup/runner.rb +54 -45
  114. data/lib/makit/setup.rb +5 -5
  115. data/lib/makit/show.rb +110 -110
  116. data/lib/makit/storage.rb +126 -126
  117. data/lib/makit/symbols.rb +170 -170
  118. data/lib/makit/task_info.rb +128 -128
  119. data/lib/makit/tasks/at_exit.rb +15 -13
  120. data/lib/makit/tasks/build.rb +22 -19
  121. data/lib/makit/tasks/clean.rb +13 -11
  122. data/lib/makit/tasks/configure.rb +10 -0
  123. data/lib/makit/tasks/format.rb +10 -0
  124. data/lib/makit/tasks/hook_manager.rb +391 -393
  125. data/lib/makit/tasks/init.rb +49 -47
  126. data/lib/makit/tasks/integrate.rb +29 -17
  127. data/lib/makit/tasks/pull_incoming.rb +13 -11
  128. data/lib/makit/tasks/setup.rb +13 -6
  129. data/lib/makit/tasks/sync.rb +17 -12
  130. data/lib/makit/tasks/tag.rb +16 -15
  131. data/lib/makit/tasks/task_monkey_patch.rb +81 -79
  132. data/lib/makit/tasks/test.rb +22 -0
  133. data/lib/makit/tasks/update.rb +18 -0
  134. data/lib/makit/tasks.rb +20 -15
  135. data/lib/makit/test_cache.rb +239 -239
  136. data/lib/makit/tree.rb +37 -37
  137. data/lib/makit/v1/makit.v1_pb.rb +35 -34
  138. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  139. data/lib/makit/version.rb +5 -5
  140. data/lib/makit/version_util.rb +21 -21
  141. data/lib/makit/wix.rb +95 -95
  142. data/lib/makit/yaml.rb +29 -29
  143. data/lib/makit/zip.rb +17 -17
  144. data/lib/makit copy.rb +44 -44
  145. data/lib/makit.rb +39 -40
  146. metadata +69 -7
  147. data/lib/makit/commands/middleware/unified_logger.rb +0 -243
data/lib/makit/logging.rb CHANGED
@@ -1,530 +1,565 @@
1
- # frozen_string_literal: true
2
-
3
- require "logger"
4
- begin
5
- require "colorize"
6
- rescue LoadError
7
- # colorize gem not available, define a no-op colorize method
8
- class String
9
- def colorize(*args)
10
- self
11
- end
12
- end
13
- end
14
- require_relative "symbols"
15
- require_relative "logging/logger"
16
- require_relative "logging/log_request"
17
- require_relative "logging/sinks/base"
18
- require_relative "logging/sinks/console"
19
- require_relative "logging/sinks/file_sink"
20
- require_relative "logging/sinks/structured"
21
- require_relative "logging/sinks/unified_file_sink"
22
- require_relative "logging/configuration"
23
-
24
- # This module provides classes for the Makit gem.
25
- module Makit
26
- # Logging infrastructure for the Makit gem
27
- #
28
- # This module provides a comprehensive logging system with multiple formatters,
29
- # multi-target output capabilities, and configurable log levels. It supports:
30
- #
31
- # - Plain text logging (suitable for files)
32
- # - Colored console output (improved terminal readability)
33
- # - Structured JSON logging (machine-parsable format)
34
- # - Multi-target logging (write to multiple destinations simultaneously)
35
- # - Sink-based output processing (similar to Commands::Runner)
36
- #
37
- # @deprecated The legacy MultiLogger, Formatter classes, and create_logger method
38
- # are deprecated and will be removed in version 0.2.0. Use the new Logger class
39
- # with sinks instead.
40
- #
41
- # @example Basic usage with new architecture (recommended)
42
- # Makit::Logging.info("Application started")
43
- # Makit::Logging.success("Build completed")
44
- # Makit::Logging.error("Something went wrong")
45
- #
46
- # @example Custom logger configuration
47
- # logger = Makit::Logging::Logger.new(
48
- # sinks: [
49
- # Makit::Logging::Sinks::Console.new,
50
- # Makit::Logging::Sinks::FileSink.new(log_file: "custom.log")
51
- # ]
52
- # )
53
- # logger.info("Custom message")
54
- #
55
- # @example Legacy usage (deprecated - will be removed in v0.2.0)
56
- # logger = Makit::Logging::MultiLogger.create_logger
57
- # logger.info("Application started")
58
- # logger.error("Something went wrong")
59
- module Logging
60
- ANSI_COLOR_REGEX = /\e\[[0-9;]*m/
61
-
62
- # Log levels that can be configured
63
- LOG_LEVELS = {
64
- debug: ::Logger::DEBUG,
65
- info: ::Logger::INFO,
66
- warn: ::Logger::WARN,
67
- error: ::Logger::ERROR,
68
- fatal: ::Logger::FATAL,
69
- }.freeze
70
-
71
- # Default log level
72
- DEFAULT_LOG_LEVEL = :info
73
-
74
- # Get the current log level from environment or use default
75
- def self.current_log_level
76
- env_level = ENV["LOG_LEVEL"]&.downcase&.to_sym
77
- return env_level if env_level && LOG_LEVELS.key?(env_level)
78
- DEFAULT_LOG_LEVEL
79
- end
80
-
81
- # Logs the duration of a rake task to a file
82
- #
83
- # This method calculates the elapsed time since the STARTTIME constant was set
84
- # and appends this information to a log file. Used to track performance of rake tasks.
85
- #
86
- # @return [nil]
87
- def self.log_rake_duration
88
- # use the STARTTIME constant to log the duration of the rake task
89
- # to the log/rake.duration.txt file
90
- duration = Time.now - STARTTIME
91
- FileUtils.mkdir_p("log")
92
- File.open("log/rake.duration.txt", "a") do |file|
93
- file.puts "Rake task duration: #{duration} seconds"
94
- end
95
- end
96
-
97
- # Plain text log formatter that strips ANSI color codes
98
- #
99
- # This formatter removes color codes from log messages and provides
100
- # clean, plain text output suitable for file logging or systems
101
- # that don't support color output.
102
- #
103
- # @deprecated This class is deprecated and will be removed in version 0.2.0.
104
- # Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink instead.
105
- class PlainFormatter < ::Logger::Formatter
106
- # Format a log message as plain text
107
- #
108
- # @param severity [String] log level (DEBUG, INFO, WARN, ERROR, FATAL)
109
- # @param time [Time] timestamp of the log message
110
- # @param _progname [String] program name (unused)
111
- # @param msg [String] the log message content
112
- # @return [String] formatted plain text log entry
113
- def call(severity, time, _progname, msg)
114
- warn "Makit::Logging::PlainFormatter is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink instead."
115
- stripped_msg = msg.gsub(ANSI_COLOR_REGEX, "") # Remove ANSI color codes
116
- timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
117
- "[#{timestamp}] #{severity}: #{stripped_msg}\n"
118
- end
119
- end
120
-
121
- # Colored log formatter for terminal output
122
- #
123
- # This formatter adds appropriate colors to different log levels
124
- # to improve readability in terminal environments. Colors are:
125
- # DEBUG (light blue), INFO (green), WARN (yellow), ERROR (red), FATAL (bold red)
126
- #
127
- # @deprecated This class is deprecated and will be removed in version 0.2.0.
128
- # Use Makit::Logging::Logger with Makit::Logging::Sinks::Console instead.
129
- class ColorFormatter < ::Logger::Formatter
130
- # Format a log message with colors
131
- #
132
- # @param severity [String] log level (DEBUG, INFO, WARN, ERROR, FATAL)
133
- # @param time [Time] timestamp of the log message
134
- # @param _progname [String] program name (unused)
135
- # @param msg [String] the log message content
136
- # @return [String] formatted colored log entry
137
- def call(severity, time, _progname, msg)
138
- warn "Makit::Logging::ColorFormatter is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with Makit::Logging::Sinks::Console instead."
139
- timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
140
- colored_severity = colorize_severity(severity)
141
- "[#{timestamp}] #{colored_severity}: #{msg}\n"
142
- end
143
-
144
- private
145
-
146
- def colorize_severity(severity)
147
- case severity
148
- when "DEBUG"
149
- severity.light_blue
150
- when "INFO"
151
- severity.green
152
- when "WARN"
153
- severity.yellow
154
- when "ERROR"
155
- severity.red
156
- when "FATAL"
157
- severity.red.bold
158
- else
159
- severity
160
- end
161
- end
162
- end
163
-
164
- # Structured JSON log formatter
165
- #
166
- # This formatter outputs log messages as JSON objects with structured
167
- # fields including timestamp, level, message, and program name.
168
- # Useful for log aggregation systems and machine parsing.
169
- #
170
- # @deprecated This class is deprecated and will be removed in version 0.2.0.
171
- # Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink (formatter: :json) instead.
172
- class StructuredFormatter < ::Logger::Formatter
173
- # Format a log message as JSON
174
- #
175
- # @param severity [String] log level (DEBUG, INFO, WARN, ERROR, FATAL)
176
- # @param time [Time] timestamp of the log message
177
- # @param progname [String] program name
178
- # @param msg [String] the log message content
179
- # @return [String] JSON formatted log entry with newline
180
- def call(severity, time, progname, msg)
181
- warn "Makit::Logging::StructuredFormatter is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink (formatter: :json) instead."
182
- timestamp = time.strftime("%Y-%m-%d %H:%M:%S.%L")
183
- {
184
- timestamp: timestamp,
185
- level: severity,
186
- message: msg,
187
- progname: progname,
188
- }.to_json + "\n"
189
- end
190
- end
191
-
192
- # Multi-target logger that writes to multiple destinations
193
- #
194
- # This logger allows writing log messages to multiple targets simultaneously,
195
- # such as both stdout and a file, or multiple files with different formats.
196
- #
197
- # @deprecated This class is deprecated and will be removed in version 0.2.0.
198
- # Use Makit::Logging::Logger with multiple middleware instead.
199
- #
200
- # @example Create a logger that writes to both console and file
201
- # stdout_logger = Logger.new($stdout)
202
- # file_logger = Logger.new("app.log")
203
- # multi_logger = MultiLogger.new(stdout_logger, file_logger)
204
- # multi_logger.info("This goes to both destinations")
205
- class MultiLogger
206
- # Initialize a new MultiLogger with multiple logging targets
207
- #
208
- # @param targets [Array<Logger>] One or more logger instances to write to
209
- def initialize(*targets)
210
- warn "Makit::Logging::MultiLogger is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with middleware instead."
211
- @targets = targets
212
- end
213
-
214
- # Add a message to all logger targets
215
- #
216
- # @param severity [Integer] The severity level (::Logger::DEBUG, ::Logger::INFO, etc.)
217
- # @param message [String, nil] The message to log (or nil if using block)
218
- # @param progname [String, nil] The program name to include in the log
219
- # @param block [Proc, nil] Optional block that returns the message to log
220
- # @return [nil]
221
- def add(severity, message = nil, progname = nil, &block)
222
- @targets.each do |logger|
223
- logger.add(severity, message, progname, &block)
224
- logger.flush if logger.respond_to?(:flush)
225
- end
226
- end
227
-
228
- # Append a message directly to all logger targets
229
- #
230
- # @param message [String] The message to append to all loggers
231
- # @return [nil]
232
- def <<(message)
233
- @targets.each do |logger|
234
- logger << message
235
- logger.flush if logger.respond_to?(:flush)
236
- end
237
- end
238
-
239
- # Close all logger targets
240
- #
241
- # @return [nil]
242
- def close
243
- @targets.each(&:close)
244
- end
245
-
246
- # Forward any unknown methods to all logger targets
247
- #
248
- # This allows calling standard Logger methods like info, debug, error, etc.
249
- # directly on the MultiLogger instance.
250
- #
251
- # @param method [Symbol] The method name to forward
252
- # @param args [Array] Arguments to pass to the method
253
- # @return [nil]
254
- def method_missing(method, ...)
255
- @targets.each { |logger| logger.send(method, ...) }
256
- end
257
-
258
- # Check if all logger targets respond to a given method
259
- #
260
- # @param method [Symbol] The method name to check
261
- # @param include_private [Boolean] Whether to include private methods
262
- # @return [Boolean] True if all logger targets respond to the method
263
- def respond_to_missing?(method, include_private = false)
264
- @targets.all? { |logger| logger.respond_to?(method, include_private) }
265
- end
266
-
267
- # Create a configured logger based on options
268
- #
269
- # This factory method creates a logger configured with appropriate formatters
270
- # and targets based on the provided options. By default, it creates a logger
271
- # that writes to both stdout (with colors) and a log file (plain text).
272
- #
273
- # @deprecated This method is deprecated and will be removed in version 0.2.0.
274
- # Use Makit::Logging::Logger.new with middleware instead.
275
- #
276
- # @param options [Hash] Logger configuration options
277
- # @option options [Symbol] :level (:info) The log level (:debug, :info, :warn, :error, :fatal)
278
- # @option options [Boolean] :file_logging (true) Whether to log to a file
279
- # @option options [String] :log_file (nil) Custom log file path, defaults to rake task-based path
280
- # @option options [Boolean] :structured_logging (false) Whether to use JSON structured logging for file output
281
- # @return [Logger, MultiLogger] A configured logger instance
282
- def self.create_logger(options = {})
283
- warn "Makit::Logging::MultiLogger.create_logger is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger.new with middleware instead."
284
- log_level = options[:level] || DEFAULT_LOG_LEVEL
285
- log_level = LOG_LEVELS[log_level] || LOG_LEVELS[DEFAULT_LOG_LEVEL]
286
-
287
- stdout_logger = ::Logger.new($stdout)
288
- stdout_logger.level = log_level
289
- stdout_logger.formatter = ColorFormatter.new
290
-
291
- # if clean or clobber commands are used, then log ONLY to stdout
292
- return stdout_logger if ARGV.include?("clean") || ARGV.include?("clobber")
293
-
294
- return stdout_logger if Makit::Environment.project_root_directory.nil?
295
-
296
- # Create file logger if logging to file is enabled
297
- if options[:file_logging] != false
298
- log_filename = create_log_filename(options)
299
- file_logger = create_file_logger(log_filename, log_level, options)
300
- return MultiLogger.new(file_logger, stdout_logger)
301
- end
302
-
303
- stdout_logger
304
- end
305
-
306
- # Create a file logger with appropriate formatter
307
- #
308
- # Creates a logger that writes to a file with the specified formatter
309
- # and log level. Ensures the directory for the log file exists.
310
- #
311
- # @param log_filename [String] Path where log file should be created
312
- # @param log_level [Integer] Log level to set (from Logger constants)
313
- # @param options [Hash] Configuration options
314
- # @option options [Boolean] :structured_logging (false) Whether to use JSON formatted logs
315
- # @return [Logger] Configured file logger
316
- def self.create_file_logger(log_filename, log_level, options)
317
- FileUtils.mkdir_p(File.dirname(log_filename))
318
-
319
- file_logger = ::Logger.new(log_filename)
320
- file_logger.level = log_level
321
-
322
- # Use structured logging for file output if requested
323
- file_logger.formatter = if options[:structured_logging]
324
- StructuredFormatter.new
325
- else
326
- PlainFormatter.new
327
- end
328
-
329
- file_logger
330
- end
331
-
332
- # Determine the appropriate log filename
333
- #
334
- # Generates a log filename based on options and the current rake task.
335
- # If a custom log file is specified in options, that is used. Otherwise,
336
- # a log file is created in the artifacts directory with a name based on
337
- # the current rake task.
338
- #
339
- # @param options [Hash] Configuration options
340
- # @option options [String] :log_file (nil) Custom log file path
341
- # @return [String] The path to use for the log file
342
- def self.create_log_filename(options)
343
- if options[:log_file]
344
- options[:log_file]
345
- elsif ARGV.empty?
346
- "#{Makit::Environment.project_root_directory}/artifacts/rake.log"
347
- else
348
- task_name = ARGV.join("_").gsub(":", "_")
349
- "#{Makit::Environment.project_root_directory}/artifacts/rake_#{task_name}.log"
350
- end
351
- end
352
- end
353
-
354
- # ===== DEPRECATED LEGACY LOGGING =====
355
- #
356
- # The following classes and methods are deprecated and will be removed in version 0.2.0:
357
- # - PlainFormatter
358
- # - ColorFormatter
359
- # - StructuredFormatter
360
- # - MultiLogger
361
- # - MultiLogger.create_logger
362
- #
363
- # MIGRATION GUIDE:
364
- #
365
- # OLD (deprecated):
366
- # logger = Makit::Logging::MultiLogger.create_logger
367
- # logger.info("message")
368
- #
369
- # NEW (recommended):
370
- # Makit::Logging.info("message") # Uses default logger
371
- # # OR
372
- # logger = Makit::Logging::Logger.new(sinks: [...])
373
- # logger.info("message")
374
- #
375
- # For custom formatting, use sinks:
376
- # logger = Makit::Logging::Logger.new(
377
- # sinks: [
378
- # Makit::Logging::Sinks::Console.new,
379
- # Makit::Logging::Sinks::FileSink.new(log_file: "app.log")
380
- # ]
381
- # )
382
-
383
- # ===== NEW LOGGING ARCHITECTURE =====
384
-
385
- # Default logger with unified file sink
386
- # This replaces the previous multi-sink approach with a single, configurable sink
387
- DEFAULT_LOGGER = Logger.new(
388
- level: current_log_level,
389
- sinks: [
390
- Sinks::UnifiedFileSink.new(
391
- configurations: [
392
- # Console output with colors and symbols
393
- {
394
- file: $stdout,
395
- format: :console,
396
- show_timestamp: false,
397
- show_level: false,
398
- },
399
- # Main log file in JSON format
400
- {
401
- file: "artifacts/makit.log",
402
- format: :json,
403
- append: true,
404
- include_metadata: true,
405
- },
406
- # Debug log file in text format
407
- {
408
- file: "artifacts/debug.log",
409
- format: :text,
410
- append: true,
411
- min_level: :debug,
412
- include_context: true,
413
- },
414
- ],
415
- ),
416
- ],
417
- )
418
-
419
- # Convenience methods that delegate to the default logger
420
- # These provide a simple API for common logging operations
421
-
422
- # Log an info message
423
- #
424
- # @param message [String] the log message
425
- # @param context [Hash] additional context information
426
- # @return [void]
427
- def self.info(message, context = {})
428
- DEFAULT_LOGGER.info(message, context)
429
- end
430
-
431
- # Log a success message
432
- #
433
- # @param message [String] the log message
434
- # @param context [Hash] additional context information
435
- # @return [void]
436
- def self.success(message, context = {})
437
- DEFAULT_LOGGER.success(message, context)
438
- end
439
-
440
- # Log an error message
441
- #
442
- # @param message [String] the log message
443
- # @param context [Hash] additional context information
444
- # @return [void]
445
- def self.error(message, context = {})
446
- DEFAULT_LOGGER.error(message, context)
447
- end
448
-
449
- # Log a warning message
450
- #
451
- # @param message [String] the log message
452
- # @param context [Hash] additional context information
453
- # @return [void]
454
- def self.warn(message, context = {})
455
- DEFAULT_LOGGER.warn(message, context)
456
- end
457
-
458
- # Log a debug message
459
- #
460
- # @param message [String] the log message
461
- # @param context [Hash] additional context information
462
- # @return [void]
463
- def self.debug(message, context = {})
464
- DEFAULT_LOGGER.debug(message, context)
465
- end
466
-
467
- # Log a fatal message
468
- #
469
- # @param message [String] the log message
470
- # @param context [Hash] additional context information
471
- # @return [void]
472
- def self.fatal(message, context = {})
473
- DEFAULT_LOGGER.fatal(message, context)
474
- end
475
-
476
- # Create a logger with environment-specific configuration
477
- #
478
- # @param environment [Symbol] environment name (:development, :production, :test, :ci)
479
- # @return [Logger] configured logger instance
480
- def self.create_logger(environment: :default)
481
- config = case environment
482
- when :development
483
- Configuration.development_config
484
- when :production
485
- Configuration.production_config
486
- when :test
487
- Configuration.test_config
488
- when :ci
489
- Configuration.ci_config
490
- else
491
- Configuration.default_config
492
- end
493
-
494
- Logger.new(
495
- sinks: [
496
- Sinks::UnifiedFileSink.new(configurations: config.configurations),
497
- ],
498
- )
499
- end
500
-
501
- # Create a logger from configuration file
502
- #
503
- # @param config_file [String] path to configuration file (YAML or JSON)
504
- # @return [Logger] configured logger instance
505
- def self.create_logger_from_file(config_file)
506
- config = if config_file.end_with?(".yaml") || config_file.end_with?(".yml")
507
- Configuration.from_yaml(config_file)
508
- elsif config_file.end_with?(".json")
509
- Configuration.from_json(config_file)
510
- else
511
- raise ArgumentError, "Configuration file must be YAML (.yaml/.yml) or JSON (.json)"
512
- end
513
-
514
- config.validate!
515
-
516
- Logger.new(
517
- sinks: [
518
- Sinks::UnifiedFileSink.new(configurations: config.configurations),
519
- ],
520
- )
521
- end
522
-
523
- # Get the default logger instance
524
- #
525
- # @return [Logger] the default logger
526
- def self.default_logger
527
- DEFAULT_LOGGER
528
- end
529
- end
530
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ begin
5
+ require "colorize"
6
+ rescue LoadError
7
+ # colorize gem not available, define a no-op colorize method
8
+ class String
9
+ def colorize(*_args)
10
+ self
11
+ end
12
+ end
13
+ end
14
+ require_relative "symbols"
15
+ require_relative "logging/logger"
16
+ require_relative "logging/log_request"
17
+ require_relative "logging/sinks/base"
18
+ require_relative "logging/sinks/console"
19
+ require_relative "logging/sinks/file_sink"
20
+ require_relative "logging/sinks/structured"
21
+ require_relative "logging/sinks/unified_file_sink"
22
+ require_relative "logging/configuration"
23
+
24
+ # This module provides classes for the Makit gem.
25
+ module Makit
26
+ # Logging infrastructure for the Makit gem
27
+ #
28
+ # This module provides a comprehensive logging system with multiple formatters,
29
+ # multi-target output capabilities, and configurable log levels. It supports:
30
+ #
31
+ # - Plain text logging (suitable for files)
32
+ # - Colored console output (improved terminal readability)
33
+ # - Structured JSON logging (machine-parsable format)
34
+ # - Multi-target logging (write to multiple destinations simultaneously)
35
+ # - Sink-based output processing (similar to Commands::Runner)
36
+ #
37
+ # @deprecated The legacy MultiLogger, Formatter classes, and create_logger method
38
+ # are deprecated and will be removed in version 0.2.0. Use the new Logger class
39
+ # with sinks instead.
40
+ #
41
+ # @example Basic usage with new architecture (recommended)
42
+ # Makit::Logging.info("Application started")
43
+ # Makit::Logging.success("Build completed")
44
+ # Makit::Logging.error("Something went wrong")
45
+ #
46
+ # @example Custom logger configuration
47
+ # logger = Makit::Logging::Logger.new(
48
+ # sinks: [
49
+ # Makit::Logging::Sinks::Console.new,
50
+ # Makit::Logging::Sinks::FileSink.new(log_file: "custom.log")
51
+ # ]
52
+ # )
53
+ # logger.info("Custom message")
54
+ #
55
+ # @example Legacy usage (deprecated - will be removed in v0.2.0)
56
+ # logger = Makit::Logging::MultiLogger.create_logger
57
+ # logger.info("Application started")
58
+ # logger.error("Something went wrong")
59
+ module Logging
60
+ ANSI_COLOR_REGEX = /\e\[[0-9;]*m/
61
+
62
+ # Log levels that can be configured
63
+ LOG_LEVELS = {
64
+ debug: ::Logger::DEBUG,
65
+ info: ::Logger::INFO,
66
+ warn: ::Logger::WARN,
67
+ error: ::Logger::ERROR,
68
+ fatal: ::Logger::FATAL,
69
+ }.freeze
70
+
71
+ # Default log level
72
+ DEFAULT_LOG_LEVEL = :info
73
+
74
+ # Get the current log level from environment or use default
75
+ def self.current_log_level
76
+ env_level = ENV["LOG_LEVEL"]&.downcase&.to_sym
77
+ return env_level if env_level && LOG_LEVELS.key?(env_level)
78
+
79
+ DEFAULT_LOG_LEVEL
80
+ end
81
+
82
+ # Get the current verbosity level from environment or use default
83
+ def self.current_verbosity
84
+ env_verbosity = ENV["VERBOSITY"]&.downcase&.to_sym
85
+ return env_verbosity if env_verbosity && %i[quiet normal verbose debug].include?(env_verbosity)
86
+
87
+ :normal
88
+ end
89
+
90
+ # Get the current verbosity level from the default logger
91
+ #
92
+ # @return [Symbol] current verbosity level (:quiet, :normal, :verbose, :debug)
93
+ def self.verbosity
94
+ DEFAULT_LOGGER.verbosity
95
+ end
96
+
97
+ # Logs the duration of a rake task to a file
98
+ #
99
+ # This method calculates the elapsed time since the STARTTIME constant was set
100
+ # and appends this information to a log file. Used to track performance of rake tasks.
101
+ #
102
+ # @return [nil]
103
+ def self.log_rake_duration
104
+ # use the STARTTIME constant to log the duration of the rake task
105
+ # to the log/rake.duration.txt file
106
+ duration = Time.now - STARTTIME
107
+ FileUtils.mkdir_p("log")
108
+ File.open("log/rake.duration.txt", "a") do |file|
109
+ file.puts "Rake task duration: #{duration} seconds"
110
+ end
111
+ end
112
+
113
+ # Plain text log formatter that strips ANSI color codes
114
+ #
115
+ # This formatter removes color codes from log messages and provides
116
+ # clean, plain text output suitable for file logging or systems
117
+ # that don't support color output.
118
+ #
119
+ # @deprecated This class is deprecated and will be removed in version 0.2.0.
120
+ # Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink instead.
121
+ class PlainFormatter < ::Logger::Formatter
122
+ # Format a log message as plain text
123
+ #
124
+ # @param severity [String] log level (DEBUG, INFO, WARN, ERROR, FATAL)
125
+ # @param time [Time] timestamp of the log message
126
+ # @param _progname [String] program name (unused)
127
+ # @param msg [String] the log message content
128
+ # @return [String] formatted plain text log entry
129
+ def call(severity, time, _progname, msg)
130
+ warn "Makit::Logging::PlainFormatter is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink instead."
131
+ stripped_msg = msg.gsub(ANSI_COLOR_REGEX, "") # Remove ANSI color codes
132
+ timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
133
+ "[#{timestamp}] #{severity}: #{stripped_msg}\n"
134
+ end
135
+ end
136
+
137
+ # Colored log formatter for terminal output
138
+ #
139
+ # This formatter adds appropriate colors to different log levels
140
+ # to improve readability in terminal environments. Colors are:
141
+ # DEBUG (light blue), INFO (green), WARN (yellow), ERROR (red), FATAL (bold red)
142
+ #
143
+ # @deprecated This class is deprecated and will be removed in version 0.2.0.
144
+ # Use Makit::Logging::Logger with Makit::Logging::Sinks::Console instead.
145
+ class ColorFormatter < ::Logger::Formatter
146
+ # Format a log message with colors
147
+ #
148
+ # @param severity [String] log level (DEBUG, INFO, WARN, ERROR, FATAL)
149
+ # @param time [Time] timestamp of the log message
150
+ # @param _progname [String] program name (unused)
151
+ # @param msg [String] the log message content
152
+ # @return [String] formatted colored log entry
153
+ def call(severity, time, _progname, msg)
154
+ warn "Makit::Logging::ColorFormatter is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with Makit::Logging::Sinks::Console instead."
155
+ timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
156
+ colored_severity = colorize_severity(severity)
157
+ "[#{timestamp}] #{colored_severity}: #{msg}\n"
158
+ end
159
+
160
+ private
161
+
162
+ def colorize_severity(severity)
163
+ case severity
164
+ when "DEBUG"
165
+ severity.light_blue
166
+ when "INFO"
167
+ severity.green
168
+ when "WARN"
169
+ severity.yellow
170
+ when "ERROR"
171
+ severity.red
172
+ when "FATAL"
173
+ severity.red.bold
174
+ else
175
+ severity
176
+ end
177
+ end
178
+ end
179
+
180
+ # Structured JSON log formatter
181
+ #
182
+ # This formatter outputs log messages as JSON objects with structured
183
+ # fields including timestamp, level, message, and program name.
184
+ # Useful for log aggregation systems and machine parsing.
185
+ #
186
+ # @deprecated This class is deprecated and will be removed in version 0.2.0.
187
+ # Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink (formatter: :json) instead.
188
+ class StructuredFormatter < ::Logger::Formatter
189
+ # Format a log message as JSON
190
+ #
191
+ # @param severity [String] log level (DEBUG, INFO, WARN, ERROR, FATAL)
192
+ # @param time [Time] timestamp of the log message
193
+ # @param progname [String] program name
194
+ # @param msg [String] the log message content
195
+ # @return [String] JSON formatted log entry with newline
196
+ def call(severity, time, progname, msg)
197
+ warn "Makit::Logging::StructuredFormatter is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with Makit::Logging::Sinks::FileSink (formatter: :json) instead."
198
+ timestamp = time.strftime("%Y-%m-%d %H:%M:%S.%L")
199
+ {
200
+ timestamp: timestamp,
201
+ level: severity,
202
+ message: msg,
203
+ progname: progname,
204
+ }.to_json + "\n"
205
+ end
206
+ end
207
+
208
+ # Multi-target logger that writes to multiple destinations
209
+ #
210
+ # This logger allows writing log messages to multiple targets simultaneously,
211
+ # such as both stdout and a file, or multiple files with different formats.
212
+ #
213
+ # @deprecated This class is deprecated and will be removed in version 0.2.0.
214
+ # Use Makit::Logging::Logger with multiple middleware instead.
215
+ #
216
+ # @example Create a logger that writes to both console and file
217
+ # stdout_logger = Logger.new($stdout)
218
+ # file_logger = Logger.new("app.log")
219
+ # multi_logger = MultiLogger.new(stdout_logger, file_logger)
220
+ # multi_logger.info("This goes to both destinations")
221
+ class MultiLogger
222
+ # Initialize a new MultiLogger with multiple logging targets
223
+ #
224
+ # @param targets [Array<Logger>] One or more logger instances to write to
225
+ def initialize(*targets)
226
+ warn "Makit::Logging::MultiLogger is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger with middleware instead."
227
+ @targets = targets
228
+ end
229
+
230
+ # Add a message to all logger targets
231
+ #
232
+ # @param severity [Integer] The severity level (::Logger::DEBUG, ::Logger::INFO, etc.)
233
+ # @param message [String, nil] The message to log (or nil if using block)
234
+ # @param progname [String, nil] The program name to include in the log
235
+ # @param block [Proc, nil] Optional block that returns the message to log
236
+ # @return [nil]
237
+ def add(severity, message = nil, progname = nil, &block)
238
+ @targets.each do |logger|
239
+ logger.add(severity, message, progname, &block)
240
+ logger.flush if logger.respond_to?(:flush)
241
+ end
242
+ end
243
+
244
+ # Append a message directly to all logger targets
245
+ #
246
+ # @param message [String] The message to append to all loggers
247
+ # @return [nil]
248
+ def <<(message)
249
+ @targets.each do |logger|
250
+ logger << message
251
+ logger.flush if logger.respond_to?(:flush)
252
+ end
253
+ end
254
+
255
+ # Close all logger targets
256
+ #
257
+ # @return [nil]
258
+ def close
259
+ @targets.each(&:close)
260
+ end
261
+
262
+ # Forward any unknown methods to all logger targets
263
+ #
264
+ # This allows calling standard Logger methods like info, debug, error, etc.
265
+ # directly on the MultiLogger instance.
266
+ #
267
+ # @param method [Symbol] The method name to forward
268
+ # @param args [Array] Arguments to pass to the method
269
+ # @return [nil]
270
+ def method_missing(method, ...)
271
+ @targets.each { |logger| logger.send(method, ...) }
272
+ end
273
+
274
+ # Check if all logger targets respond to a given method
275
+ #
276
+ # @param method [Symbol] The method name to check
277
+ # @param include_private [Boolean] Whether to include private methods
278
+ # @return [Boolean] True if all logger targets respond to the method
279
+ def respond_to_missing?(method, include_private = false)
280
+ @targets.all? { |logger| logger.respond_to?(method, include_private) }
281
+ end
282
+
283
+ # Create a configured logger based on options
284
+ #
285
+ # This factory method creates a logger configured with appropriate formatters
286
+ # and targets based on the provided options. By default, it creates a logger
287
+ # that writes to both stdout (with colors) and a log file (plain text).
288
+ #
289
+ # @deprecated This method is deprecated and will be removed in version 0.2.0.
290
+ # Use Makit::Logging::Logger.new with middleware instead.
291
+ #
292
+ # @param options [Hash] Logger configuration options
293
+ # @option options [Symbol] :level (:info) The log level (:debug, :info, :warn, :error, :fatal)
294
+ # @option options [Boolean] :file_logging (true) Whether to log to a file
295
+ # @option options [String] :log_file (nil) Custom log file path, defaults to rake task-based path
296
+ # @option options [Boolean] :structured_logging (false) Whether to use JSON structured logging for file output
297
+ # @return [Logger, MultiLogger] A configured logger instance
298
+ def self.create_logger(options = {})
299
+ warn "Makit::Logging::MultiLogger.create_logger is deprecated and will be removed in version 0.2.0. Use Makit::Logging::Logger.new with middleware instead."
300
+ log_level = options[:level] || DEFAULT_LOG_LEVEL
301
+ log_level = LOG_LEVELS[log_level] || LOG_LEVELS[DEFAULT_LOG_LEVEL]
302
+
303
+ stdout_logger = ::Logger.new($stdout)
304
+ stdout_logger.level = log_level
305
+ stdout_logger.formatter = ColorFormatter.new
306
+
307
+ # if clean or clobber commands are used, then log ONLY to stdout
308
+ return stdout_logger if ARGV.include?("clean") || ARGV.include?("clobber")
309
+
310
+ return stdout_logger if Makit::Environment.project_root_directory.nil?
311
+
312
+ # Create file logger if logging to file is enabled
313
+ if options[:file_logging] != false
314
+ log_filename = create_log_filename(options)
315
+ file_logger = create_file_logger(log_filename, log_level, options)
316
+ return MultiLogger.new(file_logger, stdout_logger)
317
+ end
318
+
319
+ stdout_logger
320
+ end
321
+
322
+ # Create a file logger with appropriate formatter
323
+ #
324
+ # Creates a logger that writes to a file with the specified formatter
325
+ # and log level. Ensures the directory for the log file exists.
326
+ #
327
+ # @param log_filename [String] Path where log file should be created
328
+ # @param log_level [Integer] Log level to set (from Logger constants)
329
+ # @param options [Hash] Configuration options
330
+ # @option options [Boolean] :structured_logging (false) Whether to use JSON formatted logs
331
+ # @return [Logger] Configured file logger
332
+ def self.create_file_logger(log_filename, log_level, options)
333
+ FileUtils.mkdir_p(File.dirname(log_filename))
334
+
335
+ file_logger = ::Logger.new(log_filename)
336
+ file_logger.level = log_level
337
+
338
+ # Use structured logging for file output if requested
339
+ file_logger.formatter = if options[:structured_logging]
340
+ StructuredFormatter.new
341
+ else
342
+ PlainFormatter.new
343
+ end
344
+
345
+ file_logger
346
+ end
347
+
348
+ # Determine the appropriate log filename
349
+ #
350
+ # Generates a log filename based on options and the current rake task.
351
+ # If a custom log file is specified in options, that is used. Otherwise,
352
+ # a log file is created in the artifacts directory with a name based on
353
+ # the current rake task.
354
+ #
355
+ # @param options [Hash] Configuration options
356
+ # @option options [String] :log_file (nil) Custom log file path
357
+ # @return [String] The path to use for the log file
358
+ def self.create_log_filename(options)
359
+ if options[:log_file]
360
+ options[:log_file]
361
+ elsif ARGV.empty?
362
+ "#{Makit::Environment.project_root_directory}/artifacts/rake.log"
363
+ else
364
+ task_name = ARGV.join("_").gsub(":", "_")
365
+ "#{Makit::Environment.project_root_directory}/artifacts/rake_#{task_name}.log"
366
+ end
367
+ end
368
+ end
369
+
370
+ # ===== DEPRECATED LEGACY LOGGING =====
371
+ #
372
+ # The following classes and methods are deprecated and will be removed in version 0.2.0:
373
+ # - PlainFormatter
374
+ # - ColorFormatter
375
+ # - StructuredFormatter
376
+ # - MultiLogger
377
+ # - MultiLogger.create_logger
378
+ #
379
+ # MIGRATION GUIDE:
380
+ #
381
+ # OLD (deprecated):
382
+ # logger = Makit::Logging::MultiLogger.create_logger
383
+ # logger.info("message")
384
+ #
385
+ # NEW (recommended):
386
+ # Makit::Logging.info("message") # Uses default logger
387
+ # # OR
388
+ # logger = Makit::Logging::Logger.new(sinks: [...])
389
+ # logger.info("message")
390
+ #
391
+ # For custom formatting, use sinks:
392
+ # logger = Makit::Logging::Logger.new(
393
+ # sinks: [
394
+ # Makit::Logging::Sinks::Console.new,
395
+ # Makit::Logging::Sinks::FileSink.new(log_file: "app.log")
396
+ # ]
397
+ # )
398
+
399
+ # ===== NEW LOGGING ARCHITECTURE =====
400
+
401
+ # Default logger with unified file sink
402
+ # This replaces the previous multi-sink approach with a single, configurable sink
403
+ DEFAULT_LOGGER = Logger.new(
404
+ level: current_log_level,
405
+ verbosity: current_verbosity,
406
+ sinks: [
407
+ Sinks::UnifiedFileSink.new(
408
+ configurations: [
409
+ # Console output with colors and symbols
410
+ {
411
+ file: $stdout,
412
+ format: :console,
413
+ show_timestamp: false,
414
+ show_level: false,
415
+ },
416
+ # Main log file in JSON format
417
+ {
418
+ file: "artifacts/makit.log",
419
+ format: :json,
420
+ append: true,
421
+ include_metadata: true,
422
+ },
423
+ # Debug log file in text format
424
+ {
425
+ file: "artifacts/debug.log",
426
+ format: :text,
427
+ append: true,
428
+ min_level: :debug,
429
+ include_context: true,
430
+ },
431
+ ],
432
+ ),
433
+ ],
434
+ )
435
+
436
+ # Convenience methods that delegate to the default logger
437
+ # These provide a simple API for common logging operations
438
+
439
+ # Log an info message
440
+ #
441
+ # @param message [String] the log message
442
+ # @param context [Hash] additional context information
443
+ # @return [void]
444
+ def self.info(message, context = {})
445
+ DEFAULT_LOGGER.info(message, context)
446
+ end
447
+
448
+ # Log a success message
449
+ #
450
+ # @param message [String] the log message
451
+ # @param context [Hash] additional context information
452
+ # @return [void]
453
+ def self.success(message, context = {})
454
+ DEFAULT_LOGGER.success(message, context)
455
+ end
456
+
457
+ # Log an error message
458
+ #
459
+ # @param message [String] the log message
460
+ # @param context [Hash] additional context information
461
+ # @return [void]
462
+ def self.error(message, context = {})
463
+ DEFAULT_LOGGER.error(message, context)
464
+ end
465
+
466
+ # Log a warning message
467
+ #
468
+ # @param message [String] the log message
469
+ # @param context [Hash] additional context information
470
+ # @return [void]
471
+ def self.warn(message, context = {})
472
+ DEFAULT_LOGGER.warn(message, context)
473
+ end
474
+
475
+ # Log a debug message
476
+ #
477
+ # @param message [String] the log message
478
+ # @param context [Hash] additional context information
479
+ # @return [void]
480
+ def self.debug(message, context = {})
481
+ DEFAULT_LOGGER.debug(message, context)
482
+ end
483
+
484
+ # Log a fatal message
485
+ #
486
+ # @param message [String] the log message
487
+ # @param context [Hash] additional context information
488
+ # @return [void]
489
+ def self.fatal(message, context = {})
490
+ DEFAULT_LOGGER.fatal(message, context)
491
+ end
492
+
493
+ # Log a verbose message (only shown in verbose or debug mode)
494
+ #
495
+ # @param message [String] the log message
496
+ # @param context [Hash] additional context information
497
+ # @return [void]
498
+ def self.verbose(message, context = {})
499
+ DEFAULT_LOGGER.verbose(message, context)
500
+ end
501
+
502
+ # Log a quiet message (shown even in quiet mode)
503
+ #
504
+ # @param message [String] the log message
505
+ # @param context [Hash] additional context information
506
+ # @return [void]
507
+ def self.quiet(message, context = {})
508
+ DEFAULT_LOGGER.quiet(message, context)
509
+ end
510
+
511
+ # Create a logger with environment-specific configuration
512
+ #
513
+ # @param environment [Symbol] environment name (:development, :production, :test, :ci)
514
+ # @return [Logger] configured logger instance
515
+ def self.create_logger(environment: :default)
516
+ config = case environment
517
+ when :development
518
+ Configuration.development_config
519
+ when :production
520
+ Configuration.production_config
521
+ when :test
522
+ Configuration.test_config
523
+ when :ci
524
+ Configuration.ci_config
525
+ else
526
+ Configuration.default_config
527
+ end
528
+
529
+ Logger.new(
530
+ sinks: [
531
+ Sinks::UnifiedFileSink.new(configurations: config.configurations),
532
+ ],
533
+ )
534
+ end
535
+
536
+ # Create a logger from configuration file
537
+ #
538
+ # @param config_file [String] path to configuration file (YAML or JSON)
539
+ # @return [Logger] configured logger instance
540
+ def self.create_logger_from_file(config_file)
541
+ config = if config_file.end_with?(".yaml") || config_file.end_with?(".yml")
542
+ Configuration.from_yaml(config_file)
543
+ elsif config_file.end_with?(".json")
544
+ Configuration.from_json(config_file)
545
+ else
546
+ raise ArgumentError, "Configuration file must be YAML (.yaml/.yml) or JSON (.json)"
547
+ end
548
+
549
+ config.validate!
550
+
551
+ Logger.new(
552
+ sinks: [
553
+ Sinks::UnifiedFileSink.new(configurations: config.configurations),
554
+ ],
555
+ )
556
+ end
557
+
558
+ # Get the default logger instance
559
+ #
560
+ # @return [Logger] the default logger
561
+ def self.default_logger
562
+ DEFAULT_LOGGER
563
+ end
564
+ end
565
+ end