Skip to content

LiveLogger v2 #8619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 52 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
c4d8930
Delete old LiveLogger
ladipro Mar 22, 2023
082e89b
Re-implement the ANSI/VT100 terminal check
ladipro Mar 22, 2023
145244b
Add Logger and Project from rainersigwald/tortillachip
ladipro Mar 22, 2023
61f6311
Fix warnings
ladipro Mar 22, 2023
0e95131
Re-enable /ll with the new LiveLogger
ladipro Mar 22, 2023
18ece94
Check if ENABLE_VIRTUAL_TERMINAL_PROCESSING sticks
ladipro Mar 22, 2023
be32f2e
Join the refresher thread on shutdown
ladipro Mar 22, 2023
d2c2220
Rerender nodes only if the output actually changed
ladipro Mar 22, 2023
332c1ff
Enable nullability checks
ladipro Mar 23, 2023
b216873
Add hyper-links to outputs
ladipro Mar 23, 2023
8154e0f
Better detection of output path
ladipro Mar 24, 2023
0d2aed1
Introduce FEATURE_LIVELOGGER
ladipro Mar 24, 2023
dc55f86
Use ReadOnlySpan/ReadOnlyMemory where appropriate
ladipro Mar 24, 2023
b73b9b9
Add warning & error handling
ladipro Mar 24, 2023
6d6b9f6
Simplify warning & error handling, set output to UTF8
ladipro Mar 27, 2023
fde43a1
Abstract output to ITerminal/Terminal
ladipro Mar 27, 2023
13a47fc
Add colors to ITerminal/Terminal
ladipro Mar 27, 2023
b46e5c7
Add 'atomic' writes to fix flickering
ladipro Mar 27, 2023
1c3db86
Use Begin/EnUpdate when finishing a project
ladipro Mar 27, 2023
f2122e2
Code cleanup and comments
ladipro Mar 28, 2023
42a9e0e
Report only output-producing projects as 'completed'
ladipro Mar 28, 2023
03f9bfc
Print project file name without path
ladipro Mar 29, 2023
a9cf5c8
Print per-project succeeded/failed upon completion
ladipro Mar 29, 2023
847b58c
Add indentation per initial mock-ups
ladipro Mar 29, 2023
981a637
Print build result summary
ladipro Mar 29, 2023
2347186
Print target framework where available
ladipro Mar 29, 2023
ece3879
Rename _notableProjects to _projects, track everything
ladipro Mar 29, 2023
8c385b0
Make the min-importance optimization aware of LiveLogger
ladipro Mar 29, 2023
aa5cf68
Add sample LiveLogger unit tests
ladipro Mar 31, 2023
107d1f8
Reduce screen flicking by delta rendering
rokonec Mar 31, 2023
f42f687
Optimize rendering loop for flickering
rokonec Mar 31, 2023
415891e
Fix and suppress warnings in LiveLogger_Tests.cs
ladipro Mar 31, 2023
28cf5ab
Add command line switch test
ladipro Mar 31, 2023
2c7c07b
Fixing using Terminal
rokonec Mar 31, 2023
c4dbf34
Merge branch 'livelogger' of https://github.com/dotnet/msbuild into l…
rokonec Mar 31, 2023
7e2c545
Thread safety fixes
rokonec Mar 31, 2023
24fc018
Minor code clean
rokonec Mar 31, 2023
b0542f3
Add #region's and minor cleanup
ladipro Mar 31, 2023
4139005
Merge remote-tracking branch 'dotnet/main' into livelogger
ladipro Mar 31, 2023
7c51985
PR feedback: Reduce block nesting in QueryIsScreenAndTryEnableAnsiCol…
ladipro Apr 4, 2023
8b3f013
PR feedback: Move top-level types to their own source files
ladipro Apr 4, 2023
69d4bd5
PR feedback: Centralize escape codes in class AnsiCodes
ladipro Apr 4, 2023
a4194b5
Hide the cursor when overwriting live lines
ladipro Apr 4, 2023
af8b875
Additionally accept -tl and -terminallogger
rainersigwald Apr 6, 2023
dae5e4f
fixup! Additionally accept -tl and -terminallogger
rainersigwald Apr 6, 2023
a276ac5
Allow explicit LiveLogger opt-in
rainersigwald Apr 6, 2023
6941938
Mark node idle when it finishes a project
rainersigwald Apr 10, 2023
4c88a51
Try to tone down the emoji
rainersigwald Apr 10, 2023
11df683
Track restore via node status
rainersigwald Apr 10, 2023
2caea92
Print project names without extension
ladipro Apr 11, 2023
3a6a34d
Merge remote-tracking branch 'dotnet/main' into livelogger
ladipro Apr 11, 2023
6b0a1c0
Add LiveLogger to MSBuild.exe as well
ladipro Apr 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 2 additions & 56 deletions src/Build/BackEnd/Client/MSBuildClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,7 @@ public MSBuildClientExitResult Execute(CancellationToken cancellationToken)
CommunicationsUtilities.Trace("Build finished.");
}

