makit 0.0.138 → 0.0.140

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 (151) 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/auto.rb +48 -48
  6. data/lib/makit/cli/build_commands.rb +500 -500
  7. data/lib/makit/cli/generators/base_generator.rb +74 -74
  8. data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
  9. data/lib/makit/cli/generators/generator_factory.rb +49 -49
  10. data/lib/makit/cli/generators/node_generator.rb +50 -50
  11. data/lib/makit/cli/generators/ruby_generator.rb +77 -77
  12. data/lib/makit/cli/generators/rust_generator.rb +50 -50
  13. data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
  14. data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
  15. data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
  16. data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -40
  17. data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
  18. data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
  19. data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
  20. data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
  21. data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
  22. data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
  23. data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
  24. data/lib/makit/cli/main.rb +69 -67
  25. data/lib/makit/cli/project_commands.rb +868 -868
  26. data/lib/makit/cli/repository_commands.rb +661 -661
  27. data/lib/makit/cli/strategy_commands.rb +51 -0
  28. data/lib/makit/cli/utility_commands.rb +521 -521
  29. data/lib/makit/commands/factory.rb +359 -359
  30. data/lib/makit/commands/middleware/base.rb +73 -73
  31. data/lib/makit/commands/middleware/cache.rb +248 -248
  32. data/lib/makit/commands/middleware/command_logger.rb +312 -312
  33. data/lib/makit/commands/middleware/validator.rb +269 -269
  34. data/lib/makit/commands/request.rb +316 -316
  35. data/lib/makit/commands/result.rb +323 -323
  36. data/lib/makit/commands/runner.rb +385 -385
  37. data/lib/makit/commands/strategies/base.rb +171 -171
  38. data/lib/makit/commands/strategies/child_process.rb +1 -1
  39. data/lib/makit/commands/strategies/synchronous.rb +139 -139
  40. data/lib/makit/commands.rb +50 -50
  41. data/lib/makit/configuration/dotnet_project.rb +12 -12
  42. data/lib/makit/configuration/gitlab_helper.rb +58 -58
  43. data/lib/makit/configuration/project.rb +168 -168
  44. data/lib/makit/configuration/rakefile_helper.rb +43 -43
  45. data/lib/makit/configuration/step.rb +34 -34
  46. data/lib/makit/configuration/timeout.rb +74 -0
  47. data/lib/makit/configuration.rb +15 -14
  48. data/lib/makit/content/default_gitignore.rb +7 -7
  49. data/lib/makit/content/default_gitignore.txt +225 -225
  50. data/lib/makit/content/default_rakefile.rb +13 -13
  51. data/lib/makit/content/gem_rakefile.rb +16 -16
  52. data/lib/makit/context.rb +1 -1
  53. data/lib/makit/data.rb +49 -49
  54. data/lib/makit/directories.rb +140 -140
  55. data/lib/makit/directory.rb +262 -262
  56. data/lib/makit/docs/files.rb +89 -89
  57. data/lib/makit/docs/rake.rb +102 -102
  58. data/lib/makit/dotnet/cli.rb +69 -69
  59. data/lib/makit/dotnet/project.rb +217 -217
  60. data/lib/makit/dotnet/solution.rb +38 -38
  61. data/lib/makit/dotnet/solution_classlib.rb +239 -239
  62. data/lib/makit/dotnet/solution_console.rb +264 -264
  63. data/lib/makit/dotnet/solution_maui.rb +354 -354
  64. data/lib/makit/dotnet/solution_wasm.rb +275 -275
  65. data/lib/makit/dotnet/solution_wpf.rb +304 -304
  66. data/lib/makit/dotnet.rb +102 -102
  67. data/lib/makit/email.rb +90 -90
  68. data/lib/makit/environment.rb +142 -142
  69. data/lib/makit/examples/runner.rb +370 -370
  70. data/lib/makit/exceptions.rb +45 -45
  71. data/lib/makit/fileinfo.rb +24 -24
  72. data/lib/makit/files.rb +43 -43
  73. data/lib/makit/gems.rb +40 -40
  74. data/lib/makit/git/cli.rb +54 -54
  75. data/lib/makit/git/repository.rb +90 -90
  76. data/lib/makit/git.rb +98 -98
  77. data/lib/makit/gitlab_runner.rb +59 -59
  78. data/lib/makit/humanize.rb +137 -137
  79. data/lib/makit/indexer.rb +47 -47
  80. data/lib/makit/logging/configuration.rb +308 -308
  81. data/lib/makit/logging/format_registry.rb +84 -84
  82. data/lib/makit/logging/formatters/base.rb +39 -39
  83. data/lib/makit/logging/formatters/console_formatter.rb +140 -140
  84. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  85. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  86. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  87. data/lib/makit/logging/log_request.rb +119 -119
  88. data/lib/makit/logging/logger.rb +199 -199
  89. data/lib/makit/logging/sinks/base.rb +91 -91
  90. data/lib/makit/logging/sinks/console.rb +72 -72
  91. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  92. data/lib/makit/logging/sinks/structured.rb +123 -123
  93. data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
  94. data/lib/makit/logging.rb +565 -565
  95. data/lib/makit/markdown.rb +75 -75
  96. data/lib/makit/mp/basic_object_mp.rb +17 -17
  97. data/lib/makit/mp/command_mp.rb +13 -13
  98. data/lib/makit/mp/command_request.mp.rb +17 -17
  99. data/lib/makit/mp/project_mp.rb +199 -199
  100. data/lib/makit/mp/string_mp.rb +191 -191
  101. data/lib/makit/nuget.rb +74 -74
  102. data/lib/makit/port.rb +32 -32
  103. data/lib/makit/process.rb +163 -163
  104. data/lib/makit/protoc.rb +107 -107
  105. data/lib/makit/rake/cli.rb +196 -196
  106. data/lib/makit/rake.rb +80 -80
  107. data/lib/makit/ruby/cli.rb +185 -185
  108. data/lib/makit/ruby.rb +25 -25
  109. data/lib/makit/secrets.rb +51 -51
  110. data/lib/makit/serializer.rb +130 -130
  111. data/lib/makit/services/builder.rb +186 -186
  112. data/lib/makit/services/error_handler.rb +226 -226
  113. data/lib/makit/services/repository_manager.rb +231 -231
  114. data/lib/makit/services/validator.rb +112 -112
  115. data/lib/makit/setup/classlib.rb +101 -101
  116. data/lib/makit/setup/gem.rb +268 -268
  117. data/lib/makit/setup/razorclasslib.rb +101 -101
  118. data/lib/makit/setup/runner.rb +54 -54
  119. data/lib/makit/setup.rb +5 -5
  120. data/lib/makit/show.rb +110 -110
  121. data/lib/makit/storage.rb +126 -126
  122. data/lib/makit/symbols.rb +170 -170
  123. data/lib/makit/task_info.rb +130 -130
  124. data/lib/makit/tasks/at_exit.rb +15 -15
  125. data/lib/makit/tasks/build.rb +22 -22
  126. data/lib/makit/tasks/clean.rb +13 -13
  127. data/lib/makit/tasks/configure.rb +10 -10
  128. data/lib/makit/tasks/format.rb +10 -10
  129. data/lib/makit/tasks/hook_manager.rb +443 -443
  130. data/lib/makit/tasks/init.rb +49 -49
  131. data/lib/makit/tasks/integrate.rb +29 -29
  132. data/lib/makit/tasks/pull_incoming.rb +13 -13
  133. data/lib/makit/tasks/setup.rb +13 -13
  134. data/lib/makit/tasks/sync.rb +17 -17
  135. data/lib/makit/tasks/tag.rb +16 -16
  136. data/lib/makit/tasks/task_monkey_patch.rb +81 -81
  137. data/lib/makit/tasks/test.rb +22 -22
  138. data/lib/makit/tasks/update.rb +18 -18
  139. data/lib/makit/tasks.rb +20 -20
  140. data/lib/makit/test_cache.rb +239 -239
  141. data/lib/makit/tree.rb +37 -37
  142. data/lib/makit/v1/makit.v1_pb.rb +35 -35
  143. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  144. data/lib/makit/version.rb +99 -99
  145. data/lib/makit/version_util.rb +21 -21
  146. data/lib/makit/wix.rb +95 -95
  147. data/lib/makit/yaml.rb +29 -29
  148. data/lib/makit/zip.rb +17 -17
  149. data/lib/makit copy.rb +44 -44
  150. data/lib/makit.rb +42 -42
  151. metadata +3 -2
data/lib/makit/logging.rb CHANGED
@@ -1,565 +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
-
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
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