diff --git a/src/Tools/Common/Commands/Utils.cs b/src/Tools/Common/Commands/Utils.cs index 9e95f1b1b9..0b28a7ff2e 100644 --- a/src/Tools/Common/Commands/Utils.cs +++ b/src/Tools/Common/Commands/Utils.cs @@ -46,10 +46,6 @@ public static int FindProcessIdWithName(string name) // processId public static int LaunchDSRouterProcess(string dsrouterCommand) { - ConsoleColor currentColor = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine("WARNING: dotnet-dsrouter is a development tool not intended for production environments."); - Console.ForegroundColor = currentColor; Console.WriteLine("For finer control over the dotnet-dsrouter options, run it separately and connect to it using -p" + Environment.NewLine); return DsRouterProcessLauncher.Launcher.Start(dsrouterCommand, default); diff --git a/src/Tools/Common/DsRouterProcessLauncher.cs b/src/Tools/Common/DsRouterProcessLauncher.cs index b62685c06e..626c333227 100644 --- a/src/Tools/Common/DsRouterProcessLauncher.cs +++ b/src/Tools/Common/DsRouterProcessLauncher.cs @@ -24,11 +24,92 @@ internal sealed partial class DsRouterProcessLauncher internal static DsRouterProcessLauncher Launcher = new(); private bool _processStarted; - private static async Task ReadAndIgnoreAllStreamAsync(StreamReader streamToIgnore, CancellationToken cancelToken) + private static async Task ReadAndLogAllLinesAsync(StreamReader streamToRead, TextWriter output, CancellationToken cancelToken) { - Memory memory = new char[4096]; - while (await streamToIgnore.ReadAsync(memory, cancelToken).ConfigureAwait(false) != 0) + string line; + while ((line = await streamToRead.ReadLineAsync(cancelToken).ConfigureAwait(false)) != null) { + // Just log with no colors if redirected + if (Console.IsOutputRedirected) + { + output.WriteLine(line); + continue; + } + + // Console coloring is not preserved, so this is a naive approach based on SimpleConsoleFormatter's output: + // https://github.com/dotnet/runtime/blob/aadcceeb03ce0ecbc2ad645de0feb10189daa64c/src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatter.cs#L163-L199 + + ConsoleColor foregroundColor = Console.ForegroundColor; + ConsoleColor backgroundColor = Console.BackgroundColor; + try + { + // Specific dotnet-dsrouter warning message + if (line.StartsWith("WARNING: dotnet-dsrouter", StringComparison.OrdinalIgnoreCase)) + { + Console.ForegroundColor = ConsoleColor.Yellow; + output.WriteLine(line); + continue; + } + + // SimpleConsoleFormatter prefixes + if (line.StartsWith("crit:", StringComparison.OrdinalIgnoreCase)) + { + Console.ForegroundColor = ConsoleColor.White; + Console.BackgroundColor = ConsoleColor.DarkRed; + output.Write("crit"); + } + else if (line.StartsWith("fail:", StringComparison.OrdinalIgnoreCase)) + { + Console.ForegroundColor = ConsoleColor.Black; + Console.BackgroundColor = ConsoleColor.DarkRed; + output.Write("fail"); + } + else if (line.StartsWith("warn:", StringComparison.OrdinalIgnoreCase)) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.BackgroundColor = ConsoleColor.Black; + output.Write("warn"); + } + else if (line.StartsWith("info:", StringComparison.OrdinalIgnoreCase)) + { + Console.ForegroundColor = ConsoleColor.DarkGreen; + Console.BackgroundColor = ConsoleColor.Black; + output.Write("info"); + } + else if (line.StartsWith("dbug:", StringComparison.OrdinalIgnoreCase)) + { + Console.ForegroundColor = ConsoleColor.Gray; + Console.BackgroundColor = ConsoleColor.Black; + output.Write("dbug"); + } + else if (line.StartsWith("trce:", StringComparison.OrdinalIgnoreCase)) + { + Console.ForegroundColor = ConsoleColor.Gray; + Console.BackgroundColor = ConsoleColor.Black; + output.Write("trce"); + } + else + { + output.WriteLine(line); + continue; // If it doesn't match any prefix, just write the line as is + } + } + finally + { + Console.ForegroundColor = foregroundColor; + Console.BackgroundColor = backgroundColor; + } + + // If we get here, we logged a prefix, so we can log the rest of the line + if (line.Length > 4) + { + output.WriteLine(line.AsSpan().Slice(4)); + } + else + { + // If the line is just the prefix, we still need to write a new line + output.WriteLine(); + } } } @@ -69,8 +150,8 @@ public int Start(string dsrouterCommand, CancellationToken ct) return -1; } - _stdErrTask = ReadAndIgnoreAllStreamAsync(_childProc.StandardError, ct); - _stdOutTask = ReadAndIgnoreAllStreamAsync(_childProc.StandardOutput, ct); + _stdErrTask = ReadAndLogAllLinesAsync(_childProc.StandardError, Console.Error, ct); + _stdOutTask = ReadAndLogAllLinesAsync(_childProc.StandardOutput, Console.Out, ct); Task.Delay(1000, ct).Wait(ct); return !_childProc.HasExited ? _childProc.Id : -2; }