if (NativeMethodsShared.IsWindows && _originalConsoleMode is not null)
{
IntPtr stdOut = NativeMethodsShared.GetStdHandle(NativeMethodsShared.STD_OUTPUT_HANDLE);
NativeMethodsShared.SetConsoleMode(stdOut, _originalConsoleMode.Value);
}
NativeMethodsShared.RestoreConsoleMode(_originalConsoleMode);

return _exitResult;
}
Expand Down Expand Up @@ -377,63 +373,13 @@ private void ReadPacketsLoop(CancellationToken cancellationToken)

private void ConfigureAndQueryConsoleProperties()
{
var (acceptAnsiColorCodes, outputIsScreen) = QueryIsScreenAndTryEnableAnsiColorCodes();
(var acceptAnsiColorCodes, var outputIsScreen, _originalConsoleMode) = NativeMethodsShared.QueryIsScreenAndTryEnableAnsiColorCodes();
int bufferWidth = QueryConsoleBufferWidth();
ConsoleColor backgroundColor = QueryConsoleBackgroundColor();

_consoleConfiguration = new TargetConsoleConfiguration(bufferWidth, acceptAnsiColorCodes, outputIsScreen, backgroundColor);
}

private (bool acceptAnsiColorCodes, bool outputIsScreen) QueryIsScreenAndTryEnableAnsiColorCodes()
{
bool acceptAnsiColorCodes = false;
bool outputIsScreen = false;

if (NativeMethodsShared.IsWindows)
{
try
{
IntPtr stdOut = NativeMethodsShared.GetStdHandle(NativeMethodsShared.STD_OUTPUT_HANDLE);
if (NativeMethodsShared.GetConsoleMode(stdOut, out uint consoleMode))
{
bool success;
if ((consoleMode & NativeMethodsShared.ENABLE_VIRTUAL_TERMINAL_PROCESSING) == NativeMethodsShared.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
{
// Console is already in required state
success = true;
}
else
{
_originalConsoleMode = consoleMode;
consoleMode |= NativeMethodsShared.ENABLE_VIRTUAL_TERMINAL_PROCESSING;
success = NativeMethodsShared.SetConsoleMode(stdOut, consoleMode);
}

if (success)
{
acceptAnsiColorCodes = true;
}

uint fileType = NativeMethodsShared.GetFileType(stdOut);
// The std out is a char type(LPT or Console)
outputIsScreen = fileType == NativeMethodsShared.FILE_TYPE_CHAR;
acceptAnsiColorCodes &= outputIsScreen;
}
}
catch (Exception ex)
{
CommunicationsUtilities.Trace("MSBuild client warning: problem during enabling support for VT100: {0}.", ex);
}
}
else
{
// On posix OSes we expect console always supports VT100 coloring unless it is redirected
acceptAnsiColorCodes = outputIsScreen = !Console.IsOutputRedirected;
}

return (acceptAnsiColorCodes: acceptAnsiColorCodes, outputIsScreen: outputIsScreen);
}

private int QueryConsoleBufferWidth()
{
int consoleBufferWidth = -1;
Expand Down
9 changes: 6 additions & 3 deletions src/Build/BackEnd/Components/Logging/LoggingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1637,7 +1637,7 @@ ILogger UnwrapLoggerType(ILogger log)
/// </remarks>
private void UpdateMinimumMessageImportance(ILogger logger)
{
var innerLogger = (logger is Evaluation.ProjectCollection.ReusableLogger reusableLogger) ? reusableLogger.OriginalLogger : logger;
var innerLogger = (logger is ProjectCollection.ReusableLogger reusableLogger) ? reusableLogger.OriginalLogger : logger;

MessageImportance? minimumImportance = innerLogger switch
{
Expand All @@ -1651,8 +1651,11 @@ private void UpdateMinimumMessageImportance(ILogger logger)
// The null logger has no effect on minimum verbosity.
Execution.BuildManager.NullLogger => null,

// If the logger is not on our whitelist, there are no importance guarantees. Fall back to "any importance".
_ => MessageImportance.Low
// The live logger consumes only high priority messages.
_ => innerLogger.GetType().FullName == "Microsoft.Build.Logging.LiveLogger.LiveLogger"
? MessageImportance.High
// If the logger is not on our allow list, there are no importance guarantees. Fall back to "any importance".
: MessageImportance.Low,
};

if (minimumImportance != null)
Expand Down
65 changes: 65 additions & 0 deletions src/Framework/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,71 @@ internal static void VerifyThrowWin32Result(int result)
}
}

#if !CLR2COMPATIBILITY
internal static (bool acceptAnsiColorCodes, bool outputIsScreen, uint? originalConsoleMode) QueryIsScreenAndTryEnableAnsiColorCodes()
{
if (Console.IsOutputRedirected)
{
// There's no ANSI terminal support is console output is redirected.
return (acceptAnsiColorCodes: false, outputIsScreen: false, originalConsoleMode: null);
}

bool acceptAnsiColorCodes = false;
bool outputIsScreen = false;
uint? originalConsoleMode = null;
if (IsWindows)
{
try
{
IntPtr stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (GetConsoleMode(stdOut, out uint consoleMode))
{
if ((consoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING)
{
// Console is already in required state.
acceptAnsiColorCodes = true;
}
else
{
originalConsoleMode = consoleMode;
consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (SetConsoleMode(stdOut, consoleMode) && GetConsoleMode(stdOut, out consoleMode))
{
// We only know if vt100 is supported if the previous call actually set the new flag, older
// systems ignore the setting.
acceptAnsiColorCodes = (consoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING;
}
}

uint fileType = GetFileType(stdOut);
// The std out is a char type (LPT or Console).
outputIsScreen = fileType == FILE_TYPE_CHAR;
acceptAnsiColorCodes &= outputIsScreen;
}
}
catch
{
// In the unlikely case that the above fails we just ignore and continue.
}
}
else
{
// On posix OSes we expect console always supports VT100 coloring unless it is explicitly marked as "dumb".
acceptAnsiColorCodes = Environment.GetEnvironmentVariable("TERM") != "dumb";
}
return (acceptAnsiColorCodes, outputIsScreen, originalConsoleMode);
}

internal static void RestoreConsoleMode(uint? originalConsoleMode)
{
if (IsWindows && originalConsoleMode is not null)
{
IntPtr stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
_ = SetConsoleMode(stdOut, originalConsoleMode.Value);
}
}
#endif // !CLR2COMPATIBILITY

#endregion

#region PInvoke
Expand Down
25 changes: 25 additions & 0 deletions src/MSBuild.UnitTests/CommandLineSwitches_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,31 @@ public void DistributedFileLoggerSwitchIdentificationTests(string distributedfil
duplicateSwitchErrorMessage.ShouldBeNull();
}

[Theory]
[InlineData("ll")]
[InlineData("LL")]
[InlineData("livelogger")]
[InlineData("LiveLogger")]
[InlineData("LIVELOGGER")]
[InlineData("tl")]
[InlineData("TL")]
[InlineData("terminallogger")]
[InlineData("TerminalLogger")]
[InlineData("TERMINALLOGGER")]
public void LiveLoggerSwitchIdentificationTests(string livelogger)
{
CommandLineSwitches.ParameterizedSwitch parameterlessSwitch;
string duplicateSwitchErrorMessage;

CommandLineSwitches.IsParameterizedSwitch(livelogger, out parameterlessSwitch, out duplicateSwitchErrorMessage, out bool multipleParametersAllowed, out string missingParametersErrorMessage, out bool unquoteParameters, out bool emptyParametersAllowed).ShouldBeTrue();
parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.LiveLogger);
duplicateSwitchErrorMessage.ShouldBeNull();
multipleParametersAllowed.ShouldBeTrue();
missingParametersErrorMessage.ShouldBeNull();
unquoteParameters.ShouldBeTrue();
emptyParametersAllowed.ShouldBeTrue();
}

[Theory]
[InlineData("flp")]
[InlineData("FLP")]
Expand Down
Loading