makit 0.0.111 → 0.0.126
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.
- checksums.yaml +4 -4
- data/lib/makit/cli/repository_commands.rb +1 -1
- data/lib/makit/commands/middleware/cache.rb +3 -3
- data/lib/makit/commands/middleware/command_logger.rb +33 -45
- data/lib/makit/commands/request.rb +63 -1
- data/lib/makit/commands/runner.rb +56 -5
- data/lib/makit/commands/strategies/base.rb +13 -2
- data/lib/makit/commands/strategies/synchronous.rb +11 -6
- data/lib/makit/commands.rb +8 -0
- data/lib/makit/configuration/gitlab_helper.rb +0 -2
- data/lib/makit/configuration/project.rb +48 -8
- data/lib/makit/configuration/step.rb +3 -3
- data/lib/makit/content/default_gitignore.txt +226 -0
- data/lib/makit/directories.rb +3 -4
- data/lib/makit/docs/files.rb +1 -1
- data/lib/makit/docs/rake.rb +1 -1
- data/lib/makit/dotnet/cli.rb +69 -65
- data/lib/makit/dotnet/project.rb +71 -7
- data/lib/makit/examples/runner.rb +2 -2
- data/lib/makit/logging/configuration.rb +9 -6
- data/lib/makit/logging/format_registry.rb +84 -84
- data/lib/makit/logging/formatters/console_formatter.rb +22 -9
- data/lib/makit/logging/log_request.rb +6 -2
- data/lib/makit/logging/logger.rb +45 -5
- data/lib/makit/logging/sinks/base.rb +91 -91
- data/lib/makit/logging/sinks/structured.rb +123 -129
- data/lib/makit/logging/sinks/unified_file_sink.rb +39 -46
- data/lib/makit/logging.rb +45 -1
- data/lib/makit/mp/project_mp.rb +6 -6
- data/lib/makit/mp/string_mp.rb +108 -265
- data/lib/makit/serializer.rb +14 -1
- data/lib/makit/services/builder.rb +5 -5
- data/lib/makit/services/repository_manager.rb +8 -6
- data/lib/makit/setup/classlib.rb +44 -7
- data/lib/makit/setup/gem.rb +268 -250
- data/lib/makit/setup/razorclasslib.rb +91 -0
- data/lib/makit/setup/runner.rb +36 -22
- data/lib/makit/setup.rb +5 -0
- data/lib/makit/symbols.rb +10 -1
- data/lib/makit/tasks/at_exit.rb +3 -1
- data/lib/makit/tasks/build.rb +16 -12
- data/lib/makit/tasks/clean.rb +2 -0
- data/lib/makit/tasks/configure.rb +10 -0
- data/lib/makit/tasks/format.rb +10 -0
- data/lib/makit/tasks/hook_manager.rb +160 -8
- data/lib/makit/tasks/init.rb +2 -0
- data/lib/makit/tasks/integrate.rb +17 -3
- data/lib/makit/tasks/pull_incoming.rb +6 -5
- data/lib/makit/tasks/setup.rb +10 -3
- data/lib/makit/tasks/sync.rb +13 -7
- data/lib/makit/tasks/tag.rb +16 -0
- data/lib/makit/tasks/task_monkey_patch.rb +58 -56
- data/lib/makit/tasks/test.rb +22 -0
- data/lib/makit/tasks/update.rb +18 -0
- data/lib/makit/tasks.rb +20 -5
- data/lib/makit/v1/makit.v1_pb.rb +1 -0
- data/lib/makit/version.rb +1 -1
- data/lib/makit/version_util.rb +21 -0
- data/lib/makit copy.rb +44 -0
- data/lib/makit.rb +31 -0
- metadata +118 -13
- data/lib/makit/command_runner.rb +0 -463
- data/lib/makit/commands/compatibility.rb +0 -365
- data/lib/makit/commands/middleware/unified_logger.rb +0 -243
- data/lib/makit/task_hooks.rb +0 -125
@@ -1,365 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "ostruct"
|
4
|
-
require "fileutils"
|
5
|
-
require_relative "runner"
|
6
|
-
require_relative "request"
|
7
|
-
require_relative "result"
|
8
|
-
|
9
|
-
module Makit
|
10
|
-
module Commands
|
11
|
-
# Compatibility layer that provides legacy interface methods for the new Commands::Runner
|
12
|
-
#
|
13
|
-
# This class bridges the gap between the old CommandRunner interface and the new
|
14
|
-
# Commands::Runner architecture, allowing existing code to work without modification
|
15
|
-
# while benefiting from the improved architecture.
|
16
|
-
class Compatibility
|
17
|
-
# @!attribute [r] runner
|
18
|
-
# @return [Runner] the underlying Commands::Runner instance
|
19
|
-
attr_reader :runner
|
20
|
-
|
21
|
-
# Initialize compatibility layer
|
22
|
-
#
|
23
|
-
# @param runner [Runner] the Commands::Runner instance to wrap
|
24
|
-
def initialize(runner = nil)
|
25
|
-
@runner = runner || create_runner_with_caching
|
26
|
-
end
|
27
|
-
|
28
|
-
# Parse command request from various input types (legacy interface)
|
29
|
-
#
|
30
|
-
# @param source [String, Hash, Request] command source
|
31
|
-
# @return [Request] normalized request
|
32
|
-
def parse_command_request(source)
|
33
|
-
case source
|
34
|
-
when String
|
35
|
-
Request.from_string(source)
|
36
|
-
when Hash
|
37
|
-
Request.from_hash(source)
|
38
|
-
when Request
|
39
|
-
source
|
40
|
-
when Makit::V1::CommandRequest
|
41
|
-
# Convert legacy CommandRequest to new Request
|
42
|
-
Request.new(
|
43
|
-
command: source.name,
|
44
|
-
arguments: source.arguments.to_a,
|
45
|
-
directory: source.directory,
|
46
|
-
timeout: source.timeout,
|
47
|
-
environment: {},
|
48
|
-
metadata: { legacy: true },
|
49
|
-
)
|
50
|
-
else
|
51
|
-
raise ArgumentError, "Invalid source type: #{source.class}"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Parse arguments (legacy interface)
|
56
|
-
#
|
57
|
-
# @param args [String, Array, Hash, Request] arguments to parse
|
58
|
-
# @return [Request] parsed request
|
59
|
-
def parse_args(args)
|
60
|
-
parse_command_request(args)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Execute command (legacy run interface)
|
64
|
-
#
|
65
|
-
# @param request_or_string [Request, String, Hash] command to run
|
66
|
-
# @return [Result] execution result converted to legacy format
|
67
|
-
def run(request_or_string)
|
68
|
-
request = parse_command_request(request_or_string)
|
69
|
-
result = @runner.execute(request)
|
70
|
-
# Store directory in result metadata for legacy compatibility
|
71
|
-
result.metadata[:directory] = request.directory
|
72
|
-
convert_to_legacy_command(result)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Execute command with caching (legacy cache_run interface)
|
76
|
-
#
|
77
|
-
# @param request_or_string [Request, String, Hash] command to run
|
78
|
-
# @param timestamp [Time, nil] cache timestamp
|
79
|
-
# @return [Result] execution result converted to legacy format
|
80
|
-
def cache_run(request_or_string, timestamp = nil)
|
81
|
-
request = parse_command_request(request_or_string)
|
82
|
-
|
83
|
-
# Add cache metadata
|
84
|
-
cache_key = generate_cache_key(request)
|
85
|
-
request.metadata[:cache_key] = cache_key
|
86
|
-
request.metadata[:cache_timestamp] = timestamp || default_timestamp
|
87
|
-
|
88
|
-
# Execute with caching middleware
|
89
|
-
result = @runner.execute(request)
|
90
|
-
# Store directory in result metadata for legacy compatibility
|
91
|
-
result.metadata[:directory] = request.directory
|
92
|
-
convert_to_legacy_command(result)
|
93
|
-
end
|
94
|
-
|
95
|
-
# Execute command with caching without raising on error (legacy cache_try interface)
|
96
|
-
#
|
97
|
-
# @param request_or_string [Request, String, Hash] command to try
|
98
|
-
# @param timestamp [Time, nil] cache timestamp
|
99
|
-
# @return [Result] execution result converted to legacy format
|
100
|
-
def cache_try(request_or_string, timestamp = nil)
|
101
|
-
request = parse_command_request(request_or_string)
|
102
|
-
request.metadata[:exit_on_error] = false
|
103
|
-
|
104
|
-
# Add cache metadata
|
105
|
-
cache_key = generate_cache_key(request)
|
106
|
-
request.metadata[:cache_key] = cache_key
|
107
|
-
request.metadata[:cache_timestamp] = timestamp || default_timestamp
|
108
|
-
|
109
|
-
# Execute with caching middleware
|
110
|
-
result = @runner.execute(request)
|
111
|
-
# Store directory in result metadata for legacy compatibility
|
112
|
-
result.metadata[:directory] = request.directory
|
113
|
-
convert_to_legacy_command(result)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Execute command without raising on error (legacy try interface)
|
117
|
-
#
|
118
|
-
# @param request_or_string [Request, String, Hash] command to try
|
119
|
-
# @return [Result] execution result converted to legacy format
|
120
|
-
def try(request_or_string)
|
121
|
-
request = parse_command_request(request_or_string)
|
122
|
-
request.metadata[:exit_on_error] = false
|
123
|
-
|
124
|
-
result = @runner.execute(request)
|
125
|
-
# Store directory in result metadata for legacy compatibility
|
126
|
-
result.metadata[:directory] = request.directory
|
127
|
-
convert_to_legacy_command(result)
|
128
|
-
end
|
129
|
-
|
130
|
-
# Show command information (legacy show interface)
|
131
|
-
#
|
132
|
-
# @param request_or_string [Request, String, Hash] command to show
|
133
|
-
# @return [Result] execution result converted to legacy format
|
134
|
-
def show(request_or_string)
|
135
|
-
request = parse_command_request(request_or_string)
|
136
|
-
request.metadata[:show_output] = true
|
137
|
-
|
138
|
-
result = @runner.execute(request)
|
139
|
-
# Store directory in result metadata for legacy compatibility
|
140
|
-
result.metadata[:directory] = request.directory
|
141
|
-
show_command(convert_to_legacy_command(result))
|
142
|
-
convert_to_legacy_command(result)
|
143
|
-
end
|
144
|
-
|
145
|
-
# Search command history for matching commands (legacy interface)
|
146
|
-
#
|
147
|
-
# @param query [String] search query
|
148
|
-
# @return [Array<Object>] matching command results
|
149
|
-
def search(query)
|
150
|
-
# For now, return empty array since we don't have command history in new architecture
|
151
|
-
# This could be enhanced with a command history middleware
|
152
|
-
[]
|
153
|
-
end
|
154
|
-
|
155
|
-
# Get cache filename for a command (legacy interface)
|
156
|
-
#
|
157
|
-
# @param command [Object] command object
|
158
|
-
# @return [String] cache filename
|
159
|
-
def get_cache_filename(command)
|
160
|
-
require "digest"
|
161
|
-
if command.respond_to?(:name) && command.respond_to?(:arguments)
|
162
|
-
content = "#{command.name} #{command.arguments.join(" ")}"
|
163
|
-
else
|
164
|
-
content = command.to_s
|
165
|
-
end
|
166
|
-
hash = Digest::SHA256.hexdigest(content)
|
167
|
-
cache_dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands", "cache")
|
168
|
-
FileUtils.mkdir_p(cache_dir)
|
169
|
-
File.join(cache_dir, "#{hash}.pb")
|
170
|
-
end
|
171
|
-
|
172
|
-
# Log rake commands to file (legacy interface)
|
173
|
-
#
|
174
|
-
# @return [void]
|
175
|
-
def log_rake_commands
|
176
|
-
dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
|
177
|
-
FileUtils.mkdir_p(dir)
|
178
|
-
|
179
|
-
# For now, create empty file since we don't have command history
|
180
|
-
# This could be enhanced with a command history middleware
|
181
|
-
File.open(File.join(dir, "rake.commands.txt"), "w") do |file|
|
182
|
-
file.puts "# No command history available in new architecture"
|
183
|
-
file.puts "# This functionality will be restored with command history middleware"
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
# Log slowest commands to file (legacy interface)
|
188
|
-
#
|
189
|
-
# @return [void]
|
190
|
-
def log_slowest_commands
|
191
|
-
dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
|
192
|
-
FileUtils.mkdir_p(dir)
|
193
|
-
|
194
|
-
# For now, create empty file since we don't have command history
|
195
|
-
# This could be enhanced with a command history middleware
|
196
|
-
File.open(File.join(dir, "slow.commands.txt"), "w") do |file|
|
197
|
-
file.puts "# No command history available in new architecture"
|
198
|
-
file.puts "# This functionality will be restored with command history middleware"
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
# Display command summary (legacy show_command interface)
|
203
|
-
#
|
204
|
-
# @param command [Makit::V1::Command, Result] command result to display
|
205
|
-
def show_command(command)
|
206
|
-
# Convert new Result to legacy format if needed
|
207
|
-
legacy_command = command.is_a?(Result) ? convert_to_legacy_command(command) : command
|
208
|
-
|
209
|
-
if legacy_command.exit_code.zero?
|
210
|
-
puts get_command_summary(legacy_command) + " (#{legacy_command.duration&.seconds || 0} seconds)".colorize(:cyan)
|
211
|
-
puts indent_string(legacy_command.output, 2).colorize(:default) if should_show_output_on_success?
|
212
|
-
else
|
213
|
-
puts get_command_summary(legacy_command) + " (exit code #{legacy_command.exit_code})".colorize(:default)
|
214
|
-
puts " directory: #{legacy_command.directory}\n"
|
215
|
-
puts " duration: #{legacy_command.duration&.seconds || 0} seconds\n"
|
216
|
-
puts indent_string(legacy_command.output, 2) if legacy_command.output&.length&.positive?
|
217
|
-
puts indent_string(legacy_command.error, 2) if legacy_command.error&.length&.positive?
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
private
|
222
|
-
|
223
|
-
# Create a runner with caching middleware
|
224
|
-
#
|
225
|
-
# @return [Runner] runner with caching middleware
|
226
|
-
def create_runner_with_caching
|
227
|
-
require_relative "middleware/cache"
|
228
|
-
|
229
|
-
Runner.new(
|
230
|
-
middleware: [
|
231
|
-
Middleware::Cache.new,
|
232
|
-
Middleware::CommandLogger.new(
|
233
|
-
log_stdout: true,
|
234
|
-
log_stderr: true,
|
235
|
-
log_performance: true,
|
236
|
-
max_output_lines: 50,
|
237
|
-
),
|
238
|
-
],
|
239
|
-
)
|
240
|
-
end
|
241
|
-
|
242
|
-
# Convert new Result to legacy Makit::V1::Command format
|
243
|
-
#
|
244
|
-
# @param result [Result] result to convert
|
245
|
-
# @return [Makit::V1::Command] legacy command object
|
246
|
-
def convert_to_legacy_command(result)
|
247
|
-
# Create a legacy command object that duck-types with Makit::V1::Command
|
248
|
-
legacy_command = OpenStruct.new
|
249
|
-
legacy_command.name = result.command.split.first
|
250
|
-
legacy_command.arguments = result.command.split[1..] || []
|
251
|
-
# Get directory from metadata if available, otherwise use current directory
|
252
|
-
legacy_command.directory = result.metadata[:directory] || Dir.pwd
|
253
|
-
legacy_command.exit_code = result.exit_code
|
254
|
-
legacy_command.output = result.stdout
|
255
|
-
legacy_command.error = result.stderr
|
256
|
-
legacy_command.started_at = convert_time_to_protobuf_timestamp(result.started_at)
|
257
|
-
legacy_command.duration = convert_duration_to_protobuf(result.duration)
|
258
|
-
|
259
|
-
# Add success? method for compatibility
|
260
|
-
def legacy_command.success?
|
261
|
-
exit_code.zero?
|
262
|
-
end
|
263
|
-
|
264
|
-
legacy_command
|
265
|
-
end
|
266
|
-
|
267
|
-
# Generate cache key for a request
|
268
|
-
#
|
269
|
-
# @param request [Request] request to generate key for
|
270
|
-
# @return [String] cache key
|
271
|
-
def generate_cache_key(request)
|
272
|
-
require "digest"
|
273
|
-
content = "#{request.command} #{request.arguments.join(" ")}"
|
274
|
-
Digest::SHA256.hexdigest(content)
|
275
|
-
end
|
276
|
-
|
277
|
-
# Get default timestamp for caching
|
278
|
-
#
|
279
|
-
# @return [Time] default timestamp
|
280
|
-
def default_timestamp
|
281
|
-
if defined?(Makit::GIT_FILE_INFOS) && Makit::GIT_FILE_INFOS.any?
|
282
|
-
Makit::GIT_FILE_INFOS.first.mtime
|
283
|
-
else
|
284
|
-
Time.now
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
# Get command summary string (legacy interface)
|
289
|
-
#
|
290
|
-
# @param command [Object] command object
|
291
|
-
# @return [String] command summary
|
292
|
-
def get_command_summary(command)
|
293
|
-
symbol = "⚠️" # warning by default
|
294
|
-
symbol = "✓" if command.exit_code&.zero?
|
295
|
-
symbol = "✗" if command.exit_code != 0
|
296
|
-
|
297
|
-
summary = "#{symbol} #{command.name} #{command.arguments.join(" ")}"
|
298
|
-
|
299
|
-
# Apply line wrapping if available
|
300
|
-
if summary.respond_to?(:to_lines) && summary.length > 80
|
301
|
-
summary.to_lines(80, command.name.length + 3)
|
302
|
-
else
|
303
|
-
summary
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
# Indent string helper
|
308
|
-
#
|
309
|
-
# @param input_string [String] string to indent
|
310
|
-
# @param indent_spaces [Integer] number of spaces to indent
|
311
|
-
# @return [String] indented string
|
312
|
-
def indent_string(input_string, indent_spaces)
|
313
|
-
return "" unless input_string
|
314
|
-
|
315
|
-
indentation = " " * indent_spaces
|
316
|
-
input_string.lines.map { |line| indentation + line }.join
|
317
|
-
end
|
318
|
-
|
319
|
-
# Check if output should be shown on success
|
320
|
-
#
|
321
|
-
# @return [Boolean] true if output should be shown
|
322
|
-
def should_show_output_on_success?
|
323
|
-
# Check if the legacy runner has this setting
|
324
|
-
if defined?(Makit::RUNNER) && Makit::RUNNER.respond_to?(:show_output_on_success)
|
325
|
-
Makit::RUNNER.show_output_on_success
|
326
|
-
else
|
327
|
-
false
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
# Convert Time to protobuf timestamp format
|
332
|
-
#
|
333
|
-
# @param time [Time] time to convert
|
334
|
-
# @return [Google::Protobuf::Timestamp] protobuf timestamp
|
335
|
-
def convert_time_to_protobuf_timestamp(time)
|
336
|
-
return nil unless time
|
337
|
-
|
338
|
-
if defined?(Google::Protobuf::Timestamp)
|
339
|
-
Google::Protobuf::Timestamp.new(seconds: time.to_i, nanos: time.nsec)
|
340
|
-
else
|
341
|
-
# Fallback object with same interface
|
342
|
-
OpenStruct.new(seconds: time.to_i, nanos: time.nsec)
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
# Convert duration to protobuf duration format
|
347
|
-
#
|
348
|
-
# @param duration [Float] duration in seconds
|
349
|
-
# @return [Google::Protobuf::Duration] protobuf duration
|
350
|
-
def convert_duration_to_protobuf(duration)
|
351
|
-
return nil unless duration
|
352
|
-
|
353
|
-
seconds = duration.to_i
|
354
|
-
nanos = ((duration - seconds) * 1_000_000_000).to_i
|
355
|
-
|
356
|
-
if defined?(Google::Protobuf::Duration)
|
357
|
-
Google::Protobuf::Duration.new(seconds: seconds, nanos: nanos)
|
358
|
-
else
|
359
|
-
# Fallback object with same interface
|
360
|
-
OpenStruct.new(seconds: seconds, nanos: nanos)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
@@ -1,243 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "base"
|
4
|
-
|
5
|
-
module Makit
|
6
|
-
module Commands
|
7
|
-
module Middleware
|
8
|
-
# Unified logging middleware that consolidates all command logging functionality
|
9
|
-
#
|
10
|
-
# This middleware replaces the need for multiple separate logging middleware
|
11
|
-
# by providing a single, comprehensive logging solution that handles console
|
12
|
-
# display, file logging, and structured logging through the Makit::Logging system.
|
13
|
-
#
|
14
|
-
# @example Basic usage
|
15
|
-
# logger = UnifiedLogger.new
|
16
|
-
# runner = Runner.new(middleware: [logger])
|
17
|
-
# result = runner.execute("git --version")
|
18
|
-
#
|
19
|
-
# @example With custom logger configuration
|
20
|
-
# custom_logger = Makit::Logging::Logger.new(
|
21
|
-
# sinks: [
|
22
|
-
# Makit::Logging::Sinks::Console.new,
|
23
|
-
# Makit::Logging::Sinks::FileSink.new(log_file: "artifacts/commands.log")
|
24
|
-
# ]
|
25
|
-
# )
|
26
|
-
# logger = UnifiedLogger.new(logger: custom_logger)
|
27
|
-
# runner = Runner.new(middleware: [logger])
|
28
|
-
class UnifiedLogger < Base
|
29
|
-
# @!attribute [r] logger
|
30
|
-
# @return [Makit::Logging::Logger] the logging instance
|
31
|
-
attr_reader :logger
|
32
|
-
|
33
|
-
# Initialize unified logging middleware.
|
34
|
-
#
|
35
|
-
# @param logger [Makit::Logging::Logger, nil] custom logger instance
|
36
|
-
# @param log_to_console [Boolean] whether to log to console
|
37
|
-
# @param log_to_file [Boolean] whether to log to file
|
38
|
-
# @param log_performance [Boolean] whether to log performance metrics
|
39
|
-
# @param log_output [Boolean] whether to log command output
|
40
|
-
def initialize(logger: nil, log_to_console: true, log_to_file: true, log_performance: true, log_output: false)
|
41
|
-
@logger = logger || create_default_logger(log_to_console, log_to_file)
|
42
|
-
@log_performance = log_performance
|
43
|
-
@log_output = log_output
|
44
|
-
end
|
45
|
-
|
46
|
-
# Execute command with unified logging.
|
47
|
-
#
|
48
|
-
# @param request [Request] command request to execute
|
49
|
-
# @yield [Request] yields request to next middleware
|
50
|
-
# @return [Result] execution result
|
51
|
-
def call(request, &block)
|
52
|
-
command_id = generate_command_id
|
53
|
-
start_time = Time.now
|
54
|
-
|
55
|
-
# Log command start
|
56
|
-
log_command_start(request, command_id)
|
57
|
-
|
58
|
-
begin
|
59
|
-
# Execute the command
|
60
|
-
result = block.call(request)
|
61
|
-
duration = Time.now - start_time
|
62
|
-
|
63
|
-
# Log command completion
|
64
|
-
log_command_completion(request, result, duration, command_id)
|
65
|
-
|
66
|
-
result
|
67
|
-
rescue => error
|
68
|
-
duration = Time.now - start_time
|
69
|
-
|
70
|
-
# Log command error
|
71
|
-
log_command_error(request, error, duration, command_id)
|
72
|
-
|
73
|
-
raise
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Check if this middleware applies to the given request.
|
78
|
-
#
|
79
|
-
# @param request [Request] command request
|
80
|
-
# @return [Boolean] true if middleware applies
|
81
|
-
def applicable?(request)
|
82
|
-
true
|
83
|
-
end
|
84
|
-
|
85
|
-
# Get middleware configuration.
|
86
|
-
#
|
87
|
-
# @return [Hash] middleware configuration
|
88
|
-
def config
|
89
|
-
{
|
90
|
-
name: "UnifiedLogger",
|
91
|
-
description: "Unified logging for command execution with console and file output",
|
92
|
-
log_performance: @log_performance,
|
93
|
-
log_output: @log_output,
|
94
|
-
logger_class: @logger.class.name,
|
95
|
-
}
|
96
|
-
end
|
97
|
-
|
98
|
-
private
|
99
|
-
|
100
|
-
# Create default logger with console and file output
|
101
|
-
#
|
102
|
-
# @param log_to_console [Boolean] whether to log to console
|
103
|
-
# @param log_to_file [Boolean] whether to log to file
|
104
|
-
# @return [Makit::Logging::Logger] configured logger
|
105
|
-
def create_default_logger(log_to_console, log_to_file)
|
106
|
-
sinks = []
|
107
|
-
|
108
|
-
if log_to_console
|
109
|
-
sinks << Makit::Logging::Sinks::Console.new
|
110
|
-
end
|
111
|
-
|
112
|
-
if log_to_file
|
113
|
-
sinks << Makit::Logging::Sinks::FileSink.new(
|
114
|
-
log_file: "artifacts/commands.log",
|
115
|
-
formatter: :json,
|
116
|
-
include_metadata: true,
|
117
|
-
)
|
118
|
-
end
|
119
|
-
|
120
|
-
Makit::Logging::Logger.new(sinks: sinks)
|
121
|
-
end
|
122
|
-
|
123
|
-
# Log command execution start.
|
124
|
-
#
|
125
|
-
# @param request [Request] command request
|
126
|
-
# @param command_id [String] unique command identifier
|
127
|
-
def log_command_start(request, command_id)
|
128
|
-
@logger.info("Command execution started", {
|
129
|
-
command_id: command_id,
|
130
|
-
command: request.command,
|
131
|
-
arguments: request.arguments,
|
132
|
-
working_directory: request.directory,
|
133
|
-
timeout: request.timeout,
|
134
|
-
environment: request.environment&.keys || [],
|
135
|
-
})
|
136
|
-
end
|
137
|
-
|
138
|
-
# Log command execution completion.
|
139
|
-
#
|
140
|
-
# @param request [Request] command request
|
141
|
-
# @param result [Result] execution result
|
142
|
-
# @param duration [Float] execution duration
|
143
|
-
# @param command_id [String] unique command identifier
|
144
|
-
def log_command_completion(request, result, duration, command_id)
|
145
|
-
log_data = {
|
146
|
-
command_id: command_id,
|
147
|
-
command: request.command,
|
148
|
-
arguments: request.arguments,
|
149
|
-
success: result.success?,
|
150
|
-
exit_code: result.exit_code,
|
151
|
-
duration: duration,
|
152
|
-
working_directory: request.directory,
|
153
|
-
}
|
154
|
-
|
155
|
-
# Add performance metrics if enabled
|
156
|
-
if @log_performance
|
157
|
-
log_data.merge!(
|
158
|
-
memory_usage: get_memory_usage,
|
159
|
-
timestamp: Time.now.iso8601,
|
160
|
-
)
|
161
|
-
end
|
162
|
-
|
163
|
-
# Add output if enabled and present
|
164
|
-
if @log_output
|
165
|
-
log_data[:stdout_lines] = result.stdout&.split("\n")&.length || 0
|
166
|
-
log_data[:stderr_lines] = result.stderr&.split("\n")&.length || 0
|
167
|
-
log_data[:stdout] = result.stdout if result.stdout && !result.stdout.empty?
|
168
|
-
log_data[:stderr] = result.stderr if result.stderr && !result.stderr.empty?
|
169
|
-
end
|
170
|
-
|
171
|
-
# Log at appropriate level based on success
|
172
|
-
if result.success?
|
173
|
-
@logger.success("Command completed successfully", log_data)
|
174
|
-
else
|
175
|
-
@logger.error("Command completed with errors", log_data)
|
176
|
-
end
|
177
|
-
|
178
|
-
# Log slow commands
|
179
|
-
if @log_performance && duration > 1.0
|
180
|
-
@logger.warn("Slow command detected",
|
181
|
-
command_id: command_id,
|
182
|
-
command: request.command,
|
183
|
-
duration: duration)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
# Log command execution error.
|
188
|
-
#
|
189
|
-
# @param request [Request] command request
|
190
|
-
# @param error [Exception] execution error
|
191
|
-
# @param duration [Float] execution duration
|
192
|
-
# @param command_id [String] unique command identifier
|
193
|
-
def log_command_error(request, error, duration, command_id)
|
194
|
-
@logger.error("Command execution failed", {
|
195
|
-
command_id: command_id,
|
196
|
-
command: request.command,
|
197
|
-
arguments: request.arguments,
|
198
|
-
working_directory: request.directory,
|
199
|
-
error_class: error.class.name,
|
200
|
-
error_message: error.message,
|
201
|
-
duration: duration,
|
202
|
-
backtrace: error.backtrace&.first(5),
|
203
|
-
})
|
204
|
-
end
|
205
|
-
|
206
|
-
# Generate a unique command identifier.
|
207
|
-
#
|
208
|
-
# @return [String] unique command ID
|
209
|
-
def generate_command_id
|
210
|
-
"#{::Process.pid}-#{Time.now.to_f}-#{rand(1000)}"
|
211
|
-
end
|
212
|
-
|
213
|
-
# Get current memory usage (if available).
|
214
|
-
#
|
215
|
-
# @return [String, nil] memory usage string or nil if unavailable
|
216
|
-
def get_memory_usage
|
217
|
-
# Try to get memory usage on different platforms
|
218
|
-
if RUBY_PLATFORM.match?(/mswin|mingw/)
|
219
|
-
# Windows - try to get memory usage
|
220
|
-
begin
|
221
|
-
"Unknown"
|
222
|
-
rescue
|
223
|
-
nil
|
224
|
-
end
|
225
|
-
else
|
226
|
-
# Unix-like systems
|
227
|
-
begin
|
228
|
-
# Try to get memory usage from /proc/self/status
|
229
|
-
if File.exist?("/proc/self/status")
|
230
|
-
status = File.read("/proc/self/status")
|
231
|
-
if match = status.match(/VmRSS:\s+(\d+)\s+kB/)
|
232
|
-
"#{match[1].to_i / 1024}MB"
|
233
|
-
end
|
234
|
-
end
|
235
|
-
rescue
|
236
|
-
nil
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|