Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c7e5c0a
Log environment variables read as properties
Forgind Mar 22, 2022
418b210
Only log random environment variables if asked
Forgind Mar 23, 2022
fb96241
Don't write a full (empty) dictionary
Forgind Mar 23, 2022
cf9c722
Only log nonempty env vars
Forgind Mar 23, 2022
d7c03b2
Fix NRE
Forgind Mar 23, 2022
5b58243
Make tests pass
Forgind Mar 23, 2022
fdee113
Only find environment properties
Forgind Mar 28, 2022
be584ed
PR comments
Forgind Mar 29, 2022
16332a7
Log on first property read
Forgind Mar 30, 2022
2a749b8
Account for prior logging and EvaluationFinished
Forgind Apr 1, 2022
150a442
Tweak tests
Forgind Apr 4, 2022
dfe55d7
Random cleanup
Forgind Apr 7, 2022
bb51b1f
Make it work across nodes
Forgind Apr 7, 2022
133f760
Merge branch 'main' of https://github.com/dotnet/msbuild into log-env…
Forgind Apr 8, 2022
775a20d
EnvironmentVariableReadEventArgs serialization
Forgind Apr 8, 2022
2fc3b00
Self comments
Forgind Apr 11, 2022
4c0f001
PR comments
Forgind Apr 13, 2022
30cb0e1
Remove IProperty.IsEnvironmentProperty
Forgind Apr 13, 2022
d13ef44
Reduce allocations in mainline case
Forgind Apr 14, 2022
01d3362
Break up long line
Forgind Apr 15, 2022
75dc9dd
Make text log align with binlog
Forgind Apr 18, 2022
7914d87
PR feedback
Forgind Apr 26, 2022
47d80f6
Filter from ProjectStarted
Forgind Apr 27, 2022
fff4f97
Add test
Forgind Apr 27, 2022
9fb427c
merge
Forgind Apr 27, 2022
0b830e5
Reorder usings
Forgind Apr 28, 2022
c2b93b9
Make list instead of yield returning
Forgind Apr 29, 2022
d1cad7b
Remove expectation of file
Forgind Apr 29, 2022
d4c2f06
Use log file instead
Forgind Apr 29, 2022
add1258
Update src/Build/BackEnd/Components/Logging/ProjectLoggingContext.cs
Forgind Apr 29, 2022
679c003
Notice env properties accessed in tasks
Forgind May 10, 2022
aa46661
PR comments
Forgind May 10, 2022
ce8dad4
Account for more cases
Forgind May 14, 2022
01ee110
One more case
Forgind May 14, 2022
ad92323
Fix another case
Forgind May 16, 2022
0316ba7
Fix condition on task execution
Forgind May 17, 2022
44aa9b6
Fixed other cases mentioned in PR
Forgind May 17, 2022
f7ccf3d
PR comments
Forgind May 27, 2022
22525b6
Using statement
Forgind May 31, 2022
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
42 changes: 41 additions & 1 deletion src/Build.UnitTests/BinaryLogger_Tests.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;

using Microsoft.Build.UnitTests.Shared;
using Shouldly;
using Xunit;
using Xunit.Abstractions;
Expand Down Expand Up @@ -138,6 +139,45 @@ public void BinaryLoggerShouldSupportFilePathExplicitParameter()
ObjectModelHelpers.BuildProjectExpectSuccess(s_testProject, binaryLogger);
}

[Fact]
public void UnusedEnvironmentVariablesDoNotAppearInBinaryLog()
{
using (TestEnvironment env = TestEnvironment.Create())
{
env.SetEnvironmentVariable("EnvVar1", "itsValue");
env.SetEnvironmentVariable("EnvVar2", "value2");
env.SetEnvironmentVariable("EnvVar3", "value3");
string contents = @"
<Project DefaultTargets=""PrintEnvVar"">

<PropertyGroup>
<MyProp1>value</MyProp1>
<MyProp2>$(EnvVar2)</MyProp2>
</PropertyGroup>

<Target Name=""PrintEnvVar"">
<Message Text=""Environment variable EnvVar3 has value $(EnvVar3)"" Importance=""High"" />
</Target>

</Project>";
TransientTestFolder logFolder = env.CreateFolder(createFolder: true);
TransientTestFile projectFile = env.CreateFile(logFolder, "myProj.proj", contents);
BinaryLogger logger = new();
logger.Parameters = _logFile;
RunnerUtilities.ExecMSBuild($"{projectFile.Path} -bl:{logger.Parameters}", out bool success);
success.ShouldBeTrue();
RunnerUtilities.ExecMSBuild($"{logger.Parameters} -flp:logfile={Path.Combine(logFolder.Path, "logFile.log")};verbosity=diagnostic", out success);
success.ShouldBeTrue();
string text = File.ReadAllText(Path.Combine(logFolder.Path, "logFile.log"));
text.ShouldContain("EnvVar2");
text.ShouldContain("value2");
text.ShouldContain("EnvVar3");
text.ShouldContain("value3");
text.ShouldNotContain("EnvVar1");
text.ShouldNotContain("itsValue");
}
}

