From 314e0dd003eaa7831f4c060933dd23f3eabf8acd Mon Sep 17 00:00:00 2001 From: filzrev <103790468+filzrev@users.noreply.github.com> Date: Fri, 26 Dec 2025 14:18:25 +0900 Subject: [PATCH 1/2] chore: fix exception logging on stdout redirected environment --- .../Extensions/SpectreConsoleExtensions.cs | 35 +++++++++++++++++ src/docfx/Program.cs | 39 ++++++++++++------- 2 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 src/docfx/Extensions/SpectreConsoleExtensions.cs diff --git a/src/docfx/Extensions/SpectreConsoleExtensions.cs b/src/docfx/Extensions/SpectreConsoleExtensions.cs new file mode 100644 index 00000000000..b7bcaa1abcc --- /dev/null +++ b/src/docfx/Extensions/SpectreConsoleExtensions.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Spectre.Console; +using Spectre.Console.Cli; + +namespace Docfx; + +internal static class SpectreConsoleExtensions +{ + public static void WriteException(this IAnsiConsole ansiConsole, Exception e) + { + if (e is CommandAppException cae) + { + if (cae.Pretty is { } pretty) + AnsiConsole.Write(pretty); + else + AnsiConsole.MarkupInterpolated($"[red]Error:[/] {e.Message}"); + return; + } + else + { + AnsiConsole.WriteException(e, new ExceptionSettings() + { + Format = ExceptionFormats.ShortenEverything, + Style = new() + { + ParameterName = Color.Grey, + ParameterType = Color.Grey78, + LineNumber = Color.Grey78, + }, + }); + } + } +} diff --git a/src/docfx/Program.cs b/src/docfx/Program.cs index 03df088dd6e..b71bb354f17 100644 --- a/src/docfx/Program.cs +++ b/src/docfx/Program.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Docfx.Common; using Spectre.Console; using Spectre.Console.Cli; @@ -39,26 +40,34 @@ internal static int Main(string[] args) static void OnException(Exception e, ITypeResolver? resolver) { - if (e is CommandAppException cae) + // Try to unwrap AggregateException. + if (e is AggregateException ae && ae.InnerExceptions.Count == 1) + e = ae.InnerExceptions[0]; + + if (!Console.IsOutputRedirected) { - if (cae.Pretty is { } pretty) - AnsiConsole.Write(pretty); - else - AnsiConsole.MarkupInterpolated($"[red]Error:[/] {e.Message}"); + // Write exception to console. + AnsiConsole.Console.WriteException(e); + + // Write exception to ReportLogListener if exists. + var reportLogListener = Logger.FindListener(x => x is ReportLogListener); + reportLogListener?.WriteLine(Logger.GetLogItem(LogLevel.Error, e.ToString(), code: ErrorCodes.Build.FatalError)); } else { - AnsiConsole.WriteException(e, new ExceptionSettings() - { - Format = ExceptionFormats.ShortenEverything, - Style = new() - { - ParameterName = Color.Grey, - ParameterType = Color.Grey78, - LineNumber = Color.Grey78, - }, - }); + // Write exception with Logger API if stdout is redirected. + // To avoid line wrap issue https://github.com/spectreconsole/spectre.console/issues/1782 + var exceptions = e is AggregateException ae2 + ? ae2.Flatten().InnerExceptions.ToArray() + : [e]; + + foreach (var ex in exceptions) + Logger.LogError(e.ToString(), code: ErrorCodes.Build.FatalError); } + + // Cleanup logger. + Logger.Flush(); + Logger.UnregisterAllListeners(); } } } From 8be6b0858d342084315dbf235fcb21e7976fbb49 Mon Sep 17 00:00:00 2001 From: filzrev <103790468+filzrev@users.noreply.github.com> Date: Fri, 26 Dec 2025 20:10:07 +0900 Subject: [PATCH 2/2] chore: fix failed test on CI by resetting error count --- test/docfx.Tests/CommandLineTest.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/docfx.Tests/CommandLineTest.cs b/test/docfx.Tests/CommandLineTest.cs index ad509286aff..66abb6b1288 100644 --- a/test/docfx.Tests/CommandLineTest.cs +++ b/test/docfx.Tests/CommandLineTest.cs @@ -1,10 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Docfx.Common; + namespace Docfx.Tests; [Collection("docfx STA")] -public static class CommandLineTest +public class CommandLineTest { [Fact] public static void PrintsVersion() @@ -31,7 +33,14 @@ public static void PrintsHelp() [Fact] public static void FailForUnknownArgs() { - Assert.Equal(-1, Program.Main(["--unknown"])); + try + { + Assert.Equal(-1, Program.Main(["--unknown"])); + } + finally + { + Logger.ResetCount(); + } } [Fact]