diff --git a/DevProxy/Commands/DevProxyCommand.cs b/DevProxy/Commands/DevProxyCommand.cs index e3db039b..b41848f0 100644 --- a/DevProxy/Commands/DevProxyCommand.cs +++ b/DevProxy/Commands/DevProxyCommand.cs @@ -43,6 +43,8 @@ sealed class DevProxyCommand : RootCommand private static bool _hasGlobalOptionsResolved; private static bool _isStdioCommandResolved; + private static bool _isJwtCommandResolved; + private static bool _isRootCommandResolved; private static bool _stdioLogFilePathResolved; public static bool HasGlobalOptions @@ -78,6 +80,47 @@ public static bool IsStdioCommand } } + public static bool IsJwtCommand + { + get + { + if (_isJwtCommandResolved) + { + return field; + } + + var args = Environment.GetCommandLineArgs(); + field = args.Length > 1 && string.Equals(args[1], "jwt", StringComparison.OrdinalIgnoreCase); + _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). + /// A subcommand is detected when the first non-program argument doesn't start with '-'. + /// + public static bool IsRootCommand + { + get + { + if (_isRootCommandResolved) + { + return field; + } + + var args = Environment.GetCommandLineArgs(); + // 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; + } + } + public static string StdioLogFilePath { get diff --git a/DevProxy/Extensions/ILoggingBuilderExtensions.cs b/DevProxy/Extensions/ILoggingBuilderExtensions.cs index 00735f24..32c26fe4 100644 --- a/DevProxy/Extensions/ILoggingBuilderExtensions.cs +++ b/DevProxy/Extensions/ILoggingBuilderExtensions.cs @@ -39,15 +39,53 @@ public static ILoggingBuilder ConfigureDevProxyLogging( return builder; } + // For jwt command, suppress all logging to console to avoid interfering with token output + if (DevProxyCommand.IsJwtCommand) + { + _ = builder + .ClearProviders() + .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 rich logging + // but 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) + .AddFilter("DevProxy.Plugins.*", LogLevel.None) .AddConsole(options => { options.FormatterName = ProxyConsoleFormatter.DefaultCategoryName; @@ -61,7 +99,6 @@ public static ILoggingBuilder ConfigureDevProxyLogging( options.ShowTimestamps = configuration.GetValue("showTimestamps", true); } ) - .AddRequestLogger() .SetMinimumLevel(configuredLogLevel); return builder;