[Fact]
public void BinaryLoggerShouldNotThrowWhenMetadataCannotBeExpanded()
{
Expand Down
61 changes: 39 additions & 22 deletions src/Build.UnitTests/BuildEventArgsSerialization_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,36 @@ public BuildEventArgsSerializationTests()
_ = ItemGroupLoggingHelper.ItemGroupIncludeLogMessagePrefix;
}

[Fact]
public void RoundtripBuildStartedEventArgs()
[Theory]
[InlineData(true)]
[InlineData(false)]
public void RoundtripBuildStartedEventArgs(bool serializeAllEnvironmentVariables)
{
var args = new BuildStartedEventArgs(
"Message",
"HelpKeyword",
DateTime.Parse("3/1/2017 11:11:56 AM"));
Roundtrip(args,
e => e.Message,
e => e.HelpKeyword,
e => e.Timestamp.ToString());

args = new BuildStartedEventArgs(
"M",
null,
new Dictionary<string, string>
{
using (TestEnvironment env = TestEnvironment.Create())
{
env.SetEnvironmentVariable("MSBUILDLOGALLENVIRONMENTVARIABLES", serializeAllEnvironmentVariables ? "1" : null);
var args = new BuildStartedEventArgs(
"Message",
"HelpKeyword",
DateTime.Parse("3/1/2017 11:11:56 AM"));
Roundtrip(args,
e => e.Message,
e => e.HelpKeyword,
e => e.Timestamp.ToString());

args = new BuildStartedEventArgs(
"M",
null,
new Dictionary<string, string>
{
{ "SampleName", "SampleValue" }
});
Roundtrip(args,
e => TranslationHelpers.ToString(e.BuildEnvironment),
e => e.HelpKeyword,
e => e.ThreadId.ToString(),
e => e.SenderName);
});
Roundtrip(args,
e => serializeAllEnvironmentVariables ? TranslationHelpers.ToString(e.BuildEnvironment) : null,
e => e.HelpKeyword,
e => e.ThreadId.ToString(),
e => e.SenderName);
}
}

[Fact]
Expand Down Expand Up @@ -173,6 +179,17 @@ public void RoundtripTaskStartedEventArgs()
e => e.ColumnNumber.ToString());
}

[Fact]
public void RoundtripEnvironmentVariableReadEventArgs()
{
EnvironmentVariableReadEventArgs args = new("VarName", "VarValue");
args.BuildEventContext = new BuildEventContext(4, 5, 6, 7);
Roundtrip(args,
e => e.Message,
e => e.EnvironmentVariableName,
e => e.BuildEventContext.ToString());
}

