Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
63 changes: 63 additions & 0 deletions src/Build.UnitTests/BackEnd/LoggingServicesLogMethod_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Microsoft.Build.Logging;
using Shouldly;
using Xunit;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
Expand Down Expand Up @@ -1046,6 +1047,62 @@ public void LogBuildFinished()
buildEvent = new BuildFinishedEventArgs(string.Empty, null /* no help keyword */, true, service.ProcessedBuildEvent.Timestamp);
Assert.True(((BuildFinishedEventArgs)service.ProcessedBuildEvent).IsEquivalent(buildEvent));
}
[Fact]
public void LogBuildStartedLoggerNames()
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
ConsoleLogger consoleLogger = new ConsoleLogger();
service.RegisterLogger(consoleLogger);

service.LogBuildStarted();
Assert.IsType<BuildMessageEventArgs>(service.ProcessedBuildEvent);
Assert.Contains("ConsoleLogger", service.ProcessedBuildEvent.Message);
Comment thread
AlesProkop marked this conversation as resolved.
Outdated
}
Comment thread
AlesProkop marked this conversation as resolved.

[Fact]
public void LogBuildFinishedLoggerPaths()
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
BinaryLogger binaryLogger = new BinaryLogger { Parameters = "test.binlog" }; ;
service.RegisterLogger(binaryLogger);
service.LogBuildFinished(true);
var pathMessage = service.AllProcessedBuildEvents
.OfType<BuildMessageEventArgs>()
.FirstOrDefault(e => e.Message.Contains("test.binlog"));
Assert.NotNull(pathMessage);
Assert.Contains("Binary log", pathMessage.Message);
}

[Fact]
public void LogFilePathsPresentInBinaryLog()
{
using var env = TestEnvironment.Create();
var binlogPath = env.ExpectFile(".binlog").Path;

var binaryLogger = new BinaryLogger { Parameters = binlogPath };
var mockLogger = new MockLogger();

using (var collection = new ProjectCollection())
{
var project = ObjectModelHelpers.CreateInMemoryProject(collection, @"
<Project>
<Target Name=""Build"" />
</Project>");
project.Build(new ILogger[] { binaryLogger, mockLogger }).ShouldBeTrue();
}

// Check the text log (MockLogger captures all messages)
mockLogger.FullLog.ShouldContain(".binlog");

// Check the binary log by replaying it
var replayLogger = new MockLogger();
var reader = new BinaryLogReplayEventSource();
replayLogger.Initialize(reader);
reader.Replay(binlogPath);
replayLogger.Shutdown();

replayLogger.FullLog.ShouldContain(".binlog");
}

[Fact]
public void LogBuildCanceled()
Expand Down Expand Up @@ -1795,6 +1852,11 @@ internal sealed class ProcessBuildEventHelper : LoggingService
/// to verify that a buildEvent was sent to ProcessLoggingEvent.
/// </summary>
private BuildEventArgs _processedBuildEvent;

/// <summary>
/// All events processed by ProcessLoggingEvent.
/// </summary>
internal List<BuildEventArgs> AllProcessedBuildEvents { get; } = new();
#endregion
#region Constructor
/// <summary>
Expand Down Expand Up @@ -1857,6 +1919,7 @@ protected internal override void ProcessLoggingEvent(object buildEvent)
if (buildEvent is BuildEventArgs buildEventArgs)
{
_processedBuildEvent = buildEventArgs;
AllProcessedBuildEvents.Add(buildEventArgs);
}
else if (buildEvent is KeyValuePair<int, BuildEventArgs> kvp)
{
Expand Down
56 changes: 56 additions & 0 deletions src/Build/BackEnd/Components/Logging/LoggingServiceLogMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Build.Experimental.BuildCheck.Infrastructure;
using Microsoft.Build.Framework;
using Microsoft.Build.Framework.Profiler;
using Microsoft.Build.Logging;
using Microsoft.Build.Shared;

using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
Expand Down Expand Up @@ -360,6 +361,9 @@ public void LogBuildStarted()

// Make sure we process this event before going any further
WaitForLoggingToProcessEvents();

// Print out all enabled logs.
LogLoggersUsed(fileNames: false);
}

/// <summary>
Expand All @@ -382,6 +386,8 @@ public void LogBuildFinished(bool success)
message = ResourceUtilities.GetResourceString(success ? "BuildFinishedSuccess" : "BuildFinishedFailure");
}
}
// Before ending the build, print out all logs that outputted a file and the location of the file.
LogLoggersUsed(fileNames: true);

