makit 0.0.157 → 0.0.158

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