[Fact]
public void RoundtripTaskFinishedEventArgs()
{
Expand Down
22 changes: 16 additions & 6 deletions src/Build.UnitTests/Evaluation/Evaluator_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4518,7 +4518,7 @@ public void VerifyMSBuildLogsAMessageWhenLocalPropertyCannotOverrideValueOfGloba
[Fact]
public void VerifyPropertyTrackingLoggingDefault()
{
// Having nothing defined should default to nothing being logged.
// Having just environment variables defined should default to nothing being logged except one environment variable read.
this.VerifyPropertyTrackingLoggingScenario(
null,
logger =>
Expand All @@ -4531,7 +4531,9 @@ public void VerifyPropertyTrackingLoggingDefault()
logger
.AllBuildEvents
.OfType<EnvironmentVariableReadEventArgs>()
.ShouldBeEmpty();
.ShouldHaveSingleItem()
.EnvironmentVariableName
.ShouldBe("DEFINED_ENVIRONMENT_VARIABLE2");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update comment on line 4521 (and similar) please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just saw one comment to update—were you thinking I should add more, or was that all?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's the only comment about empty environment, it's all we need. I think I thought there were others in other test cases?


logger
.AllBuildEvents
Expand Down Expand Up @@ -4560,7 +4562,9 @@ public void VerifyPropertyTrackingLoggingPropertyReassignment()
logger
.AllBuildEvents
.OfType<EnvironmentVariableReadEventArgs>()
.ShouldBeEmpty();
.ShouldHaveSingleItem()
.EnvironmentVariableName
.ShouldBe("DEFINED_ENVIRONMENT_VARIABLE2");

logger
.AllBuildEvents
Expand Down Expand Up @@ -4589,7 +4593,9 @@ public void VerifyPropertyTrackingLoggingNone()
logger
.AllBuildEvents
.OfType<EnvironmentVariableReadEventArgs>()
.ShouldBeEmpty();
.ShouldHaveSingleItem()
.EnvironmentVariableName
.ShouldBe("DEFINED_ENVIRONMENT_VARIABLE2");

logger
.AllBuildEvents
Expand Down Expand Up @@ -4618,7 +4624,9 @@ public void VerifyPropertyTrackingLoggingPropertyInitialValue()
logger
.AllBuildEvents
.OfType<EnvironmentVariableReadEventArgs>()
.ShouldBeEmpty();
.ShouldHaveSingleItem()
.EnvironmentVariableName
.ShouldBe("DEFINED_ENVIRONMENT_VARIABLE2");

logger
.AllBuildEvents
Expand Down Expand Up @@ -4702,7 +4710,9 @@ public void VerifyPropertyTrackingLoggingUninitializedPropertyRead()
logger
.AllBuildEvents
.OfType<EnvironmentVariableReadEventArgs>()
.ShouldBeEmpty();
.ShouldHaveSingleItem()
.EnvironmentVariableName
.ShouldBe("DEFINED_ENVIRONMENT_VARIABLE2");

logger
.AllBuildEvents
Expand Down
65 changes: 26 additions & 39 deletions src/Build.UnitTests/Utilities_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Collections.Generic;
using System.IO;
using Xunit.Abstractions;
using Shouldly;

#nullable disable

Expand Down Expand Up @@ -80,55 +81,41 @@ public UtilitiesTestReadOnlyLoad()
[Fact]
public void CommentsInPreprocessing()
{
Microsoft.Build.Construction.XmlDocumentWithLocation.ClearReadOnlyFlags_UnitTestsOnly();
using TestEnvironment env = TestEnvironment.Create();
XmlDocumentWithLocation.ClearReadOnlyFlags_UnitTestsOnly();

string input = FileUtilities.GetTemporaryFile();
string output = FileUtilities.GetTemporaryFile();
TransientTestFile inputFile = env.CreateFile("tempInput.tmp", ObjectModelHelpers.CleanupFileContents(@"
<Project DefaultTargets='Build'>
<Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets'/>
</Project>"));
TransientTestFile outputFile = env.CreateFile("tempOutput.tmp");

string _initialLoadFilesWriteable = Environment.GetEnvironmentVariable("MSBUILDLOADALLFILESASWRITEABLE");
try
{
Environment.SetEnvironmentVariable("MSBUILDLOADALLFILESASWRITEABLE", "1");

string content = ObjectModelHelpers.CleanupFileContents(@"
<Project DefaultTargets='Build' ToolsVersion='msbuilddefaulttoolsversion' xmlns='msbuildnamespace'>
<Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets'/>
</Project>");
File.WriteAllText(input, content);
env.SetEnvironmentVariable("MSBUILDLOADALLFILESASWRITEABLE", "1");

#if FEATURE_GET_COMMANDLINE
Assert.Equal(MSBuildApp.ExitType.Success, MSBuildApp.Execute(@"c:\bin\msbuild.exe """ + input +
(NativeMethodsShared.IsUnixLike ? @""" -pp:""" : @""" /pp:""") + output + @""""));
MSBuildApp.Execute(@"c:\bin\msbuild.exe """ + inputFile.Path +
(NativeMethodsShared.IsUnixLike ? @""" -pp:""" : @""" /pp:""") + outputFile.Path + @"""")
.ShouldBe(MSBuildApp.ExitType.Success);
#else
Assert.Equal(
MSBuildApp.ExitType.Success,
MSBuildApp.Execute(
new[] { @"c:\bin\msbuild.exe", '"' + input + '"',
'"' + (NativeMethodsShared.IsUnixLike ? "-pp:" : "/pp:") + output + '"'}));
Assert.Equal(
MSBuildApp.ExitType.Success,
MSBuildApp.Execute(
new[] { @"c:\bin\msbuild.exe", '"' + inputFile.Path + '"',
'"' + (NativeMethodsShared.IsUnixLike ? "-pp:" : "/pp:") + outputFile.Path + '"'}));
#endif

bool foundDoNotModify = false;
foreach (string line in File.ReadLines(output))
bool foundDoNotModify = false;
foreach (string line in File.ReadLines(outputFile.Path))
{
line.ShouldNotContain("<!---->", "This is what it will look like if we're loading read/only");

if (line.Contains("DO NOT MODIFY")) // this is in a comment in our targets
{
if (line.Contains("<!---->")) // This is what it will look like if we're loading read/only
{
Assert.True(false);
}

if (line.Contains("DO NOT MODIFY")) // this is in a comment in our targets
{
foundDoNotModify = true;
}
foundDoNotModify = true;
}

Assert.True(foundDoNotModify);
}
finally
{
File.Delete(input);
File.Delete(output);
Environment.SetEnvironmentVariable("MSBUILDLOADALLFILESASWRITEABLE", _initialLoadFilesWriteable);
}

foundDoNotModify.ShouldBeTrue();
}

[Fact]
Expand Down
26 changes: 6 additions & 20 deletions src/Build/BackEnd/Components/Logging/LoggingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1432,20 +1432,8 @@ private void LoggingEventProcessor(object loggingEvent)
/// </summary>
private void RouteBuildEvent(object loggingEvent)
{
BuildEventArgs buildEventArgs = null;

if (loggingEvent is BuildEventArgs bea)
{
buildEventArgs = bea;
}
else if (loggingEvent is KeyValuePair<int, BuildEventArgs> kvp)
{
buildEventArgs = kvp.Value;
}
else
{
ErrorUtilities.ThrowInternalError("Unknown logging item in queue:" + loggingEvent.GetType().FullName);
}
BuildEventArgs buildEventArgs = loggingEvent as BuildEventArgs ?? (loggingEvent as KeyValuePair<int, BuildEventArgs>?)?.Value;
ErrorUtilities.VerifyThrow(buildEventArgs is not null, "Unknown logging item in queue:" + loggingEvent.GetType().FullName);

if (buildEventArgs is BuildWarningEventArgs warningEvent)
{
Expand Down Expand Up @@ -1489,14 +1477,12 @@ private void RouteBuildEvent(object loggingEvent)
};
}
}

if (loggingEvent is BuildErrorEventArgs errorEvent)
else if (loggingEvent is BuildErrorEventArgs errorEvent)
{
// Keep track of build submissions that have logged errors. If there is no build context, add BuildEventContext.InvalidSubmissionId.
_buildSubmissionIdsThatHaveLoggedErrors.Add(errorEvent.BuildEventContext?.SubmissionId ?? BuildEventContext.InvalidSubmissionId);
}

if (loggingEvent is ProjectFinishedEventArgs projectFinishedEvent && projectFinishedEvent.BuildEventContext != null)
else if (loggingEvent is ProjectFinishedEventArgs projectFinishedEvent && projectFinishedEvent.BuildEventContext != null)
{
int key = GetWarningsAsErrorOrMessageKey(projectFinishedEvent);
_warningsAsErrorsByProject?.Remove(key);
Expand Down Expand Up @@ -1541,7 +1527,7 @@ private void RouteBuildEvent(BuildEventArgs eventArg)
TryRaiseProjectStartedEvent(eventArg);

// The event has not been through a filter yet. All events must go through a filter before they make it to a logger
if (_filterEventSource != null) // Loggers may not be registered
if (_filterEventSource != null) // Loggers may not be registered
{
// Send the event to the filter, the Consume will not return until all of the loggers which have registered to the event have process
// them.
Expand All @@ -1562,7 +1548,7 @@ private void RouteBuildEvent(BuildEventArgs eventArg)
{
if (!sink.HaveLoggedBuildStartedEvent)
{
sink.Consume(eventArg, (int)pair.Key);
sink.Consume(eventArg, pair.Key);
}

// Reset the HaveLoggedBuildStarted event because no one else will be sending a build started event to any loggers at this time.
Expand Down
11 changes: 4 additions & 7 deletions src/Build/BackEnd/Components/Logging/LoggingServiceLogMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,14 +388,11 @@ public void LogBuildStarted()
message = ResourceUtilities.GetResourceString("BuildStarted");
}

IDictionary<string, string> environmentProperties = null;
IDictionary<string, string> environmentProperties = _componentHost?.BuildParameters != null && Traits.Instance.LogAllEnvironmentVariables ?
_componentHost.BuildParameters.BuildProcessEnvironment
: null;

if (_componentHost?.BuildParameters != null)
{
environmentProperties = _componentHost.BuildParameters.BuildProcessEnvironment;
}

BuildStartedEventArgs buildEvent = new BuildStartedEventArgs(message, null /* no help keyword */, environmentProperties);
BuildStartedEventArgs buildEvent = new(message, helpKeyword: null, environmentProperties);

// Raise the event with the filters
ProcessLoggingEvent(buildEvent);
Expand Down
Loading