BuildFinishedEventArgs buildEvent = new BuildFinishedEventArgs(message, null /* no help keyword */, success);

Expand All @@ -391,6 +397,56 @@ public void LogBuildFinished(bool success)
WaitForLoggingToProcessEvents();
}

/// <summary>
/// Prints either the names of enabled logs (except for Forwarding logs)
/// or the file paths of the logs, depending on the value of the fileNames parameter.
/// </summary>
/// <param name="fileNames">If true, logs the file paths of the logs; otherwise, logs the names of the enabled logs.</param>
private void LogLoggersUsed(bool fileNames)
{
var list_of_log_names = new List<string>();
Comment thread
AlesProkop marked this conversation as resolved.
Outdated
foreach (ILogger logger in Loggers)
{
ILogger actual = logger is ReusableLogger reusable
? reusable.OriginalLogger
: logger;
// We don't want to log the name of the forwarding logger, since it may be confusing.
if (actual is CentralForwardingLogger == true)
{
continue;
}

if (fileNames)
{
(string logType, string path) = actual switch
{
BinaryLogger bl => ("Binary log", bl.FilePath),
FileLogger fl => ("File log", fl.FilePath),
_ => (null, null)
};
if (!string.IsNullOrEmpty(path))
{
var msgEvent = new BuildMessageEventArgs(
ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("LogFileOutputPath", logType, path),
null, null, MessageImportance.High);
msgEvent.BuildEventContext = BuildEventContext.Invalid;
ProcessLoggingEvent(msgEvent);
}
}
else
{
list_of_log_names.Add(actual.GetType().Name);
}
}
if (list_of_log_names.Count != 0)
{
var msgEvent = new BuildMessageEventArgs(
ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("LogEnabledLogs", string.Join(", ", list_of_log_names)),
null, null, MessageImportance.High);
msgEvent.BuildEventContext = BuildEventContext.Invalid;
ProcessLoggingEvent(msgEvent);
}
}
/// <inheritdoc />
public void LogBuildCanceled()
{
Expand Down
5 changes: 5 additions & 0 deletions src/Build/Logging/FileLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ private void ApplyFileLoggerParameter(string parameterName, string parameterValu
/// </summary>
private string _logFileName = "msbuild.log";

/// <summary>
/// The path to the log file.
/// </summary>
internal string FilePath => Path.GetFullPath(_logFileName);

/// <summary>
/// fileWriter is the stream that has been opened on our log file.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions src/Build/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@
<data name="BuildFinishedSuccess" xml:space="preserve">
<value>Build succeeded.</value>
</data>
<data name="LogFileOutputPath" xml:space="preserve">
Comment thread
AlesProkop marked this conversation as resolved.
<value>{0} output file: {1}</value>
<comment>{0} is the log type (e.g. "Binary log", "File log"). {1} is the full file path.</comment>
</data>
<data name="LogEnabledLogs" xml:space="preserve">
<value>Enabled logs: {0}</value>
<comment>{0} is a comma-separated list of log types (e.g. "Binary log", "File log").</comment>
</data>
<data name="BuildStartedWithTime" xml:space="preserve">
<value>Build started {0}.</value>
</data>
Expand Down
10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Build/Resources/xlf/Strings.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading