diff --git a/Directory.Build.props b/Directory.Build.props
index 4698f8dc721..682278abda0 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -92,4 +92,9 @@ ates https://learn.microsoft.com/en-gb/dotnet/fundamentals/syslib-diagnostics/sy
true
+
+
+
+
+
diff --git a/eng/BannedSymbols.txt b/eng/BannedSymbols.txt
new file mode 100644
index 00000000000..0c817f442fc
--- /dev/null
+++ b/eng/BannedSymbols.txt
@@ -0,0 +1,7 @@
+// Banned BuildEventContext constructors - use CreateInitial/CreateForSubmission/CreateForNode + WithXxx() builder methods instead.
+// These constructors make it easy to accidentally drop evaluation IDs and other critical context data.
+// See BuildEventContext.cs for the recommended builder pattern.
+M:Microsoft.Build.Framework.BuildEventContext.#ctor(System.Int32,System.Int32,System.Int32,System.Int32);Use BuildEventContext.CreateInitial/CreateForNode + WithXxx() builder methods instead
+M:Microsoft.Build.Framework.BuildEventContext.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32);Use BuildEventContext.CreateInitial/CreateForNode + WithXxx() builder methods instead
+M:Microsoft.Build.Framework.BuildEventContext.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32);Use BuildEventContext.CreateInitial + WithXxx() builder methods instead
+M:Microsoft.Build.Framework.BuildEventContext.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32);Use BuildEventContext.CreateInitial + WithXxx() builder methods instead
diff --git a/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs b/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs
index f26704bbc6e..64f81efeff3 100644
--- a/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs
@@ -796,7 +796,7 @@ private void SetupTaskFactory(TaskHostParameters factoryParameters, bool explici
factoryParameters = factoryParameters.WithTaskHostFactoryExplicitlyRequested(true);
}
- _loadedType = _taskFactory.InitializeFactory(_loadInfo, "TaskToTestFactories", new Dictionary(), string.Empty, factoryParameters, explicitlyLaunchTaskHost, new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)), ElementLocation.Create("NONE"), String.Empty);
+ _loadedType = _taskFactory.InitializeFactory(_loadInfo, "TaskToTestFactories", new Dictionary(), string.Empty, factoryParameters, explicitlyLaunchTaskHost, new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)), ElementLocation.Create("NONE"), String.Empty);
Assert.True(_loadedType.Assembly.Equals(_loadInfo)); // "Expected the AssemblyLoadInfo to be equal"
}
diff --git a/src/Build.UnitTests/BackEnd/BatchingEngine_Tests.cs b/src/Build.UnitTests/BackEnd/BatchingEngine_Tests.cs
index 837ca550c2d..1530dd11d5a 100644
--- a/src/Build.UnitTests/BackEnd/BatchingEngine_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/BatchingEngine_Tests.cs
@@ -57,7 +57,7 @@ public void GetBuckets()
parameters,
CreateLookup(itemsByType, properties),
MockElementLocation.Instance,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
Assert.Equal(5, buckets.Count);
@@ -74,7 +74,7 @@ public void GetBuckets()
Directory.GetCurrentDirectory(),
MockElementLocation.Instance,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4))));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4))));
Assert.Equal("a.doc;b.doc;c.doc;d.doc;e.doc", bucket.Expander.ExpandIntoStringAndUnescape("@(doc)", ExpanderOptions.ExpandItems, MockElementLocation.Instance));
Assert.Equal("unittests.foo", bucket.Expander.ExpandIntoStringAndUnescape("$(bogus)$(UNITTESTS)", ExpanderOptions.ExpandPropertiesAndMetadata, MockElementLocation.Instance));
}
@@ -146,7 +146,7 @@ public void ValidUnqualifiedMetadataReference()
parameters,
CreateLookup(itemsByType, properties),
null,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
Assert.Equal(2, buckets.Count);
}
@@ -184,7 +184,7 @@ public void InvalidUnqualifiedMetadataReference()
parameters,
CreateLookup(itemsByType, properties),
MockElementLocation.Instance,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
});
}
///
@@ -209,7 +209,7 @@ public void NoItemsConsumed()
parameters,
CreateLookup(itemsByType, properties),
MockElementLocation.Instance,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
});
}
///
@@ -239,7 +239,7 @@ public void Regress_Mutation_DuplicateBatchingBucketsAreFoldedTogether()
parameters,
CreateLookup(itemsByType, properties),
null,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
// If duplicate buckets have been folded correctly, then there will be exactly one bucket here
// containing both a.foo and b.foo.
diff --git a/src/Build.UnitTests/BackEnd/BuildRequestEngine_Tests.cs b/src/Build.UnitTests/BackEnd/BuildRequestEngine_Tests.cs
index 3d9c91ca2c4..f8f5da044f1 100644
--- a/src/Build.UnitTests/BackEnd/BuildRequestEngine_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/BuildRequestEngine_Tests.cs
@@ -335,7 +335,7 @@ public void TestEngineShutdownWhileActive()
BuildRequest request = CreateNewBuildRequest(1, targets);
VerifyEngineStatus(BuildRequestEngineStatus.Uninitialized, true);
- _engine.InitializeForBuild(new NodeLoggingContext(_host.LoggingService, 0, false));
+ _engine.InitializeForBuild(CreateForTesting(_host));
// We neeed to get the status changed AutoResetEvent returned to the non-signaled state correctly after each status change for verifying the engine status via waiting for a signal next time.
// Make sure it returns back to the non-signaled state.
VerifyEngineStatus(BuildRequestEngineStatus.Idle);
@@ -366,7 +366,7 @@ public void TestSimpleBuildScenario()
BuildRequest request = CreateNewBuildRequest(1, targets);
VerifyEngineStatus(BuildRequestEngineStatus.Uninitialized, true);
- _engine.InitializeForBuild(new NodeLoggingContext(_host.LoggingService, 0, false));
+ _engine.InitializeForBuild(CreateForTesting(_host));
VerifyEngineStatus(BuildRequestEngineStatus.Idle);
_engine.SubmitBuildRequest(request);
@@ -400,7 +400,7 @@ public void TestBuildWithChildren()
// Kick it off
VerifyEngineStatus(BuildRequestEngineStatus.Uninitialized, true);
- _engine.InitializeForBuild(new NodeLoggingContext(_host.LoggingService, 0, false));
+ _engine.InitializeForBuild(CreateForTesting(_host));
VerifyEngineStatus(BuildRequestEngineStatus.Idle);
_engine.SubmitBuildRequest(request);
@@ -455,7 +455,7 @@ public void TestBuildWithNewConfiguration()
// Kick it off
VerifyEngineStatus(BuildRequestEngineStatus.Uninitialized, true);
- _engine.InitializeForBuild(new NodeLoggingContext(_host.LoggingService, 0, false));
+ _engine.InitializeForBuild(CreateForTesting(_host));
VerifyEngineStatus(BuildRequestEngineStatus.Idle);
_engine.SubmitBuildRequest(request);
@@ -501,6 +501,8 @@ public void TestShutdown()
{
}
+ private NodeLoggingContext CreateForTesting(MockHost host) => new NodeLoggingContext(host.LoggingService, BuildEventContext.Invalid.WithNodeId(0), 0, false);
+
private BuildRequest CreateNewBuildRequest(int configurationId, string[] targets)
{
BuildRequest request = new BuildRequest(1 /* submission id */, _nodeRequestId++, configurationId, targets, null, BuildEventContext.Invalid, null);
diff --git a/src/Build.UnitTests/BackEnd/BuildResult_Tests.cs b/src/Build.UnitTests/BackEnd/BuildResult_Tests.cs
index be5d2c61db8..bf39a089ddf 100644
--- a/src/Build.UnitTests/BackEnd/BuildResult_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/BuildResult_Tests.cs
@@ -310,7 +310,7 @@ public void TestEnumerator()
[Fact]
public void TestTranslation()
{
- BuildRequest request = new BuildRequest(1, 1, 2, new string[] { "alpha", "omega" }, null, new BuildEventContext(1, 1, 2, 3, 4, 5), null);
+ BuildRequest request = new BuildRequest(1, 1, 2, new string[] { "alpha", "omega" }, null, BuildEventContext.CreateInitial(1, 1).WithEvaluationId(2).WithProjectInstanceId(3).WithProjectContextId(4).WithTaskId(5), null);
BuildResult result = new BuildResult(request, new BuildAbortedException());
TaskItem fooTaskItem = new TaskItem("foo", "asdf.proj");
@@ -347,7 +347,7 @@ public void TestTranslation()
[Fact]
public void TestTranslationPreservesEvaluationId()
{
- BuildRequest request = new(1, 1, 2, ["Build"], null, new BuildEventContext(1, 1, 2, 3, 4, 5), null);
+ BuildRequest request = new(1, 1, 2, ["Build"], null, BuildEventContext.CreateInitial(1, 1).WithProjectInstanceId(2).WithProjectContextId(3).WithTargetId(4).WithTaskId(5), null);
BuildResult result = new(request, new BuildAbortedException())
{
EvaluationId = 42,
diff --git a/src/Build.UnitTests/BackEnd/EventSourceSink_Tests.cs b/src/Build.UnitTests/BackEnd/EventSourceSink_Tests.cs
index 0f6e34c6449..8a3b305b9fd 100644
--- a/src/Build.UnitTests/BackEnd/EventSourceSink_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/EventSourceSink_Tests.cs
@@ -756,7 +756,7 @@ internal sealed class RaiseEventHelper
///
private static BuildWarningEventArgs s_buildWarning = new BuildWarningEventArgs("SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender")
{
- BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6)
+ BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6)
};
///
diff --git a/src/Build.UnitTests/BackEnd/IntrinsicTask_Tests.cs b/src/Build.UnitTests/BackEnd/IntrinsicTask_Tests.cs
index 8feb2a31d9c..85b07831ef0 100644
--- a/src/Build.UnitTests/BackEnd/IntrinsicTask_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/IntrinsicTask_Tests.cs
@@ -3958,7 +3958,7 @@ private static IntrinsicTask CreateIntrinsicTask(string content)
ProjectInstance projectInstance = project.CreateProjectInstance();
ProjectTargetInstanceChild targetChild = projectInstance.Targets["t"].Children.First();
- NodeLoggingContext nodeContext = new NodeLoggingContext(new MockLoggingService(), 1, false);
+ NodeLoggingContext nodeContext = new NodeLoggingContext(new MockLoggingService(), BuildEventContext.Invalid.WithNodeId(1), 1, false);
BuildRequestEntry entry = new BuildRequestEntry(new BuildRequest(1 /* submissionId */, 0, 1, new string[] { "t" }, null, BuildEventContext.Invalid, null), new BuildRequestConfiguration(1, new BuildRequestData("projectFile", new Dictionary(), "3.5", Array.Empty(), null), "2.0"), CreateStubTaskEnvironment());
entry.RequestConfiguration.Project = projectInstance;
IntrinsicTask task = IntrinsicTask.InstantiateTask(
@@ -3993,7 +3993,7 @@ internal static void AssertItemEvaluationFromTarget(string projectContents, stri
var projectInstance = project.CreateProjectInstance();
var targetChild = projectInstance.Targets["t"].Children.First();
- var nodeContext = new NodeLoggingContext(new MockLoggingService(), 1, false);
+ var nodeContext = new NodeLoggingContext(new MockLoggingService(), BuildEventContext.Invalid.WithNodeId(1), 1, false);
var entry = new BuildRequestEntry(new BuildRequest(1 /* submissionId */, 0, 1, new string[] { targetName }, null, BuildEventContext.Invalid, null), new BuildRequestConfiguration(1, new BuildRequestData("projectFile", new Dictionary(), "3.5", Array.Empty(), null), "2.0"), CreateStubTaskEnvironment());
entry.RequestConfiguration.Project = projectInstance;
var task = IntrinsicTask.InstantiateTask(
diff --git a/src/Build.UnitTests/BackEnd/LoggingContext_Tests.cs b/src/Build.UnitTests/BackEnd/LoggingContext_Tests.cs
index 435f06a0369..cea00d9df50 100644
--- a/src/Build.UnitTests/BackEnd/LoggingContext_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/LoggingContext_Tests.cs
@@ -22,13 +22,15 @@ public LoggingContext_Tests(ITestOutputHelper outputHelper)
_output = outputHelper;
}
+ private NodeLoggingContext CreateNodeLoggingContext(int nodeId, bool isInProc) => new NodeLoggingContext(new MockLoggingService(_output.WriteLine), BuildEventContext.Invalid.WithNodeId(nodeId), nodeId, isInProc);
+
///
/// A few simple tests for NodeLoggingContexts.
///
[Fact]
public void CreateValidNodeLoggingContexts()
{
- NodeLoggingContext context = new NodeLoggingContext(new MockLoggingService(_output.WriteLine), 1, true);
+ NodeLoggingContext context = CreateNodeLoggingContext(1, true);
context.IsInProcNode.ShouldBeTrue();
context.IsValid.ShouldBeTrue();
@@ -37,7 +39,7 @@ public void CreateValidNodeLoggingContexts()
context.BuildEventContext.NodeId.ShouldBe(1);
- NodeLoggingContext context2 = new NodeLoggingContext(new MockLoggingService(_output.WriteLine), 2, false);
+ NodeLoggingContext context2 = CreateNodeLoggingContext(2, false);
context2.IsInProcNode.ShouldBeFalse();
context2.IsValid.ShouldBeTrue();
@@ -57,14 +59,14 @@ public void InvalidNodeIdOnNodeLoggingContext()
{
Assert.Throws(() =>
{
- _ = new NodeLoggingContext(new MockLoggingService(), -2, true);
+ _ = CreateNodeLoggingContext(-2, true);
});
}
[Fact]
public void HasLoggedErrors()
{
- NodeLoggingContext context = new NodeLoggingContext(new MockLoggingService(_output.WriteLine), 1, true);
+ NodeLoggingContext context = CreateNodeLoggingContext(1, true);
context.HasLoggedErrors.ShouldBeFalse();
context.LogCommentFromText(Framework.MessageImportance.High, "Test message");
diff --git a/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs b/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs
index 7db8ea66ddd..68311523a20 100644
--- a/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/LoggingService_Tests.cs
@@ -788,13 +788,15 @@ public void TreatWarningsAsErrorWhenAllSpecified(int loggerMode, int nodeId)
[Fact]
public void VerifyWarningsPromotedToErrorsAreCounted()
{
- ILoggingService ls = LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1);
+ var submissionId = 1;
+ var nodeId = 1;
+ ILoggingService ls = LoggingService.CreateLoggingService(LoggerMode.Synchronous, nodeId);
ls.WarningsAsErrors = new HashSet();
ls.WarningsAsErrors.Add("FOR123");
BuildWarningEventArgs warningArgs = new("abc", "FOR123", "", 0, 0, 0, 0, "warning message", "keyword", "sender");
- warningArgs.BuildEventContext = new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidProjectContextId, 5, 6);
+ warningArgs.BuildEventContext = BuildEventContext.Invalid.WithSubmissionId(submissionId).WithNodeId(nodeId);
ls.LogBuildEvent(warningArgs);
- ls.HasBuildSubmissionLoggedErrors(1).ShouldBeTrue();
+ ls.HasBuildSubmissionLoggedErrors(submissionId).ShouldBeTrue();
}
///
@@ -952,13 +954,11 @@ private MockLogger GetLoggedEventsWithWarningsAsErrorsOrMessages(
{
IBuildComponentHost host = new MockHost();
- BuildEventContext buildEventContext = new BuildEventContext(
- submissionId: 0,
- nodeId: 1,
- projectInstanceId: 2,
- projectContextId: -1,
- targetId: -1,
- taskId: -1);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(0, 1)
+ .WithProjectInstanceId(2)
+ .WithProjectContextId(-1)
+ .WithTargetId(-1)
+ .WithTaskId(-1);
BuildRequestData buildRequestData = new BuildRequestData("projectFile", new Dictionary(), "Current", new[] { "Build" }, null);
@@ -974,7 +974,9 @@ private MockLogger GetLoggedEventsWithWarningsAsErrorsOrMessages(
loggingService.RegisterLogger(logger);
- BuildEventContext projectStarted = loggingService.LogProjectStarted(buildEventContext, 0, buildEventContext.ProjectInstanceId, BuildEventContext.Invalid, "projectFile", "Build", Enumerable.Empty(), Enumerable.Empty());
+ var projectStartedArgs = loggingService.CreateProjectStartedForLocalProject(BuildEventContext.Invalid, buildEventContext.ProjectInstanceId, "projectFile", "Build", null, Enumerable.Empty(), Enumerable.Empty(), null);
+ loggingService.LogProjectStarted(projectStartedArgs);
+ BuildEventContext projectStarted = projectStartedArgs.BuildEventContext;
if (warningsAsErrorsForProject != null)
{
diff --git a/src/Build.UnitTests/BackEnd/LoggingServicesLogMethod_Tests.cs b/src/Build.UnitTests/BackEnd/LoggingServicesLogMethod_Tests.cs
index 3fe5fcd8e6e..7ab72b7448c 100644
--- a/src/Build.UnitTests/BackEnd/LoggingServicesLogMethod_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/LoggingServicesLogMethod_Tests.cs
@@ -33,12 +33,12 @@ public class LoggingServicesLogMethod_Tests
///
/// A generic valid build event context which can be used in the tests.
///
- private static BuildEventContext s_buildEventContext = new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4);
+ private static readonly BuildEventContext s_taskBuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 1).WithTargetId(2).WithTaskId(4);
///
- /// buildevent context for target events, note the invalid taskId, target started and finished events have this.
+ /// buildevent context for target events - this will have invalid TaskId, target started and finished events have this.
///
- private static BuildEventContext s_targetBuildEventContext = new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, -1);
+ private static readonly BuildEventContext s_targetBuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 2).WithTargetId(2);
#endregion
#region Event based logging method tests
@@ -102,7 +102,7 @@ public void LogErrorNullMessageResource()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogError(s_buildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), null, "MyTask");
+ service.LogError(s_taskBuildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), null, "MyTask");
});
}
@@ -115,7 +115,7 @@ public void LogErrorEmptyMessageResource()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogError(s_buildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), string.Empty, "MyTask");
+ service.LogError(s_taskBuildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), string.Empty, "MyTask");
});
}
@@ -135,7 +135,7 @@ public void LogErrorGoodParameters()
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogError(s_buildEventContext, subcategoryKey, fileInfo, "FatalTaskError", taskName);
+ service.LogError(s_taskBuildEventContext, subcategoryKey, fileInfo, "FatalTaskError", taskName);
VerifyBuildErrorEventArgs(fileInfo, errorCode, helpKeyword, message, service, subcategory);
}
@@ -165,7 +165,7 @@ public void LogInvalidProjectFileErrorNullException()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogInvalidProjectFileError(s_buildEventContext, null);
+ service.LogInvalidProjectFileError(s_taskBuildEventContext, null);
});
}
@@ -182,21 +182,21 @@ public void LogInvalidProjectFileError()
// Log the exception for the first time
Assert.False(exception.HasBeenLogged);
- service.LogInvalidProjectFileError(s_buildEventContext, exception);
+ service.LogInvalidProjectFileError(s_taskBuildEventContext, exception);
Assert.True(exception.HasBeenLogged);
BuildEventFileInfo fileInfo = new BuildEventFileInfo(exception.ProjectFile, exception.LineNumber, exception.ColumnNumber, exception.EndLineNumber, exception.EndColumnNumber);
VerifyBuildErrorEventArgs(fileInfo, exception.ErrorCode, exception.HelpKeyword, exception.BaseMessage, service, exception.ErrorSubcategory);
// Verify when the exception is logged again that it does not actually get logged due to it already being logged
service.ResetProcessedBuildEvent();
- service.LogInvalidProjectFileError(s_buildEventContext, exception);
+ service.LogInvalidProjectFileError(s_taskBuildEventContext, exception);
Assert.Null(service.ProcessedBuildEvent);
// Reset the HasLogged field and verify OnlyLogCriticalEvents does not effect the logging of the message
service.ResetProcessedBuildEvent();
service.OnlyLogCriticalEvents = true;
exception.HasBeenLogged = false;
- service.LogInvalidProjectFileError(s_buildEventContext, exception);
+ service.LogInvalidProjectFileError(s_taskBuildEventContext, exception);
VerifyBuildErrorEventArgs(fileInfo, exception.ErrorCode, exception.HelpKeyword, exception.BaseMessage, service, exception.ErrorSubcategory);
}
@@ -226,7 +226,7 @@ public void LogFatalErrorNullFileInfo()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalError(s_buildEventContext, new Exception("SuperException"), null, "FatalTaskError", "TaskName");
+ service.LogFatalError(s_taskBuildEventContext, new Exception("SuperException"), null, "FatalTaskError", "TaskName");
});
}
@@ -244,7 +244,7 @@ public void LogFatalErrorNullException()
string message;
GenerateMessageFromExceptionAndResource(null, resourceName, out errorCode, out helpKeyword, out message, parameters);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalError(s_buildEventContext, null, fileInfo, resourceName, parameters);
+ service.LogFatalError(s_taskBuildEventContext, null, fileInfo, resourceName, parameters);
VerifyBuildErrorEventArgs(fileInfo, errorCode, helpKeyword, message, service, null);
}
@@ -258,7 +258,7 @@ public void LogFatalErrorNullMessageResourceName()
{
BuildEventFileInfo fileInfo = new BuildEventFileInfo("foo.cs", 1, 2, 3, 4);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalError(s_buildEventContext, new Exception("SuperException"), fileInfo, null);
+ service.LogFatalError(s_taskBuildEventContext, new Exception("SuperException"), fileInfo, null);
});
}
@@ -272,7 +272,7 @@ public void LogFatalErrorEmptyMessageResourceName()
{
BuildEventFileInfo fileInfo = new BuildEventFileInfo("foo.cs", 1, 2, 3, 4);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalError(s_buildEventContext, new Exception("SuperException"), fileInfo, string.Empty, null);
+ service.LogFatalError(s_taskBuildEventContext, new Exception("SuperException"), fileInfo, string.Empty, null);
});
}
@@ -293,7 +293,7 @@ public void LogFatalErrorAllGoodInput()
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalError(s_buildEventContext, exception, fileInfo, resourceName, parameter);
+ service.LogFatalError(s_taskBuildEventContext, exception, fileInfo, resourceName, parameter);
VerifyBuildErrorEventArgs(fileInfo, errorCode, helpKeyword, message, service, null);
}
#endregion
@@ -315,7 +315,7 @@ public void LogFatalBuildErrorGoodInput()
GenerateMessageFromExceptionAndResource(exception, resourceName, out errorCode, out helpKeyword, out message);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalBuildError(s_buildEventContext, exception, fileInfo);
+ service.LogFatalBuildError(s_taskBuildEventContext, exception, fileInfo);
VerifyBuildErrorEventArgs(fileInfo, errorCode, helpKeyword, message, service, null);
}
#endregion
@@ -332,7 +332,7 @@ public void LogFatalTaskErrorNullTaskNameName()
{
BuildEventFileInfo fileInfo = new BuildEventFileInfo("foo.cs", 1, 2, 3, 4);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalTaskError(s_buildEventContext, new Exception("SuperException"), fileInfo, null);
+ service.LogFatalTaskError(s_taskBuildEventContext, new Exception("SuperException"), fileInfo, null);
});
}
@@ -351,13 +351,13 @@ public void LogFatalTaskError()
string message;
GenerateMessageFromExceptionAndResource(exception, resourceName, out errorCode, out helpKeyword, out message, parameters);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogFatalTaskError(s_buildEventContext, exception, fileInfo, parameters);
+ service.LogFatalTaskError(s_taskBuildEventContext, exception, fileInfo, parameters);
VerifyBuildErrorEventArgs(fileInfo, errorCode, helpKeyword, message, service, null);
// Test when the task name is empty
GenerateMessageFromExceptionAndResource(exception, resourceName, out errorCode, out helpKeyword, out message, String.Empty);
service.ResetProcessedBuildEvent();
- service.LogFatalTaskError(s_buildEventContext, exception, fileInfo, string.Empty);
+ service.LogFatalTaskError(s_taskBuildEventContext, exception, fileInfo, string.Empty);
VerifyBuildErrorEventArgs(fileInfo, errorCode, helpKeyword, message, service, null);
}
#endregion
@@ -385,7 +385,7 @@ public void LogErrorFromTextNullFileInfo()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogErrorFromText(s_buildEventContext, "SubCategoryForSolutionParsingErrors", "WarningCode", "HelpKeyword", null, "Message");
+ service.LogErrorFromText(s_taskBuildEventContext, "SubCategoryForSolutionParsingErrors", "WarningCode", "HelpKeyword", null, "Message");
});
}
@@ -509,7 +509,7 @@ public void LogTaskWarningFromExceptionNullTaskName()
{
BuildEventFileInfo fileInfo = new BuildEventFileInfo("foo.cs", 1, 2, 3, 4);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogTaskWarningFromException(s_buildEventContext, null, fileInfo, null);
+ service.LogTaskWarningFromException(s_taskBuildEventContext, null, fileInfo, null);
});
}
@@ -523,7 +523,7 @@ public void LogTaskWarningFromExceptionEmptyTaskName()
{
BuildEventFileInfo fileInfo = new BuildEventFileInfo("foo.cs", 1, 2, 3, 4);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogTaskWarningFromException(s_buildEventContext, null, fileInfo, null);
+ service.LogTaskWarningFromException(s_taskBuildEventContext, null, fileInfo, null);
});
}
@@ -544,14 +544,14 @@ public void LogTaskWarningFromException()
// Check with a null exception
GenerateMessageFromExceptionAndResource(null, resourceName, out warningCode, out helpKeyword, out message, parameters);
- service.LogTaskWarningFromException(s_buildEventContext, null, fileInfo, parameters);
+ service.LogTaskWarningFromException(s_taskBuildEventContext, null, fileInfo, parameters);
VerifyBuildWarningEventArgs(fileInfo, warningCode, helpKeyword, message, service, null);
// Check when the exception is not null
service.ResetProcessedBuildEvent();
Exception exception = new Exception("SuperException");
GenerateMessageFromExceptionAndResource(exception, resourceName, out warningCode, out helpKeyword, out message, parameters);
- service.LogTaskWarningFromException(s_buildEventContext, exception, fileInfo, parameters);
+ service.LogTaskWarningFromException(s_taskBuildEventContext, exception, fileInfo, parameters);
VerifyBuildWarningEventArgs(fileInfo, warningCode, helpKeyword, message, service, null);
}
#endregion
@@ -566,7 +566,7 @@ public void LogWarningNullMessageResource()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogWarning(s_buildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), null, "MyTask");
+ service.LogWarning(s_taskBuildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), null, "MyTask");
});
}
@@ -579,7 +579,7 @@ public void LogWarningEmptyMessageResource()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogWarning(s_buildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), string.Empty, "MyTask");
+ service.LogWarning(s_taskBuildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo("foo.cs"), string.Empty, "MyTask");
});
}
@@ -619,7 +619,7 @@ public void LogWarningFromTextNullFileInfo()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogWarningFromText(s_buildEventContext, "SubCategoryForSolutionParsingErrors", "WarningCode", "HelpKeyword", null, "Message");
+ service.LogWarningFromText(s_taskBuildEventContext, "SubCategoryForSolutionParsingErrors", "WarningCode", "HelpKeyword", null, "Message");
});
}
@@ -676,7 +676,7 @@ public void LogCommentNullMessageResourceName()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogComment(s_buildEventContext, MessageImportance.Low, null, null);
+ service.LogComment(s_taskBuildEventContext, MessageImportance.Low, null, null);
});
}
@@ -689,7 +689,7 @@ public void LogCommentEmptyMessageResourceName()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogComment(s_buildEventContext, MessageImportance.Low, String.Empty, null);
+ service.LogComment(s_taskBuildEventContext, MessageImportance.Low, String.Empty, null);
});
}
@@ -706,13 +706,13 @@ public void LogCommentGoodMessage()
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
// Verify message is logged when OnlyLogCriticalEvents is false
- service.LogComment(s_buildEventContext, messageImportance, "BuildFinishedSuccess");
+ service.LogComment(s_taskBuildEventContext, messageImportance, "BuildFinishedSuccess");
VerityBuildMessageEventArgs(service, messageImportance, message);
// Verify no message is logged when OnlyLogCriticalEvents is true
service.ResetProcessedBuildEvent();
service.OnlyLogCriticalEvents = true;
- service.LogComment(s_buildEventContext, MessageImportance.Normal, "BuildFinishedSuccess");
+ service.LogComment(s_taskBuildEventContext, MessageImportance.Normal, "BuildFinishedSuccess");
Assert.Null(service.ProcessedBuildEvent);
}
@@ -729,7 +729,7 @@ public void LogCommentFromTextNullMessage()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogCommentFromText(s_buildEventContext, MessageImportance.Low, null);
+ service.LogCommentFromText(s_taskBuildEventContext, MessageImportance.Low, null);
});
}
@@ -740,7 +740,7 @@ public void LogCommentFromTextNullMessage()
public void LogCommentFromTextEmptyMessage()
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogCommentFromText(s_buildEventContext, MessageImportance.Low, string.Empty);
+ service.LogCommentFromText(s_taskBuildEventContext, MessageImportance.Low, string.Empty);
}
///
@@ -766,12 +766,12 @@ public void LogCommentFromTextGoodMessage()
string message = ResourceUtilities.GetResourceString("BuildFinishedSuccess");
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogCommentFromText(s_buildEventContext, messageImportance, ResourceUtilities.GetResourceString("BuildFinishedSuccess"));
+ service.LogCommentFromText(s_taskBuildEventContext, messageImportance, ResourceUtilities.GetResourceString("BuildFinishedSuccess"));
VerityBuildMessageEventArgs(service, messageImportance, message);
service.ResetProcessedBuildEvent();
service.OnlyLogCriticalEvents = true;
- service.LogCommentFromText(s_buildEventContext, MessageImportance.Normal, ResourceUtilities.GetResourceString("BuildFinishedSuccess"));
+ service.LogCommentFromText(s_taskBuildEventContext, MessageImportance.Normal, ResourceUtilities.GetResourceString("BuildFinishedSuccess"));
Assert.Null(service.ProcessedBuildEvent);
}
#endregion
@@ -782,20 +782,6 @@ public void LogCommentFromTextGoodMessage()
#region ProjectStarted
- ///
- /// Expect an exception to be thrown if a null build event context is passed in
- /// and OnlyLogCriticalEvents is false
- ///
- [Fact]
- public void ProjectStartedNullBuildEventContext()
- {
- Assert.Throws(() =>
- {
- ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogProjectStarted(null, 1, 2, s_buildEventContext, "ProjectFile", "TargetNames", null, null);
- });
- }
-
///
/// Expect an exception to be thrown if a null build event context is passed in
/// and OnlyLogCriticalEvents is false
@@ -806,7 +792,8 @@ public void ProjectStartedNullParentBuildEventContext()
Assert.Throws(() =>
{
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogProjectStarted(s_buildEventContext, 1, 2, null, "ProjectFile", "TargetNames", null, null);
+ var args = service.CreateProjectStartedForLocalProject(null, 2, "ProjectFile", "TargetNames", null, null, null, null);
+ service.LogProjectStarted(args);
});
}
@@ -841,8 +828,10 @@ public void ProjectStartedEventTests(string projectFile, string targetNames)
BuildRequestConfiguration config = new BuildRequestConfiguration(2, data, "4.0");
cache.AddConfiguration(config);
- BuildEventContext context = service.LogProjectStarted(s_buildEventContext, 1, 2, s_buildEventContext, projectFile, targetNames, null, null);
- BuildEventContext parentBuildEventContext = s_buildEventContext;
+ var args = service.CreateProjectStartedForLocalProject(s_taskBuildEventContext, 2, projectFile, targetNames, null, null, null, null);
+ service.LogProjectStarted(args);
+ BuildEventContext context = args.BuildEventContext;
+ BuildEventContext parentBuildEventContext = s_taskBuildEventContext;
VerifyProjectStartedEventArgs(service, context.ProjectContextId, message, projectFile, targetNames, parentBuildEventContext, context);
service.ResetProcessedBuildEvent();
@@ -857,6 +846,7 @@ public void ProjectStartedProvidedProjectContextId()
const int SubmissionId = 1;
const int EvaluationId = 2;
const int ConfigurationId = 3;
+ BuildEventContext context = BuildEventContext.CreateInitial(SubmissionId, Scheduler.InProcNodeId).WithEvaluationId(EvaluationId).WithProjectInstanceId(ConfigurationId);
const string ProjectFile = "SomeProjectFile";
MockHost componentHost = new MockHost();
@@ -867,22 +857,15 @@ public void ProjectStartedProvidedProjectContextId()
BuildRequestConfiguration config = new BuildRequestConfiguration(ConfigurationId, data, "4.0");
cache.AddConfiguration(config);
- BuildEventContext projectCacheBuildEventContext = service.CreateProjectCacheBuildEventContext(SubmissionId, EvaluationId, ConfigurationId, ProjectFile);
+ BuildEventContext projectCacheBuildEventContext = service.CreateProjectCacheBuildEventContext(context, ProjectFile);
projectCacheBuildEventContext.NodeId.ShouldBe(Scheduler.InProcNodeId);
projectCacheBuildEventContext.ProjectContextId.ShouldNotBe(BuildEventContext.InvalidProjectContextId);
- BuildEventContext nodeBuildEventContext = new BuildEventContext(Scheduler.InProcNodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
- BuildEventContext projectStartedBuildEventContext = service.LogProjectStarted(
- nodeBuildEventContext,
- submissionId: SubmissionId,
- configurationId: ConfigurationId,
- parentBuildEventContext: BuildEventContext.Invalid,
- projectFile: ProjectFile,
- targetNames: "TargetNames",
- properties: null,
- items: null,
- evaluationId: EvaluationId,
- projectContextId: projectCacheBuildEventContext.ProjectContextId);
+ BuildEventContext nodeBuildEventContext = BuildEventContext.CreateInitial(0, Scheduler.InProcNodeId);
+ var args = service.CreateProjectStartedForLocalProject(BuildEventContext.Invalid, ConfigurationId, ProjectFile, "TargetNames", null, null, null, null);
+ args.BuildEventContext = args.BuildEventContext.WithProjectContextId(projectCacheBuildEventContext.ProjectContextId); // Use provided project context ID
+ service.LogProjectStarted(args);
+ BuildEventContext projectStartedBuildEventContext = args.BuildEventContext;
projectStartedBuildEventContext.ProjectContextId.ShouldBe(projectCacheBuildEventContext.ProjectContextId);
}
@@ -906,62 +889,15 @@ public void ProjectStartedProvidedUnknownProjectContextIdInProcNode()
BuildRequestConfiguration config = new BuildRequestConfiguration(ConfigurationId, data, "4.0");
cache.AddConfiguration(config);
- BuildEventContext nodeBuildEventContext = new BuildEventContext(Scheduler.InProcNodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
+ BuildEventContext parentBuildEventContext = BuildEventContext.CreateInitial(SubmissionId, Scheduler.InProcNodeId).WithEvaluationId(EvaluationId);
+ BuildEventContext remoteBuildEventContextWithKnownBadContextOnCurrentNode = parentBuildEventContext.WithProjectContextId(ProjectContextId);
Assert.Throws(() =>
{
- service.LogProjectStarted(
- nodeBuildEventContext,
- submissionId: SubmissionId,
- configurationId: ConfigurationId,
- parentBuildEventContext: BuildEventContext.Invalid,
- projectFile: ProjectFile,
- targetNames: "TargetNames",
- properties: null,
- items: null,
- evaluationId: EvaluationId,
- projectContextId: ProjectContextId);
+ var args = service.CreateProjectStartedForCachedProject(parentBuildEventContext, remoteBuildEventContextWithKnownBadContextOnCurrentNode, BuildEventContext.Invalid, null, ProjectFile, "TargetNames", null);
+ service.LogProjectStarted(args);
});
}
- ///
- /// Expect an unknown project context id to be accepted on an out-of-proc node.
- ///
- [Fact]
- public void ProjectStartedProvidedUnknownProjectContextIdOutOfProcNode()
- {
- const int SubmissionId = 1;
- const int EvaluationId = 2;
- const int ConfigurationId = 3;
- const string ProjectFile = "SomeProjectFile";
- const int NodeId = 2;
- const int ProjectContextId = 123;
-
- // Ensure we didn't pick the one bad const value
- NodeId.ShouldNotBe(Scheduler.InProcNodeId);
-
- MockHost componentHost = new MockHost();
- ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1, componentHost);
- ConfigCache cache = (ConfigCache)componentHost.GetComponent(BuildComponentType.ConfigCache);
-
- BuildRequestData data = new BuildRequestData(ProjectFile, new Dictionary(StringComparer.OrdinalIgnoreCase), "toolsVersion", Array.Empty(), null);
- BuildRequestConfiguration config = new BuildRequestConfiguration(ConfigurationId, data, "4.0");
- cache.AddConfiguration(config);
-
- BuildEventContext nodeBuildEventContext = new BuildEventContext(NodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
- BuildEventContext projectStartedBuildEventContext = service.LogProjectStarted(
- nodeBuildEventContext,
- submissionId: SubmissionId,
- configurationId: ConfigurationId,
- parentBuildEventContext: BuildEventContext.Invalid,
- projectFile: ProjectFile,
- targetNames: "TargetNames",
- properties: null,
- items: null,
- evaluationId: EvaluationId,
- projectContextId: ProjectContextId);
- projectStartedBuildEventContext.ProjectContextId.ShouldBe(ProjectContextId);
- }
-
#endregion
#region ProjectFinished
@@ -1276,8 +1212,8 @@ public void LogTelemetryTest()
TestLogTelemetry(buildEventContext: null, eventName: "no context and no properties", properties: null);
TestLogTelemetry(buildEventContext: null, eventName: "no context but with properties", properties: eventProperties);
- TestLogTelemetry(buildEventContext: s_buildEventContext, eventName: "event context but no properties", properties: null);
- TestLogTelemetry(buildEventContext: s_buildEventContext, eventName: "event context and properties", properties: eventProperties);
+ TestLogTelemetry(buildEventContext: s_taskBuildEventContext, eventName: "event context but no properties", properties: null);
+ TestLogTelemetry(buildEventContext: s_taskBuildEventContext, eventName: "event context and properties", properties: eventProperties);
}
private void TestLogTelemetry(BuildEventContext buildEventContext, string eventName, IDictionary properties)
@@ -1348,7 +1284,7 @@ private void TestLogErrorFromText(string errorCode, string helpKeyword, string s
}
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogErrorFromText(s_buildEventContext, subcategoryKey, errorCode, helpKeyword, fileInfo, message);
+ service.LogErrorFromText(s_taskBuildEventContext, subcategoryKey, errorCode, helpKeyword, fileInfo, message);
VerifyBuildErrorEventArgs(fileInfo, errorCode, helpKeyword, message, service, subcategory);
}
@@ -1369,7 +1305,7 @@ private void TestLogWarningFromText(string warningCode, string helpKeyword, stri
}
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogWarningFromText(s_buildEventContext, subcategoryKey, warningCode, helpKeyword, fileInfo, message);
+ service.LogWarningFromText(s_taskBuildEventContext, subcategoryKey, warningCode, helpKeyword, fileInfo, message);
VerifyBuildWarningEventArgs(fileInfo, warningCode, helpKeyword, message, service, subcategory);
}
@@ -1387,7 +1323,7 @@ private void TestLogWarning(string taskName, string subCategoryKey)
string message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword(out warningCode, out helpKeyword, "FatalTaskError", taskName);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogWarning(s_buildEventContext, subCategoryKey, fileInfo, "FatalTaskError", taskName);
+ service.LogWarning(s_taskBuildEventContext, subCategoryKey, fileInfo, "FatalTaskError", taskName);
VerifyBuildWarningEventArgs(fileInfo, warningCode, helpKeyword, message, service, subcategory);
}
@@ -1403,11 +1339,11 @@ private void TestProjectFinishedEvent(string projectFile, bool success)
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1, componentHost);
try
{
- service.LogProjectFinished(s_buildEventContext, projectFile, success);
+ service.LogProjectFinished(s_taskBuildEventContext, projectFile, success);
}
catch (InternalErrorException ex)
{
- Assert.Contains("ContextID " + s_buildEventContext.ProjectContextId, ex.Message);
+ Assert.Contains("ContextID " + s_taskBuildEventContext.ProjectContextId, ex.Message);
}
finally
{
@@ -1421,15 +1357,9 @@ private void TestProjectFinishedEvent(string projectFile, bool success)
cache.AddConfiguration(config);
// Now do it the right way -- with a matching ProjectStarted.
- BuildEventContext projectContext = service.LogProjectStarted(
- new BuildEventContext(1, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId),
- 1,
- 2,
- s_buildEventContext,
- projectFile,
- null,
- null,
- null);
+ var projectStartedArgs = service.CreateProjectStartedForLocalProject(s_taskBuildEventContext, 2, projectFile, null, null, null, null, null);
+ service.LogProjectStarted(projectStartedArgs);
+ BuildEventContext projectContext = projectStartedArgs.BuildEventContext;
service.LogProjectFinished(projectContext, projectFile, success);
@@ -1450,12 +1380,12 @@ private void TestTaskStartedEvent(string taskName, string projectFile, string pr
string taskAssemblyLocation = Assembly.GetExecutingAssembly().Location;
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogTaskStarted(s_buildEventContext, taskName, projectFile, projectFileOfTask, taskAssemblyLocation);
+ service.LogTaskStarted(s_taskBuildEventContext, taskName, projectFile, projectFileOfTask, taskAssemblyLocation);
VerifyTaskStartedEvent(taskName, projectFile, projectFileOfTask, message, service, taskAssemblyLocation);
service.ResetProcessedBuildEvent();
service.OnlyLogCriticalEvents = true;
- service.LogTaskStarted(s_buildEventContext, taskName, projectFile, projectFileOfTask, taskAssemblyLocation);
+ service.LogTaskStarted(s_taskBuildEventContext, taskName, projectFile, projectFileOfTask, taskAssemblyLocation);
Assert.Null(service.ProcessedBuildEvent);
}
@@ -1470,12 +1400,12 @@ private void TestTaskFinished(string taskName, string projectFile, string projec
{
string message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword(succeeded ? "TaskFinishedSuccess" : "TaskFinishedFailure", taskName);
ProcessBuildEventHelper service = (ProcessBuildEventHelper)ProcessBuildEventHelper.CreateLoggingService(LoggerMode.Synchronous, 1);
- service.LogTaskFinished(s_buildEventContext, taskName, projectFile, projectFileOfTask, succeeded);
+ service.LogTaskFinished(s_taskBuildEventContext, taskName, projectFile, projectFileOfTask, succeeded);
VerifyTaskFinishedEvent(taskName, projectFile, projectFileOfTask, succeeded, message, service);
service.ResetProcessedBuildEvent();
service.OnlyLogCriticalEvents = true;
- service.LogTaskFinished(s_buildEventContext, taskName, projectFile, projectFileOfTask, succeeded);
+ service.LogTaskFinished(s_taskBuildEventContext, taskName, projectFile, projectFileOfTask, succeeded);
Assert.Null(service.ProcessedBuildEvent);
}
@@ -1624,7 +1554,7 @@ private void VerifyTaskFinishedEvent(string taskName, string projectFile, string
taskName,
succeeded,
service.ProcessedBuildEvent.Timestamp);
- taskEvent.BuildEventContext = s_buildEventContext;
+ taskEvent.BuildEventContext = s_taskBuildEventContext;
Assert.True(((TaskFinishedEventArgs)service.ProcessedBuildEvent).IsEquivalent(taskEvent));
}
@@ -1646,7 +1576,7 @@ private void VerifyTaskStartedEvent(string taskName, string projectFile, string
taskName,
service.ProcessedBuildEvent.Timestamp,
taskAssemblyLocation);
- taskEvent.BuildEventContext = s_buildEventContext;
+ taskEvent.BuildEventContext = s_taskBuildEventContext;
Assert.True(((TaskStartedEventArgs)service.ProcessedBuildEvent).IsEquivalent(taskEvent));
}
@@ -1710,7 +1640,7 @@ private void VerityBuildMessageEventArgs(ProcessBuildEventHelper service, Messag
messageImportance,
service.ProcessedBuildEvent.Timestamp);
- buildMessageEvent.BuildEventContext = s_buildEventContext;
+ buildMessageEvent.BuildEventContext = s_taskBuildEventContext;
Assert.True(((BuildMessageEventArgs)service.ProcessedBuildEvent).IsEquivalent(buildMessageEvent));
}
@@ -1737,7 +1667,7 @@ private void VerifyBuildWarningEventArgs(BuildEventFileInfo fileInfo, string war
helpKeyword,
"MSBuild",
service.ProcessedBuildEvent.Timestamp);
- buildEvent.BuildEventContext = s_buildEventContext;
+ buildEvent.BuildEventContext = s_taskBuildEventContext;
Assert.True(buildEvent.IsEquivalent((BuildWarningEventArgs)service.ProcessedBuildEvent));
}
@@ -1764,7 +1694,7 @@ private void VerifyBuildErrorEventArgs(BuildEventFileInfo fileInfo, string error
helpKeyword,
"MSBuild",
service.ProcessedBuildEvent.Timestamp);
- buildEvent.BuildEventContext = s_buildEventContext;
+ buildEvent.BuildEventContext = s_taskBuildEventContext;
Assert.True(buildEvent.IsEquivalent((BuildErrorEventArgs)service.ProcessedBuildEvent));
}
diff --git a/src/Build.UnitTests/BackEnd/MockLoggingService.cs b/src/Build.UnitTests/BackEnd/MockLoggingService.cs
index 0042f36fa4d..b0b866feb1d 100644
--- a/src/Build.UnitTests/BackEnd/MockLoggingService.cs
+++ b/src/Build.UnitTests/BackEnd/MockLoggingService.cs
@@ -525,12 +525,12 @@ public void LogBuildCanceled()
}
///
- public BuildEventContext CreateEvaluationBuildEventContext(int nodeId, int submissionId)
- => new BuildEventContext(0, 0, 0, 0, 0, 0, 0);
+ public BuildEventContext CreateEvaluationBuildEventContext(BuildEventContext parentBuildEventContext)
+ => parentBuildEventContext.WithEvaluationId(0);
///
- public BuildEventContext CreateProjectCacheBuildEventContext(int submissionId, int evaluationId, int projectInstanceId, string projectFile)
- => new BuildEventContext(0, 0, 0, 0, 0, 0, 0);
+ public BuildEventContext CreateProjectCacheBuildEventContext(BuildEventContext parentBuildEventContext, string projectFile)
+ => parentBuildEventContext.WithProjectContextId(0);
///
public void LogProjectEvaluationStarted(BuildEventContext eventContext, string projectFile)
@@ -550,40 +550,27 @@ public void LogProjectEvaluationFinished(
{
}
- ///
- /// Logs a project started event
- ///
- public BuildEventContext LogProjectStarted(
- BuildEventContext nodeBuildEventContext,
- int submissionId,
- int configurationId,
- BuildEventContext parentBuildEventContext,
- string projectFile,
- string targetNames,
- IEnumerable properties,
- IEnumerable items,
- int evaluationId = BuildEventContext.InvalidEvaluationId,
- int projectContextId = BuildEventContext.InvalidProjectContextId)
- {
- return new BuildEventContext(0, 0, 0, 0);
- }
-
public void LogProjectStarted(ProjectStartedEventArgs args)
{ }
- public ProjectStartedEventArgs CreateProjectStarted(
- BuildEventContext nodeBuildEventContext,
- int submissionId,
- int configurationId,
+ public ProjectStartedEventArgs CreateProjectStartedForLocalProject(
BuildEventContext parentBuildEventContext,
+ int configurationId,
string projectFile,
string targetNames,
+ IDictionary globalProperties,
IEnumerable properties,
IEnumerable items,
- int evaluationId = BuildEventContext.InvalidEvaluationId,
- int projectContextId = BuildEventContext.InvalidProjectContextId)
+ string toolsVersion)
{
- return new ProjectStartedEventArgs(
+ // Create a mock project context ID for testing
+ int projectContextId = configurationId;
+
+ BuildEventContext projectBuildEventContext = parentBuildEventContext
+ .WithProjectInstanceId(configurationId)
+ .WithProjectContextId(projectContextId);
+
+ var buildEvent = new ProjectStartedEventArgs(
configurationId,
message: null,
helpKeyword: null,
@@ -591,7 +578,42 @@ public ProjectStartedEventArgs CreateProjectStarted(
targetNames,
properties,
items,
- parentBuildEventContext);
+ parentBuildEventContext,
+ globalProperties,
+ toolsVersion);
+
+ buildEvent.BuildEventContext = projectBuildEventContext;
+ return buildEvent;
+ }
+
+ public ProjectStartedEventArgs CreateProjectStartedForCachedProject(
+ BuildEventContext currentNodeBuildEventContext,
+ BuildEventContext remoteNodeEvaluationBuildEventContext,
+ BuildEventContext parentBuildEventContext,
+ IDictionary globalProperties,
+ string projectFile,
+ string targetNames,
+ string toolsVersion)
+ {
+ BuildEventContext projectBuildEventContext = parentBuildEventContext
+ .WithProjectInstanceId(remoteNodeEvaluationBuildEventContext.ProjectInstanceId)
+ .WithProjectContextId(remoteNodeEvaluationBuildEventContext.ProjectContextId);
+
+ var buildEvent = new ProjectStartedEventArgs(
+ remoteNodeEvaluationBuildEventContext.ProjectInstanceId,
+ message: null,
+ helpKeyword: null,
+ projectFile,
+ targetNames,
+ null, // No properties for cache scenarios in mock
+ null, // No items for cache scenarios in mock
+ parentBuildEventContext,
+ globalProperties,
+ toolsVersion,
+ remoteNodeEvaluationBuildEventContext); // Pass original context
+
+ buildEvent.BuildEventContext = projectBuildEventContext;
+ return buildEvent;
}
///
@@ -614,7 +636,7 @@ public void LogProjectFinished(BuildEventContext projectBuildEventContext, strin
/// The build event context for the target
public BuildEventContext LogTargetStarted(BuildEventContext projectBuildEventContext, string targetName, string projectFile, string projectFileOfTargetElement, string parentTargetName, TargetBuiltReason buildReason)
{
- return new BuildEventContext(0, 0, 0, 0);
+ return BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(0);
}
///
@@ -652,7 +674,7 @@ public void LogTaskStarted(BuildEventContext targetBuildEventContext, string tas
/// The task logging context
public BuildEventContext LogTaskStarted2(BuildEventContext targetBuildEventContext, string taskName, string projectFile, string projectFileOfTaskNode, int line, int column, string taskAssemblyLocation)
{
- return new BuildEventContext(0, 0, 0, 0);
+ return BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(0);
}
///
@@ -689,17 +711,17 @@ public void PopulateBuildTelemetryWithErrors(Framework.Telemetry.BuildTelemetry
public ICollection GetWarningsAsErrors(BuildEventContext context)
{
- throw new NotImplementedException();
+ return Array.Empty();
}
public ICollection GetWarningsNotAsErrors(BuildEventContext context)
{
- throw new NotImplementedException();
+ return Array.Empty();
}
public ICollection GetWarningsAsMessages(BuildEventContext context)
{
- throw new NotImplementedException();
+ return Array.Empty();
}
public void LogIncludeFile(BuildEventContext buildEventContext, string filePath)
diff --git a/src/Build.UnitTests/BackEnd/NodePackets_Tests.cs b/src/Build.UnitTests/BackEnd/NodePackets_Tests.cs
index 8ca50416de7..5577f65a441 100644
--- a/src/Build.UnitTests/BackEnd/NodePackets_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/NodePackets_Tests.cs
@@ -123,7 +123,7 @@ public void VerifyEventType()
private static BuildEventContext CreateBuildEventContext()
{
- return new BuildEventContext(1, 2, 3, 4, 5, 6, 7);
+ return BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6).WithTaskId(7);
}
private static ProjectEvaluationStartedEventArgs CreateProjectEvaluationStarted()
@@ -262,7 +262,7 @@ public void TestTranslation()
{
new ResponseFileUsedEventArgs("path"),
new UninitializedPropertyReadEventArgs("prop", "message", "help", "sender", MessageImportance.Normal),
- new EnvironmentVariableReadEventArgs("env", "message", "file", 0, 0) { BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6) },
+ new EnvironmentVariableReadEventArgs("env", "message", "file", 0, 0) { BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6) },
new PropertyReassignmentEventArgs("prop", "prevValue", "newValue", "loc", "message", "help", "sender", MessageImportance.Normal),
new PropertyInitialValueSetEventArgs("prop", "val", "propsource", "message", "help", "sender", MessageImportance.Normal),
new MetaprojectGeneratedEventArgs("metaName", "path", "message"),
@@ -294,31 +294,31 @@ public void TestTranslation()
{
ExtendedData = /*lang=json*/ "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary { { "m1", "v1" }, { "m2", "v2" } },
- BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
+ BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7)
},
new ExtendedBuildWarningEventArgs("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = /*lang=json*/ "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary { { "m1", "v1" }, { "m2", "v2" } },
- BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
+ BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7)
},
new ExtendedBuildMessageEventArgs("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", MessageImportance.Normal, DateTime.UtcNow, "arg1")
{
ExtendedData = /*lang=json*/ "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary { { "m1", "v1" }, { "m2", "v2" } },
- BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
+ BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7)
},
new ExtendedCustomBuildEventArgs("extCustom", "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = /*lang=json*/ "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary { { "m1", "v1" }, { "m2", "v2" } },
- BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
+ BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7)
},
new ExtendedCriticalBuildMessageEventArgs("extCritMsg", "Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "Sender", DateTime.Now, "arg1")
{
ExtendedData = /*lang=json*/ "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary { { "m1", "v1" }, { "m2", "v2" } },
- BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
+ BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7)
},
new GeneratedFileUsedEventArgs("path", "some content"),
};
diff --git a/src/Build.UnitTests/BackEnd/RequestBuilder_Tests.cs b/src/Build.UnitTests/BackEnd/RequestBuilder_Tests.cs
index bb5b64ced35..a0fc257ec6c 100644
--- a/src/Build.UnitTests/BackEnd/RequestBuilder_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/RequestBuilder_Tests.cs
@@ -337,10 +337,7 @@ private void WaitForEvent(WaitHandle evt, string eventName)
}
}
- private NodeLoggingContext GetNodeLoggingContext()
- {
- return new NodeLoggingContext(_host, 1, false);
- }
+ private NodeLoggingContext GetNodeLoggingContext() => new NodeLoggingContext(_host, BuildEventContext.Invalid.WithNodeId(1), 1, false);
///
/// Verifies NeedsResultsTransfer returns false in MT mode, even when ResultsNodeId
diff --git a/src/Build.UnitTests/BackEnd/SdkResolverService_Tests.cs b/src/Build.UnitTests/BackEnd/SdkResolverService_Tests.cs
index 95730b3440a..bc967b4087b 100644
--- a/src/Build.UnitTests/BackEnd/SdkResolverService_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/SdkResolverService_Tests.cs
@@ -38,7 +38,10 @@ public SdkResolverService_Tests()
_loggingContext = new MockLoggingContext(
loggingService,
- new BuildEventContext(0, 0, BuildEventContext.InvalidProjectContextId, 0, 0));
+ BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 0)
+ .WithProjectInstanceId(0)
+ .WithTargetId(0)
+ .WithTaskId(0));
}
[Fact]
diff --git a/src/Build.UnitTests/BackEnd/TargetBuilder_Tests.cs b/src/Build.UnitTests/BackEnd/TargetBuilder_Tests.cs
index 005ef4da7bb..1f9085cf7f3 100644
--- a/src/Build.UnitTests/BackEnd/TargetBuilder_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/TargetBuilder_Tests.cs
@@ -1694,7 +1694,9 @@ private ProjectInstance CreateTestProject(string projectBodyContents, string ini
/// The context
private ProjectLoggingContext GetProjectLoggingContext(BuildRequestEntry entry)
{
- return new ProjectLoggingContext(new NodeLoggingContext(_host, 1, false), entry);
+ var nodeContext = new NodeLoggingContext(_host, BuildEventContext.Invalid.WithNodeId(1), 1, false);
+ var (_, context) = ProjectLoggingContext.CreateForLocalBuild(nodeContext, entry);
+ return context;
}
///
diff --git a/src/Build.UnitTests/BackEnd/TargetEntry_Tests.cs b/src/Build.UnitTests/BackEnd/TargetEntry_Tests.cs
index 140cbaa94dc..4104cd32b22 100644
--- a/src/Build.UnitTests/BackEnd/TargetEntry_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/TargetEntry_Tests.cs
@@ -1085,7 +1085,9 @@ private ProjectInstance CreateTestProject(bool returnsAttributeEnabled)
/// The project logging context.
private ProjectLoggingContext GetProjectLoggingContext(BuildRequestEntry entry)
{
- return new ProjectLoggingContext(new NodeLoggingContext(_host, 1, false), entry);
+ var nodeContext = new NodeLoggingContext(_host, BuildEventContext.Invalid.WithNodeId(1), 1, false);
+ var (_, context) = ProjectLoggingContext.CreateForLocalBuild(nodeContext, entry);
+ return context;
}
///
diff --git a/src/Build.UnitTests/BackEnd/TargetResult_Tests.cs b/src/Build.UnitTests/BackEnd/TargetResult_Tests.cs
index d9fb204fb78..b3d57ff8d79 100644
--- a/src/Build.UnitTests/BackEnd/TargetResult_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/TargetResult_Tests.cs
@@ -90,7 +90,12 @@ public void TestTranslationNoException()
{
TaskItem item = new TaskItem("foo", "bar.proj");
item.SetMetadata("a", "b");
- var buildEventContext = new Framework.BuildEventContext(1, 2, 3, 4, 5, 6, 7);
+ var buildEventContext = Framework.BuildEventContext.CreateInitial(1, 2)
+ .WithEvaluationId(3)
+ .WithProjectInstanceId(4)
+ .WithProjectContextId(5)
+ .WithTargetId(6)
+ .WithTaskId(7);
TargetResult result = new TargetResult(
new TaskItem[] { item },
diff --git a/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs b/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
index 24f959157d4..b2b3780d772 100644
--- a/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
@@ -981,7 +981,7 @@ public void TestTaskResolutionFailureWithUsingTask()
_loggingService = new MockLoggingService();
Dispose();
_host = new TaskExecutionHost();
- TargetLoggingContext tlc = new TargetLoggingContext(_loggingService, new BuildEventContext(1, 1, BuildEventContext.InvalidProjectContextId, 1));
+ TargetLoggingContext tlc = new TargetLoggingContext(_loggingService, BuildEventContext.CreateInitial(1, 1).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(1));
ProjectInstance project = CreateTestProject();
_host.InitializeForTask(
@@ -1012,7 +1012,7 @@ public void TestTaskResolutionFailureWithNoUsingTask()
{
Dispose();
_host = new TaskExecutionHost();
- TargetLoggingContext tlc = new TargetLoggingContext(_loggingService, new BuildEventContext(1, 1, BuildEventContext.InvalidProjectContextId, 1));
+ TargetLoggingContext tlc = new TargetLoggingContext(_loggingService, BuildEventContext.CreateInitial(1, 1).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(1));
ProjectInstance project = CreateTestProject();
_host.InitializeForTask(
@@ -1244,7 +1244,7 @@ private void InitializeHost(bool throwOnExecute)
_logger = new MockLogger();
_loggingService.RegisterLogger(_logger);
_host = new TaskExecutionHost();
- TargetLoggingContext tlc = new TargetLoggingContext(_loggingService, new BuildEventContext(1, 1, BuildEventContext.InvalidProjectContextId, 1));
+ TargetLoggingContext tlc = new TargetLoggingContext(_loggingService, BuildEventContext.CreateInitial(1, 1).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(1));
// Set up a temporary project and add some items to it.
ProjectInstance project = CreateTestProject();
diff --git a/src/Build.UnitTests/BackEnd/TaskRegistry_Tests.cs b/src/Build.UnitTests/BackEnd/TaskRegistry_Tests.cs
index b751aef4688..5231fcac727 100644
--- a/src/Build.UnitTests/BackEnd/TaskRegistry_Tests.cs
+++ b/src/Build.UnitTests/BackEnd/TaskRegistry_Tests.cs
@@ -68,7 +68,7 @@ public class TaskRegistry_Tests
///
/// Build event context to use when logging
///
- private readonly BuildEventContext _loggerContext = new BuildEventContext(2, 2, 2, 2);
+ private readonly BuildEventContext _loggerContext = BuildEventContext.CreateInitial(2, 2).WithEvaluationId(2).WithProjectInstanceId(2);
///
/// Element location to use when logging
@@ -1134,7 +1134,7 @@ public void TaskFactoryWithNullTaskTypeLogsError()
TaskRegistry registry = CreateTaskRegistryAndRegisterTasks(elementList);
- InvalidProjectFileException exception = Should.Throw(() => registry.GetRegisteredTask("Task1", "none", TaskHostParameters.Empty, false, new TargetLoggingContext(_loggingService, new BuildEventContext(1, 1, BuildEventContext.InvalidProjectContextId, 1)), ElementLocation.Create("none", 1, 2), false));
+ InvalidProjectFileException exception = Should.Throw(() => registry.GetRegisteredTask("Task1", "none", TaskHostParameters.Empty, false, new TargetLoggingContext(_loggingService, BuildEventContext.CreateInitial(1, 1).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(1)), ElementLocation.Create("none", 1, 2), false));
exception.ErrorCode.ShouldBe("MSB4175");
@@ -2117,7 +2117,7 @@ internal static Expander GetExpand
pg,
secondaryItemsByName,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
return expander;
}
diff --git a/src/Build.UnitTests/BuildEventArgsSerialization_Tests.cs b/src/Build.UnitTests/BuildEventArgsSerialization_Tests.cs
index 12d33ccc514..eb8cce28d65 100644
--- a/src/Build.UnitTests/BuildEventArgsSerialization_Tests.cs
+++ b/src/Build.UnitTests/BuildEventArgsSerialization_Tests.cs
@@ -90,7 +90,7 @@ public void RoundtripBuildFinishedEventArgs()
null,
succeeded: true,
eventTimestamp: DateTime.Parse("12/12/2015 06:11:56 PM"));
- args.BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6);
+ args.BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6);
Roundtrip(args,
e => ToString(e.BuildEventContext),
@@ -159,10 +159,10 @@ public void RoundtripProjectStartedEventArgs()
targetNames: "Build",
properties: new List() { new DictionaryEntry("Key", "Value") },
items: new List() { new DictionaryEntry("Key", new MyTaskItem() { ItemSpec = "TestItemSpec" }) },
- parentBuildEventContext: new BuildEventContext(7, 8, 9, 10, 11, 12),
+ parentBuildEventContext: BuildEventContext.CreateInitial(7, 8).WithEvaluationId(9).WithProjectInstanceId(10).WithProjectContextId(11).WithTaskId(12),
globalProperties: new Dictionary() { { "GlobalKey", "GlobalValue" } },
toolsVersion: "Current");
- args.BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6);
+ args.BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6);
Roundtrip(args,
e => ToString(e.BuildEventContext),
@@ -263,7 +263,7 @@ public void RoundtripTaskStartedEventArgs()
public void RoundtripEnvironmentVariableReadEventArgs()
{
EnvironmentVariableReadEventArgs args = new("VarName", "VarValue", "file", 10, 20);
- args.BuildEventContext = new BuildEventContext(4, 5, 6, 7);
+ args.BuildEventContext = BuildEventContext.CreateInitial(4, 5).WithEvaluationId(6).WithProjectInstanceId(7);
Roundtrip(args,
e => e.Message,
e => e.EnvironmentVariableName,
@@ -343,7 +343,7 @@ public void RoundtripExtendedErrorEventArgs_SerializedAsError(bool withOptionalD
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7) : null,
};
Roundtrip(args,
@@ -416,7 +416,7 @@ public void RoundtripExtendedWarningEventArgs_SerializedAsWarning(bool withOptio
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7) : null,
};
Roundtrip(args,
@@ -492,7 +492,7 @@ public void RoundtripExtendedBuildMessageEventArgs_SerializedAsMessage(bool with
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7) : null,
};
Roundtrip(args,
@@ -580,7 +580,7 @@ public void ExtendedCustomBuildEventArgs_SerializedAsMessage(bool withOptionalDa
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7) : null,
};
@@ -675,7 +675,7 @@ public void RoundtripExtendedCriticalBuildMessageEventArgs(bool withOptionalData
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7) : null,
};
@@ -902,7 +902,7 @@ public void RoundtripTargetSkippedEventArgs()
SkipReason = TargetSkipReason.PreviouslyBuiltSuccessfully,
Condition = "$(condition) == true",
EvaluatedCondition = "true == true",
- OriginalBuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7),
+ OriginalBuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTaskId(6).WithTargetId(7),
OriginallySucceeded = false,
TargetFile = "foo.csproj"
};
diff --git a/src/Build.UnitTests/ConfigureableForwardingLogger_Tests.cs b/src/Build.UnitTests/ConfigureableForwardingLogger_Tests.cs
index 7ccdbeeb57b..3f945c1089b 100644
--- a/src/Build.UnitTests/ConfigureableForwardingLogger_Tests.cs
+++ b/src/Build.UnitTests/ConfigureableForwardingLogger_Tests.cs
@@ -49,7 +49,7 @@ protected override void ForwardToCentralLogger(BuildEventArgs e)
public ConfigureableForwardingLogger_Tests()
{
- BuildEventContext context = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext context = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
_error.BuildEventContext = context;
_warning.BuildEventContext = context;
_targetStarted.BuildEventContext = context;
diff --git a/src/Build.UnitTests/ConsoleLogger_Tests.cs b/src/Build.UnitTests/ConsoleLogger_Tests.cs
index 3456745feb2..de40d674978 100644
--- a/src/Build.UnitTests/ConsoleLogger_Tests.cs
+++ b/src/Build.UnitTests/ConsoleLogger_Tests.cs
@@ -457,19 +457,19 @@ public void NullEventFields()
// Not all parameters are null here, but that's fine, we assume the engine will never
// fire a ProjectStarted without a project name, etc.
es.Consume(new BuildStartedEventArgs(null, null));
- es.Consume(new ProjectStartedEventArgs(1, null, null, "p", null, null, null, parentBuildEventContext: new BuildEventContext(1, 1, 1, 1)) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new TargetStartedEventArgs(null, null, "t", null, null) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new TaskStartedEventArgs(null, null, null, null, "task") { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new BuildMessageEventArgs(null, null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new BuildWarningEventArgs(null, null, null, 0, 0, 0, 0, null, null, null) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new BuildErrorEventArgs(null, null, null, 0, 0, 0, 0, null, null, null) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new TaskFinishedEventArgs(null, null, null, null, "task", true) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new TargetFinishedEventArgs(null, null, "t", null, null, true) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new ProjectFinishedEventArgs(null, null, "p", true) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new BuildFinishedEventArgs(null, null, true) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new BuildFinishedEventArgs(null, null, true) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new BuildFinishedEventArgs(null, null, true) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
- es.Consume(new MyCustomBuildEventArgs2() { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ es.Consume(new ProjectStartedEventArgs(1, null, null, "p", null, null, null, parentBuildEventContext: BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1)) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new TargetStartedEventArgs(null, null, "t", null, null) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new TaskStartedEventArgs(null, null, null, null, "task") { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new BuildMessageEventArgs(null, null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new BuildWarningEventArgs(null, null, null, 0, 0, 0, 0, null, null, null) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new BuildErrorEventArgs(null, null, null, 0, 0, 0, 0, null, null, null) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new TaskFinishedEventArgs(null, null, null, null, "task", true) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new TargetFinishedEventArgs(null, null, "t", null, null, true) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new ProjectFinishedEventArgs(null, null, "p", true) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new BuildFinishedEventArgs(null, null, true) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new BuildFinishedEventArgs(null, null, true) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new BuildFinishedEventArgs(null, null, true) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
+ es.Consume(new MyCustomBuildEventArgs2() { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
// No exception raised
}
@@ -482,7 +482,7 @@ public void NullEventFieldsParallel()
sc.Write, sc.SetColor,
sc.ResetColor);
L.Initialize(es, 2);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs(null, null);
bse.BuildEventContext = buildEventContext;
@@ -599,7 +599,7 @@ public void SingleMessageTest(LoggerVerbosity loggerVerbosity, MessageImportance
BuildMessageEventArgs be = new BuildMessageEventArgs(message, "help", "sender", messageImportance)
{
- BuildEventContext = new BuildEventContext(1, 2, 3, 4)
+ BuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 1).WithTargetId(2).WithProjectContextId(3).WithTaskId(4)
};
eventSourceSink.Consume(be);
@@ -655,7 +655,7 @@ public void ColorTest(string expectedMessageType, string expectedColor)
throw new InvalidOperationException($"Invalid expectedMessageType '{expectedMessageType}'");
}
- buildEventArgs.BuildEventContext = new BuildEventContext(1, 2, 3, 4);
+ buildEventArgs.BuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 1).WithTargetId(2).WithProjectContextId(3).WithTaskId(4);
EventSourceSink eventSourceSink = new EventSourceSink();
SimulatedConsole console = new SimulatedConsole();
@@ -684,13 +684,13 @@ public void TestQuietWithHighMessage()
sc.ResetColor);
L.Initialize(es);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null);
bse.BuildEventContext = buildEventContext;
es.Consume(bse);
- ProjectStartedEventArgs pse = new ProjectStartedEventArgs(1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 1, 1, 1));
+ ProjectStartedEventArgs pse = new ProjectStartedEventArgs(1, "ps", null, "fname", "", null, null, BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1));
pse.BuildEventContext = buildEventContext;
es.Consume(pse);
@@ -734,13 +734,13 @@ public void TestQuietWithError()
sc.Write, sc.SetColor, sc.ResetColor);
L.Initialize(es);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null);
bse.BuildEventContext = buildEventContext;
es.Consume(bse);
- ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 2, 3, 4));
+ ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4));
pse.BuildEventContext = buildEventContext;
es.Consume(pse);
@@ -795,13 +795,13 @@ public void TestQuietWithWarning()
sc.Write, sc.SetColor, sc.ResetColor);
L.Initialize(es);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null);
bse.BuildEventContext = buildEventContext;
es.Consume(bse);
- ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 2, 3, 4));
+ ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4));
pse.BuildEventContext = buildEventContext;
es.Consume(pse);
@@ -857,13 +857,13 @@ public void TestMinimalWithNormalMessage()
sc.ResetColor);
L.Initialize(es);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null);
bse.BuildEventContext = buildEventContext;
es.Consume(bse);
- ProjectStartedEventArgs pse = new ProjectStartedEventArgs(1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 1, 1, 1));
+ ProjectStartedEventArgs pse = new ProjectStartedEventArgs(1, "ps", null, "fname", "", null, null, BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1));
pse.BuildEventContext = buildEventContext;
es.Consume(pse);
@@ -910,13 +910,13 @@ public void TestMinimalWithError()
sc.Write, sc.SetColor, sc.ResetColor);
L.Initialize(es);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null);
bse.BuildEventContext = buildEventContext;
es.Consume(bse);
- ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 2, 3, 4));
+ ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4));
pse.BuildEventContext = buildEventContext;
es.Consume(pse);
@@ -970,13 +970,13 @@ public void TestMinimalWithWarning()
sc.Write, sc.SetColor, sc.ResetColor);
L.Initialize(es);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null);
bse.BuildEventContext = buildEventContext;
es.Consume(bse);
- ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 2, 3, 4));
+ ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4));
pse.BuildEventContext = buildEventContext;
es.Consume(pse);
@@ -1031,13 +1031,13 @@ public void TestDirectEventHandlers()
sc.Write, sc.SetColor, sc.ResetColor);
L.Initialize(es);
- BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null);
bse.BuildEventContext = buildEventContext;
L.BuildStartedHandler(null, bse);
- ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 2, 3, 4));
+ ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4));
pse.BuildEventContext = buildEventContext;
L.ProjectStartedHandler(null, pse);
@@ -1090,7 +1090,7 @@ public void CustomDisplayedAtDetailed()
L.Initialize(es);
MyCustomBuildEventArgs c = new MyCustomBuildEventArgs("msg");
- c.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ c.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(c);
@@ -1108,7 +1108,7 @@ public void CustomDisplayedAtDiagnosticMP()
MyCustomBuildEventArgs c =
new MyCustomBuildEventArgs("msg");
- c.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ c.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(c);
sc.ToString().ShouldContain("msg");
@@ -1123,7 +1123,7 @@ public void CustomNotDisplayedAtNormal()
L.Initialize(es);
MyCustomBuildEventArgs c = new MyCustomBuildEventArgs("msg");
- c.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ c.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(c);
@@ -1146,7 +1146,7 @@ private void WriteAndValidateProperties(BaseConsoleLogger cl, SimulatedConsole s
string prop3;
BuildEventArgs buildEvent = new BuildErrorEventArgs("", "", "", 0, 0, 0, 0, "", "", "");
- buildEvent.BuildEventContext = new BuildEventContext(1, 2, 3, 4);
+ buildEvent.BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
((ParallelConsoleLogger)cl).WriteProperties(buildEvent, properties);
prop1 = String.Format(CultureInfo.CurrentCulture, "{0} = {1}", "prop1", "val1");
prop2 = String.Format(CultureInfo.CurrentCulture, "{0} = {1}", "prop2", "val2");
@@ -1367,7 +1367,7 @@ private void WriteAndValidateItems(BaseConsoleLogger cl, SimulatedConsole sc, bo
string item3metadatum = string.Empty;
BuildEventArgs buildEvent = new BuildErrorEventArgs("", "", "", 0, 0, 0, 0, "", "", "");
- buildEvent.BuildEventContext = new BuildEventContext(1, 2, 3, 4);
+ buildEvent.BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
((ParallelConsoleLogger)cl).WriteItems(buildEvent, items);
item1spec = Environment.NewLine + " spec" + Environment.NewLine;
item2spec = Environment.NewLine + " spec2" + Environment.NewLine;
@@ -1424,7 +1424,7 @@ public void WriteItemsEmptyList()
SimulatedConsole sc = new SimulatedConsole();
BaseConsoleLogger cl = new ParallelConsoleLogger(LoggerVerbosity.Diagnostic, sc.Write, null, null);
BuildEventArgs buildEvent = new BuildErrorEventArgs("", "", "", 0, 0, 0, 0, "", "", "");
- buildEvent.BuildEventContext = new BuildEventContext(1, 2, 3, 4);
+ buildEvent.BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
((ParallelConsoleLogger)cl).WriteItems(buildEvent, items);
string log = sc.ToString();
@@ -1444,7 +1444,7 @@ public void WritePropertiesEmptyList()
SimulatedConsole sc = new SimulatedConsole();
var cl = new ParallelConsoleLogger(LoggerVerbosity.Diagnostic, sc.Write, null, null);
BuildEventArgs buildEvent = new BuildErrorEventArgs("", "", "", 0, 0, 0, 0, "", "", "");
- buildEvent.BuildEventContext = new BuildEventContext(1, 2, 3, 4);
+ buildEvent.BuildEventContext = BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4);
cl.WriteProperties(buildEvent, properties);
string log = sc.ToString();
@@ -1550,13 +1550,13 @@ public void ResetConsoleLoggerStateTestBasic()
// Introduce a warning
BuildWarningEventArgs bwea = new BuildWarningEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender");
- bwea.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ bwea.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(bwea);
// Introduce an error
BuildErrorEventArgs beea = new BuildErrorEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender");
- beea.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ beea.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(beea);
@@ -1637,13 +1637,13 @@ public void ResetConsoleLoggerState_Initialize()
// Introduce a warning
BuildWarningEventArgs bwea = new BuildWarningEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender");
- bwea.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ bwea.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(bwea);
// Introduce an error
BuildErrorEventArgs beea = new BuildErrorEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender");
- beea.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ beea.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(beea);
@@ -1719,8 +1719,8 @@ public void ResetConsoleLoggerState_PerformanceCounters()
// BuildStarted Event
es.Consume(new BuildStartedEventArgs("bs", null));
// Project Started Event
- ProjectStartedEventArgs project1Started = new ProjectStartedEventArgs(1, null, null, "p", "t", null, null, new BuildEventContext(BuildEventContext.InvalidNodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId));
- project1Started.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ ProjectStartedEventArgs project1Started = new ProjectStartedEventArgs(1, null, null, "p", "t", null, null, BuildEventContext.CreateInitial(0, BuildEventContext.InvalidNodeId));
+ project1Started.BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
es.Consume(project1Started);
TargetStartedEventArgs targetStarted1 = new TargetStartedEventArgs(null, null, "t", null, null);
targetStarted1.BuildEventContext = project1Started.BuildEventContext;
@@ -1748,7 +1748,7 @@ public void ResetConsoleLoggerState_PerformanceCounters()
ProjectStartedEventArgs project2Started = new ProjectStartedEventArgs(2, null, null, "p2", "t2", null, null, project1Started.BuildEventContext);
// Project Started Event
- project2Started.BuildEventContext = new BuildEventContext(2, 2, 2, 2);
+ project2Started.BuildEventContext = BuildEventContext.CreateInitial(2, 2).WithEvaluationId(2).WithProjectInstanceId(2);
es.Consume(project2Started);
TargetStartedEventArgs targetStarted2 = new TargetStartedEventArgs(null, null, "t2", null, null);
targetStarted2.BuildEventContext = project2Started.BuildEventContext;
@@ -1833,7 +1833,7 @@ public void DeferredMessages()
L.Initialize(es, 2);
es.Consume(new BuildStartedEventArgs("bs", null));
TaskCommandLineEventArgs messsage1 = new TaskCommandLineEventArgs("Message", null, MessageImportance.High);
- messsage1.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ messsage1.BuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 1).WithTargetId(1).WithProjectContextId(1).WithTaskId(1);
// Message Event
es.Consume(messsage1);
es.Consume(new BuildFinishedEventArgs("bf", null, true));
@@ -1847,7 +1847,7 @@ public void DeferredMessages()
L.Initialize(es, 2);
es.Consume(new BuildStartedEventArgs("bs", null));
BuildMessageEventArgs messsage2 = new BuildMessageEventArgs("Message", null, null, MessageImportance.High);
- messsage2.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ messsage2.BuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 1).WithTargetId(2).WithProjectContextId(3).WithTaskId(4);
// Message Event
es.Consume(messsage2);
es.Consume(new BuildFinishedEventArgs("bf", null, true));
@@ -1861,7 +1861,7 @@ public void DeferredMessages()
L.Initialize(es, 2);
es.Consume(new BuildStartedEventArgs("bs", null));
messsage2 = new BuildMessageEventArgs("Message", null, null, MessageImportance.High);
- messsage2.BuildEventContext = new BuildEventContext(1, 1, 1, 1);
+ messsage2.BuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 1).WithTargetId(2).WithProjectContextId(3).WithTaskId(4);
// Message Event
es.Consume(messsage2);
ProjectStartedEventArgs project = new ProjectStartedEventArgs(1, "Hello,", "HI", "None", "Build", null, null, messsage1.BuildEventContext);
@@ -1893,8 +1893,7 @@ public void VerifyMPLoggerSwitch()
L.Initialize(es);
}
es.Consume(new BuildStartedEventArgs("bs", null));
- BuildEventContext context = new BuildEventContext(1, 1, 1, 1);
- BuildEventContext context2 = new BuildEventContext(2, 2, 2, 2);
+ BuildEventContext context = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
ProjectStartedEventArgs project = new ProjectStartedEventArgs(1, "Hello,", "HI", "None", "Build", null, null, context);
project.BuildEventContext = context;
@@ -1923,8 +1922,8 @@ public void TestPrintTargetNamePerMessage()
ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor);
L.Initialize(es, 2);
es.Consume(new BuildStartedEventArgs("bs", null));
- BuildEventContext context = new BuildEventContext(1, 1, 1, 1);
- BuildEventContext context2 = new BuildEventContext(2, 2, 2, 2);
+ BuildEventContext context = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1);
+ BuildEventContext context2 = BuildEventContext.CreateInitial(2, 2).WithEvaluationId(2).WithProjectInstanceId(2);
ProjectStartedEventArgs project = new ProjectStartedEventArgs(1, "Hello,", "HI", "None", "Build", null, null, context);
project.BuildEventContext = context;
diff --git a/src/Build.UnitTests/Construction/SolutionFilter_Tests.cs b/src/Build.UnitTests/Construction/SolutionFilter_Tests.cs
index a779efcc5b1..632f7e23b43 100644
--- a/src/Build.UnitTests/Construction/SolutionFilter_Tests.cs
+++ b/src/Build.UnitTests/Construction/SolutionFilter_Tests.cs
@@ -27,7 +27,7 @@ public class SolutionFilter_Tests : IDisposable
{
private readonly ITestOutputHelper output;
- private static readonly BuildEventContext _buildEventContext = new BuildEventContext(0, 0, BuildEventContext.InvalidProjectContextId, 0);
+ private static readonly BuildEventContext _buildEventContext = BuildEventContext.CreateInitial(0, 0).WithProjectContextId(BuildEventContext.InvalidProjectContextId);
public SolutionFilter_Tests(ITestOutputHelper output)
{
diff --git a/src/Build.UnitTests/Construction/SolutionProjectGenerator_Tests.cs b/src/Build.UnitTests/Construction/SolutionProjectGenerator_Tests.cs
index 6f1a3f1ae91..b143bc411af 100644
--- a/src/Build.UnitTests/Construction/SolutionProjectGenerator_Tests.cs
+++ b/src/Build.UnitTests/Construction/SolutionProjectGenerator_Tests.cs
@@ -35,7 +35,7 @@ public class SolutionProjectGenerator_Tests : IDisposable
private string _originalVisualStudioVersion = null;
- private static readonly BuildEventContext _buildEventContext = new BuildEventContext(0, 0, BuildEventContext.InvalidProjectContextId, 0);
+ private static readonly BuildEventContext _buildEventContext = BuildEventContext.CreateInitial(0, 0).WithProjectContextId(BuildEventContext.InvalidProjectContextId);
private const string _longLineString = "a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-a-really-long-string-";
diff --git a/src/Build.UnitTests/Definition/ToolsVersion_Tests.cs b/src/Build.UnitTests/Definition/ToolsVersion_Tests.cs
index 23d5fc1aa63..927e0c163c4 100644
--- a/src/Build.UnitTests/Definition/ToolsVersion_Tests.cs
+++ b/src/Build.UnitTests/Definition/ToolsVersion_Tests.cs
@@ -35,7 +35,7 @@ public void OverrideTasksAreFoundInOverridePath()
using var collection = new ProjectCollection();
Toolset t = new Toolset("toolsversionname", dir, new PropertyDictionary(), collection, new DirectoryGetFiles(this.getFiles), new LoadXmlFromPath(this.loadXmlFromPath), overrideDir, new DirectoryExists(this.directoryExists));
- LoggingContext loggingContext = TestLoggingContext.CreateTestContext(new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ LoggingContext loggingContext = TestLoggingContext.CreateTestContext(BuildEventContext.CreateInitial(1, 2).WithEvaluationId(BuildEventContext.InvalidProjectContextId).WithProjectInstanceId(4));
TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(loggingContext, e.ProjectRootElementCache);
TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(loggingContext, e.ProjectRootElementCache);
@@ -81,7 +81,7 @@ public void OverrideTaskPathIsRelative()
MockLogger mockLogger = new MockLogger();
LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1);
service.RegisterLogger(mockLogger);
- LoggingContext loggingContext = new TestLoggingContext(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ LoggingContext loggingContext = new TestLoggingContext(service, BuildEventContext.CreateInitial(1, 2).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(4));
TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(loggingContext, e.ProjectRootElementCache);
@@ -101,7 +101,7 @@ public void OverrideTaskPathHasInvalidChars()
MockLogger mockLogger = new MockLogger();
LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1);
service.RegisterLogger(mockLogger);
- LoggingContext loggingContext = new TestLoggingContext(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ LoggingContext loggingContext = new TestLoggingContext(service, BuildEventContext.CreateInitial(1, 2).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(4));
TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(loggingContext, e.ProjectRootElementCache);
Assert.NotNull(taskoverrideRegistry);
@@ -120,7 +120,7 @@ public void OverrideTaskPathHasTooLongOfAPath()
MockLogger mockLogger = new MockLogger();
LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1);
service.RegisterLogger(mockLogger);
- LoggingContext loggingContext = new TestLoggingContext(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ LoggingContext loggingContext = new TestLoggingContext(service, BuildEventContext.CreateInitial(1, 2).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(4));
TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(loggingContext, e.ProjectRootElementCache);
Assert.NotNull(taskoverrideRegistry);
@@ -140,7 +140,7 @@ public void OverrideTaskPathIsNotFound()
MockLogger mockLogger = new MockLogger();
LoggingService service = (LoggingService)LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1);
service.RegisterLogger(mockLogger);
- LoggingContext loggingContext = new TestLoggingContext(service, new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ LoggingContext loggingContext = new TestLoggingContext(service, BuildEventContext.CreateInitial(1, 2).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(4));
TaskRegistry taskoverrideRegistry = (TaskRegistry)t.GetOverrideTaskRegistry(loggingContext, e.ProjectRootElementCache);
Assert.NotNull(taskoverrideRegistry);
@@ -164,7 +164,7 @@ public void DefaultTasksAreFoundInToolsPath()
null,
new DirectoryExists(this.directoryExists));
- LoggingContext loggingContext = TestLoggingContext.CreateTestContext(new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ LoggingContext loggingContext = TestLoggingContext.CreateTestContext(BuildEventContext.CreateInitial(1, 2).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(4));
TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(loggingContext, ProjectCollection.GlobalProjectCollection.ProjectRootElementCache);
string[] expectedRegisteredTasks = { "a1", "a2", "a3", "a4", "b1", "e1", "g1", "g2", "g3" };
@@ -931,7 +931,7 @@ public void InlineTasksInDotTasksFile()
null,
new DirectoryExists(directoryExists));
- LoggingContext loggingContext = TestLoggingContext.CreateTestContext(new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ LoggingContext loggingContext = TestLoggingContext.CreateTestContext(BuildEventContext.CreateInitial(1, 2).WithProjectContextId(BuildEventContext.InvalidProjectContextId).WithTaskId(4));
TaskRegistry taskRegistry = (TaskRegistry)t.GetTaskRegistry(loggingContext, ProjectCollection.GlobalProjectCollection.ProjectRootElementCache);
diff --git a/src/Build.UnitTests/Evaluation/Evaluator_Tests.cs b/src/Build.UnitTests/Evaluation/Evaluator_Tests.cs
index 7c289d90ef0..b3ef3bbda53 100644
--- a/src/Build.UnitTests/Evaluation/Evaluator_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Evaluator_Tests.cs
@@ -4497,7 +4497,7 @@ public void VerifyConditionEvaluatorResetStateOnFailure()
Directory.GetCurrentDirectory(),
MockElementLocation.Instance,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
Assert.Fail("Expect exception due to the value of property \"TargetOSFamily\" is not a number.");
}
catch (InvalidProjectFileException e)
@@ -4515,7 +4515,7 @@ public void VerifyConditionEvaluatorResetStateOnFailure()
Directory.GetCurrentDirectory(),
MockElementLocation.Instance,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4))));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4))));
}
///
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index 017537189f2..f181eeca922 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -104,7 +104,7 @@ public void ExpandAllIntoTaskItems3()
pg,
itemsByType,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
IList itemsOut = expander.ExpandIntoTaskItemsLeaveEscaped("foo;bar;@(compile);@(resource)", ExpanderOptions.ExpandPropertiesAndItems, MockElementLocation.Instance);
@@ -853,7 +853,7 @@ private Expander CreateExpander()
pg,
ig,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
return expander;
}
@@ -2372,7 +2372,7 @@ public void PropertyFunctionInCondition()
Directory.GetCurrentDirectory(),
MockElementLocation.Instance,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4))));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4))));
Assert.True(
ConditionEvaluator.EvaluateCondition(
@"'$(PathRoot.EndsWith(" + Path.DirectorySeparatorChar + "))' == 'false'",
@@ -2382,7 +2382,7 @@ public void PropertyFunctionInCondition()
Directory.GetCurrentDirectory(),
MockElementLocation.Instance,
FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4))));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4))));
}
///
@@ -5246,7 +5246,10 @@ public void FastPathValidationTest(string methodInvocationMetadata)
loggingService.RegisterLogger(logger);
var loggingContext = new MockLoggingContext(
loggingService,
- new BuildEventContext(0, 0, BuildEventContext.InvalidProjectContextId, 0, 0));
+ BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 0)
+ .WithProjectInstanceId(0)
+ .WithTargetId(0)
+ .WithTaskId(0));
_ = new Expander(
new PropertyDictionary(),
@@ -5283,7 +5286,10 @@ public void PropertyFunctionRegisterBuildCheck()
loggingService.RegisterLogger(logger);
var loggingContext = new MockLoggingContext(
loggingService,
- new BuildEventContext(0, 0, BuildEventContext.InvalidProjectContextId, 0, 0));
+ BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 0)
+ .WithProjectInstanceId(0)
+ .WithTargetId(0)
+ .WithTaskId(0));
var dummyAssemblyFile = env.CreateFile(env.CreateFolder(), "test.dll");
var result = new Expander(new PropertyDictionary(), FileSystems.Default, loggingContext)
diff --git a/src/Build.UnitTests/Evaluation/ItemSpec_Tests.cs b/src/Build.UnitTests/Evaluation/ItemSpec_Tests.cs
index 06b32c45258..68c7b7127fd 100644
--- a/src/Build.UnitTests/Evaluation/ItemSpec_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/ItemSpec_Tests.cs
@@ -93,7 +93,7 @@ private ProjectInstanceExpander CreateExpander(Dictionary item
new PropertyDictionary(),
itemDictionary,
(IFileSystem)FileSystems.Default,
- new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)));
+ new TestLoggingContext(null!, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
}
private static ItemDictionary ToItemDictionary(Dictionary itemTypes)
diff --git a/src/Build.UnitTests/Evaluation/UsedUninitializedProperties_Tests.cs b/src/Build.UnitTests/Evaluation/UsedUninitializedProperties_Tests.cs
index f9de1bc6144..63ece0629cd 100644
--- a/src/Build.UnitTests/Evaluation/UsedUninitializedProperties_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/UsedUninitializedProperties_Tests.cs
@@ -15,7 +15,7 @@ public sealed class UsedUninitializedProperties_Tests
[Fact]
public void Basics()
{
- PropertiesUseTracker props = new(TestLoggingContext.CreateTestContext(new BuildEventContext(1, 2, 3, 4)));
+ PropertiesUseTracker props = new(TestLoggingContext.CreateTestContext(BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4)));
Assert.False(props.TryGetPropertyElementLocation("Hello", out IElementLocation? elementLocation));
Assert.Null(elementLocation);
diff --git a/src/Build.UnitTests/FileLogger_Tests.cs b/src/Build.UnitTests/FileLogger_Tests.cs
index 28161a9a783..005d40996f7 100644
--- a/src/Build.UnitTests/FileLogger_Tests.cs
+++ b/src/Build.UnitTests/FileLogger_Tests.cs
@@ -58,7 +58,7 @@ public void BasicNoExistingFile()
try
{
log = FileUtilities.GetTemporaryFileName();
- SetUpFileLoggerAndLogMessage("logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ SetUpFileLoggerAndLogMessage("logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
VerifyFileContent(log, "message here");
}
finally
@@ -84,7 +84,7 @@ public void InvalidFile()
try
{
- SetUpFileLoggerAndLogMessage("logfile=||invalid||", new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ SetUpFileLoggerAndLogMessage("logfile=||invalid||", new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
}
finally
{
@@ -111,7 +111,7 @@ public void SpecificVerbosity()
fl.Parameters = "verbosity=diagnostic;logfile=" + log; // diagnostic specific setting
fl.Verbosity = LoggerVerbosity.Quiet; // quiet global setting
fl.Initialize(es);
- fl.MessageHandler(null, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ fl.MessageHandler(null, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
fl.Shutdown();
// expect message to appear because diagnostic not quiet verbosity was used
@@ -213,7 +213,7 @@ public void ValidEncoding()
try
{
log = FileUtilities.GetTemporaryFileName();
- SetUpFileLoggerAndLogMessage("encoding=utf-16;logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ SetUpFileLoggerAndLogMessage("encoding=utf-16;logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
byte[] content = ReadRawBytes(log);
// FF FE is the BOM for UTF16
@@ -240,7 +240,7 @@ public void ValidEncoding2()
try
{
log = FileUtilities.GetTemporaryFileName();
- SetUpFileLoggerAndLogMessage("encoding=utf-8;logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ SetUpFileLoggerAndLogMessage("encoding=utf-8;logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
byte[] content = ReadRawBytes(log);
// EF BB BF is the BOM for UTF8
@@ -290,7 +290,7 @@ public void BasicExistingFileNoAppend()
{
log = FileUtilities.GetTemporaryFileName();
WriteContentToFile(log);
- SetUpFileLoggerAndLogMessage("logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ SetUpFileLoggerAndLogMessage("logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
VerifyFileContent(log, "message here");
}
finally
@@ -314,7 +314,7 @@ public void BasicExistingFileAppend()
{
log = FileUtilities.GetTemporaryFileName();
WriteContentToFile(log);
- SetUpFileLoggerAndLogMessage("append;logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ SetUpFileLoggerAndLogMessage("append;logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
VerifyFileContent(log, "existing content\nmessage here");
}
finally
@@ -339,7 +339,7 @@ public void BasicNoExistingDirectory()
try
{
- SetUpFileLoggerAndLogMessage("logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = new BuildEventContext(1, 1, 1, 1) });
+ SetUpFileLoggerAndLogMessage("logfile=" + log, new BuildMessageEventArgs("message here", null, null, MessageImportance.High) { BuildEventContext = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1) });
VerifyFileContent(log, "message here");
}
finally
diff --git a/src/Build.UnitTests/Instance/ProjectInstance_Internal_Tests.cs b/src/Build.UnitTests/Instance/ProjectInstance_Internal_Tests.cs
index 2aea8c3eff2..3f56a2ee822 100644
--- a/src/Build.UnitTests/Instance/ProjectInstance_Internal_Tests.cs
+++ b/src/Build.UnitTests/Instance/ProjectInstance_Internal_Tests.cs
@@ -856,7 +856,7 @@ public void GetImportPathsAndImportPathsIncludingDuplicates(bool useDirectConstr
using ProjectCollection projectCollection = new ProjectCollection();
BuildParameters buildParameters = new BuildParameters(projectCollection) { ProjectLoadSettings = projectLoadSettings };
- BuildEventContext buildEventContext = new BuildEventContext(0, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(BuildEventContext.InvalidProjectContextId).WithProjectInstanceId(BuildEventContext.InvalidTaskId);
using ProjectRootElementFromString projectRootElementFromString = new(projectFileContent);
ProjectRootElement rootElement = projectRootElementFromString.Project;
diff --git a/src/Build.UnitTests/Telemetry/Telemetry_Tests.cs b/src/Build.UnitTests/Telemetry/Telemetry_Tests.cs
index 59dd45747a3..803d95bb80d 100644
--- a/src/Build.UnitTests/Telemetry/Telemetry_Tests.cs
+++ b/src/Build.UnitTests/Telemetry/Telemetry_Tests.cs
@@ -492,7 +492,10 @@ public void TelemetryCollector_AccumulatesAndSendsOnFinalize()
var loggingContext = new MockLoggingContext(
loggingService,
- new BuildEventContext(1, 2, BuildEventContext.InvalidProjectContextId, 4));
+ BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 1)
+ .WithProjectInstanceId(2)
+ .WithProjectContextId(BuildEventContext.InvalidProjectContextId)
+ .WithTargetId(4));
// Add data via the collector API.
var key = new TaskOrTargetTelemetryKey("TestTarget", isCustom: true, isFromNugetCache: false, isFromMetaProject: false);
diff --git a/src/Build.UnitTests/TerminalLogger_Tests.cs b/src/Build.UnitTests/TerminalLogger_Tests.cs
index 6b3c22897ad..eac632cc60d 100644
--- a/src/Build.UnitTests/TerminalLogger_Tests.cs
+++ b/src/Build.UnitTests/TerminalLogger_Tests.cs
@@ -247,14 +247,12 @@ public void CreateTerminalOrConsoleLogger_ParsesVerbosity(string? argsString, Lo
///
private BuildEventContext MakeBuildEventContext(int evalId = 1, int projectContextId = 1, int nodeId = 1)
{
- return new BuildEventContext(
- submissionId: -1,
- nodeId: nodeId,
- evaluationId: evalId,
- projectInstanceId: -1,
- projectContextId: projectContextId,
- targetId: 1,
- taskId: 1);
+ return BuildEventContext.CreateInitial(-1, nodeId)
+ .WithEvaluationId(evalId)
+ .WithProjectInstanceId(-1)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(1)
+ .WithTaskId(1);
}
private BuildStartedEventArgs MakeBuildStartedEventArgs(BuildEventContext? buildEventContext = null)
@@ -720,7 +718,7 @@ public Task LogEvaluationErrorFromEngine()
"MSB0001", "EvaluationError", "MSBUILD", 0, 0, 0, 0,
"An error occurred during evaluation.", null, null)
{
- BuildEventContext = new BuildEventContext(1, -1, -1, -1) // context that belongs to no project
+ BuildEventContext = BuildEventContext.CreateInitial(1, -1).WithEvaluationId(-1).WithProjectInstanceId(-1) // context that belongs to no project
});
});
diff --git a/src/Build/BackEnd/BuildManager/BuildManager.cs b/src/Build/BackEnd/BuildManager/BuildManager.cs
index 3a871f1cca4..c5d493ce358 100644
--- a/src/Build/BackEnd/BuildManager/BuildManager.cs
+++ b/src/Build/BackEnd/BuildManager/BuildManager.cs
@@ -1638,13 +1638,7 @@ internal void ExecuteSubmission(
where TResultData : BuildResultBase
{
// For the current submission we only know the SubmissionId and that it happened on scheduler node - all other BuildEventContext dimensions are unknown now.
- BuildEventContext buildEventContext = new BuildEventContext(
- submission.SubmissionId,
- nodeId: 1,
- BuildEventContext.InvalidProjectInstanceId,
- BuildEventContext.InvalidProjectContextId,
- BuildEventContext.InvalidTargetId,
- BuildEventContext.InvalidTaskId);
+ BuildEventContext buildEventContext = submission.BuildEventContext;
BuildSubmissionStartedEventArgs submissionStartedEvent = new(
submission.BuildRequestDataBase.GlobalPropertiesLookup,
@@ -1732,7 +1726,7 @@ private void LoadSolutionIntoConfiguration(BuildRequestConfiguration config, Bui
var buildEventContext = request.BuildEventContext;
if (buildEventContext == BuildEventContext.Invalid)
{
- buildEventContext = new BuildEventContext(request.SubmissionId, 0, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ buildEventContext = BuildEventContext.CreateForSubmission(request.SubmissionId);
}
var instances = ProjectInstance.LoadSolutionForBuild(
@@ -1994,7 +1988,7 @@ void LogInvalidProjectFileError(InvalidProjectFileException projectException)
{
if (!projectException.HasBeenLogged)
{
- BuildEventContext buildEventContext = new BuildEventContext(submission.SubmissionId, 1, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ BuildEventContext buildEventContext = CreateErrorLoggingContext(submission.SubmissionId);
((IBuildComponentHost)this).LoggingService.LogInvalidProjectFileError(buildEventContext, projectException);
projectException.HasBeenLogged = true;
}
@@ -2016,6 +2010,13 @@ private void WaitForAllLoggingServiceEventsToBeProcessed()
((LoggingService)((IBuildComponentHost)this).LoggingService).WaitForLoggingToProcessEvents();
}
+ ///
+ /// Creates a BuildEventContext suitable for error logging for the given submission.
+ ///
+ /// The submission ID
+ /// A BuildEventContext for logging errors
+ private static BuildEventContext CreateErrorLoggingContext(int submissionId) => BuildEventContext.CreateForSubmission(submissionId);
+
private static void AddBuildRequestToSubmission(BuildSubmission submission, int configurationId, int projectContextId = BuildEventContext.InvalidProjectContextId)
{
submission.BuildRequest = new BuildRequest(
@@ -2103,7 +2104,7 @@ void IssueBuildSubmissionToSchedulerImpl(BuildSubmission submission, bool allowM
{
if (!projectException.HasBeenLogged)
{
- BuildEventContext projectBuildEventContext = new BuildEventContext(submission.SubmissionId, 1, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ BuildEventContext projectBuildEventContext = CreateErrorLoggingContext(submission.SubmissionId);
((IBuildComponentHost)this).LoggingService.LogInvalidProjectFileError(projectBuildEventContext, projectException);
projectException.HasBeenLogged = true;
}
@@ -2119,7 +2120,7 @@ void IssueBuildSubmissionToSchedulerImpl(BuildSubmission submission, bool allowM
if (ex is not InvalidProjectFileException)
{
- var buildEventContext = new BuildEventContext(submission.SubmissionId, 1, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ var buildEventContext = CreateErrorLoggingContext(submission.SubmissionId);
((IBuildComponentHost)this).LoggingService.LogFatalBuildError(buildEventContext, ex, new BuildEventFileInfo(submission.BuildRequestData.ProjectFullPath));
}
}
@@ -2177,14 +2178,7 @@ private void ExecuteGraphBuildScheduler(GraphBuildSubmission submission)
null,
_buildParameters,
((IBuildComponentHost)this).LoggingService,
- new BuildEventContext(
- submission.SubmissionId,
- _buildParameters.NodeId,
- BuildEventContext.InvalidEvaluationId,
- BuildEventContext.InvalidProjectInstanceId,
- BuildEventContext.InvalidProjectContextId,
- BuildEventContext.InvalidTargetId,
- BuildEventContext.InvalidTaskId),
+ BuildEventContext.CreateInitial(submission.SubmissionId, _buildParameters.NodeId),
SdkResolverService,
submission.SubmissionId,
projectLoadSettings);
@@ -2713,7 +2707,9 @@ private void HandleResult(int node, BuildResult result)
{
BuildEventContext buildEventContext = _projectStartedEvents.TryGetValue(result.SubmissionId, out BuildEventArgs? buildEventArgs)
? buildEventArgs.BuildEventContext!
- : new BuildEventContext(result.SubmissionId, node, configuration.Project?.EvaluationId ?? BuildEventContext.InvalidEvaluationId, configuration.ConfigurationId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ : BuildEventContext.CreateInitial(result.SubmissionId, node)
+ .WithEvaluationId(configuration.ProjectEvaluationId)
+ .WithProjectInstanceId(configuration.ConfigurationId);
try
{
_projectCacheService.HandleBuildResultAsync(configuration, result, buildEventContext, _executionCancellationTokenSource!.Token).Wait();
@@ -2752,9 +2748,8 @@ private void HandleNodeShutdown(int node, NodeShutdown shutdownPacket)
ILoggingService loggingService = ((IBuildComponentHost)this).GetComponent(BuildComponentType.LoggingService);
foreach (BuildSubmissionBase submission in _buildSubmissions.Values)
{
- BuildEventContext buildEventContext = new BuildEventContext(submission.SubmissionId, BuildEventContext.InvalidNodeId, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
string exception = DebugUtils.ReadAnyExceptionFromFile(_instantiationTimeUtc);
- loggingService?.LogError(buildEventContext, new BuildEventFileInfo(string.Empty) /* no project file */, "ChildExitedPrematurely", node, DebugUtils.DebugDumpPath, exception);
+ loggingService?.LogError(submission.BuildEventContext, new BuildEventFileInfo(string.Empty) /* no project file */, "ChildExitedPrematurely", node, DebugUtils.DebugDumpPath, exception);
}
}
else if (shutdownPacket.Reason == NodeShutdownReason.Error && _buildSubmissions.Values.Count == 0)
@@ -2908,7 +2903,7 @@ private void PerformSchedulingActions(IEnumerable responses)
if (newNodes?.Count != response.NumberOfNodesToCreate || newNodes.Any(n => n == null))
{
- BuildEventContext buildEventContext = new BuildEventContext(0, Scheduler.VirtualNode, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ BuildEventContext buildEventContext = BuildEventContext.CreateForSubmission(0);
((IBuildComponentHost)this).LoggingService.LogError(buildEventContext, new BuildEventFileInfo(String.Empty), "UnableToCreateNode", response.RequiredNodeType.ToString("G"));
throw new BuildAbortedException(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("UnableToCreateNode", response.RequiredNodeType.ToString("G")));
diff --git a/src/Build/BackEnd/BuildManager/BuildSubmissionBase.cs b/src/Build/BackEnd/BuildManager/BuildSubmissionBase.cs
index 8195c79aa0e..7b3921c8c04 100644
--- a/src/Build/BackEnd/BuildManager/BuildSubmissionBase.cs
+++ b/src/Build/BackEnd/BuildManager/BuildSubmissionBase.cs
@@ -3,6 +3,7 @@
using System;
using System.Threading;
+using Microsoft.Build.BackEnd;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Execution
@@ -43,6 +44,7 @@ protected internal BuildSubmissionBase(BuildManager buildManager, int submission
CompletionEvent = new ManualResetEvent(false);
LoggingCompleted = false;
CompletionInvoked = 0;
+ BuildEventContext = Framework.BuildEventContext.CreateInitial(submissionId, Scheduler.VirtualNode);
}
///
@@ -55,6 +57,11 @@ protected internal BuildSubmissionBase(BuildManager buildManager, int submission
///
public int SubmissionId { get; }
+ ///
+ /// The build event context for this submission. This will have the submission ID set, and a nodeId of the scheduler's virtual node..
+ ///
+ public Framework.BuildEventContext BuildEventContext { get; }
+
///
/// The asynchronous context provided to , if any.
///
diff --git a/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs b/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs
index baccd0cdf14..4d2fb4e9f91 100644
--- a/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs
+++ b/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs
@@ -862,6 +862,7 @@ private void EvaluateRequestStates()
completedEntry.Result.DefaultTargets = configuration.ProjectDefaultTargets;
completedEntry.Result.InitialTargets = configuration.ProjectInitialTargets;
completedEntry.Result.ProjectTargets = configuration.ProjectTargets;
+ completedEntry.Result.EvaluationId = configuration.ProjectEvaluationId;
}
TraceEngine("ERS: Request is now {0}({1}) (nr {2}) has had its builder cleaned up.", completedEntry.Request.GlobalRequestId, completedEntry.Request.ConfigurationId, completedEntry.Request.NodeRequestId);
diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs
index 360b60d70b8..f0d755ebe45 100644
--- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs
+++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs
@@ -356,7 +356,7 @@ bool TryReuseAnyFromPossibleRunningNodes(int currentProcessId, int nodeId)
string msg = ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("NodeReused", nodeId, nodeToReuse.Id);
_componentHost.LoggingService.LogBuildEvent(new BuildMessageEventArgs(msg, null, null, MessageImportance.Low)
{
- BuildEventContext = new BuildEventContext(nodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId)
+ BuildEventContext = BuildEventContext.CreateInitial(0 /* submission ID */, nodeId)
});
CreateNodeContext(nodeId, nodeToReuse, nodeStream, result.NegotiatedPacketVersion);
diff --git a/src/Build/BackEnd/Components/Logging/EvaluationLoggingContext.cs b/src/Build/BackEnd/Components/Logging/EvaluationLoggingContext.cs
index ff39ef63976..d92f0f212cb 100644
--- a/src/Build/BackEnd/Components/Logging/EvaluationLoggingContext.cs
+++ b/src/Build/BackEnd/Components/Logging/EvaluationLoggingContext.cs
@@ -20,7 +20,7 @@ internal class EvaluationLoggingContext : LoggingContext
public EvaluationLoggingContext(ILoggingService loggingService, BuildEventContext buildEventContext, string projectFile)
: base(
loggingService,
- loggingService.CreateEvaluationBuildEventContext(buildEventContext.NodeId, buildEventContext.SubmissionId))
+ loggingService.CreateEvaluationBuildEventContext(buildEventContext))
{
_projectFile = projectFile;
IsValid = true;
diff --git a/src/Build/BackEnd/Components/Logging/ILoggingService.cs b/src/Build/BackEnd/Components/Logging/ILoggingService.cs
index 822b29f9a1b..68297ec1892 100644
--- a/src/Build/BackEnd/Components/Logging/ILoggingService.cs
+++ b/src/Build/BackEnd/Components/Logging/ILoggingService.cs
@@ -513,20 +513,17 @@ MessageImportance MinimumRequiredMessageImportance
///
/// Create an evaluation context, by generating a new evaluation id.
///
- /// The node id
- /// The submission id
+ /// The parent context to derive the new evaluation context from
///
- BuildEventContext CreateEvaluationBuildEventContext(int nodeId, int submissionId);
+ BuildEventContext CreateEvaluationBuildEventContext(BuildEventContext parentContext);
///
- /// Create a project cache context, by generating a new project context id.
+ /// Create a project-level build event context, by generating a new project context id and applying it to a parent context scope.
///
- /// The submission id
- /// The evaluation id
- /// The project instance id
+ /// The parent context to derive the new project cache context from
/// Project file being built
///
- BuildEventContext CreateProjectCacheBuildEventContext(int submissionId, int evaluationId, int projectInstanceId, string projectFile);
+ BuildEventContext CreateProjectCacheBuildEventContext(BuildEventContext parentBuildEventContext, string projectFile);
///
/// Logs that a project evaluation has started
@@ -554,45 +551,58 @@ void LogProjectEvaluationFinished(
IEnumerable items,
ProfilerResult? profilerResult);
+ void LogProjectStarted(ProjectStartedEventArgs args);
+
///
- /// Log that a project has started
- ///
- /// The logging context of the node which is building this project.
- /// The id of the build submission.
- /// The id of the project configuration which is about to start
- /// The build context of the parent project which asked this project to build
- /// The project file path of the project about to be built
- /// The entrypoint target names for this project
- /// The initial properties of the project
- /// The initial items of the project
- /// EvaluationId of the project instance
- /// The project context id
- /// The BuildEventContext to use for this project.
- BuildEventContext LogProjectStarted(
- BuildEventContext nodeBuildEventContext,
- int submissionId,
- int configurationId,
+ /// Creates a ProjectStartedEventArgs for a locally-building project -
+ /// meaning one that is not served from cache and is building on the current node.
+ ///
+ /// The parent build event context for the project that is starting.
+ /// The configuration ID of the project that is starting.
+ /// The project file path of the project that is starting.
+ /// The target names that are being built.
+ /// The global properties for the project instance.
+ /// The initial properties for the project instance, if any.
+ /// The initial items for the project instance, if any.
+ /// The tools version for the project instance.
+ ///
+ /// We _could_ pass in BuildRequest/BuildRequestConfiguration for most of this data, but that makes layering/dependency
+ /// tracking of the namespaces more complex, and we don't really need the full objects here.
+ ///
+ ProjectStartedEventArgs CreateProjectStartedForLocalProject(
BuildEventContext parentBuildEventContext,
+ int configurationId,
string projectFile,
string targetNames,
+ IDictionary globalProperties,
IEnumerable properties,
IEnumerable items,
- int evaluationId = BuildEventContext.InvalidEvaluationId,
- int projectContextId = BuildEventContext.InvalidProjectContextId);
-
- void LogProjectStarted(ProjectStartedEventArgs args);
-
- ProjectStartedEventArgs CreateProjectStarted(
- BuildEventContext nodeBuildEventContext,
- int submissionId,
- int configurationId,
+ string toolsVersion);
+
+ ///
+ /// Creates a ProjectStartedEventArgs for a project that was already built on another node, so
+ /// is being served from cache. Unlike the local-build case, we don't have properties/items
+ /// because they were not deserialized from the cache.
+ ///
+ /// The build event context on the current node.
+ /// The complete evaluation build event context on the remote node.
+ /// The parent build event context for the project that is already built.
+ /// The global properties for the project instance, from the configuration.
+ /// The project file path of the project that is already built.
+ /// The target names that were built.
+ /// The tools version for the project instance.
+ ///
+ /// We _could_ pass in BuildRequest/BuildRequestConfiguration for most of this data, but that makes layering/dependency
+ /// tracking of the namespaces more complex, and we don't really need the full objects here.
+ ///
+ ProjectStartedEventArgs CreateProjectStartedForCachedProject(
+ BuildEventContext currentNodeBuildEventContext,
+ BuildEventContext remoteNodeEvaluationBuildEventContext,
BuildEventContext parentBuildEventContext,
+ IDictionary globalProperties,
string projectFile,
string targetNames,
- IEnumerable properties,
- IEnumerable items,
- int evaluationId = BuildEventContext.InvalidEvaluationId,
- int projectContextId = BuildEventContext.InvalidProjectContextId);
+ string toolsVersion);
///
/// Log that the project has finished
diff --git a/src/Build/BackEnd/Components/Logging/LoggingServiceLogMethods.cs b/src/Build/BackEnd/Components/Logging/LoggingServiceLogMethods.cs
index 31c9f55eeb0..a4a5dbdbcd4 100644
--- a/src/Build/BackEnd/Components/Logging/LoggingServiceLogMethods.cs
+++ b/src/Build/BackEnd/Components/Logging/LoggingServiceLogMethods.cs
@@ -401,14 +401,12 @@ public void LogBuildCanceled()
}
///
- public BuildEventContext CreateEvaluationBuildEventContext(int nodeId, int submissionId)
- => new BuildEventContext(submissionId, nodeId, NextEvaluationId, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ public BuildEventContext CreateEvaluationBuildEventContext(BuildEventContext parentContext)
+ => parentContext.WithEvaluationId(NextEvaluationId);
///
public BuildEventContext CreateProjectCacheBuildEventContext(
- int submissionId,
- int evaluationId,
- int projectInstanceId,
+ BuildEventContext parentBuildEventContext,
string projectFile)
{
int projectContextId = NextProjectId;
@@ -416,11 +414,8 @@ public BuildEventContext CreateProjectCacheBuildEventContext(
// In the future if some LogProjectCacheStarted event is created, move this there to align with evaluation and build execution.
_projectFileMap[projectContextId] = projectFile;
- // Because the project cache runs in the BuildManager, it makes some sense to associate logging with the in-proc node.
- // If a invalid node id is used the messages become deferred in the console logger and spit out at the end.
- int nodeId = Scheduler.InProcNodeId;
-
- return new BuildEventContext(submissionId, nodeId, evaluationId, projectInstanceId, projectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ return parentBuildEventContext
+ .WithProjectContextId(projectContextId);
}
///
@@ -470,115 +465,28 @@ public void LogProjectEvaluationFinished(
ProcessLoggingEvent(buildEvent);
}
- ///
- /// Logs that a project build has started
- ///
- /// The event context of the node which is spawning this project.
- /// The id of the submission.
- /// The id of the project configuration which is about to start
- /// BuildEventContext of the project who is requesting "projectFile" to build
- /// Project file to build
- /// Target names to build
- /// Initial property list
- /// Initial items list
- /// EvaluationId of the project instance
- /// The project context id
- /// The build event context for the project.
- /// parentBuildEventContext is null
- /// projectBuildEventContext is null
- public BuildEventContext LogProjectStarted(
- BuildEventContext nodeBuildEventContext,
- int submissionId,
- int configurationId,
- BuildEventContext parentBuildEventContext,
- string projectFile,
- string targetNames,
- IEnumerable properties,
- IEnumerable items,
- int evaluationId = BuildEventContext.InvalidEvaluationId,
- int projectContextId = BuildEventContext.InvalidProjectContextId)
- {
- var args = CreateProjectStarted(nodeBuildEventContext,
- submissionId,
- configurationId,
- parentBuildEventContext,
- projectFile,
- targetNames,
- properties,
- items,
- evaluationId,
- projectContextId);
-
- this.LogProjectStarted(args);
-
- return args.BuildEventContext;
- }
-
public void LogProjectStarted(ProjectStartedEventArgs buildEvent)
{
ProcessLoggingEvent(buildEvent);
}
- public ProjectStartedEventArgs CreateProjectStarted(
- BuildEventContext nodeBuildEventContext,
- int submissionId,
- int configurationId,
+ ///
+ public ProjectStartedEventArgs CreateProjectStartedForLocalProject(
BuildEventContext parentBuildEventContext,
+ int configurationId,
string projectFile,
string targetNames,
+ IDictionary globalProperties,
IEnumerable properties,
IEnumerable items,
- int evaluationId = BuildEventContext.InvalidEvaluationId,
- int projectContextId = BuildEventContext.InvalidProjectContextId)
+ string toolsVersion)
{
- ErrorUtilities.VerifyThrow(nodeBuildEventContext != null, "Need a nodeBuildEventContext");
-
- if (projectContextId == BuildEventContext.InvalidProjectContextId)
- {
- projectContextId = NextProjectId;
-
- // PERF: Not using VerifyThrow to avoid boxing of projectBuildEventContext.ProjectContextId in the non-error case.
- if (_projectFileMap.ContainsKey(projectContextId))
- {
- ErrorUtilities.ThrowInternalError("ContextID {0} for project {1} should not already be in the ID-to-file mapping!", projectContextId, projectFile);
- }
-
- _projectFileMap[projectContextId] = projectFile;
- }
- else
- {
- // A projectContextId was provided, so use it with some sanity checks
- if (_projectFileMap.TryGetValue(projectContextId, out string existingProjectFile))
- {
- if (!projectFile.Equals(existingProjectFile, StringComparison.OrdinalIgnoreCase))
- {
- ErrorUtilities.ThrowInternalError("ContextID {0} was already in the ID-to-project file mapping but the project file {1} did not match the provided one {2}!", projectContextId, existingProjectFile, projectFile);
- }
- }
- else
- {
- // Currently, an existing projectContextId can only be provided in the project cache scenario, which runs on the in-proc node.
- // If there was a cache miss and the build was scheduled on a worker node, it may not have seen this projectContextId yet.
- // So we only need this sanity check for the in-proc node.
- if (nodeBuildEventContext.NodeId == Scheduler.InProcNodeId)
- {
- ErrorUtilities.ThrowInternalError("ContextID {0} should have been in the ID-to-project file mapping but wasn't!", projectContextId);
- }
-
- _projectFileMap[projectContextId] = projectFile;
- }
- }
-
- BuildEventContext projectBuildEventContext = new BuildEventContext(submissionId, nodeBuildEventContext.NodeId, evaluationId, configurationId, projectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ var projectContextId = GenerateNewProjectContextId(projectFile);
ErrorUtilities.VerifyThrow(parentBuildEventContext != null, "Need a parentBuildEventContext");
-
- ErrorUtilities.VerifyThrow(_configCache.Value.HasConfiguration(configurationId), "Cannot find the project configuration while injecting non-serialized data from out-of-proc node.");
- var buildRequestConfiguration = _configCache.Value[configurationId];
-
- // Always log GlobalProperties on ProjectStarted
- // See https://github.com/dotnet/msbuild/issues/6341 for details
- IDictionary globalProperties = buildRequestConfiguration.GlobalProperties.ToDictionary();
+ BuildEventContext projectBuildEventContext = parentBuildEventContext
+ .WithProjectInstanceId(configurationId)
+ .WithProjectContextId(projectContextId);
var buildEvent = new ProjectStartedEventArgs(
configurationId,
@@ -590,12 +498,118 @@ public ProjectStartedEventArgs CreateProjectStarted(
items,
parentBuildEventContext,
globalProperties,
- buildRequestConfiguration.ToolsVersion);
+ toolsVersion);
buildEvent.BuildEventContext = projectBuildEventContext;
return buildEvent;
}
+ ///
+ /// Ensures that the projectContextId is valid and updates the project file map to track which contexts apply to which project files.
+ ///
+ /// The project file path to be associated with this project context ID.
+ /// The project context ID to use (either the provided one or a newly generated one).
+ private int GenerateNewProjectContextId(string projectFile)
+ {
+ var generatedProjectContextId = NextProjectId;
+
+ // PERF: Not using VerifyThrow to avoid boxing of projectBuildEventContext.ProjectContextId in the non-error case.
+ if (_projectFileMap.ContainsKey(generatedProjectContextId))
+ {
+ ErrorUtilities.ThrowInternalError("ContextID {0} for project {1} should not already be in the ID-to-file mapping!", generatedProjectContextId, projectFile);
+ }
+
+ _projectFileMap[generatedProjectContextId] = projectFile;
+ return generatedProjectContextId;
+ }
+
+ ///
+ /// Validates that a preexisting projectContextId is valid and updates the project file map to track which contexts apply to which project files.
+ ///
+ /// The remote node evaluation context containing the project context ID to validate.
+ /// The project file path to be associated with this project context ID.
+ /// The node ID of the current node - used to validate that only the in-proc scheduler node is re-using cached project context IDs.
+ /// Either the same context, if the projectContextId exists in the map already, or a new context with a generated projectContextId if it did not.
+ private BuildEventContext ValidatePreexistingProjectContextId(BuildEventContext remoteNodeEvaluationContext, string projectFile, int currentNodeId)
+ {
+ if (remoteNodeEvaluationContext.ProjectContextId == BuildEventContext.InvalidProjectContextId)
+ {
+ // No projectContextId was provided, so generate a new one to represent this invocation of the project
+ int newProjectContextId = GenerateNewProjectContextId(projectFile);
+ return remoteNodeEvaluationContext.WithProjectContextId(newProjectContextId);
+ }
+
+ // A projectContextId was provided, so use it with some sanity checks
+ else if (_projectFileMap.TryGetValue(remoteNodeEvaluationContext.ProjectContextId, out string existingProjectFile))
+ {
+ if (!projectFile.Equals(existingProjectFile, StringComparison.OrdinalIgnoreCase))
+ {
+ ErrorUtilities.ThrowInternalError("ContextID {0} was already in the ID-to-project file mapping but the project file {1} did not match the provided one {2}!", remoteNodeEvaluationContext.ProjectContextId, existingProjectFile, projectFile);
+ }
+ return remoteNodeEvaluationContext;
+ }
+ else
+ {
+ // Currently, an existing projectContextId can only be provided in the project cache scenario, which runs on the in-proc node.
+ // If there was a cache miss and the build was scheduled on a worker node, it may not have seen this projectContextId yet.
+ // So we only need this sanity check for the in-proc node.
+ if (currentNodeId == Scheduler.InProcNodeId)
+ {
+ ErrorUtilities.ThrowInternalError("ContextID {0} should have been in the ID-to-project file mapping but wasn't!", remoteNodeEvaluationContext.ProjectContextId);
+ }
+
+ _projectFileMap[remoteNodeEvaluationContext.ProjectContextId] = projectFile;
+ return remoteNodeEvaluationContext;
+ }
+ }
+
+ ///
+ public ProjectStartedEventArgs CreateProjectStartedForCachedProject(
+ BuildEventContext currentNodeBuildEventContext,
+ BuildEventContext remoteNodeEvaluationBuildEventContext,
+ BuildEventContext parentBuildEventContext,
+ IDictionary globalProperties,
+ string projectFile,
+ string targetNames,
+ string toolsVersion)
+ {
+ // Cached project events can be logged from either:
+ // 1. The scheduler's virtual node (when the scheduler serves a request from cache)
+ // 2. A worker node (when BuildRequestEngine satisfies a request from its local cache)
+ BuildEventContext validatedRemoteNodeEvaluationBuildContext = ValidatePreexistingProjectContextId(
+ remoteNodeEvaluationBuildEventContext,
+ projectFile,
+ currentNodeBuildEventContext.NodeId);
+
+ int configurationId = remoteNodeEvaluationBuildEventContext.ProjectInstanceId;
+
+ // we need to be a valid BuildEventContext for a ProjectLoggingContext out of this, so we need to make sure
+ // we have ProjectContextId set. We derive from the validated remote context rather than the parent
+ // to preserve submissionId, nodeId, and evaluationId - which are needed for the OnProjectFinished
+ // handler to find the submission and call CompleteLogging().
+ BuildEventContextBuilder thisEventBuildEventContext = validatedRemoteNodeEvaluationBuildContext
+ .WithTargetId(BuildEventContext.InvalidTargetId)
+ .WithTaskId(BuildEventContext.InvalidTaskId);
+
+ ProjectStartedEventArgs buildEvent = new(
+ projectId: configurationId,
+ message: null,
+ helpKeyword: null,
+ projectFile: projectFile,
+ targetNames: targetNames,
+ properties: null, // Do not log properties on cached project builds - callers must look up from the 'real' ProjectStartedEventArgs if needed
+ items: null, // Do not log items on cached project builds - callers must look up from the 'real' ProjectStartedEventArgs if needed
+ parentBuildEventContext: parentBuildEventContext,
+ globalProperties: globalProperties,
+ toolsVersion: toolsVersion,
+ originalBuildEventContext: validatedRemoteNodeEvaluationBuildContext)
+ {
+ BuildEventContext = thisEventBuildEventContext,
+ };
+
+ return buildEvent;
+ }
+
///
/// Logs that a project has finished
///
@@ -641,13 +655,7 @@ public void LogProjectFinished(BuildEventContext projectBuildEventContext, strin
public BuildEventContext LogTargetStarted(BuildEventContext projectBuildEventContext, string targetName, string projectFile, string projectFileOfTargetElement, string parentTargetName, TargetBuiltReason buildReason)
{
ErrorUtilities.VerifyThrow(projectBuildEventContext != null, "projectBuildEventContext is null");
- BuildEventContext targetBuildEventContext = new BuildEventContext(
- projectBuildEventContext.SubmissionId,
- projectBuildEventContext.NodeId,
- projectBuildEventContext.ProjectInstanceId,
- projectBuildEventContext.ProjectContextId,
- NextTargetId,
- BuildEventContext.InvalidTaskId);
+ BuildEventContext targetBuildEventContext = projectBuildEventContext.WithTargetId(NextTargetId);
if (!OnlyLogCriticalEvents)
{
@@ -738,13 +746,7 @@ public void LogTaskStarted(BuildEventContext taskBuildEventContext, string taskN
public BuildEventContext LogTaskStarted2(BuildEventContext targetBuildEventContext, string taskName, string projectFile, string projectFileOfTaskNode, int line, int column, string taskAssemblyLocation)
{
ErrorUtilities.VerifyThrow(targetBuildEventContext != null, "targetBuildEventContext is null");
- BuildEventContext taskBuildEventContext = new BuildEventContext(
- targetBuildEventContext.SubmissionId,
- targetBuildEventContext.NodeId,
- targetBuildEventContext.ProjectInstanceId,
- targetBuildEventContext.ProjectContextId,
- targetBuildEventContext.TargetId,
- NextTaskId);
+ BuildEventContext taskBuildEventContext = targetBuildEventContext.WithTaskId(NextTaskId);
if (!OnlyLogCriticalEvents)
{
diff --git a/src/Build/BackEnd/Components/Logging/NodeLoggingContext.cs b/src/Build/BackEnd/Components/Logging/NodeLoggingContext.cs
index d1d202fbb74..87a8990edd0 100644
--- a/src/Build/BackEnd/Components/Logging/NodeLoggingContext.cs
+++ b/src/Build/BackEnd/Components/Logging/NodeLoggingContext.cs
@@ -19,10 +19,11 @@ internal class NodeLoggingContext : BuildLoggingContext
/// Used to create the initial, base logging context for the node.
///
/// The logging service to use.
+ /// The parent build event context to associate this node logging context with
/// The
/// true if this is an in-process node, otherwise false.
- internal NodeLoggingContext(ILoggingService loggingService, int nodeId, bool inProcNode)
- : base(loggingService, new BuildEventContext(nodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId), inProcNode)
+ internal NodeLoggingContext(ILoggingService loggingService, BuildEventContext parentContext, int nodeId, bool inProcNode)
+ : base(loggingService, parentContext.WithNodeId(nodeId), inProcNode)
{
ErrorUtilities.VerifyThrow(nodeId != BuildEventContext.InvalidNodeId, "Should not ever be given an invalid NodeId");
@@ -73,23 +74,20 @@ internal ProjectLoggingContext LogProjectStarted(BuildRequestEntry requestEntry)
internal (ProjectStartedEventArgs, ProjectLoggingContext) CreateProjectLoggingContext(BuildRequestEntry requestEntry)
{
ErrorUtilities.VerifyThrow(this.IsValid, "Build not started.");
- return ProjectLoggingContext.CreateLoggingContext(this, requestEntry);
+ return ProjectLoggingContext.CreateForLocalBuild(this, requestEntry);
}
///
- /// Log that a project has started if it is serviced from the cache
+ /// Log that a project has started if it is serviced from the cache.
+ /// Uses cache-specific pathway that immediately logs ProjectStarted with minimal data.
///
/// The build request.
/// The configuration used to build the request.
- /// The BuildEventContext to use for this project.
- internal ProjectLoggingContext LogProjectStarted(BuildRequest request, BuildRequestConfiguration configuration)
+ /// The ProjectLoggingContext for this cached project.
+ internal ProjectLoggingContext LogProjectStartedFromCache(BuildRequest request, BuildRequestConfiguration configuration)
{
ErrorUtilities.VerifyThrow(this.IsValid, "Build not started.");
-
- // Use the persisted ProjectEvaluationId which remains available even when the project is cached.
- int evaluationId = configuration?.ProjectEvaluationId ?? BuildEventContext.InvalidEvaluationId;
-
- return new ProjectLoggingContext(this, request, configuration.ProjectFullPath, configuration.ToolsVersion, evaluationId);
+ return ProjectLoggingContext.CreateForCacheBuild(this, request, configuration);
}
///
@@ -98,7 +96,7 @@ internal ProjectLoggingContext LogProjectStarted(BuildRequest request, BuildRequ
///
internal void LogRequestHandledFromCache(BuildRequest request, BuildRequestConfiguration configuration, BuildResult result)
{
- ProjectLoggingContext projectLoggingContext = LogProjectStarted(request, configuration);
+ ProjectLoggingContext projectLoggingContext = LogProjectStartedFromCache(request, configuration);
// When pulling a request from the cache, we want to make sure we log a target skipped event for any targets which
// were used to build the request including default and initial targets.
diff --git a/src/Build/BackEnd/Components/Logging/ProjectLoggingContext.cs b/src/Build/BackEnd/Components/Logging/ProjectLoggingContext.cs
index 6f467e25d9b..eeb80c08f56 100644
--- a/src/Build/BackEnd/Components/Logging/ProjectLoggingContext.cs
+++ b/src/Build/BackEnd/Components/Logging/ProjectLoggingContext.cs
@@ -3,7 +3,6 @@
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
using Microsoft.Build.Collections;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
@@ -31,231 +30,190 @@ internal class ProjectLoggingContext : BuildLoggingContext
private readonly ProjectTelemetry _projectTelemetry = new ProjectTelemetry();
///
- /// Constructs a project logging context.
+ /// Private constructor - use factory methods instead.
///
- internal ProjectLoggingContext(NodeLoggingContext nodeLoggingContext, BuildRequestEntry requestEntry)
- : this
- (
- nodeLoggingContext,
- requestEntry.Request.SubmissionId,
- requestEntry.Request.ConfigurationId,
- requestEntry.RequestConfiguration.ProjectFullPath,
- requestEntry.Request.Targets,
- requestEntry.RequestConfiguration.ToolsVersion,
- requestEntry.RequestConfiguration.Project.PropertiesToBuildWith,
- requestEntry.RequestConfiguration.Project.ItemsToBuildWith,
- requestEntry.Request.ParentBuildEventContext,
- requestEntry.RequestConfiguration.Project.EvaluationId,
- requestEntry.Request.ProjectContextId)
- {
- }
-
- ///
- /// Constructs a project logging context.
- ///
- internal ProjectLoggingContext(
+ private ProjectLoggingContext(
NodeLoggingContext nodeLoggingContext,
- BuildRequest request,
+ BuildEventContext buildEventContext,
string projectFullPath,
- string toolsVersion,
- int evaluationId = BuildEventContext.InvalidEvaluationId)
- : this
- (
- nodeLoggingContext,
- request.SubmissionId,
- request.ConfigurationId,
- projectFullPath,
- request.Targets,
- toolsVersion,
- projectProperties: null,
- projectItems: null,
- request.ParentBuildEventContext,
- evaluationId,
- request.ProjectContextId)
+ string toolsVersion)
+ : base(nodeLoggingContext, buildEventContext)
{
+ _projectFullPath = projectFullPath;
+
+ // No need to log a redundant message in the common case
+ if (toolsVersion != "Current")
+ {
+ LoggingService.LogComment(BuildEventContext, MessageImportance.Low, "ToolsVersionInEffectForBuild", toolsVersion);
+ }
+
+ IsValid = true;
}
///
- /// Creates ProjectLoggingContext, without logging ProjectStartedEventArgs as a side effect.
- /// The ProjectStartedEventArgs is returned as well - so that it can be later logged explicitly
+ /// Creates ProjectLoggingContext for real local project builds.
+ /// Returns both ProjectStartedEventArgs (for caller to configure) and ProjectLoggingContext.
+ /// Does NOT log ProjectStarted immediately.
///
- public static (ProjectStartedEventArgs, ProjectLoggingContext) CreateLoggingContext(
+ public static (ProjectStartedEventArgs, ProjectLoggingContext) CreateForLocalBuild(
NodeLoggingContext nodeLoggingContext, BuildRequestEntry requestEntry)
{
- ProjectStartedEventArgs args = CreateProjectStarted(
- nodeLoggingContext,
- requestEntry.Request.SubmissionId,
- requestEntry.Request.ConfigurationId,
+ IEnumerable properties = GetProjectProperties(
+ nodeLoggingContext.LoggingService,
+ requestEntry.RequestConfiguration.Project?.PropertiesToBuildWith);
+ IEnumerable items = GetProjectItems(
+ nodeLoggingContext.LoggingService,
+ requestEntry.RequestConfiguration.Project?.ItemsToBuildWith);
+
+ IDictionary globalProperties = requestEntry.RequestConfiguration.GlobalProperties.ToDictionary();
+
+ BuildEventContext parentBuildEventContext = requestEntry.Request.ParentBuildEventContext == BuildEventContext.Invalid
+ ? nodeLoggingContext.BuildEventContext.WithEvaluationId(requestEntry.RequestConfiguration.ProjectEvaluationId).WithSubmissionId(requestEntry.Request.SubmissionId)
+ : requestEntry.Request.ParentBuildEventContext;
+
+ ProjectStartedEventArgs args = nodeLoggingContext.LoggingService.CreateProjectStartedForLocalProject(
+ parentBuildEventContext,
+ requestEntry.RequestConfiguration.ConfigurationId,
requestEntry.RequestConfiguration.ProjectFullPath,
- requestEntry.Request.Targets,
- requestEntry.RequestConfiguration.ToolsVersion,
- requestEntry.RequestConfiguration.Project.PropertiesToBuildWith,
- requestEntry.RequestConfiguration.Project.ItemsToBuildWith,
- requestEntry.Request.ParentBuildEventContext,
- requestEntry.RequestConfiguration.Project.EvaluationId,
- requestEntry.Request.ProjectContextId);
+ string.Join(";", requestEntry.Request.Targets),
+ globalProperties,
+ properties,
+ items,
+ requestEntry.RequestConfiguration.ToolsVersion);
- return (args, new ProjectLoggingContext(nodeLoggingContext, args));
- }
+ // The child project's BuildEventContext must use the child's evaluationId and current node's nodeId,
+ // not the parent's. The parent context is only used as the parentBuildEventContext field on the event args.
+ args.BuildEventContext = args.BuildEventContext
+ .WithEvaluationId(requestEntry.RequestConfiguration.ProjectEvaluationId)
+ .WithNodeId(nodeLoggingContext.BuildEventContext.NodeId);
- private ProjectLoggingContext(
- NodeLoggingContext nodeLoggingContext,
- ProjectStartedEventArgs projectStarted)
- : base(nodeLoggingContext, projectStarted.BuildEventContext)
- {
- _projectFullPath = projectStarted.ProjectFile;
-
- // No need to log a redundant message in the common case
- if (projectStarted.ToolsVersion != "Current")
- {
- LoggingService.LogComment(this.BuildEventContext, MessageImportance.Low, "ToolsVersionInEffectForBuild", projectStarted.ToolsVersion);
- }
+ var context = new ProjectLoggingContext(
+ nodeLoggingContext,
+ args.BuildEventContext,
+ args.ProjectFile,
+ args.ToolsVersion);
- this.IsValid = true;
+ return (args, context);
}
///
- /// Constructs a project logging contexts.
+ /// Creates ProjectLoggingContext for cached project builds.
+ /// Immediately logs ProjectStarted event with minimal data.
///
- private ProjectLoggingContext(
+ public static ProjectLoggingContext CreateForCacheBuild(
NodeLoggingContext nodeLoggingContext,
- int submissionId,
- int configurationId,
- string projectFullPath,
- List targets,
- string toolsVersion,
- PropertyDictionary projectProperties,
- IItemDictionary projectItems,
- BuildEventContext parentBuildEventContext,
- int evaluationId,
- int projectContextId)
- : base(nodeLoggingContext,
- CreateInitialContext(nodeLoggingContext,
- submissionId,
- configurationId,
- projectFullPath,
- targets,
- toolsVersion,
- projectProperties,
- projectItems,
- parentBuildEventContext,
- evaluationId,
- projectContextId))
+ BuildRequest request,
+ BuildRequestConfiguration configuration)
{
- _projectFullPath = projectFullPath;
-
- // No need to log a redundant message in the common case
- if (toolsVersion != "Current")
- {
- LoggingService.LogComment(this.BuildEventContext, MessageImportance.Low, "ToolsVersionInEffectForBuild", toolsVersion);
- }
+ BuildEventContext buildEventContext = CreateAndLogProjectStartedForCache(
+ nodeLoggingContext,
+ request,
+ configuration);
- this.IsValid = true;
+ return new ProjectLoggingContext(
+ nodeLoggingContext,
+ buildEventContext,
+ configuration.ProjectFullPath,
+ configuration.ToolsVersion);
}
- private static BuildEventContext CreateInitialContext(
+ ///
+ /// Creates BuildEventContext and logs ProjectStarted for cache scenarios.
+ ///
+ private static BuildEventContext CreateAndLogProjectStartedForCache(
NodeLoggingContext nodeLoggingContext,
- int submissionId,
- int configurationId,
- string projectFullPath,
- List targets,
- string toolsVersion,
- PropertyDictionary projectProperties,
- IItemDictionary projectItems,
- BuildEventContext parentBuildEventContext,
- int evaluationId,
- int projectContextId)
+ BuildRequest newRequestThatWasServedFromCache,
+ BuildRequestConfiguration configuration)
{
- ProjectStartedEventArgs args = CreateProjectStarted(
- nodeLoggingContext,
- submissionId,
- configurationId,
- projectFullPath,
- targets,
- toolsVersion,
- projectProperties,
- projectItems,
- parentBuildEventContext,
- evaluationId,
- projectContextId);
+ // Create a remote node evaluation context with the original evaluation ID
+ BuildEventContext remoteNodeEvaluationBuildEventContext = BuildEventContext.CreateInitial(
+ newRequestThatWasServedFromCache.SubmissionId,
+ configuration.ResultsNodeId) // Use the node that originally built this project configuration
+ .WithEvaluationId(configuration.ProjectEvaluationId)
+ .WithProjectInstanceId(configuration.ConfigurationId);
+ // we don't know the projectContextId of the remote eval, so we don't set it at all.
+ // the new request _does not have_ a valid projectContextId to go off of.
+
+ IDictionary globalProperties = configuration.GlobalProperties.ToDictionary();
+
+ ProjectStartedEventArgs args = nodeLoggingContext.LoggingService.CreateProjectStartedForCachedProject(
+ nodeLoggingContext.BuildEventContext, // Current node context
+ remoteNodeEvaluationBuildEventContext, // Original remote node context
+ newRequestThatWasServedFromCache.ParentBuildEventContext,
+ globalProperties,
+ configuration.ProjectFullPath,
+ string.Join(";", newRequestThatWasServedFromCache.Targets),
+ configuration.ToolsVersion);
nodeLoggingContext.LoggingService.LogProjectStarted(args);
-
return args.BuildEventContext;
}
- private static ProjectStartedEventArgs CreateProjectStarted(
- NodeLoggingContext nodeLoggingContext,
- int submissionId,
- int configurationId,
- string projectFullPath,
- List targets,
- string toolsVersion,
- PropertyDictionary projectProperties,
- IItemDictionary projectItems,
- BuildEventContext parentBuildEventContext,
- int evaluationId,
- int projectContextId)
+ ///
+ /// Gets project properties for logging if appropriate - as determined by the logging service.
+ ///
+ private static IEnumerable GetProjectProperties(
+ ILoggingService loggingService,
+ PropertyDictionary projectProperties)
{
- IEnumerable properties = null;
- IEnumerable items = null;
-
- ILoggingService loggingService = nodeLoggingContext.LoggingService;
-
- string[] propertiesToSerialize = loggingService.PropertiesToSerialize;
-
- // If we are only logging critical events lets not pass back the items or properties
- if (!loggingService.OnlyLogCriticalEvents &&
- loggingService.IncludeEvaluationPropertiesAndItemsInProjectStartedEvent &&
- (!loggingService.RunningOnRemoteNode || loggingService.SerializeAllProperties))
+ if (projectProperties == null ||
+ loggingService.OnlyLogCriticalEvents ||
+ !loggingService.IncludeEvaluationPropertiesAndItemsInProjectStartedEvent)
{
- if (projectProperties is null)
- {
- properties = [];
- }
- else if (Traits.LogAllEnvironmentVariables)
- {
- properties = projectProperties.GetCopyOnReadEnumerable(property => new DictionaryEntry(property.Name, property.EvaluatedValue));
- }
- else
- {
- properties = projectProperties.Filter(p => p is not EnvironmentDerivedProjectPropertyInstance || EnvironmentUtilities.IsWellKnownEnvironmentDerivedProperty(p.Name), p => new DictionaryEntry(p.Name, p.EvaluatedValue));
- }
-
- items = projectItems?.GetCopyOnReadEnumerable(item => new DictionaryEntry(item.ItemType, new TaskItem(item))) ?? [];
+ return null;
}
- if (projectProperties != null &&
- loggingService.IncludeEvaluationPropertiesAndItemsInProjectStartedEvent &&
- propertiesToSerialize?.Length > 0 &&
- !loggingService.SerializeAllProperties)
+ // When PropertiesToSerialize is set (e.g. MsBuildForwardPropertiesFromChild),
+ // filter to only those properties regardless of RunningOnRemoteNode.
+ string[] propertiesToSerialize = loggingService.PropertiesToSerialize;
+ if (propertiesToSerialize?.Length > 0 && !loggingService.SerializeAllProperties)
{
- PropertyDictionary projectPropertiesToSerialize = new PropertyDictionary();
+ PropertyDictionary filtered = new();
foreach (string propertyToGet in propertiesToSerialize)
{
ProjectPropertyInstance instance = projectProperties[propertyToGet];
+ if (instance is not null)
{
- if (instance != null)
- {
- projectPropertiesToSerialize.Set(instance);
- }
+ filtered.Set(instance);
}
}
- properties = projectPropertiesToSerialize.Select((ProjectPropertyInstance property) => new DictionaryEntry(property.Name, property.EvaluatedValue));
+ return filtered.GetCopyOnReadEnumerable(p => new DictionaryEntry(p.Name, p.EvaluatedValue));
}
- return loggingService.CreateProjectStarted(
- nodeLoggingContext.BuildEventContext,
- submissionId,
- configurationId,
- parentBuildEventContext,
- projectFullPath,
- string.Join(";", targets),
- properties,
- items,
- evaluationId,
- projectContextId);
+ if (loggingService.RunningOnRemoteNode && !loggingService.SerializeAllProperties)
+ {
+ return null;
+ }
+
+ if (Traits.LogAllEnvironmentVariables)
+ {
+ return projectProperties.GetCopyOnReadEnumerable(property => new DictionaryEntry(property.Name, property.EvaluatedValue));
+ }
+ else
+ {
+ return projectProperties.Filter(
+ p => p is not EnvironmentDerivedProjectPropertyInstance || EnvironmentUtilities.IsWellKnownEnvironmentDerivedProperty(p.Name),
+ p => new DictionaryEntry(p.Name, p.EvaluatedValue));
+ }
+ }
+
+ ///
+ /// Gets project items for logging if appropriate - as determined by the logging service.
+ ///
+ private static IEnumerable GetProjectItems(
+ ILoggingService loggingService,
+ IItemDictionary projectItems)
+ {
+ if (projectItems == null ||
+ loggingService.OnlyLogCriticalEvents ||
+ !loggingService.IncludeEvaluationPropertiesAndItemsInProjectStartedEvent ||
+ (loggingService.RunningOnRemoteNode && !loggingService.SerializeAllProperties))
+ {
+ return null;
+ }
+
+ return projectItems.GetCopyOnReadEnumerable(item => new DictionaryEntry(item.ItemType, new TaskItem(item)));
}
///
@@ -269,9 +227,9 @@ private static ProjectStartedEventArgs CreateProjectStarted(
/// Did the build succeede or not
internal void LogProjectFinished(bool success)
{
- ErrorUtilities.VerifyThrow(this.IsValid, "invalid");
+ ErrorUtilities.VerifyThrow(IsValid, "invalid");
LoggingService.LogProjectFinished(BuildEventContext, _projectFullPath, success);
- this.IsValid = false;
+ IsValid = false;
}
///
@@ -279,7 +237,7 @@ internal void LogProjectFinished(bool success)
///
internal TargetLoggingContext LogTargetBatchStarted(string projectFullPath, ProjectTargetInstance target, string parentTargetName, TargetBuiltReason buildReason)
{
- ErrorUtilities.VerifyThrow(this.IsValid, "invalid");
+ ErrorUtilities.VerifyThrow(IsValid, "invalid");
return new TargetLoggingContext(this, projectFullPath, target, parentTargetName, buildReason);
}
}
diff --git a/src/Build/BackEnd/Components/ProjectCache/ProjectCacheService.cs b/src/Build/BackEnd/Components/ProjectCache/ProjectCacheService.cs
index ba83ecb8c95..ed42b7bd32c 100644
--- a/src/Build/BackEnd/Components/ProjectCache/ProjectCacheService.cs
+++ b/src/Build/BackEnd/Components/ProjectCache/ProjectCacheService.cs
@@ -533,11 +533,7 @@ public void PostCacheRequest(CacheRequest cacheRequest, CancellationToken cancel
BuildRequestData buildRequest = new BuildRequestData(
cacheRequest.Configuration.Project,
cacheRequest.Submission.BuildRequestData?.TargetNames.ToArray() ?? []);
- BuildEventContext buildEventContext = _loggingService.CreateProjectCacheBuildEventContext(
- cacheRequest.Submission.SubmissionId,
- evaluationId: cacheRequest.Configuration.Project.EvaluationId,
- projectInstanceId: cacheRequest.Configuration.ConfigurationId,
- projectFile: cacheRequest.Configuration.Project.FullPath);
+ BuildEventContext buildEventContext = _loggingService.CreateProjectCacheBuildEventContext(GetCacheRequestBuildEventContext(cacheRequest), projectFile: cacheRequest.Configuration.Project.FullPath);
CacheResult cacheResult;
try
@@ -562,11 +558,11 @@ void EvaluateProjectIfNecessary(BuildSubmission submission, BuildRequestConfigur
{
if (!configuration.IsLoaded)
{
+ BuildEventContext parentBuildContext = submission.BuildEventContext;
configuration.LoadProjectIntoConfiguration(
_buildManager,
submission.BuildRequestData!.Flags,
- submission.SubmissionId,
- Scheduler.InProcNodeId);
+ parentBuildContext);
// If we're taking the time to evaluate, avoid having other nodes to repeat the same evaluation.
// Based on the assumption that ProjectInstance serialization is faster than evaluating from scratch.
@@ -576,6 +572,11 @@ void EvaluateProjectIfNecessary(BuildSubmission submission, BuildRequestConfigur
}
}
+ private BuildEventContext GetCacheRequestBuildEventContext(CacheRequest cacheRequest) =>
+ BuildEventContext.CreateForNode(Scheduler.VirtualNode)
+ .WithEvaluationId(cacheRequest.Configuration.ProjectEvaluationId)
+ .WithProjectInstanceId(cacheRequest.Configuration.ConfigurationId);
+
private async ValueTask GetCacheResultAsync(BuildRequestData buildRequest, BuildRequestConfiguration buildRequestConfiguration, BuildEventContext buildEventContext, CancellationToken cancellationToken)
{
ErrorUtilities.VerifyThrowInternalNull(buildRequest.ProjectInstance, nameof(buildRequest.ProjectInstance));
diff --git a/src/Build/BackEnd/Components/RequestBuilder/RequestBuilder.cs b/src/Build/BackEnd/Components/RequestBuilder/RequestBuilder.cs
index ad869205157..2413e0e3169 100644
--- a/src/Build/BackEnd/Components/RequestBuilder/RequestBuilder.cs
+++ b/src/Build/BackEnd/Components/RequestBuilder/RequestBuilder.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
@@ -1158,8 +1158,7 @@ private async Task BuildProject()
_requestEntry.RequestConfiguration.LoadProjectIntoConfiguration(
_componentHost,
RequestEntry.Request.BuildRequestDataFlags,
- RequestEntry.Request.SubmissionId,
- _nodeLoggingContext.BuildEventContext.NodeId);
+ _nodeLoggingContext.BuildEventContext.WithSubmissionId(RequestEntry.Request.SubmissionId));
}
// Set SDK-resolved environment variables if they haven't been set yet for this configuration
@@ -1179,13 +1178,8 @@ private async Task BuildProject()
}
catch
{
- // make sure that any errors thrown by a child project are logged in the context of their parent project: create a temporary projectLoggingContext
- _projectLoggingContext = new ProjectLoggingContext(
- _nodeLoggingContext,
- _requestEntry.Request,
- _requestEntry.RequestConfiguration.ProjectFullPath,
- _requestEntry.RequestConfiguration.ToolsVersion);
-
+ // make sure that any errors thrown by a child project are logged in the context of their parent project
+ _projectLoggingContext = _nodeLoggingContext.LogProjectStarted(_requestEntry);
throw;
}
finally
@@ -1249,7 +1243,7 @@ private async Task BuildProject()
BuildResult result = await _targetBuilder.BuildTargets(_projectLoggingContext, _requestEntry, this,
allTargets, _requestEntry.RequestConfiguration.BaseLookup, _cancellationTokenSource.Token);
- // Populate the evaluation ID from the configuration for sending to the central node.
+ // Populate the evaluation ID from the configuration for sending to the central node.
result.EvaluationId = _requestEntry.RequestConfiguration.ProjectEvaluationId;
UpdateStatisticsPostBuild();
diff --git a/src/Build/BackEnd/Components/Scheduler/Scheduler.cs b/src/Build/BackEnd/Components/Scheduler/Scheduler.cs
index 8306de90171..940b6d93fde 100644
--- a/src/Build/BackEnd/Components/Scheduler/Scheduler.cs
+++ b/src/Build/BackEnd/Components/Scheduler/Scheduler.cs
@@ -41,7 +41,7 @@ internal class Scheduler : IScheduler
internal const int ResultsTransferredId = -2;
///
- /// The in-proc node id
+ /// The in-proc node id for the worker node that performs work the scheduler itself assigns on the same 'logical' node.
///
internal const int InProcNodeId = 1;
@@ -57,6 +57,12 @@ internal class Scheduler : IScheduler
///
private const double DefaultCustomSchedulerForSQLConfigurationLimitMultiplier = 1.1;
+ ///
+ /// The build event context for the scheduler node - can be used as a 'root' context for contexts' derived or needed when running scheduler operations.
+ ///
+ private static BuildEventContext s_schedulerNodeBuildEventContext = BuildEventContext.CreateForNode(VirtualNode);
+
+
#region Scheduler Data
///
@@ -599,7 +605,7 @@ public void Reset()
public void WriteDetailedSummary(int submissionId)
{
ILoggingService loggingService = _componentHost.LoggingService;
- BuildEventContext context = new BuildEventContext(submissionId, 0, 0, 0, 0, 0);
+ BuildEventContext context = s_schedulerNodeBuildEventContext.WithSubmissionId(submissionId);
loggingService.LogComment(context, MessageImportance.Normal, "DetailedSummaryHeader");
foreach (SchedulableRequest request in _schedulingData.GetRequestsByHierarchy(null))
@@ -674,7 +680,7 @@ public void InitializeComponent(IBuildComponentHost host)
_componentHost = host;
_resultsCache = (IResultsCache)_componentHost.GetComponent(BuildComponentType.ResultsCache);
_configCache = (IConfigCache)_componentHost.GetComponent(BuildComponentType.ConfigCache);
- _inprocNodeContext = new NodeLoggingContext(_componentHost.LoggingService, InProcNodeId, true);
+ _inprocNodeContext = new NodeLoggingContext(_componentHost.LoggingService, s_schedulerNodeBuildEventContext, InProcNodeId, true);
}
///
@@ -2036,13 +2042,7 @@ private bool CheckIfCacheMissOnReferencedProjectIsAllowedAndErrorIfNot(int nodeF
string projectFullPath = _configCache[request.ConfigurationId].ProjectFullPath;
string parentProjectFullPath = GetParentConfigurationId(request, _configCache, _schedulingData).ProjectFullPath;
_componentHost.LoggingService.LogComment(
- new BuildEventContext(
- request.SubmissionId,
- 1,
- BuildEventContext.InvalidProjectInstanceId,
- BuildEventContext.InvalidProjectContextId,
- BuildEventContext.InvalidTargetId,
- BuildEventContext.InvalidTaskId),
+ s_schedulerNodeBuildEventContext.WithSubmissionId(request.SubmissionId),
MessageImportance.Normal,
"SkippedConstraintsOnRequest",
parentProjectFullPath,
@@ -2197,8 +2197,7 @@ private ScheduleResponse GetResponseForResult(int parentRequestNode, BuildReques
private void LogRequestHandledFromCache(BuildRequest request, BuildResult result)
{
BuildRequestConfiguration configuration = _configCache[request.ConfigurationId];
- int nodeId = _schedulingData.GetAssignedNodeForRequestConfiguration(request.ConfigurationId);
- NodeLoggingContext nodeContext = new NodeLoggingContext(_componentHost.LoggingService, nodeId, true);
+ NodeLoggingContext nodeContext = new NodeLoggingContext(_componentHost.LoggingService, s_schedulerNodeBuildEventContext, VirtualNode, true);
nodeContext.LogRequestHandledFromCache(request, configuration, result);
TraceScheduler(
@@ -2949,7 +2948,7 @@ private void DumpRequestSpec(StreamWriter file, SchedulableRequest request, int
private void WriteSchedulingPlan(int submissionId)
{
SchedulingPlan plan = new SchedulingPlan(_configCache, _schedulingData);
- plan.WritePlan(submissionId, _componentHost.LoggingService, new BuildEventContext(submissionId, 0, 0, 0, 0, 0));
+ plan.WritePlan(submissionId, _componentHost.LoggingService, s_schedulerNodeBuildEventContext.WithSubmissionId(submissionId));
}
///
@@ -2958,7 +2957,7 @@ private void WriteSchedulingPlan(int submissionId)
private void ReadSchedulingPlan(int submissionId)
{
_schedulingPlan = new SchedulingPlan(_configCache, _schedulingData);
- _schedulingPlan.ReadPlan(submissionId, _componentHost.LoggingService, new BuildEventContext(submissionId, 0, 0, 0, 0, 0));
+ _schedulingPlan.ReadPlan(submissionId, _componentHost.LoggingService, s_schedulerNodeBuildEventContext.WithSubmissionId(submissionId));
}
#endregion
diff --git a/src/Build/BackEnd/Node/InProcNode.cs b/src/Build/BackEnd/Node/InProcNode.cs
index 2e61667a0c2..22eab32a813 100644
--- a/src/Build/BackEnd/Node/InProcNode.cs
+++ b/src/Build/BackEnd/Node/InProcNode.cs
@@ -38,6 +38,11 @@ internal class InProcNode : INode, INodePacketFactory
///
private string _savedCurrentDirectory;
+ ///
+ /// The build event context for this node - will usually only have the node id set.
+ ///
+ private BuildEventContext _buildEventContext;
+
///
/// The node logging context.
///
@@ -502,8 +507,10 @@ private void HandleNodeConfiguration(NodeConfiguration configuration)
ILoggingService loggingService = _componentHost.LoggingService;
loggingService.OnLoggingThreadException += OnLoggingThreadException;
+ _buildEventContext = BuildEventContext.CreateForNode(configuration.NodeId);
+
// Now prep the buildRequestEngine for the build.
- _loggingContext = new NodeLoggingContext(loggingService, configuration.NodeId, true /* inProcNode */);
+ _loggingContext = new NodeLoggingContext(loggingService, _buildEventContext, configuration.NodeId, true /* inProcNode */);
_buildRequestEngine.OnEngineException += _engineExceptionEventHandler;
_buildRequestEngine.OnNewConfigurationRequest += _newConfigurationRequestEventHandler;
diff --git a/src/Build/BackEnd/Node/OutOfProcNode.cs b/src/Build/BackEnd/Node/OutOfProcNode.cs
index 70915c42942..d5ba703b4bd 100644
--- a/src/Build/BackEnd/Node/OutOfProcNode.cs
+++ b/src/Build/BackEnd/Node/OutOfProcNode.cs
@@ -65,6 +65,7 @@ public class OutOfProcNode : INode, IBuildComponentHost, INodePacketFactory, INo
///
private BuildParameters _buildParameters;
+
///
/// The logging service.
///
@@ -100,6 +101,11 @@ public class OutOfProcNode : INode, IBuildComponentHost, INodePacketFactory, INo
///
private NodeConfiguration _currentConfiguration;
+ ///
+ /// The build event context for this node, will usually only have the node ID set.
+ ///
+ private BuildEventContext _buildEventContext;
+
///
/// The queue of packets we have received but which have not yet been processed.
///
@@ -846,8 +852,9 @@ private void HandleNodeConfiguration(NodeConfiguration configuration)
_loggingService.SerializeAllProperties = false;
}
+ _buildEventContext = BuildEventContext.CreateForNode(configuration.NodeId);
// Now prep the buildRequestEngine for the build.
- _loggingContext = new NodeLoggingContext(_loggingService, configuration.NodeId, false /* inProcNode */);
+ _loggingContext = new NodeLoggingContext(_loggingService, _buildEventContext, configuration.NodeId, false /* inProcNode */);
if (_shutdownException != null)
{
diff --git a/src/Build/BackEnd/Shared/BuildRequestConfiguration.cs b/src/Build/BackEnd/Shared/BuildRequestConfiguration.cs
index 8d1dc211da6..f200c250548 100644
--- a/src/Build/BackEnd/Shared/BuildRequestConfiguration.cs
+++ b/src/Build/BackEnd/Shared/BuildRequestConfiguration.cs
@@ -459,8 +459,7 @@ private void SetProjectBasedState(ProjectInstance project)
internal void LoadProjectIntoConfiguration(
IBuildComponentHost componentHost,
BuildRequestDataFlags buildRequestDataFlags,
- int submissionId,
- int nodeId)
+ BuildEventContext parentBuildEventContext)
{
ErrorUtilities.VerifyThrow(!IsLoaded, "Already loaded the project for this configuration id {0}.", ConfigurationId);
@@ -511,16 +510,9 @@ internal void LoadProjectIntoConfiguration(
toolsVersionOverride,
componentHost.BuildParameters,
componentHost.LoggingService,
- new BuildEventContext(
- submissionId,
- nodeId,
- BuildEventContext.InvalidEvaluationId,
- BuildEventContext.InvalidProjectInstanceId,
- BuildEventContext.InvalidProjectContextId,
- BuildEventContext.InvalidTargetId,
- BuildEventContext.InvalidTaskId),
+ parentBuildEventContext,
sdkResolverService,
- submissionId,
+ parentBuildEventContext.SubmissionId,
projectLoadSettings);
});
}
diff --git a/src/Build/BackEnd/Shared/BuildResult.cs b/src/Build/BackEnd/Shared/BuildResult.cs
index e657cfc2e2c..5784c46fb1f 100644
--- a/src/Build/BackEnd/Shared/BuildResult.cs
+++ b/src/Build/BackEnd/Shared/BuildResult.cs
@@ -100,6 +100,11 @@ public class BuildResult : BuildResultBase, INodePacket, IBuildResults
///
private Exception? _requestException;
+ ///
+ /// The evaluation ID of the project used for this build.
+ ///
+ private int _evaluationId = BuildEventContext.InvalidEvaluationId;
+
///
/// The overall result calculated in the constructor.
///
@@ -145,11 +150,6 @@ public class BuildResult : BuildResultBase, INodePacket, IBuildResults
///
private BuildRequestDataFlags _buildRequestDataFlags;
- ///
- /// The evaluation ID of the project used for this build.
- ///
- private int _evaluationId = BuildEventContext.InvalidEvaluationId;
-
private string? _schedulerInducedError;
private HashSet? _projectTargets;
@@ -431,17 +431,6 @@ public ProjectInstance? ProjectStateAfterBuild
///
public BuildRequestDataFlags? BuildRequestDataFlags => (_version > 0) ? _buildRequestDataFlags : null;
- ///
- /// The evaluation ID of the project used for this build.
- ///
- internal int EvaluationId
- {
- [DebuggerStepThrough]
- get => _evaluationId;
- [DebuggerStepThrough]
- set => _evaluationId = value;
- }
-
///
/// Returns the node packet type.
///
@@ -511,6 +500,17 @@ internal HashSet? ProjectTargets
set => _projectTargets = value;
}
+ ///
+ /// The evaluation ID of the project used for this build.
+ ///
+ internal int EvaluationId
+ {
+ [DebuggerStepThrough]
+ get => _evaluationId;
+ [DebuggerStepThrough]
+ set => _evaluationId = value;
+ }
+
///
/// Container used to transport errors from the scheduler (issued while computing a build result)
/// to the TaskHost that has the proper logging context (project id, target id, task id, file location)
diff --git a/src/Build/BuildCheck/Infrastructure/BuildCheckBuildEventHandler.cs b/src/Build/BuildCheck/Infrastructure/BuildCheckBuildEventHandler.cs
index bd1d71a89f5..59341b6f309 100644
--- a/src/Build/BuildCheck/Infrastructure/BuildCheckBuildEventHandler.cs
+++ b/src/Build/BuildCheck/Infrastructure/BuildCheckBuildEventHandler.cs
@@ -180,9 +180,5 @@ private string BuildCsvString(string title, Dictionary rowData
=> title + Environment.NewLine + String.Join(Environment.NewLine, rowData.Select(a => $"{a.Key},{a.Value}")) + Environment.NewLine;
private BuildEventContext GetBuildEventContext(BuildEventArgs e) => e.BuildEventContext
- ?? new BuildEventContext(
- BuildEventContext.InvalidNodeId,
- BuildEventContext.InvalidTargetId,
- BuildEventContext.InvalidProjectContextId,
- BuildEventContext.InvalidTaskId);
+ ?? BuildEventContext.Invalid;
}
diff --git a/src/Build/BuildCheck/Infrastructure/BuildCheckManagerProvider.cs b/src/Build/BuildCheck/Infrastructure/BuildCheckManagerProvider.cs
index 89998bad255..b48be3bdca8 100644
--- a/src/Build/BuildCheck/Infrastructure/BuildCheckManagerProvider.cs
+++ b/src/Build/BuildCheck/Infrastructure/BuildCheckManagerProvider.cs
@@ -649,7 +649,7 @@ public void StartProjectRequest(ICheckContext checkContext, string projectFullPa
{
foreach (BuildEventArgs deferredArgs in list)
{
- deferredArgs.BuildEventContext = deferredArgs.BuildEventContext!.WithInstanceIdAndContextId(buildEventContext);
+ deferredArgs.BuildEventContext = deferredArgs.BuildEventContext!.WithProjectInstanceId(buildEventContext.ProjectInstanceId).WithProjectContextId(buildEventContext.ProjectContextId);
checkContext.DispatchBuildEvent(deferredArgs);
}
list.Clear();
diff --git a/src/Build/Definition/Project.cs b/src/Build/Definition/Project.cs
index 222d8aa13ea..f68c012df4d 100644
--- a/src/Build/Definition/Project.cs
+++ b/src/Build/Definition/Project.cs
@@ -67,7 +67,11 @@ public class Project : ILinkableObject
///
/// Context to log messages and events in.
///
- private static readonly BuildEventContext s_buildEventContext = new BuildEventContext(0 /* node ID */, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
+ ///
+ /// This should only be used on pathways that create Projects outside of the MSBuild exe workflow - users directly loading Projects, etc.
+ /// In such cases we don't have a live set of nodes (yet?), but we still need contexts for message association.
+ ///
+ private static readonly BuildEventContext s_errorBuildEventContext = BuildEventContext.CreateForSubmission(0);
private ProjectLink implementation;
private IProjectLinkInternal implementationInternal;
@@ -1922,7 +1926,7 @@ public ProjectImpl(Project owner, XmlReader xmlReader, IDictionary loggers, IEnum
{
if (!IsBuildEnabled)
{
- LoggingService.LogError(s_buildEventContext, new BuildEventFileInfo(FullPath), "SecurityProjectBuildDisabled");
+ LoggingService.LogError(s_errorBuildEventContext, new BuildEventFileInfo(FullPath), "SecurityProjectBuildDisabled");
if (LoggingService is LoggingService defaultLoggingService)
{
defaultLoggingService.WaitForLoggingToProcessEvents();
@@ -3553,7 +3557,7 @@ public string ExpandItemIncludeBestEffortLeaveEscaped(ProjectItemElement renamed
_data.Expander,
LoggingService,
FullPath,
- s_buildEventContext);
+ s_errorBuildEventContext);
if (items.Count != 1)
{
@@ -3620,7 +3624,7 @@ private List AddItemHelper(ProjectItemElement itemElement, string u
_data.Expander,
LoggingService,
FullPath,
- s_buildEventContext);
+ s_errorBuildEventContext);
foreach (ProjectItem item in items)
{
@@ -3708,7 +3712,7 @@ private void ReevaluateIfNecessary(
}
catch (InvalidProjectFileException ex)
{
- loggingServiceForEvaluation.LogInvalidProjectFileError(s_buildEventContext, ex);
+ loggingServiceForEvaluation.LogInvalidProjectFileError(s_errorBuildEventContext, ex);
throw;
}
}
@@ -3747,7 +3751,7 @@ private void Reevaluate(
ProjectCollection,
Owner._directoryCacheFactory,
ProjectCollection.ProjectRootElementCache,
- s_buildEventContext,
+ s_errorBuildEventContext,
evaluationContext.SdkResolverService,
BuildEventContext.InvalidSubmissionId,
evaluationContext,
diff --git a/src/Build/Definition/ProjectCollection.cs b/src/Build/Definition/ProjectCollection.cs
index cf120f7961a..379247a6a45 100644
--- a/src/Build/Definition/ProjectCollection.cs
+++ b/src/Build/Definition/ProjectCollection.cs
@@ -100,6 +100,15 @@ public class ProjectCollection : IToolsetProvider, IBuildComponent, IDisposable
///
private static ProjectCollection s_globalProjectCollection;
+ ///
+ /// Context to log messages and events in.
+ ///
+ ///
+ /// This should only be used on pathways that create ProjectCollections outside of the MSBuild exe workflow - users directly loading Projects, etc.
+ /// In such cases we don't have a live set of nodes (yet?), but we still need contexts for message association.
+ ///
+ private static readonly BuildEventContext s_errorBuildEventContext = BuildEventContext.CreateForSubmission(0);
+
///
/// Gets the file version of the file in which the Engine assembly lies.
///
@@ -384,8 +393,7 @@ public ProjectCollection(IDictionary globalProperties, IEnumerab
}
catch (InvalidProjectFileException ex2)
{
- BuildEventContext buildEventContext = new BuildEventContext(0 /* node ID */, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
- LoggingService.LogInvalidProjectFileError(buildEventContext, ex2);
+ LoggingService.LogInvalidProjectFileError(s_errorBuildEventContext, ex2);
throw;
}
}
@@ -1261,8 +1269,7 @@ public Project LoadProject(string fileName, IDictionary globalPr
}
catch (InvalidProjectFileException ex)
{
- var buildEventContext = new BuildEventContext(0 /* node ID */, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
- LoggingService.LogInvalidProjectFileError(buildEventContext, ex);
+ LoggingService.LogInvalidProjectFileError(s_errorBuildEventContext, ex);
throw;
}
}
diff --git a/src/Build/Instance/ProjectInstance.cs b/src/Build/Instance/ProjectInstance.cs
index b7dea631294..f824f2d9abb 100644
--- a/src/Build/Instance/ProjectInstance.cs
+++ b/src/Build/Instance/ProjectInstance.cs
@@ -78,6 +78,16 @@ public enum ProjectInstanceSettings
[DebuggerDisplay(@"{FullPath} #Targets={TargetsCount} DefaultTargets={(DefaultTargets == null) ? System.String.Empty : System.String.Join("";"", DefaultTargets.ToArray())} ToolsVersion={Toolset.ToolsVersion} InitialTargets={(InitialTargets == null) ? System.String.Empty : System.String.Join("";"", InitialTargets.ToArray())} #GlobalProperties={GlobalProperties.Count} #Properties={Properties.Count} #ItemTypes={ItemTypes.Count} #Items={Items.Count}")]
public class ProjectInstance : IPropertyProvider, IItemProvider, IEvaluatorData, ITranslatable
{
+
+ ///
+ /// Context to log messages and events in.
+ ///
+ ///
+ /// This should only be used on pathways that create ProjectInstances outside of the MSBuild exe workflow - users directly loading Projects, etc.
+ /// In such cases we don't have a live set of nodes (yet?), but we still need contexts for message association.
+ ///
+ private static readonly BuildEventContext s_errorBuildEventContext = BuildEventContext.CreateForSubmission(0);
+
///
/// Targets in the project after overrides have been resolved.
/// This is an unordered collection keyed by target name.
@@ -313,7 +323,7 @@ private ProjectInstance(string projectFile, IDictionary globalPr
Interactive = interactive
};
- BuildEventContext buildEventContext = new BuildEventContext(buildParameters.NodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
+ BuildEventContext buildEventContext = s_errorBuildEventContext.WithNodeId(buildParameters.NodeId).WithSubmissionId(0);
ProjectRootElement xml = ProjectRootElement.OpenProjectOrSolution(projectFile, globalProperties, toolsVersion, buildParameters.ProjectRootElementCache, true /*Explicitly Loaded*/);
Initialize(xml, globalProperties, toolsVersion, subToolsetVersion, 0 /* no solution version provided */, buildParameters, projectCollection.LoggingService, buildEventContext,
@@ -543,14 +553,12 @@ static List GetImportFullPathsIncludingDuplicates(ObjectModelRemoting.Pr
private ProjectInstance(ProjectRootElement xml, IDictionary globalProperties, string toolsVersion, string subToolsetVersion, ProjectCollection projectCollection,
ProjectLoadSettings? projectLoadSettings, EvaluationContext evaluationContext, IDirectoryCacheFactory directoryCacheFactory, bool interactive)
{
- BuildEventContext buildEventContext = new BuildEventContext(0, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
-
BuildParameters buildParameters = new BuildParameters(projectCollection)
{
Interactive = interactive
};
- Initialize(xml, globalProperties, toolsVersion, subToolsetVersion, 0 /* no solution version specified */, buildParameters, projectCollection.LoggingService, buildEventContext,
+ Initialize(xml, globalProperties, toolsVersion, subToolsetVersion, 0 /* no solution version specified */, buildParameters, projectCollection.LoggingService, s_errorBuildEventContext,
projectLoadSettings: projectLoadSettings, evaluationContext: evaluationContext, directoryCacheFactory: directoryCacheFactory);
}
@@ -618,8 +626,8 @@ internal ProjectInstance(string projectFile, ProjectInstance projectToInheritFro
/// A new project instance
internal ProjectInstance(ProjectRootElement xml, IDictionary globalProperties, string toolsVersion, int visualStudioVersionFromSolution, ProjectCollection projectCollection, ISdkResolverService sdkResolverService, int submissionId)
{
- BuildEventContext buildEventContext = new BuildEventContext(0, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId);
- Initialize(xml, globalProperties, toolsVersion, null, visualStudioVersionFromSolution, new BuildParameters(projectCollection), projectCollection.LoggingService, buildEventContext, sdkResolverService, submissionId);
+ BuildEventContext buildEventContext = BuildEventContext.CreateInitial(0 /* submission ID */, 0 /* node ID */);
+ Initialize(xml, globalProperties, toolsVersion, null, visualStudioVersionFromSolution, new BuildParameters(projectCollection), projectCollection.LoggingService, s_errorBuildEventContext, sdkResolverService, submissionId);
}
///
@@ -633,7 +641,7 @@ internal ProjectInstance(ProjectRootElement xml, IDictionary glo
///
internal ProjectInstance(ProjectRootElement xml, IDictionary globalProperties, string toolsVersion, ILoggingService loggingService, int visualStudioVersionFromSolution, ProjectCollection projectCollection, ISdkResolverService sdkResolverService, int submissionId)
{
- BuildEventContext buildEventContext = new BuildEventContext(submissionId, 0, BuildEventContext.InvalidProjectInstanceId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidTaskId);
+ BuildEventContext buildEventContext = s_errorBuildEventContext.WithSubmissionId(submissionId);
Initialize(xml, globalProperties, toolsVersion, null, visualStudioVersionFromSolution, new BuildParameters(projectCollection), loggingService, buildEventContext, sdkResolverService, submissionId);
}
diff --git a/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs b/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
index 69afeee1674..dd38e66145f 100644
--- a/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
+++ b/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
@@ -1475,14 +1475,12 @@ private BuildEventContext ReadBuildEventContext()
evaluationId = ReadInt32();
}
- var result = new BuildEventContext(
- submissionId,
- nodeId,
- evaluationId,
- projectInstanceId,
- projectContextId,
- targetId,
- taskId);
+ var result = BuildEventContext.CreateInitial(submissionId, nodeId)
+ .WithEvaluationId(evaluationId)
+ .WithProjectInstanceId(projectInstanceId)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(targetId)
+ .WithTaskId(taskId);
return result;
}
diff --git a/src/BuildCheck.UnitTests/BuildCheckManagerProviderTests.cs b/src/BuildCheck.UnitTests/BuildCheckManagerProviderTests.cs
index 1f24fe1934f..338012a164c 100644
--- a/src/BuildCheck.UnitTests/BuildCheckManagerProviderTests.cs
+++ b/src/BuildCheck.UnitTests/BuildCheckManagerProviderTests.cs
@@ -41,7 +41,7 @@ public void ProcessCheckAcquisitionTest(bool isCheckRuleExist, string[] expected
MockBuildCheckAcquisition(isCheckRuleExist);
MockEnabledDataSourcesDefinition();
- _testedInstance.ProcessCheckAcquisition(new CheckAcquisitionData("DummyPath", "ProjectPath"), new CheckLoggingContext(_loggingService, new BuildEventContext(1, 2, 3, 4, 5, 6, 7)));
+ _testedInstance.ProcessCheckAcquisition(new CheckAcquisitionData("DummyPath", "ProjectPath"), new CheckLoggingContext(_loggingService, BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6).WithTaskId(7)));
_logger.AllBuildEvents.Where(be => be.GetType() == typeof(BuildMessageEventArgs)).Select(be => be.Message).ToArray()
.ShouldBeEquivalentTo(expectedMessages);
diff --git a/src/Framework.UnitTests/CustomEventArgSerialization_Tests.cs b/src/Framework.UnitTests/CustomEventArgSerialization_Tests.cs
index 0da144267c5..a6c0f7536ac 100644
--- a/src/Framework.UnitTests/CustomEventArgSerialization_Tests.cs
+++ b/src/Framework.UnitTests/CustomEventArgSerialization_Tests.cs
@@ -16,6 +16,9 @@ namespace Microsoft.Build.UnitTests
{
public class CustomEventArgSerialization_Tests : IDisposable
{
+
+ private static readonly BuildEventContext defaultContext = BuildEventContext.CreateInitial(5, 4).WithEvaluationId(3).WithProjectInstanceId(2);
+
// Generic build class to test custom serialization of abstract class BuildEventArgs
internal sealed class GenericBuildEventArg : BuildEventArgs
{
@@ -59,7 +62,7 @@ public void TestGenericBuildEventArgs()
{
// Test using reasonable messages
GenericBuildEventArg genericEvent = new GenericBuildEventArg("Message", "HelpKeyword", "SenderName");
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -76,7 +79,7 @@ public void TestGenericBuildEventArgs()
// Test using empty strings
_stream.Position = 0;
genericEvent = new GenericBuildEventArg(string.Empty, string.Empty, string.Empty);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -101,7 +104,7 @@ public void TestGenericBuildEventArgs()
// Deserialize and Verify
_stream.Position = 0;
newGenericEvent = new GenericBuildEventArg(null, null, null);
- newGenericEvent.BuildEventContext = new BuildEventContext(1, 3, 4, 5);
+ newGenericEvent.BuildEventContext = BuildEventContext.CreateInitial(1, 3).WithEvaluationId(4).WithProjectInstanceId(5);
newGenericEvent.CreateFromStream(_reader, _eventArgVersion);
_stream.Position.ShouldBe(streamWriteEndPosition); // "Stream End Positions Should Match"
VerifyGenericEventArg(genericEvent, newGenericEvent);
@@ -125,7 +128,7 @@ public void TestBuildErrorEventArgs()
{
// Test using reasonable messages
BuildErrorEventArgs genericEvent = new BuildErrorEventArgs("Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "SenderName");
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -142,7 +145,7 @@ public void TestBuildErrorEventArgs()
// Test using empty strings
_stream.Position = 0;
genericEvent = new BuildErrorEventArgs(string.Empty, string.Empty, string.Empty, 1, 2, 3, 4, string.Empty, string.Empty, string.Empty);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -176,7 +179,7 @@ public void TestBuildErrorEventArgs()
// Test using HelpLink
_stream.Position = 0;
genericEvent = new BuildErrorEventArgs("Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "SenderName", "HelpLink", DateTime.Now);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -210,7 +213,7 @@ public void TestBuildFinishedEventArgs()
{
// Test using reasonable messages
BuildFinishedEventArgs genericEvent = new BuildFinishedEventArgs("Message", "HelpKeyword", true);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -225,7 +228,7 @@ public void TestBuildFinishedEventArgs()
// Test using empty strings
_stream.Position = 0;
genericEvent = new BuildFinishedEventArgs(string.Empty, string.Empty, true);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -258,7 +261,7 @@ public void TestBuildMessageEventArgs()
{
// Test using reasonable messages
BuildMessageEventArgs genericEvent = new BuildMessageEventArgs("Message", "HelpKeyword", "SenderName", MessageImportance.High);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -276,7 +279,7 @@ public void TestBuildMessageEventArgs()
_stream.Position = 0;
// Make sure empty strings are passed correctly
genericEvent = new BuildMessageEventArgs(string.Empty, string.Empty, string.Empty, MessageImportance.Low);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -328,7 +331,7 @@ public void TestBuildMessageEventArgsWithFileInfo()
{
// Test using reasonable messages
BuildMessageEventArgs messageEvent = new BuildMessageEventArgs("SubCategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "SenderName", MessageImportance.High);
- messageEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ messageEvent.BuildEventContext = defaultContext;
// Serialize
messageEvent.WriteToStream(_writer);
@@ -345,7 +348,7 @@ public void TestBuildMessageEventArgsWithFileInfo()
_stream.Position = 0;
// Make sure empty strings are passed correctly
messageEvent = new BuildMessageEventArgs(string.Empty, string.Empty, string.Empty, 1, 2, 3, 4, string.Empty, string.Empty, string.Empty, MessageImportance.Low);
- messageEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ messageEvent.BuildEventContext = defaultContext;
// Serialize
messageEvent.WriteToStream(_writer);
@@ -381,7 +384,7 @@ public void TestCriticalBuildMessageEventArgs()
{
// Test using reasonable messages
CriticalBuildMessageEventArgs criticalMessageEvent = new CriticalBuildMessageEventArgs("SubCategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "SenderName");
- criticalMessageEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ criticalMessageEvent.BuildEventContext = defaultContext;
// Serialize
criticalMessageEvent.WriteToStream(_writer);
@@ -399,7 +402,7 @@ public void TestCriticalBuildMessageEventArgs()
_stream.Position = 0;
// Make sure empty strings are passed correctly
criticalMessageEvent = new CriticalBuildMessageEventArgs(string.Empty, string.Empty, string.Empty, 1, 2, 3, 4, string.Empty, string.Empty, string.Empty);
- criticalMessageEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ criticalMessageEvent.BuildEventContext = defaultContext;
// Serialize
criticalMessageEvent.WriteToStream(_writer);
@@ -435,7 +438,7 @@ public void TestBuildWarningEventArgs()
{
// Test with reasonable messages
BuildWarningEventArgs genericEvent = new BuildWarningEventArgs("Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "SenderName");
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -452,7 +455,7 @@ public void TestBuildWarningEventArgs()
// Test with empty strings
_stream.Position = 0;
genericEvent = new BuildWarningEventArgs(string.Empty, string.Empty, string.Empty, 1, 2, 3, 4, string.Empty, string.Empty, string.Empty);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -486,7 +489,7 @@ public void TestBuildWarningEventArgs()
// Test with help link
_stream.Position = 0;
genericEvent = new BuildWarningEventArgs("Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "SenderName", "HelpLink", DateTime.Now, null);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -520,7 +523,7 @@ public void TestProjectFinishedEventArgs()
{
// Test with reasonable values
ProjectFinishedEventArgs genericEvent = new ProjectFinishedEventArgs("Message", "HelpKeyword", "ProjectFile", true);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -538,7 +541,7 @@ public void TestProjectFinishedEventArgs()
// Test with empty strings
_stream.Position = 0;
genericEvent = new ProjectFinishedEventArgs(string.Empty, string.Empty, string.Empty, true);
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
// Serialize
genericEvent.WriteToStream(_writer);
@@ -586,8 +589,8 @@ public void TestProjectStartedPropertySerialization()
propertyList.Add(new DictionaryEntry("WorkSpaceOwner", "The workspace owner"));
propertyList.Add(new DictionaryEntry("IAmBlank", string.Empty));
- ProjectStartedEventArgs genericEvent = new ProjectStartedEventArgs(8, "Message", "HelpKeyword", "ProjectFile", null, propertyList, null, new BuildEventContext(7, 8, 9, 10));
- genericEvent.BuildEventContext = new BuildEventContext(7, 8, 9, 10);
+ ProjectStartedEventArgs genericEvent = new ProjectStartedEventArgs(8, "Message", "HelpKeyword", "ProjectFile", null, propertyList, null, BuildEventContext.CreateInitial(7, 8).WithEvaluationId(9).WithProjectInstanceId(10));
+ genericEvent.BuildEventContext = BuildEventContext.CreateInitial(7, 8).WithEvaluationId(9).WithProjectInstanceId(10);
// Serialize
genericEvent.WriteToStream(_writer);
@@ -650,8 +653,8 @@ private void AssertDictionaryEntry(List entryList, List { { "Key", "Value" } } };
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
TelemetryEventArgs newGenericEvent = RoundTrip(genericEvent);
@@ -994,7 +997,7 @@ public void TestTelemetryEventArgs_NullProperties()
{
// Test using reasonable values
TelemetryEventArgs genericEvent = new TelemetryEventArgs { EventName = "Good", Properties = null };
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
TelemetryEventArgs newGenericEvent = RoundTrip(genericEvent);
@@ -1011,7 +1014,7 @@ public void TestTelemetryEventArgs_NullEventName()
{
// Test using null event name
TelemetryEventArgs genericEvent = new TelemetryEventArgs { EventName = null, Properties = new Dictionary { { "Key", "Value" } } };
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
TelemetryEventArgs newGenericEvent = RoundTrip(genericEvent);
@@ -1024,7 +1027,7 @@ public void TestTelemetryEventArgs_NullPropertyValue()
{
// Test using null property value name
TelemetryEventArgs genericEvent = new TelemetryEventArgs { EventName = "Good", Properties = new Dictionary { { "Key", null } } };
- genericEvent.BuildEventContext = new BuildEventContext(5, 4, 3, 2);
+ genericEvent.BuildEventContext = defaultContext;
TelemetryEventArgs newGenericEvent = RoundTrip(genericEvent);
diff --git a/src/Framework.UnitTests/EventArgs_Tests.cs b/src/Framework.UnitTests/EventArgs_Tests.cs
index 451ec654a16..626089c167a 100644
--- a/src/Framework.UnitTests/EventArgs_Tests.cs
+++ b/src/Framework.UnitTests/EventArgs_Tests.cs
@@ -29,7 +29,10 @@ public class EventArgs_Tests
public EventArgs_Tests()
{
s_baseGenericEvent = new GenericBuildEventArgs("Message", "HelpKeyword", "senderName");
- s_baseGenericEvent.BuildEventContext = new BuildEventContext(9, 8, 7, 6);
+ s_baseGenericEvent.BuildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, 9)
+ .WithProjectContextId(7)
+ .WithTargetId(8)
+ .WithTaskId(6);
}
///
@@ -57,19 +60,19 @@ public void EventArgsCtors()
[Fact]
public void ExerciseBuildEventContext()
{
- BuildEventContext parentBuildEventContext = new BuildEventContext(0, 0, 0, 0, 0, 0, 0);
-
- BuildEventContext currentBuildEventContext = new BuildEventContext(0, 1, 2, 3, 4, 5, 6);
-
- BuildEventContext currentBuildEventContextSubmission = new BuildEventContext(1, 0, 0, 0, 0, 0, 0);
- BuildEventContext currentBuildEventContextNode = new BuildEventContext(0, 1, 0, 0, 0, 0, 0);
- BuildEventContext currentBuildEventContextEvaluation = new BuildEventContext(0, 0, 1, 0, 0, 0, 0);
- BuildEventContext currentBuildEventContextProjectInstance = new BuildEventContext(0, 0, 0, 1, 0, 0, 0);
- BuildEventContext currentBuildEventProjectContext = new BuildEventContext(0, 0, 0, 0, 1, 0, 0);
- BuildEventContext currentBuildEventContextTarget = new BuildEventContext(0, 0, 0, 0, 0, 1, 0);
- BuildEventContext currentBuildEventContextTask = new BuildEventContext(0, 0, 0, 0, 0, 0, 1);
- BuildEventContext allDifferent = new BuildEventContext(1, 1, 1, 1, 1, 1, 1);
- BuildEventContext allSame = new BuildEventContext(0, 0, 0, 0, 0, 0, 0);
+ BuildEventContext parentBuildEventContext = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(0).WithProjectContextId(0).WithTargetId(0).WithTaskId(0);
+
+ BuildEventContext currentBuildEventContext = BuildEventContext.CreateInitial(0, 1).WithEvaluationId(2).WithProjectInstanceId(3).WithProjectContextId(4).WithTargetId(5).WithTaskId(6);
+
+ BuildEventContext currentBuildEventContextSubmission = BuildEventContext.CreateInitial(1, 0).WithEvaluationId(0).WithProjectInstanceId(0).WithProjectContextId(0).WithTargetId(0).WithTaskId(0);
+ BuildEventContext currentBuildEventContextNode = BuildEventContext.CreateInitial(0, 1).WithEvaluationId(0).WithProjectInstanceId(0).WithProjectContextId(0).WithTargetId(0).WithTaskId(0);
+ BuildEventContext currentBuildEventContextEvaluation = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(1).WithProjectInstanceId(0).WithProjectContextId(0).WithTargetId(0).WithTaskId(0);
+ BuildEventContext currentBuildEventContextProjectInstance = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(1).WithProjectContextId(0).WithTargetId(0).WithTaskId(0);
+ BuildEventContext currentBuildEventProjectContext = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(0).WithProjectContextId(1).WithTargetId(0).WithTaskId(0);
+ BuildEventContext currentBuildEventContextTarget = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(0).WithProjectContextId(0).WithTargetId(1).WithTaskId(0);
+ BuildEventContext currentBuildEventContextTask = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(0).WithProjectContextId(0).WithTargetId(0).WithTaskId(1);
+ BuildEventContext allDifferent = BuildEventContext.CreateInitial(1, 1).WithEvaluationId(1).WithProjectInstanceId(1).WithProjectContextId(1).WithTargetId(1).WithTaskId(1);
+ BuildEventContext allSame = BuildEventContext.CreateInitial(0, 0).WithEvaluationId(0).WithProjectInstanceId(0).WithProjectContextId(0).WithTargetId(0).WithTaskId(0);
ProjectStartedEventArgs startedEvent = new ProjectStartedEventArgs(-1, "Message", "HELP", "File", "Targets", null, null, parentBuildEventContext);
startedEvent.BuildEventContext = currentBuildEventContext;
diff --git a/src/Framework.UnitTests/ExtendedBuildEventArgs_Tests.cs b/src/Framework.UnitTests/ExtendedBuildEventArgs_Tests.cs
index 47a7bbe5b54..cf36b3856fa 100644
--- a/src/Framework.UnitTests/ExtendedBuildEventArgs_Tests.cs
+++ b/src/Framework.UnitTests/ExtendedBuildEventArgs_Tests.cs
@@ -26,7 +26,7 @@ public void ExtendedCustomBuildEventArgs_SerializationDeserialization(bool withO
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6).WithTaskId(7) : null,
};
using MemoryStream stream = new MemoryStream();
@@ -64,7 +64,7 @@ public void ExtendedErrorEventArgs_SerializationDeserialization(bool withOptiona
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6).WithTaskId(7) : null,
};
using MemoryStream stream = new MemoryStream();
@@ -103,7 +103,7 @@ public void ExtendedWarningEventArgs_SerializationDeserialization(bool withOptio
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6).WithTaskId(7) : null,
};
using MemoryStream stream = new MemoryStream();
@@ -141,7 +141,7 @@ public void ExtendedMessageEventArgs_SerializationDeserialization(bool withOptio
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6).WithTaskId(7) : null,
};
using MemoryStream stream = new MemoryStream();
@@ -178,7 +178,7 @@ public void ExtendedCriticalMessageEventArgs_SerializationDeserialization(bool w
{
ExtendedData = withOptionalData ? /*lang=json*/ "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary { { "m1", "v1" }, { "m2", "v2" } } : null,
- BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
+ BuildEventContext = withOptionalData ? BuildEventContext.CreateInitial(1, 2).WithEvaluationId(3).WithProjectInstanceId(4).WithProjectContextId(5).WithTargetId(6).WithTaskId(7) : null,
};
using MemoryStream stream = new MemoryStream();
diff --git a/src/Framework.UnitTests/ProjectStartedEventArgs_Tests.cs b/src/Framework.UnitTests/ProjectStartedEventArgs_Tests.cs
index a8ba7a3286a..067ad3f27db 100644
--- a/src/Framework.UnitTests/ProjectStartedEventArgs_Tests.cs
+++ b/src/Framework.UnitTests/ProjectStartedEventArgs_Tests.cs
@@ -21,7 +21,6 @@ public class ProjectStartedEventArgs_Tests
///
public ProjectStartedEventArgs_Tests()
{
- BuildEventContext parentBuildEventContext = new BuildEventContext(2, 3, 4, 5);
}
///
diff --git a/src/Framework/BinaryReaderExtensions.cs b/src/Framework/BinaryReaderExtensions.cs
index 8cc81b03988..98d73e4f153 100644
--- a/src/Framework/BinaryReaderExtensions.cs
+++ b/src/Framework/BinaryReaderExtensions.cs
@@ -78,7 +78,12 @@ public static BuildEventContext ReadBuildEventContext(this BinaryReader reader)
int projectInstanceId = reader.ReadInt32();
int evaluationId = reader.ReadInt32();
- var buildEventContext = new BuildEventContext(submissionId, nodeId, evaluationId, projectInstanceId, projectContextId, targetId, taskId);
+ var buildEventContext = BuildEventContext.CreateInitial(submissionId, nodeId)
+ .WithEvaluationId(evaluationId)
+ .WithProjectInstanceId(projectInstanceId)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(targetId)
+ .WithTaskId(taskId);
return buildEventContext;
}
diff --git a/src/Framework/BinaryTranslator.cs b/src/Framework/BinaryTranslator.cs
index 518b31ab30b..802d98f33e3 100644
--- a/src/Framework/BinaryTranslator.cs
+++ b/src/Framework/BinaryTranslator.cs
@@ -485,14 +485,20 @@ public void Translate(ref TimeSpan value)
/// The context to be translated.
public void Translate(ref BuildEventContext value)
{
- value = new BuildEventContext(
- _reader.ReadInt32(),
- _reader.ReadInt32(),
- _reader.ReadInt32(),
- _reader.ReadInt32(),
- _reader.ReadInt32(),
- _reader.ReadInt32(),
- _reader.ReadInt32());
+ int submissionId = _reader.ReadInt32();
+ int nodeId = _reader.ReadInt32();
+ int evaluationId = _reader.ReadInt32();
+ int projectInstanceId = _reader.ReadInt32();
+ int projectContextId = _reader.ReadInt32();
+ int targetId = _reader.ReadInt32();
+ int taskId = _reader.ReadInt32();
+
+ value = BuildEventContext.CreateInitial(submissionId, nodeId)
+ .WithEvaluationId(evaluationId)
+ .WithProjectInstanceId(projectInstanceId)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(targetId)
+ .WithTaskId(taskId);
}
///
diff --git a/src/Framework/BuildEventArgs.cs b/src/Framework/BuildEventArgs.cs
index 3ea2c615208..97dd3c089d0 100644
--- a/src/Framework/BuildEventArgs.cs
+++ b/src/Framework/BuildEventArgs.cs
@@ -240,11 +240,19 @@ internal virtual void CreateFromStream(BinaryReader reader, int version)
int submissionId = reader.ReadInt32();
int projectInstanceId = reader.ReadInt32();
int evaluationId = reader.ReadInt32();
- buildEventContext = new BuildEventContext(submissionId, nodeId, evaluationId, projectInstanceId, projectContextId, targetId, taskId);
+ buildEventContext = BuildEventContext.CreateInitial(submissionId, nodeId)
+ .WithEvaluationId(evaluationId)
+ .WithProjectInstanceId(projectInstanceId)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(targetId)
+ .WithTaskId(taskId);
}
else
{
- buildEventContext = new BuildEventContext(nodeId, targetId, projectContextId, taskId);
+ buildEventContext = BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, nodeId)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(targetId)
+ .WithTaskId(taskId);
}
}
}
diff --git a/src/Framework/BuildEventContext.cs b/src/Framework/BuildEventContext.cs
index 83a7a1f9330..a9f5d4c6e28 100644
--- a/src/Framework/BuildEventContext.cs
+++ b/src/Framework/BuildEventContext.cs
@@ -2,12 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.ComponentModel;
namespace Microsoft.Build.Framework
{
///
/// Will provide location information for an event, this is especially
- /// needed in a multi processor environment
+ /// needed in a multi processor environment.
+ ///
+ /// BuildEventContext objects should be created using the static CreateInitial method
+ /// for the root context, then using the fluent WithXxx methods to create derived contexts
+ /// that preserve all ID properties while updating specific ones.
///
[Serializable]
public class BuildEventContext
@@ -51,37 +56,68 @@ public class BuildEventContext
#endregion
- #region Constructor
-
///
- /// This is the original constructor. No one should ever use this except internally for backward compatibility.
+ /// This is the original constructor. No one should ever use this except internally for backward compatibility.
+ /// Use , , or and the fluent WithXxx methods instead.
///
+ ///
+ /// This constructor is obsolete and will be removed in a future version.
+ /// It does not set , , or ,
+ /// making it easy to accidentally lose important context data.
+ /// Prefer the builder pattern: BuildEventContext.CreateInitial(submissionId, nodeId).WithProjectContextId(...).WithTargetId(...).WithTaskId(...)
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
public BuildEventContext(
int nodeId,
int targetId,
int projectContextId,
int taskId)
- : this(InvalidSubmissionId, nodeId, InvalidEvaluationId, InvalidProjectInstanceId, projectContextId, targetId, taskId)
{
- // UNDONE: This is obsolete.
+ _submissionId = InvalidSubmissionId;
+ _nodeId = nodeId;
+ _evaluationId = InvalidEvaluationId;
+ _projectInstanceId = InvalidProjectInstanceId;
+ _projectContextId = projectContextId;
+ _targetId = targetId;
+ _taskId = taskId;
}
///
/// Constructs a BuildEventContext with a specified project instance id.
- ///
+ /// Use , , or and the fluent WithXxx methods instead.
+ ///
+ ///
+ /// This constructor is obsolete and will be removed in a future version.
+ /// It does not set or ,
+ /// making it easy to accidentally lose important context data.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
public BuildEventContext(
int nodeId,
int projectInstanceId,
int projectContextId,
int targetId,
int taskId)
- : this(InvalidSubmissionId, nodeId, InvalidEvaluationId, projectInstanceId, projectContextId, targetId, taskId)
{
+ _submissionId = InvalidSubmissionId;
+ _nodeId = nodeId;
+ _evaluationId = InvalidEvaluationId;
+ _projectInstanceId = projectInstanceId;
+ _projectContextId = projectContextId;
+ _targetId = targetId;
+ _taskId = taskId;
}
///
- /// Constructs a BuildEventContext with a specific submission id
+ /// Constructs a BuildEventContext with a specific submission id.
+ /// Use , , or and the fluent WithXxx methods instead.
///
+ ///
+ /// This constructor is obsolete and will be removed in a future version.
+ /// It does not set ,
+ /// making it easy to accidentally lose important context data.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
public BuildEventContext(
int submissionId,
int nodeId,
@@ -89,13 +125,26 @@ public BuildEventContext(
int projectContextId,
int targetId,
int taskId)
- : this(submissionId, nodeId, InvalidEvaluationId, projectInstanceId, projectContextId, targetId, taskId)
{
+ _submissionId = submissionId;
+ _nodeId = nodeId;
+ _evaluationId = InvalidEvaluationId;
+ _projectInstanceId = projectInstanceId;
+ _projectContextId = projectContextId;
+ _targetId = targetId;
+ _taskId = taskId;
}
///
- /// Constructs a BuildEventContext
+ /// Constructs a BuildEventContext with all parameters specified.
+ /// Use , , or and the fluent WithXxx methods instead.
///
+ ///
+ /// This constructor is obsolete and will be removed in a future version.
+ /// Prefer the builder pattern which makes it impossible to accidentally drop ID values:
+ /// BuildEventContext.CreateInitial(submissionId, nodeId).WithEvaluationId(...).WithProjectInstanceId(...)
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
public BuildEventContext(
int submissionId,
int nodeId,
@@ -114,24 +163,117 @@ public BuildEventContext(
_projectInstanceId = projectInstanceId;
}
- #endregion
- internal BuildEventContext WithInstanceIdAndContextId(int projectInstanceId, int projectContextId)
- {
- return new BuildEventContext(_submissionId, _nodeId, _evaluationId, projectInstanceId, projectContextId,
- _targetId, _taskId);
- }
+ #region Builders
- internal BuildEventContext WithInstanceIdAndContextId(BuildEventContext other)
- {
- return WithInstanceIdAndContextId(other.ProjectInstanceId, other.ProjectContextId);
- }
+ ///
+ /// Creates a root context for a build submission. Used by BuildManager when starting a new submission.
+ /// The node ID will be set later when the submission is assigned to a node.
+ ///
+ /// The submission ID
+ /// A builder for creating the BuildEventContext
+ public static BuildEventContextBuilder CreateForSubmission(int submissionId) =>
+ new BuildEventContextBuilder()
+ .WithSubmissionId(submissionId)
+ .WithNodeId(InvalidNodeId);
+
+ ///
+ /// Creates a root context for a node. Used by nodes when initializing their logging context.
+ /// The submission ID will be set later when processing build requests.
+ ///
+ /// The node ID
+ /// A builder for creating the BuildEventContext
+ public static BuildEventContextBuilder CreateForNode(int nodeId) =>
+ new BuildEventContextBuilder()
+ .WithSubmissionId(InvalidSubmissionId)
+ .WithNodeId(nodeId);
+
+ ///
+ /// Creates an initial BuildEventContext for the beginning of a build.
+ /// Uses the efficient builder pattern to minimize allocations.
+ ///
+ ///
+ /// The submission ID
+ /// The node ID
+ /// A new BuildEventContext with the specified submission and node ID
+ /// Strongly suggest not using this member directly. Prefer building off of an inherited ,
+ /// or use the more-directed factory functions or and build from there.
+ public static BuildEventContextBuilder CreateInitial(int submissionId, int nodeId) => new BuildEventContextBuilder().WithSubmissionId(submissionId).WithNodeId(nodeId);
+
+ ///
+ /// Creates a new builder with the specified submission ID, preserving all other IDs.
+ /// Returns a builder to enable efficient chaining without intermediate allocations.
+ /// Call Build() to create the final BuildEventContext.
+ ///
+ /// The new submission ID
+ /// A builder with the updated submission ID
+ public BuildEventContextBuilder WithSubmissionId(int submissionId) => Builder(this).WithSubmissionId(submissionId);
+
+ ///
+ /// Creates a new builder with the specified node ID, preserving all other IDs.
+ /// Returns a builder to enable efficient chaining without intermediate allocations.
+ /// Call Build() to create the final BuildEventContext.
+ ///
+ /// The new node ID
+ /// A builder with the updated node ID
+ public BuildEventContextBuilder WithNodeId(int nodeId) => Builder(this).WithNodeId(nodeId);
+
+ ///
+ /// Creates a new builder with the specified evaluation ID, preserving all other IDs.
+ /// Returns a builder to enable efficient chaining without intermediate allocations.
+ /// Call Build() to create the final BuildEventContext.
+ ///
+ /// The new evaluation ID
+ /// A builder with the updated evaluation ID
+ public BuildEventContextBuilder WithEvaluationId(int evaluationId) => Builder(this).WithEvaluationId(evaluationId);
+
+ ///
+ /// Creates a new builder with the specified project instance ID, preserving all other IDs.
+ /// Returns a builder to enable efficient chaining without intermediate allocations.
+ /// Call Build() to create the final BuildEventContext.
+ ///
+ /// The new project instance ID
+ /// A builder with the updated project instance ID
+ public BuildEventContextBuilder WithProjectInstanceId(int projectInstanceId) => Builder(this).WithProjectInstanceId(projectInstanceId);
+
+ ///
+ /// Creates a new builder with the specified project context ID, preserving all other IDs.
+ /// Returns a builder to enable efficient chaining without intermediate allocations.
+ /// Call Build() to create the final BuildEventContext.
+ ///
+ /// The new project context ID
+ /// A builder with the updated project context ID
+ public BuildEventContextBuilder WithProjectContextId(int projectContextId) => Builder(this).WithProjectContextId(projectContextId);
+
+ ///
+ /// Creates a new builder with the specified target ID, preserving all other IDs.
+ /// Returns a builder to enable efficient chaining without intermediate allocations.
+ /// Call Build() to create the final BuildEventContext.
+ ///
+ /// The new target ID
+ /// A builder with the updated target ID
+ public BuildEventContextBuilder WithTargetId(int targetId) => Builder(this).WithTargetId(targetId);
+
+ ///
+ /// Creates a new builder with the specified task ID, preserving all other IDs.
+ /// Returns a builder to enable efficient chaining without intermediate allocations.
+ /// Call Build() to create the final BuildEventContext.
+ ///
+ /// The new task ID
+ /// A builder with the updated task ID
+ public BuildEventContextBuilder WithTaskId(int taskId) => Builder(this).WithTaskId(taskId);
+ #endregion
#region Properties
///
/// Returns a default invalid BuildEventContext
///
- public static BuildEventContext Invalid { get; } = new BuildEventContext(InvalidNodeId, InvalidTargetId, InvalidProjectContextId, InvalidTaskId);
+ public static BuildEventContext Invalid { get; } = CreateInitial(InvalidSubmissionId, InvalidNodeId)
+ .WithEvaluationId(InvalidEvaluationId)
+ .WithProjectInstanceId(InvalidProjectInstanceId)
+ .WithProjectContextId(InvalidProjectContextId)
+ .WithTargetId(InvalidTargetId)
+ .WithTaskId(InvalidTaskId);
///
/// Retrieves the Evaluation id.
@@ -159,7 +301,7 @@ internal BuildEventContext WithInstanceIdAndContextId(BuildEventContext other)
public int TaskId => _taskId;
///
- /// Retrieves the project instance id.
+ /// Retrieves the project instance id, AKA the Configuration Id (AKA BuildRequestConfiguration.Id)
///
public int ProjectInstanceId => _projectInstanceId;
@@ -297,20 +439,182 @@ public override bool Equals(object? obj)
///
/// BuildEventContext to compare to this instance
/// True if the value fields are the same, false if otherwise
- private bool InternalEquals(BuildEventContext buildEventContext)
- {
- return _nodeId == buildEventContext.NodeId
+ private bool InternalEquals(BuildEventContext buildEventContext) => _nodeId == buildEventContext.NodeId
&& _projectContextId == buildEventContext.ProjectContextId
&& _targetId == buildEventContext.TargetId
&& _taskId == buildEventContext.TaskId
&& _evaluationId == buildEventContext._evaluationId
&& _projectInstanceId == buildEventContext._projectInstanceId;
- }
#endregion
- public override string ToString()
+ public override string ToString() => $"Node={NodeId} Submission={SubmissionId} ProjectContext={ProjectContextId} ProjectInstance={ProjectInstanceId} Eval={EvaluationId} Target={TargetId} Task={TaskId}";
+
+ #region Builder Pattern
+
+ ///
+ /// Creates a new builder initialized from an existing BuildEventContext.
+ /// This allows for efficient copying and modification of existing contexts.
+ ///
+ /// The BuildEventContext to copy values from
+ /// A new BuildEventContextBuilder initialized with the source values
+ public static BuildEventContextBuilder Builder(BuildEventContext source) => new(source);
+
+ #endregion
+ }
+
+ ///
+ /// A ref struct builder for efficiently constructing BuildEventContext instances.
+ /// This builder eliminates heap allocations during the building process and provides
+ /// a fluent API for setting context properties.
+ ///
+ /// Usage:
+ /// var context = BuildEventContext.Builder()
+ /// .WithSubmissionId(1)
+ /// .WithNodeId(2)
+ /// .WithProjectInstanceId(3)
+ /// .Build();
+ ///
+ public ref struct BuildEventContextBuilder
+ {
+ private int _submissionId;
+ private int _nodeId;
+ private int _evaluationId;
+ private int _projectInstanceId;
+ private int _projectContextId;
+ private int _targetId;
+ private int _taskId;
+
+ ///
+ /// Initializes a new BuildEventContextBuilder with invalid values for all IDs.
+ ///
+ public BuildEventContextBuilder()
+ {
+ _submissionId = BuildEventContext.InvalidSubmissionId;
+ _nodeId = BuildEventContext.InvalidNodeId;
+ _evaluationId = BuildEventContext.InvalidEvaluationId;
+ _projectInstanceId = BuildEventContext.InvalidProjectInstanceId;
+ _projectContextId = BuildEventContext.InvalidProjectContextId;
+ _targetId = BuildEventContext.InvalidTargetId;
+ _taskId = BuildEventContext.InvalidTaskId;
+ }
+
+ ///
+ /// Initializes a new BuildEventContextBuilder with values from an existing BuildEventContext.
+ ///
+ /// The BuildEventContext to copy values from
+ public BuildEventContextBuilder(BuildEventContext source)
+ {
+ _submissionId = source.SubmissionId;
+ _nodeId = source.NodeId;
+ _evaluationId = source.EvaluationId;
+ _projectInstanceId = source.ProjectInstanceId;
+ _projectContextId = source.ProjectContextId;
+ _targetId = source.TargetId;
+ _taskId = source.TaskId;
+ }
+
+ ///
+ /// Sets the submission ID and returns this builder for chaining.
+ ///
+ /// The submission ID
+ /// This builder instance
+ public BuildEventContextBuilder WithSubmissionId(int submissionId)
+ {
+ _submissionId = submissionId;
+ return this;
+ }
+
+ ///
+ /// Sets the node ID and returns this builder for chaining.
+ ///
+ /// The node ID
+ /// This builder instance
+ public BuildEventContextBuilder WithNodeId(int nodeId)
+ {
+ _nodeId = nodeId;
+ return this;
+ }
+
+ ///
+ /// Sets the evaluation ID and returns this builder for chaining.
+ ///
+ /// The evaluation ID
+ /// This builder instance
+ public BuildEventContextBuilder WithEvaluationId(int evaluationId)
+ {
+ _evaluationId = evaluationId;
+ return this;
+ }
+
+ ///
+ /// Sets the project instance ID and returns this builder for chaining.
+ ///
+ /// The project instance ID
+ /// This builder instance
+ public BuildEventContextBuilder WithProjectInstanceId(int projectInstanceId)
+ {
+ _projectInstanceId = projectInstanceId;
+ return this;
+ }
+
+ ///
+ /// Sets the project context ID and returns this builder for chaining.
+ ///
+ /// The project context ID
+ /// This builder instance
+ public BuildEventContextBuilder WithProjectContextId(int projectContextId)
+ {
+ _projectContextId = projectContextId;
+ return this;
+ }
+
+ ///
+ /// Sets the target ID and returns this builder for chaining.
+ ///
+ /// The target ID
+ /// This builder instance
+ public BuildEventContextBuilder WithTargetId(int targetId)
+ {
+ _targetId = targetId;
+ return this;
+ }
+
+ ///
+ /// Sets the task ID and returns this builder for chaining.
+ ///
+ /// The task ID
+ /// This builder instance
+ public BuildEventContextBuilder WithTaskId(int taskId)
+ {
+ _taskId = taskId;
+ return this;
+ }
+
+ ///
+ /// Builds the final BuildEventContext instance.
+ /// This is the only operation that allocates memory on the heap.
+ ///
+ /// A new BuildEventContext with the configured values
+#pragma warning disable RS0030 // Banned API - Build() is the only sanctioned way to create BuildEventContext from builder
+ public readonly BuildEventContext Build() => new BuildEventContext(
+ _submissionId,
+ _nodeId,
+ _evaluationId,
+ _projectInstanceId,
+ _projectContextId,
+ _targetId,
+ _taskId);
+#pragma warning restore RS0030
+
+ ///
+ /// Implicit conversion from builder to BuildEventContext for convenience.
+ /// This allows the builder to be used directly where a BuildEventContext is expected.
+ ///
+ /// The builder to convert
+ /// A new BuildEventContext built from the builder
+ public static implicit operator BuildEventContext(BuildEventContextBuilder builder)
{
- return $"Node={NodeId} Submission={SubmissionId} ProjectContext={ProjectContextId} ProjectInstance={ProjectInstanceId} Eval={EvaluationId} Target={TargetId} Task={TaskId}";
+ return builder.Build();
}
}
}
diff --git a/src/Framework/ProjectStartedEventArgs.cs b/src/Framework/ProjectStartedEventArgs.cs
index 57aefbe97c4..1026c82c2ea 100644
--- a/src/Framework/ProjectStartedEventArgs.cs
+++ b/src/Framework/ProjectStartedEventArgs.cs
@@ -117,6 +117,38 @@ public ProjectStartedEventArgs(
this.ToolsVersion = toolsVersion;
}
+ ///
+ /// This constructor allows event data to be initialized including the original build event context.
+ /// Sender is assumed to be "MSBuild".
+ ///
+ /// project id
+ /// text message
+ /// help keyword
+ /// project name
+ /// targets we are going to build (empty indicates default targets)
+ /// list of properties
+ /// list of items
+ /// event context info for the parent project
+ /// An containing global properties.
+ /// The tools version.
+ /// original build event context from the remote node. This should contain node, submission, evaluation and projectInstance Ids at minimum.
+ public ProjectStartedEventArgs(
+ int projectId,
+ string message,
+ string helpKeyword,
+ string? projectFile,
+ string? targetNames,
+ IEnumerable? properties,
+ IEnumerable? items,
+ BuildEventContext? parentBuildEventContext,
+ IDictionary? globalProperties,
+ string? toolsVersion,
+ BuildEventContext? originalBuildEventContext)
+ : this(projectId, message, helpKeyword, projectFile, targetNames, properties, items, parentBuildEventContext, globalProperties, toolsVersion)
+ {
+ this.originalBuildEventContext = originalBuildEventContext;
+ }
+
///
/// This constructor allows event data to be initialized. Also the timestamp can be set
/// Sender is assumed to be "MSBuild".
@@ -139,7 +171,7 @@ public ProjectStartedEventArgs(
: base(message, helpKeyword, "MSBuild", eventTimestamp)
{
this.projectFile = projectFile;
- this.targetNames = targetNames ?? String.Empty;
+ this.targetNames = targetNames ?? string.Empty;
this.properties = properties;
this.items = items;
}
@@ -173,6 +205,36 @@ public ProjectStartedEventArgs(
this.projectId = projectId;
}
+ ///
+ /// This constructor allows event data to be initialized including the original build event context.
+ /// Sender is assumed to be "MSBuild".
+ ///
+ /// project id
+ /// text message
+ /// help keyword
+ /// project name
+ /// targets we are going to build (empty indicates default targets)
+ /// list of properties
+ /// list of items
+ /// event context info for the parent project
+ /// original build event context from the remote node
+ /// The of the event.
+ public ProjectStartedEventArgs(
+ int projectId,
+ string message,
+ string helpKeyword,
+ string? projectFile,
+ string? targetNames,
+ IEnumerable? properties,
+ IEnumerable? items,
+ BuildEventContext? parentBuildEventContext,
+ BuildEventContext? originalBuildEventContext,
+ DateTime eventTimestamp)
+ : this(projectId, message, helpKeyword, projectFile, targetNames, properties, items, parentBuildEventContext, eventTimestamp)
+ {
+ this.originalBuildEventContext = originalBuildEventContext;
+ }
+
// ProjectId is only contained in the project started event.
// This number indicated the instance id of the project and can be
// used when debugging to determine if two projects with the same name
@@ -205,6 +267,22 @@ public BuildEventContext? ParentProjectBuildEventContext
}
}
+ [OptionalField(VersionAdded = 3)]
+ private BuildEventContext? originalBuildEventContext;
+
+ ///
+ /// The (possibly null) from the original project build.
+ /// This contains the full context data from when the project was first built on the original node,
+ /// and should be used for evaluation ID tracking and build correlation in distributed scenarios.
+ ///
+ public BuildEventContext? OriginalBuildEventContext
+ {
+ get
+ {
+ return originalBuildEventContext;
+ }
+ }
+
///
/// The name of the project file
///
@@ -350,7 +428,7 @@ public IEnumerable? Items
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
- writer.Write((Int32)projectId);
+ writer.Write(projectId);
if (parentProjectBuildEventContext == null)
{
@@ -359,12 +437,15 @@ internal override void WriteToStream(BinaryWriter writer)
else
{
writer.Write((byte)1);
- writer.Write((Int32)parentProjectBuildEventContext.NodeId);
- writer.Write((Int32)parentProjectBuildEventContext.ProjectContextId);
- writer.Write((Int32)parentProjectBuildEventContext.TargetId);
- writer.Write((Int32)parentProjectBuildEventContext.TaskId);
- writer.Write((Int32)parentProjectBuildEventContext.SubmissionId);
- writer.Write((Int32)parentProjectBuildEventContext.ProjectInstanceId);
+ writer.Write(parentProjectBuildEventContext.NodeId);
+ writer.Write(parentProjectBuildEventContext.ProjectContextId);
+ writer.Write(parentProjectBuildEventContext.TargetId);
+ writer.Write(parentProjectBuildEventContext.TaskId);
+ // added these in version 20
+ writer.Write(parentProjectBuildEventContext.SubmissionId);
+ writer.Write(parentProjectBuildEventContext.ProjectInstanceId);
+ // added this in version 36
+ writer.Write(parentProjectBuildEventContext.EvaluationId);
}
writer.WriteOptionalString(projectFile);
@@ -401,6 +482,23 @@ internal override void WriteToStream(BinaryWriter writer)
WriteCollection(writer, WarningsAsErrors);
WriteCollection(writer, WarningsNotAsErrors);
WriteCollection(writer, WarningsAsMessages);
+
+ // Write OriginalBuildEventContext (version 3+ field)
+ if (originalBuildEventContext == null)
+ {
+ writer.Write((byte)0);
+ }
+ else
+ {
+ writer.Write((byte)1);
+ writer.Write(originalBuildEventContext.SubmissionId);
+ writer.Write(originalBuildEventContext.NodeId);
+ writer.Write(originalBuildEventContext.EvaluationId);
+ writer.Write(originalBuildEventContext.ProjectInstanceId);
+ writer.Write(originalBuildEventContext.ProjectContextId);
+ writer.Write(originalBuildEventContext.TargetId);
+ writer.Write(originalBuildEventContext.TaskId);
+ }
}
///
@@ -424,16 +522,28 @@ internal override void CreateFromStream(BinaryReader reader, int version)
int targetId = reader.ReadInt32();
int taskId = reader.ReadInt32();
+ var builder =
+ BuildEventContext.CreateInitial(BuildEventContext.InvalidSubmissionId, nodeId)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(targetId)
+ .WithTaskId(taskId);
+
if (version > 20)
{
int submissionId = reader.ReadInt32();
int projectInstanceId = reader.ReadInt32();
- parentProjectBuildEventContext = new BuildEventContext(submissionId, nodeId, projectInstanceId, projectContextId, targetId, taskId);
- }
- else
- {
- parentProjectBuildEventContext = new BuildEventContext(nodeId, targetId, projectContextId, taskId);
+
+ builder = builder.WithSubmissionId(submissionId)
+ .WithProjectInstanceId(projectInstanceId);
+
+ if (version >= 36)
+ {
+ int evaluationId = reader.ReadInt32();
+ builder = builder.WithEvaluationId(evaluationId);
+ }
}
+
+ parentProjectBuildEventContext = builder.Build();
}
projectFile = reader.ReadByte() == 0 ? null : reader.ReadString();
@@ -473,6 +583,32 @@ internal override void CreateFromStream(BinaryReader reader, int version)
WarningsAsErrors = ReadStringSet(reader);
WarningsNotAsErrors = ReadStringSet(reader);
WarningsAsMessages = ReadStringSet(reader);
+
+ // Read OriginalBuildEventContext (version 3+ field)
+ if (version >= 3)
+ {
+ if (reader.ReadByte() == 0)
+ {
+ originalBuildEventContext = null;
+ }
+ else
+ {
+ int submissionId = reader.ReadInt32();
+ int nodeId = reader.ReadInt32();
+ int evaluationId = reader.ReadInt32();
+ int projectInstanceId = reader.ReadInt32();
+ int projectContextId = reader.ReadInt32();
+ int targetId = reader.ReadInt32();
+ int taskId = reader.ReadInt32();
+
+ originalBuildEventContext = BuildEventContext.CreateInitial(submissionId, nodeId)
+ .WithEvaluationId(evaluationId)
+ .WithProjectInstanceId(projectInstanceId)
+ .WithProjectContextId(projectContextId)
+ .WithTargetId(targetId)
+ .WithTaskId(taskId);
+ }
+ }
}
private static void WriteCollection(BinaryWriter writer, ICollection? collection)
@@ -521,6 +657,7 @@ private void SetDefaultsBeforeSerialization(StreamingContext sc)
// Don't want to set the default before deserialization is completed to a new event context because
// that would most likely be a lot of wasted allocations
parentProjectBuildEventContext = null;
+ originalBuildEventContext = null;
}
[OnDeserialized]
@@ -530,6 +667,11 @@ private void SetDefaultsAfterSerialization(StreamingContext sc)
{
parentProjectBuildEventContext = BuildEventContext.Invalid;
}
+
+ if (originalBuildEventContext == null)
+ {
+ originalBuildEventContext = BuildEventContext.Invalid;
+ }
}
#endregion