makit 0.0.99 → 0.0.112

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