From 6e5edfe0e553e6a5e928143f8018aa57ea85a645 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 08:06:08 +0000 Subject: [PATCH 1/8] Initial plan From 85250289136073486f97ed97062d8832f6706f74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 08:13:37 +0000 Subject: [PATCH 2/8] Fix extra logging in non-root commands by filtering plugin messages Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- DevProxy/Commands/DevProxyCommand.cs | 19 ++++++++++++++++++ .../Extensions/ILoggingBuilderExtensions.cs | 20 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/DevProxy/Commands/DevProxyCommand.cs b/DevProxy/Commands/DevProxyCommand.cs index e3db039b..61d292fc 100644 --- a/DevProxy/Commands/DevProxyCommand.cs +++ b/DevProxy/Commands/DevProxyCommand.cs @@ -40,9 +40,12 @@ sealed class DevProxyCommand : RootCommand private static readonly string[] globalOptions = ["--version"]; private static readonly string[] helpOptions = ["--help", "-h", "/h", "-?", "/?"]; + // Built-in subcommands + private static readonly string[] subCommands = ["msgraphdb", "config", "outdated", "jwt", "cert", "stdio"]; private static bool _hasGlobalOptionsResolved; private static bool _isStdioCommandResolved; + private static bool _isSubCommandResolved; private static bool _stdioLogFilePathResolved; public static bool HasGlobalOptions @@ -78,6 +81,22 @@ public static bool IsStdioCommand } } + public static bool IsSubCommand + { + get + { + if (_isSubCommandResolved) + { + return field; + } + + var args = Environment.GetCommandLineArgs(); + field = args.Any(arg => subCommands.Contains(arg)); + _isSubCommandResolved = true; + return field; + } + } + public static string StdioLogFilePath { get diff --git a/DevProxy/Extensions/ILoggingBuilderExtensions.cs b/DevProxy/Extensions/ILoggingBuilderExtensions.cs index 00735f24..3537d12d 100644 --- a/DevProxy/Extensions/ILoggingBuilderExtensions.cs +++ b/DevProxy/Extensions/ILoggingBuilderExtensions.cs @@ -39,6 +39,26 @@ public static ILoggingBuilder ConfigureDevProxyLogging( return builder; } + // For subcommands (except stdio), use simple console logging without rich formatting + // to avoid interfering with the command's output. Filter out plugin messages. + if (DevProxyCommand.IsSubCommand) + { + _ = builder + .ClearProviders() + .AddFilter("Microsoft.Hosting.*", LogLevel.None) + .AddFilter("Microsoft.AspNetCore.*", LogLevel.None) + .AddFilter("Microsoft.Extensions.*", LogLevel.None) + .AddFilter("System.*", LogLevel.None) + .AddFilter("DevProxy.Plugins.*", LogLevel.None) + .AddSimpleConsole(options => + { + options.SingleLine = true; + options.IncludeScopes = false; + }) + .SetMinimumLevel(configuredLogLevel); + return builder; + } + _ = builder .AddFilter("Microsoft.Hosting.*", LogLevel.Error) .AddFilter("Microsoft.AspNetCore.*", LogLevel.Error) From ccf902b993e8ebcd83d29aea7e26583d8bfdc112 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 10:40:49 +0000 Subject: [PATCH 3/8] Refactor: Use IsRootCommand instead of listing subcommand names Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- DevProxy/Commands/DevProxyCommand.cs | 21 ++++++++++++------- .../Extensions/ILoggingBuilderExtensions.cs | 12 ++++------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/DevProxy/Commands/DevProxyCommand.cs b/DevProxy/Commands/DevProxyCommand.cs index 61d292fc..13e61269 100644 --- a/DevProxy/Commands/DevProxyCommand.cs +++ b/DevProxy/Commands/DevProxyCommand.cs @@ -40,12 +40,10 @@ sealed class DevProxyCommand : RootCommand private static readonly string[] globalOptions = ["--version"]; private static readonly string[] helpOptions = ["--help", "-h", "/h", "-?", "/?"]; - // Built-in subcommands - private static readonly string[] subCommands = ["msgraphdb", "config", "outdated", "jwt", "cert", "stdio"]; private static bool _hasGlobalOptionsResolved; private static bool _isStdioCommandResolved; - private static bool _isSubCommandResolved; + private static bool _isRootCommandResolved; private static bool _stdioLogFilePathResolved; public static bool HasGlobalOptions @@ -81,18 +79,27 @@ public static bool IsStdioCommand } } - public static bool IsSubCommand + /// + /// Determines if the root command (proxy itself) is being invoked. + /// Returns true when no subcommand is specified (only options or no args). + /// A subcommand is detected when the first non-program argument doesn't start with '-'. + /// + public static bool IsRootCommand { get { - if (_isSubCommandResolved) + if (_isRootCommandResolved) { return field; } var args = Environment.GetCommandLineArgs(); - field = args.Any(arg => subCommands.Contains(arg)); - _isSubCommandResolved = true; + // Skip the first argument which is the program name + // If there are no more arguments, it's the root command + // If the first argument starts with '-', it's an option (root command) + // Otherwise, it's a subcommand name + field = args.Length <= 1 || args[1].StartsWith('-'); + _isRootCommandResolved = true; return field; } } diff --git a/DevProxy/Extensions/ILoggingBuilderExtensions.cs b/DevProxy/Extensions/ILoggingBuilderExtensions.cs index 3537d12d..31fb1b41 100644 --- a/DevProxy/Extensions/ILoggingBuilderExtensions.cs +++ b/DevProxy/Extensions/ILoggingBuilderExtensions.cs @@ -39,9 +39,10 @@ public static ILoggingBuilder ConfigureDevProxyLogging( return builder; } - // For subcommands (except stdio), use simple console logging without rich formatting - // to avoid interfering with the command's output. Filter out plugin messages. - if (DevProxyCommand.IsSubCommand) + // Only the root command (proxy itself) uses rich logging. + // All subcommands use simple logging without rich formatting to avoid + // interfering with command output + if (!DevProxyCommand.IsRootCommand) { _ = builder .ClearProviders() @@ -50,11 +51,6 @@ public static ILoggingBuilder ConfigureDevProxyLogging( .AddFilter("Microsoft.Extensions.*", LogLevel.None) .AddFilter("System.*", LogLevel.None) .AddFilter("DevProxy.Plugins.*", LogLevel.None) - .AddSimpleConsole(options => - { - options.SingleLine = true; - options.IncludeScopes = false; - }) .SetMinimumLevel(configuredLogLevel); return builder; } From eb12d79ff2d73721351a5e7592d01c0fa902a71d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:11:47 +0000 Subject: [PATCH 4/8] Handle jwt command separately: no console logging, other subcommands log Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- DevProxy/Commands/DevProxyCommand.cs | 17 +++++ .../Extensions/ILoggingBuilderExtensions.cs | 76 +++++++++++-------- 2 files changed, 62 insertions(+), 31 deletions(-) diff --git a/DevProxy/Commands/DevProxyCommand.cs b/DevProxy/Commands/DevProxyCommand.cs index 13e61269..4a835871 100644 --- a/DevProxy/Commands/DevProxyCommand.cs +++ b/DevProxy/Commands/DevProxyCommand.cs @@ -43,6 +43,7 @@ sealed class DevProxyCommand : RootCommand private static bool _hasGlobalOptionsResolved; private static bool _isStdioCommandResolved; + private static bool _isJwtCommandResolved; private static bool _isRootCommandResolved; private static bool _stdioLogFilePathResolved; @@ -79,6 +80,22 @@ public static bool IsStdioCommand } } + public static bool IsJwtCommand + { + get + { + if (_isJwtCommandResolved) + { + return field; + } + + var args = Environment.GetCommandLineArgs(); + field = args.Contains("jwt"); + _isJwtCommandResolved = true; + return field; + } + } + /// /// Determines if the root command (proxy itself) is being invoked. /// Returns true when no subcommand is specified (only options or no args). diff --git a/DevProxy/Extensions/ILoggingBuilderExtensions.cs b/DevProxy/Extensions/ILoggingBuilderExtensions.cs index 31fb1b41..de1774a3 100644 --- a/DevProxy/Extensions/ILoggingBuilderExtensions.cs +++ b/DevProxy/Extensions/ILoggingBuilderExtensions.cs @@ -39,45 +39,59 @@ public static ILoggingBuilder ConfigureDevProxyLogging( return builder; } - // Only the root command (proxy itself) uses rich logging. - // All subcommands use simple logging without rich formatting to avoid - // interfering with command output - if (!DevProxyCommand.IsRootCommand) + // For jwt command, suppress all logging to console to avoid interfering with token output + if (DevProxyCommand.IsJwtCommand) { _ = builder .ClearProviders() - .AddFilter("Microsoft.Hosting.*", LogLevel.None) - .AddFilter("Microsoft.AspNetCore.*", LogLevel.None) - .AddFilter("Microsoft.Extensions.*", LogLevel.None) - .AddFilter("System.*", LogLevel.None) - .AddFilter("DevProxy.Plugins.*", LogLevel.None) + .SetMinimumLevel(LogLevel.None); + return builder; + } + + // For root command (proxy itself), use rich logging + if (DevProxyCommand.IsRootCommand) + { + _ = builder + .AddFilter("Microsoft.Hosting.*", LogLevel.Error) + .AddFilter("Microsoft.AspNetCore.*", LogLevel.Error) + .AddFilter("Microsoft.Extensions.*", LogLevel.Error) + .AddFilter("System.*", LogLevel.Error) + // Only show plugin messages when no global options are set + .AddFilter("DevProxy.Plugins.*", level => + level >= configuredLogLevel && + !DevProxyCommand.HasGlobalOptions) + .AddConsole(options => + { + options.FormatterName = ProxyConsoleFormatter.DefaultCategoryName; + options.LogToStandardErrorThreshold = LogLevel.Warning; + } + ) + .AddConsoleFormatter(options => + { + options.IncludeScopes = true; + options.ShowSkipMessages = configuration.GetValue("showSkipMessages", true); + options.ShowTimestamps = configuration.GetValue("showTimestamps", true); + } + ) + .AddRequestLogger() .SetMinimumLevel(configuredLogLevel); return builder; } + // For other subcommands (cert, config, outdated, msgraphdb), use simple console logging + // with plugin messages filtered out _ = builder - .AddFilter("Microsoft.Hosting.*", LogLevel.Error) - .AddFilter("Microsoft.AspNetCore.*", LogLevel.Error) - .AddFilter("Microsoft.Extensions.*", LogLevel.Error) - .AddFilter("System.*", LogLevel.Error) - // Only show plugin messages when no global options are set - .AddFilter("DevProxy.Plugins.*", level => - level >= configuredLogLevel && - !DevProxyCommand.HasGlobalOptions) - .AddConsole(options => - { - options.FormatterName = ProxyConsoleFormatter.DefaultCategoryName; - options.LogToStandardErrorThreshold = LogLevel.Warning; - } - ) - .AddConsoleFormatter(options => - { - options.IncludeScopes = true; - options.ShowSkipMessages = configuration.GetValue("showSkipMessages", true); - options.ShowTimestamps = configuration.GetValue("showTimestamps", true); - } - ) - .AddRequestLogger() + .ClearProviders() + .AddFilter("Microsoft.Hosting.*", LogLevel.None) + .AddFilter("Microsoft.AspNetCore.*", LogLevel.None) + .AddFilter("Microsoft.Extensions.*", LogLevel.None) + .AddFilter("System.*", LogLevel.None) + .AddFilter("DevProxy.Plugins.*", LogLevel.None) + .AddSimpleConsole(options => + { + options.SingleLine = true; + options.IncludeScopes = false; + }) .SetMinimumLevel(configuredLogLevel); return builder; From 516df64ade9e3957ff5bca7d700064d4b97be758 Mon Sep 17 00:00:00 2001 From: Waldek Mastykarz Date: Sun, 18 Jan 2026 18:46:48 +0100 Subject: [PATCH 5/8] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- DevProxy/Commands/DevProxyCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DevProxy/Commands/DevProxyCommand.cs b/DevProxy/Commands/DevProxyCommand.cs index 4a835871..b41848f0 100644 --- a/DevProxy/Commands/DevProxyCommand.cs +++ b/DevProxy/Commands/DevProxyCommand.cs @@ -90,7 +90,7 @@ public static bool IsJwtCommand } var args = Environment.GetCommandLineArgs(); - field = args.Contains("jwt"); + field = args.Length > 1 && string.Equals(args[1], "jwt", StringComparison.OrdinalIgnoreCase); _isJwtCommandResolved = true; return field; } From 098c076212a7dca57fdaf7b4107079055e677ff6 Mon Sep 17 00:00:00 2001 From: waldekmastykarz Date: Sun, 18 Jan 2026 18:49:43 +0100 Subject: [PATCH 6/8] Enhance logging for non-root subcommands by adjusting filter levels and adding console formatter --- .../Extensions/ILoggingBuilderExtensions.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/DevProxy/Extensions/ILoggingBuilderExtensions.cs b/DevProxy/Extensions/ILoggingBuilderExtensions.cs index de1774a3..39b190f9 100644 --- a/DevProxy/Extensions/ILoggingBuilderExtensions.cs +++ b/DevProxy/Extensions/ILoggingBuilderExtensions.cs @@ -81,17 +81,28 @@ public static ILoggingBuilder ConfigureDevProxyLogging( // For other subcommands (cert, config, outdated, msgraphdb), use simple console logging // with plugin messages filtered out _ = builder - .ClearProviders() - .AddFilter("Microsoft.Hosting.*", LogLevel.None) - .AddFilter("Microsoft.AspNetCore.*", LogLevel.None) - .AddFilter("Microsoft.Extensions.*", LogLevel.None) - .AddFilter("System.*", LogLevel.None) - .AddFilter("DevProxy.Plugins.*", LogLevel.None) - .AddSimpleConsole(options => - { - options.SingleLine = true; - options.IncludeScopes = false; - }) + .AddFilter("Microsoft.Hosting.*", LogLevel.Error) + .AddFilter("Microsoft.AspNetCore.*", LogLevel.Error) + .AddFilter("Microsoft.Extensions.*", LogLevel.Error) + .AddFilter("System.*", LogLevel.Error) + // Only show plugin messages when no global options are set + .AddFilter("DevProxy.Plugins.*", level => + level >= configuredLogLevel && + !DevProxyCommand.HasGlobalOptions) + .AddConsole(options => + { + options.FormatterName = ProxyConsoleFormatter.DefaultCategoryName; + options.LogToStandardErrorThreshold = LogLevel.Warning; + } + ) + .AddConsoleFormatter(options => + { + options.IncludeScopes = true; + options.ShowSkipMessages = configuration.GetValue("showSkipMessages", true); + options.ShowTimestamps = configuration.GetValue("showTimestamps", true); + } + ) + .AddRequestLogger() .SetMinimumLevel(configuredLogLevel); return builder; From 8ecf3a40e0ded0e8d7287051b1481824b5c67996 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 10:09:37 +0000 Subject: [PATCH 7/8] Fix subcommands to use simple logging with plugin messages filtered out Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- .../Extensions/ILoggingBuilderExtensions.cs | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/DevProxy/Extensions/ILoggingBuilderExtensions.cs b/DevProxy/Extensions/ILoggingBuilderExtensions.cs index 39b190f9..97154613 100644 --- a/DevProxy/Extensions/ILoggingBuilderExtensions.cs +++ b/DevProxy/Extensions/ILoggingBuilderExtensions.cs @@ -81,28 +81,17 @@ public static ILoggingBuilder ConfigureDevProxyLogging( // For other subcommands (cert, config, outdated, msgraphdb), use simple console logging // with plugin messages filtered out _ = builder - .AddFilter("Microsoft.Hosting.*", LogLevel.Error) - .AddFilter("Microsoft.AspNetCore.*", LogLevel.Error) - .AddFilter("Microsoft.Extensions.*", LogLevel.Error) - .AddFilter("System.*", LogLevel.Error) - // Only show plugin messages when no global options are set - .AddFilter("DevProxy.Plugins.*", level => - level >= configuredLogLevel && - !DevProxyCommand.HasGlobalOptions) - .AddConsole(options => - { - options.FormatterName = ProxyConsoleFormatter.DefaultCategoryName; - options.LogToStandardErrorThreshold = LogLevel.Warning; - } - ) - .AddConsoleFormatter(options => - { - options.IncludeScopes = true; - options.ShowSkipMessages = configuration.GetValue("showSkipMessages", true); - options.ShowTimestamps = configuration.GetValue("showTimestamps", true); - } - ) - .AddRequestLogger() + .ClearProviders() + .AddSimpleConsole(options => + { + options.SingleLine = true; + options.IncludeScopes = false; + }) + .AddFilter("Microsoft.Hosting.*", LogLevel.None) + .AddFilter("Microsoft.AspNetCore.*", LogLevel.None) + .AddFilter("Microsoft.Extensions.*", LogLevel.None) + .AddFilter("System.*", LogLevel.None) + .AddFilter("DevProxy.Plugins.*", LogLevel.None) .SetMinimumLevel(configuredLogLevel); return builder; From c7c1793c33d3d29c8eed0b1ecdc783956eb8cf57 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 10:35:23 +0000 Subject: [PATCH 8/8] Keep rich logging for subcommands, only suppress plugin messages Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- .../Extensions/ILoggingBuilderExtensions.cs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/DevProxy/Extensions/ILoggingBuilderExtensions.cs b/DevProxy/Extensions/ILoggingBuilderExtensions.cs index 97154613..32c26fe4 100644 --- a/DevProxy/Extensions/ILoggingBuilderExtensions.cs +++ b/DevProxy/Extensions/ILoggingBuilderExtensions.cs @@ -78,20 +78,27 @@ public static ILoggingBuilder ConfigureDevProxyLogging( return builder; } - // For other subcommands (cert, config, outdated, msgraphdb), use simple console logging - // with plugin messages filtered out + // For other subcommands (cert, config, outdated, msgraphdb), use rich logging + // but with plugin messages filtered out _ = builder - .ClearProviders() - .AddSimpleConsole(options => - { - options.SingleLine = true; - options.IncludeScopes = false; - }) - .AddFilter("Microsoft.Hosting.*", LogLevel.None) - .AddFilter("Microsoft.AspNetCore.*", LogLevel.None) - .AddFilter("Microsoft.Extensions.*", LogLevel.None) - .AddFilter("System.*", LogLevel.None) + .AddFilter("Microsoft.Hosting.*", LogLevel.Error) + .AddFilter("Microsoft.AspNetCore.*", LogLevel.Error) + .AddFilter("Microsoft.Extensions.*", LogLevel.Error) + .AddFilter("System.*", LogLevel.Error) .AddFilter("DevProxy.Plugins.*", LogLevel.None) + .AddConsole(options => + { + options.FormatterName = ProxyConsoleFormatter.DefaultCategoryName; + options.LogToStandardErrorThreshold = LogLevel.Warning; + } + ) + .AddConsoleFormatter(options => + { + options.IncludeScopes = true; + options.ShowSkipMessages = configuration.GetValue("showSkipMessages", true); + options.ShowTimestamps = configuration.GetValue("showTimestamps", true); + } + ) .SetMinimumLevel(configuredLogLevel); return builder;