makit 0.0.169 → 0.0.170

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