зеркало из https://github.com/microsoft/BuildXL.git
Merged PR 712282: Change the warning logging message displayed on ADO console for DX65 warnings.
Created a new PR as the old one has a lot of test commits. Adding changes to AzureDevOpsListener.cs to change the warning logging message displayed on ADO for DX65 warnings. Modified the unit tests to accommodate the corresponding coding changes in DevOpsListener.cs Modified Interfaces.Proto file accordingly to ensure the PipProcessEvent works for PipProcessWarnings and PipProcessErrors. Refactored PipProcessErrorEventFields class to accommodate both PipProcessErrorEvent and PipProcessWarningEvents. Created another constructor for PipProcessWarning event to avoid issues related to default values. Before: https://dev.azure.com/mseng/Domino/_build/results?buildId=19672141&view=logs&j=275f1d19-1bd8-5591-b06b-07d489ea915a&t=1e890290-1da7-4ac9-b698-21f5ae7ff179 After: https://dev.azure.com/mseng/Domino/_build/results?buildId=19671509&view=logs&j=275f1d19-1bd8-5591-b06b-07d489ea915a&t=9dd78ff8-514f-446d-b196-fc754a84acf9&l=375 This change highlights only OutputToLog segment of DX65 warning message as we want only this part to be highlighted. Adding the previous PR as that has some of the comments related to this PR. https://dev.azure.com/mseng/Domino/_git/BuildXL.Internal/pullrequest/711253
This commit is contained in:
Родитель
32b607700e
Коммит
621bffcfc4
|
@ -189,24 +189,32 @@ namespace BuildXL
|
|||
int dxCode = eventData.EventId;
|
||||
var message = eventData.Message;
|
||||
var args = eventData.Payload == null ? CollectionUtilities.EmptyArray<object>() : eventData.Payload.ToArray();
|
||||
var addFormattingToEventMessage = Environment.NewLine;
|
||||
|
||||
// construct a short message for ADO console
|
||||
if ((eventData.EventId == (int)LogEventId.PipProcessError)
|
||||
|| (eventData.EventId == (int)SharedLogEventId.DistributionWorkerForwardedError && (int)args[1] == (int)LogEventId.PipProcessError))
|
||||
{
|
||||
dxCode = (int)LogEventId.PipProcessError;
|
||||
var pipProcessError = new PipProcessErrorEventFields(eventData.Payload, eventData.EventId != (int)LogEventId.PipProcessError);
|
||||
var pipProcessError = new PipProcessEventFields(eventData.Payload, forwardedPayload: eventData.EventId != (int)LogEventId.PipProcessError, isPipProcessError: true);
|
||||
var pipSemiStableHash = Pip.FormatSemiStableHash(pipProcessError.PipSemiStableHash);
|
||||
var formattedDXCode = FormatErrorCode(dxCode);
|
||||
var formattedDXCode = FormatErrorCode((int)LogEventId.PipProcessError);
|
||||
|
||||
// Splitting the error message into different segments and logging them individually as we want only OutputsToLog to be highlighted.
|
||||
var errorMessagePrefix = @$"{formattedDXCode}[{pipSemiStableHash}, {pipProcessError.ShortPipDescription}, {pipProcessError.PipSpecPath}] - failed with exit code {pipProcessError.ExitCode}, {pipProcessError.OptionalMessage}";
|
||||
m_console.WriteOutputLine(MessageLevel.Info, errorMessagePrefix);
|
||||
var errorMessageSuffix = $"{pipProcessError.MessageAboutPathsToLog}{addFormattingToEventMessage}{pipProcessError.PathsToLog}";
|
||||
LogPipProcessEventMessage(errorMessagePrefix, pipProcessError.OutputToLog, errorMessageSuffix, eventType);
|
||||
}
|
||||
else if ((eventData.EventId == (int)LogEventId.PipProcessWarning)
|
||||
|| (eventData.EventId == (int)SharedLogEventId.DistributionWorkerForwardedWarning && (int)args[1] == (int)LogEventId.PipProcessWarning))
|
||||
{
|
||||
var pipProcessWarning = new PipProcessEventFields(eventData.Payload, forwardedPayload: eventData.EventId != (int)LogEventId.PipProcessWarning, isPipProcessError: false);
|
||||
var formattedDXCode = FormatErrorCode((int)LogEventId.PipProcessWarning);
|
||||
var pipSemiStableHash = Pip.FormatSemiStableHash(pipProcessWarning.PipSemiStableHash);
|
||||
|
||||
LogIssue(eventType, pipProcessError.OutputToLog);
|
||||
|
||||
var addFormattingToErrorMessage = Environment.NewLine;
|
||||
var errorMessageSuffix = $"{pipProcessError.MessageAboutPathsToLog}{addFormattingToErrorMessage}{pipProcessError.PathsToLog}";
|
||||
m_console.WriteOutputLine(MessageLevel.Info, errorMessageSuffix);
|
||||
// Splitting the warning message into different segments and logging them individually as we want only OutputsToLog to be highlighted.
|
||||
var warningMessagePrefix = @$"{formattedDXCode}[{pipSemiStableHash}, {pipProcessWarning.PipDescription}, {pipProcessWarning.PipSpecPath}] - warnings";
|
||||
var warningMessageSuffix = $"{pipProcessWarning.MessageAboutPathsToLog}{addFormattingToEventMessage}{pipProcessWarning.PathsToLog}";
|
||||
LogPipProcessEventMessage(warningMessagePrefix, pipProcessWarning.OutputToLog, warningMessageSuffix, eventType);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -221,6 +229,17 @@ namespace BuildXL
|
|||
}
|
||||
}
|
||||
|
||||
private void LogPipProcessEventMessage(string eventPrefix, string eventIssue, string eventSuffix, string eventType)
|
||||
{
|
||||
m_console.WriteOutputLine(MessageLevel.Info, eventPrefix);
|
||||
LogIssue(eventType, eventIssue);
|
||||
string formattedEventSuffix = eventSuffix.TrimEnd(Environment.NewLine.ToCharArray());
|
||||
if (!string.IsNullOrEmpty(formattedEventSuffix))
|
||||
{
|
||||
m_console.WriteOutputLine(MessageLevel.Info, formattedEventSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
private void LogIssue(string eventType, string message)
|
||||
{
|
||||
// This method logs message body which needs to be highlighted.
|
||||
|
|
|
@ -82,13 +82,13 @@ namespace BuildXL
|
|||
}
|
||||
|
||||
/// <nodoc />
|
||||
internal static void ApplyIfPipError(EventWrittenEventArgs eventData, Action<PipProcessErrorEventFields, string> addPipErrors)
|
||||
internal static void ApplyIfPipError(EventWrittenEventArgs eventData, Action<PipProcessEventFields, string> addPipErrors)
|
||||
{
|
||||
switch (eventData.EventId)
|
||||
{
|
||||
case (int)LogEventId.PipProcessError:
|
||||
{
|
||||
addPipErrors(new PipProcessErrorEventFields(eventData.Payload, false), LocalWorker.MachineName);
|
||||
addPipErrors(new PipProcessEventFields(eventData.Payload, forwardedPayload: false, isPipProcessError: true), LocalWorker.MachineName);
|
||||
}
|
||||
break;
|
||||
case (int)SharedLogEventId.DistributionWorkerForwardedError:
|
||||
|
@ -96,7 +96,7 @@ namespace BuildXL
|
|||
var actualEventId = (int)eventData.Payload[1];
|
||||
if (actualEventId == (int)LogEventId.PipProcessError)
|
||||
{
|
||||
var pipProcessErrorEventFields = new PipProcessErrorEventFields(eventData.Payload, true);
|
||||
var pipProcessErrorEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: true, isPipProcessError: true);
|
||||
addPipErrors(pipProcessErrorEventFields, (string)eventData.Payload[16]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using BuildXL;
|
||||
using BuildXL.Processes.Tracing;
|
||||
using BuildXL.Utilities.Instrumentation.Common;
|
||||
|
@ -19,53 +20,73 @@ namespace Test.BuildXL
|
|||
{
|
||||
public class DevOpsListenerTests : XunitBuildXLTest
|
||||
{
|
||||
PipProcessErrorEventFields m_eventFields;
|
||||
private PipProcessEventFields m_pipProcessEventFields;
|
||||
private const int AdoConsoleMaxIssuesToLog = 100;
|
||||
private const string PipProcessEditEventMessage = "You may have edited the PipProcessEvent and/or WorkerForwardedEvent fields, update the test and/or struct PipProcessEventFields.";
|
||||
|
||||
private int adoConsoleMaxIssuesToLog = 100;
|
||||
public DevOpsListenerTests(ITestOutputHelper output) : base(output){}
|
||||
public DevOpsListenerTests(ITestOutputHelper output) : base(output) { }
|
||||
|
||||
[Fact]
|
||||
public void LogAzureDevOpsIssueTest()
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void LogAzureDevOpsIssueTest(bool isPipProcessError)
|
||||
{
|
||||
m_eventListener.RegisterEventSource(global::BuildXL.Processes.ETWLogger.Log);
|
||||
m_eventListener.NestedLoggerHandler += eventData =>
|
||||
{
|
||||
m_eventFields = new PipProcessErrorEventFields(eventData.Payload, false);
|
||||
if (isPipProcessError)
|
||||
{
|
||||
m_pipProcessEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: false, isPipProcessError: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pipProcessEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: false, isPipProcessError: false);
|
||||
}
|
||||
};
|
||||
|
||||
using (var testElements = PipProcessErrorTestElement.Create(this))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, testElements.Console, DateTime.Now, testElements.ViewModel, false, null, adoConsoleMaxIssuesToLog))
|
||||
using (var testElements = PipProcessEventTestElement.Create(this, isPipProcessError: isPipProcessError))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, testElements.Console, DateTime.Now, testElements.ViewModel, false, null, AdoConsoleMaxIssuesToLog))
|
||||
{
|
||||
listener.RegisterEventSource(global::BuildXL.Processes.ETWLogger.Log);
|
||||
testElements.LogPipProcessError();
|
||||
testElements.Console.ValidateCallForPipProcessErrorinADO(MessageLevel.Info, testElements.ExpectingConsoleLog);
|
||||
XAssert.AreEqual(m_eventFields, testElements.PipProcessError, "You may edit the PipProcessError event fields, update the test and/or struct PipProcessErrorEventFields.");
|
||||
AssertErrorEventLogged(LogEventId.PipProcessError);
|
||||
if (isPipProcessError)
|
||||
{
|
||||
testElements.LogPipProcessError();
|
||||
XAssert.AreEqual(m_pipProcessEventFields, testElements.PipProcessError, PipProcessEditEventMessage);
|
||||
AssertErrorEventLogged(LogEventId.PipProcessError);
|
||||
}
|
||||
else
|
||||
{
|
||||
testElements.LogPipProcessWarning();
|
||||
XAssert.AreEqual(m_pipProcessEventFields, testElements.PipProcessWarning, PipProcessEditEventMessage);
|
||||
AssertWarningEventLogged(LogEventId.PipProcessWarning);
|
||||
}
|
||||
testElements.Console.ValidateCallForPipProcessEventinADO(MessageLevel.Info, testElements.ExpectingConsoleLog);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateErrorCap()
|
||||
{
|
||||
adoConsoleMaxIssuesToLog = 1;
|
||||
var adoConsoleMaxIssuesToLog = 1;
|
||||
m_eventListener.RegisterEventSource(global::BuildXL.Processes.ETWLogger.Log);
|
||||
m_eventListener.NestedLoggerHandler += eventData =>
|
||||
{
|
||||
m_eventFields = new PipProcessErrorEventFields(eventData.Payload, false);
|
||||
m_pipProcessEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: false, isPipProcessError: true);
|
||||
};
|
||||
|
||||
using (var testElements = PipProcessErrorTestElement.Create(this))
|
||||
using (var testElements = PipProcessEventTestElement.Create(this, isPipProcessError: true))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, testElements.Console, DateTime.Now, testElements.ViewModel, false, null, adoConsoleMaxIssuesToLog))
|
||||
{
|
||||
listener.RegisterEventSource(global::BuildXL.Processes.ETWLogger.Log);
|
||||
|
||||
// First log should go through as normal
|
||||
testElements.LogPipProcessError();
|
||||
testElements.Console.ValidateCallForPipProcessErrorinADO(MessageLevel.Info, testElements.ExpectingConsoleLog);
|
||||
testElements.Console.ValidateCallForPipProcessEventinADO(MessageLevel.Info, testElements.ExpectingConsoleLog);
|
||||
|
||||
// Second will log the message about being truncated
|
||||
testElements.LogPipProcessError();
|
||||
testElements.Console.ValidateCallForPipProcessErrorinADO(MessageLevel.Info, new List<string>{ $"##vso[task.logIssue type=error;] Future messages of this level are truncated" });
|
||||
testElements.LogPipProcessError();
|
||||
testElements.Console.ValidateCallForPipProcessEventinADO(MessageLevel.Info, new List<string> { $"##vso[task.logIssue type=error;] Future messages of this level are truncated" });
|
||||
|
||||
// Third should result in no more messages logged
|
||||
testElements.LogPipProcessError();
|
||||
|
@ -82,15 +103,15 @@ namespace Test.BuildXL
|
|||
var eventName = "PipProcessError";
|
||||
var text = "Pip process error message";
|
||||
var pipSemiStableHash = (long)24;
|
||||
|
||||
|
||||
m_eventListener.RegisterEventSource(global::BuildXL.Engine.ETWLogger.Log);
|
||||
m_eventListener.NestedLoggerHandler += eventData =>
|
||||
{
|
||||
m_eventFields = new PipProcessErrorEventFields(eventData.Payload, true);
|
||||
m_pipProcessEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: true, isPipProcessError: true);
|
||||
};
|
||||
|
||||
using (var testElements = PipProcessErrorTestElement.Create(this))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, testElements.Console, DateTime.Now, testElements.ViewModel, false, null, adoConsoleMaxIssuesToLog))
|
||||
using (var testElements = PipProcessEventTestElement.Create(this, isPipProcessError: true))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, testElements.Console, DateTime.Now, testElements.ViewModel, false, null, AdoConsoleMaxIssuesToLog))
|
||||
{
|
||||
listener.RegisterEventSource(global::BuildXL.Engine.ETWLogger.Log);
|
||||
global::BuildXL.Engine.Tracing.Logger.Log.DistributionWorkerForwardedError(LoggingContext, new WorkerForwardedEvent()
|
||||
|
@ -99,31 +120,87 @@ namespace Test.BuildXL
|
|||
EventName = eventName,
|
||||
EventKeywords = 0,
|
||||
Text = text,
|
||||
PipProcessErrorEvent = testElements.PipProcessError,
|
||||
PipProcessEvent = testElements.PipProcessError,
|
||||
});
|
||||
testElements.Console.ValidateCallForPipProcessErrorinADO(MessageLevel.Info, testElements.ExpectingConsoleLog);
|
||||
testElements.Console.ValidateCallForPipProcessEventinADO(MessageLevel.Info, testElements.ExpectingConsoleLog);
|
||||
XAssert.IsTrue(testElements.ViewModel.BuildSummary.PipErrors.Any(e => e.SemiStablePipId == $"Pip{(pipSemiStableHash):X16}"));
|
||||
XAssert.AreEqual(m_eventFields, testElements.PipProcessError, "You may edit the PipProcessError and/or WorkerForwardedEvent fields, and/or struct PipProcessErrorEventFields.");
|
||||
XAssert.AreEqual(m_pipProcessEventFields, testElements.PipProcessError, PipProcessEditEventMessage);
|
||||
AssertErrorEventLogged(SharedLogEventId.DistributionWorkerForwardedError);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates some boilerplate code shared by tests that require calls to log methods
|
||||
/// </summary>
|
||||
private class PipProcessErrorTestElement : IDisposable
|
||||
[Fact]
|
||||
public void ForwardedPipProcessWarningTest()
|
||||
{
|
||||
public PipProcessErrorEventFields PipProcessError;
|
||||
var eventName = "PipProcessWarning";
|
||||
var warningMessage = "I'm a warning you want to ignore; it hurts.";
|
||||
|
||||
m_eventListener.RegisterEventSource(global::BuildXL.Engine.ETWLogger.Log);
|
||||
m_eventListener.NestedLoggerHandler += eventData =>
|
||||
{
|
||||
m_pipProcessEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: true, isPipProcessError: false);
|
||||
};
|
||||
|
||||
using (var testElements = PipProcessEventTestElement.Create(this, isPipProcessError: false))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, testElements.Console, DateTime.Now, testElements.ViewModel, false, null, AdoConsoleMaxIssuesToLog))
|
||||
{
|
||||
listener.RegisterEventSource(global::BuildXL.Engine.ETWLogger.Log);
|
||||
global::BuildXL.Engine.Tracing.Logger.Log.DistributionWorkerForwardedWarning(LoggingContext, new WorkerForwardedEvent()
|
||||
{
|
||||
EventId = (int)LogEventId.PipProcessWarning,
|
||||
EventName = eventName,
|
||||
EventKeywords = 0,
|
||||
Text = warningMessage,
|
||||
PipProcessEvent = testElements.PipProcessWarning,
|
||||
});
|
||||
testElements.Console.ValidateCallForPipProcessEventinADO(MessageLevel.Info, testElements.ExpectingConsoleLog);
|
||||
XAssert.AreEqual(m_pipProcessEventFields, testElements.PipProcessWarning, PipProcessEditEventMessage);
|
||||
AssertWarningEventLogged(SharedLogEventId.DistributionWorkerForwardedWarning);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates some boilerplate code shared by tests that require calls to log methods for PipProcessError and PipProcessWarning events.
|
||||
/// </summary>
|
||||
private class PipProcessEventTestElement : IDisposable
|
||||
{
|
||||
public PipProcessEventFields PipProcessError;
|
||||
public PipProcessEventFields PipProcessWarning;
|
||||
public List<string> ExpectingConsoleLog = new List<string>();
|
||||
public MockConsole Console;
|
||||
public BuildViewModel ViewModel;
|
||||
private LoggingContext m_loggingContext;
|
||||
|
||||
public static PipProcessErrorTestElement Create(BuildXLTestBase testBase)
|
||||
public static PipProcessEventTestElement Create(BuildXLTestBase testBase, bool isPipProcessError = false)
|
||||
{
|
||||
var result = new PipProcessErrorTestElement();
|
||||
var result = new PipProcessEventTestElement();
|
||||
long totalElapsedTimeMs = Convert.ToInt64(TimeSpan.FromSeconds(15).TotalMilliseconds);
|
||||
var pipProcessError = new PipProcessErrorEventFields(
|
||||
var addFormattingToErrorMessage = Environment.NewLine;
|
||||
|
||||
if (isPipProcessError)
|
||||
{
|
||||
var pipProcessError = PipProcessEventFields.CreatePipProcessErrorEventFields(
|
||||
(long)24,
|
||||
"my cool pip",
|
||||
@"specs\mypip.dsc",
|
||||
@"specs\workingDir",
|
||||
"coolpip.exe",
|
||||
"Failure message Line1\r\nFailure message Line2\rFailure message Line3\n",
|
||||
"Find output file in following path:",
|
||||
@"specs\workingDir\out.txt",
|
||||
-1,
|
||||
"what does this do?",
|
||||
"my pip",
|
||||
totalElapsedTimeMs);
|
||||
var errorPrefix = @$"DX0064 [Pip0000000000000018, {pipProcessError.ShortPipDescription}, {pipProcessError.PipSpecPath}] - failed with exit code {pipProcessError.ExitCode}, {pipProcessError.OptionalMessage}";
|
||||
var processedErrorOutputToLog = "##vso[task.logIssue type=error;]Failure message Line1%0D%0A##[error]Failure message Line2%0D##[error]Failure message Line3%0A##[error]";
|
||||
var errorSuffix = $"{pipProcessError.MessageAboutPathsToLog}{addFormattingToErrorMessage}{pipProcessError.PathsToLog}";
|
||||
result.AddToExpectingConsoleLogList(errorPrefix, processedErrorOutputToLog, errorSuffix, result.ExpectingConsoleLog);
|
||||
result.PipProcessError = pipProcessError;
|
||||
}
|
||||
else
|
||||
{
|
||||
var pipProcessWarning = PipProcessEventFields.CreatePipProcessWarningEventFields(
|
||||
(long)24,
|
||||
"my cool pip",
|
||||
@"specs\mypip.dsc",
|
||||
|
@ -131,20 +208,14 @@ namespace Test.BuildXL
|
|||
"coolpip.exe",
|
||||
"Failure message Line1\r\nFailure message Line2\rFailure message Line3\n",
|
||||
"Find output file in following path:",
|
||||
@"specs\workingDir\out.txt",
|
||||
-1,
|
||||
"what does this do?",
|
||||
"my pip",
|
||||
totalElapsedTimeMs);
|
||||
@"specs\workingDir\out.txt");
|
||||
var warningPrefix = @$"DX0065 [Pip0000000000000018, {pipProcessWarning.PipDescription}, {pipProcessWarning.PipSpecPath}] - warnings";
|
||||
var processedWarningOutputToLog = "##vso[task.logIssue type=warning;]Failure message Line1%0D%0A##[warning]Failure message Line2%0D##[warning]Failure message Line3%0A##[warning]";
|
||||
var warningSuffix = $"{pipProcessWarning.MessageAboutPathsToLog}{addFormattingToErrorMessage}{pipProcessWarning.PathsToLog}";
|
||||
result.PipProcessWarning = pipProcessWarning;
|
||||
result.AddToExpectingConsoleLogList(warningPrefix, processedWarningOutputToLog, warningSuffix, result.ExpectingConsoleLog);
|
||||
}
|
||||
|
||||
var addFormattingToErrorMessage = Environment.NewLine;
|
||||
var errorPrefix = @$"DX0064 [Pip0000000000000018, {pipProcessError.ShortPipDescription}, {pipProcessError.PipSpecPath}] - failed with exit code {pipProcessError.ExitCode}, {pipProcessError.OptionalMessage}";
|
||||
var processedErrorOutputToLog = "##vso[task.logIssue type=error;]Failure message Line1%0D%0A##[error]Failure message Line2%0D##[error]Failure message Line3%0A##[error]";
|
||||
var errorSuffix = $"{pipProcessError.MessageAboutPathsToLog}{addFormattingToErrorMessage}{pipProcessError.PathsToLog}";
|
||||
result.ExpectingConsoleLog.Add(errorPrefix);
|
||||
result.ExpectingConsoleLog.Add(processedErrorOutputToLog);
|
||||
result.ExpectingConsoleLog.Add(errorSuffix);
|
||||
result.PipProcessError = pipProcessError;
|
||||
result.Console = new MockConsole();
|
||||
result.ViewModel = new BuildViewModel();
|
||||
var buildSummaryFilePath = Path.Combine(testBase.TestOutputDirectory, "test.md");
|
||||
|
@ -154,6 +225,13 @@ namespace Test.BuildXL
|
|||
return result;
|
||||
}
|
||||
|
||||
public void AddToExpectingConsoleLogList(string eventPrefix, string eventIssue, string eventSuffix, List<string> expectingConsoleLog)
|
||||
{
|
||||
expectingConsoleLog.Add(eventPrefix);
|
||||
expectingConsoleLog.Add(eventIssue);
|
||||
expectingConsoleLog.Add(eventSuffix);
|
||||
}
|
||||
|
||||
public void LogPipProcessError()
|
||||
{
|
||||
global::BuildXL.Processes.Tracing.Logger.Log.PipProcessError(m_loggingContext,
|
||||
|
@ -171,6 +249,19 @@ namespace Test.BuildXL
|
|||
PipProcessError.PipExecutionTimeMs);
|
||||
}
|
||||
|
||||
public void LogPipProcessWarning()
|
||||
{
|
||||
global::BuildXL.Processes.Tracing.Logger.Log.PipProcessWarning(m_loggingContext,
|
||||
PipProcessWarning.PipSemiStableHash,
|
||||
PipProcessWarning.PipDescription,
|
||||
PipProcessWarning.PipSpecPath,
|
||||
PipProcessWarning.PipWorkingDirectory,
|
||||
PipProcessWarning.PipExe,
|
||||
PipProcessWarning.OutputToLog,
|
||||
PipProcessWarning.MessageAboutPathsToLog,
|
||||
PipProcessWarning.PathsToLog);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Console.Dispose();
|
||||
|
@ -187,7 +278,7 @@ namespace Test.BuildXL
|
|||
var console = new MockConsole();
|
||||
BuildViewModel viewModel = new BuildViewModel();
|
||||
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, console, DateTime.Now, viewModel, false, null, adoConsoleMaxIssuesToLog))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, console, DateTime.Now, viewModel, false, null, AdoConsoleMaxIssuesToLog))
|
||||
{
|
||||
listener.RegisterEventSource(global::BuildXL.Engine.ETWLogger.Log);
|
||||
global::BuildXL.Engine.Tracing.Logger.Log.DistributionWorkerForwardedError(LoggingContext, new WorkerForwardedEvent()
|
||||
|
@ -215,7 +306,7 @@ namespace Test.BuildXL
|
|||
var console = new MockConsole();
|
||||
BuildViewModel viewModel = new BuildViewModel();
|
||||
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, console, DateTime.Now, viewModel, false, null, adoConsoleMaxIssuesToLog))
|
||||
using (AzureDevOpsListener listener = new AzureDevOpsListener(Events.Log, console, DateTime.Now, viewModel, false, null, AdoConsoleMaxIssuesToLog))
|
||||
{
|
||||
listener.RegisterEventSource(global::BuildXL.Scheduler.ETWLogger.Log);
|
||||
listener.RegisterEventSource(global::BuildXL.Pips.ETWLogger.Log);
|
||||
|
@ -252,10 +343,10 @@ namespace Test.BuildXL
|
|||
limitingResource: "",
|
||||
perfInfoForLog: "",
|
||||
overwriteable: true,
|
||||
copyFileDone:100,
|
||||
copyFileDone: 100,
|
||||
copyFileNotDone: 100,
|
||||
writeFileDone: 10,
|
||||
writeFileNotDone:10,
|
||||
writeFileNotDone: 10,
|
||||
procsRemoted: 0);
|
||||
console.ValidateCall(MessageLevel.Info, $"##vso[task.setprogress value={currentProgress};]Pip Execution phase");
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Test.BuildXL
|
|||
private MessageLevel m_lastMessageLevel;
|
||||
// This list is used in ADOConsole for DX64 errors where the message is split into various segments and logged to ensure that only a part of the error message is highlighted.
|
||||
private List<string> m_errorMessage = new List<string>();
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace Test.BuildXL
|
|||
m_errorMessage.Clear();
|
||||
}
|
||||
|
||||
public void ValidateCallForPipProcessErrorinADO(MessageLevel messageLevel, List<string> expectedErrorMessage)
|
||||
public void ValidateCallForPipProcessEventinADO(MessageLevel messageLevel, List<string> expectedErrorMessage)
|
||||
{
|
||||
XAssert.IsNotNull(m_errorMessage.LastOrDefault(), "WriteOutputLine was not called");
|
||||
XAssert.AreEqual(messageLevel, m_lastMessageLevel);
|
||||
|
|
|
@ -131,9 +131,9 @@ message EventMessage
|
|||
// The message for the event
|
||||
string Text = 6;
|
||||
|
||||
oneof ErrorEvent {
|
||||
// The original pipProcessError event if exist
|
||||
PipProcessErrorEvent PipProcessErrorEvent = 7;
|
||||
oneof PipProcessErrorOrWarningEvent {
|
||||
// The original pipProcessError/pipProcessWarning event if exist
|
||||
PipProcessEvent PipProcessEvent = 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,7 +345,11 @@ message PipGraphCacheDescriptor {
|
|||
google.protobuf.BytesValue PipGraphId = 15;
|
||||
}
|
||||
|
||||
message PipProcessErrorEvent {
|
||||
/// <summary>
|
||||
/// Event message for PipProcessError/PipProcessWarning.
|
||||
/// Since the last four fields are present only for PipProcessError event they are made optional for PipProcessWarning.
|
||||
/// </summary>
|
||||
message PipProcessEvent {
|
||||
int64 PipSemiStableHash = 1;
|
||||
string PipDescription = 2;
|
||||
string PipSpecPath = 3;
|
||||
|
@ -354,8 +358,8 @@ message PipProcessErrorEvent {
|
|||
string OutputToLog = 6;
|
||||
string MessageAboutPathsToLog = 7;
|
||||
string PathsToLog = 8;
|
||||
int32 ExitCode = 9;
|
||||
string OptionalMessage = 10;
|
||||
string ShortPipDescription = 11;
|
||||
int64 PipExecutionTimeMs = 12;
|
||||
optional int32 ExitCode = 9;
|
||||
optional string OptionalMessage = 10;
|
||||
optional string ShortPipDescription = 11;
|
||||
optional int64 PipExecutionTimeMs = 12;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace BuildXL.Engine.Distribution
|
|||
|
||||
m_loggingContext = loggingContext;
|
||||
|
||||
for (int i = 0; i < config.RemoteWorkerCount; i++)
|
||||
for (int i = 0; i < config.RemoteWorkerCount; i++)
|
||||
{
|
||||
ServiceLocation serviceLocation = null;
|
||||
if (i < config.BuildWorkers.Count)
|
||||
|
@ -207,19 +207,19 @@ namespace BuildXL.Engine.Distribution
|
|||
|
||||
if (forwardedEvent.EventId == (int)BuildXL.Processes.Tracing.LogEventId.PipProcessError)
|
||||
{
|
||||
var pipProcessErrorEvent = new PipProcessErrorEventFields(
|
||||
forwardedEvent.PipProcessErrorEvent.PipSemiStableHash,
|
||||
forwardedEvent.PipProcessErrorEvent.PipDescription,
|
||||
forwardedEvent.PipProcessErrorEvent.PipSpecPath,
|
||||
forwardedEvent.PipProcessErrorEvent.PipWorkingDirectory,
|
||||
forwardedEvent.PipProcessErrorEvent.PipExe,
|
||||
forwardedEvent.PipProcessErrorEvent.OutputToLog,
|
||||
forwardedEvent.PipProcessErrorEvent.MessageAboutPathsToLog,
|
||||
forwardedEvent.PipProcessErrorEvent.PathsToLog,
|
||||
forwardedEvent.PipProcessErrorEvent.ExitCode,
|
||||
forwardedEvent.PipProcessErrorEvent.OptionalMessage,
|
||||
forwardedEvent.PipProcessErrorEvent.ShortPipDescription,
|
||||
forwardedEvent.PipProcessErrorEvent.PipExecutionTimeMs
|
||||
var pipProcessErrorEvent = PipProcessEventFields.CreatePipProcessErrorEventFields(
|
||||
forwardedEvent.PipProcessEvent.PipSemiStableHash,
|
||||
forwardedEvent.PipProcessEvent.PipDescription,
|
||||
forwardedEvent.PipProcessEvent.PipSpecPath,
|
||||
forwardedEvent.PipProcessEvent.PipWorkingDirectory,
|
||||
forwardedEvent.PipProcessEvent.PipExe,
|
||||
forwardedEvent.PipProcessEvent.OutputToLog,
|
||||
forwardedEvent.PipProcessEvent.MessageAboutPathsToLog,
|
||||
forwardedEvent.PipProcessEvent.PathsToLog,
|
||||
forwardedEvent.PipProcessEvent.ExitCode,
|
||||
forwardedEvent.PipProcessEvent.OptionalMessage,
|
||||
forwardedEvent.PipProcessEvent.ShortPipDescription,
|
||||
forwardedEvent.PipProcessEvent.PipExecutionTimeMs
|
||||
);
|
||||
|
||||
logForwardedError(
|
||||
|
@ -231,9 +231,10 @@ namespace BuildXL.Engine.Distribution
|
|||
EventId = forwardedEvent.EventId,
|
||||
EventName = forwardedEvent.EventName,
|
||||
EventKeywords = forwardedEvent.EventKeywords,
|
||||
PipProcessErrorEvent = pipProcessErrorEvent,
|
||||
PipProcessEvent = pipProcessErrorEvent,
|
||||
});
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
logForwardedError(
|
||||
m_loggingContext,
|
||||
|
@ -253,16 +254,44 @@ namespace BuildXL.Engine.Distribution
|
|||
}
|
||||
break;
|
||||
case EventLevel.Warning:
|
||||
Logger.Log.DistributionWorkerForwardedWarning(
|
||||
m_loggingContext,
|
||||
new WorkerForwardedEvent()
|
||||
{
|
||||
Text = forwardedEvent.Text,
|
||||
WorkerName = worker.Name,
|
||||
EventId = forwardedEvent.EventId,
|
||||
EventName = forwardedEvent.EventName,
|
||||
EventKeywords = forwardedEvent.EventKeywords,
|
||||
});
|
||||
if (forwardedEvent.EventId == (int)BuildXL.Processes.Tracing.LogEventId.PipProcessWarning)
|
||||
{
|
||||
var pipProcessWarningEvent = PipProcessEventFields.CreatePipProcessWarningEventFields(
|
||||
forwardedEvent.PipProcessEvent.PipSemiStableHash,
|
||||
forwardedEvent.PipProcessEvent.PipDescription,
|
||||
forwardedEvent.PipProcessEvent.PipSpecPath,
|
||||
forwardedEvent.PipProcessEvent.PipWorkingDirectory,
|
||||
forwardedEvent.PipProcessEvent.PipExe,
|
||||
forwardedEvent.PipProcessEvent.OutputToLog,
|
||||
forwardedEvent.PipProcessEvent.MessageAboutPathsToLog,
|
||||
forwardedEvent.PipProcessEvent.PathsToLog
|
||||
);
|
||||
|
||||
Logger.Log.DistributionWorkerForwardedWarning(
|
||||
m_loggingContext,
|
||||
new WorkerForwardedEvent()
|
||||
{
|
||||
Text = forwardedEvent.Text,
|
||||
WorkerName = worker.WorkerIpAddress,
|
||||
EventId = forwardedEvent.EventId,
|
||||
EventName = forwardedEvent.EventName,
|
||||
EventKeywords = forwardedEvent.EventKeywords,
|
||||
PipProcessEvent = pipProcessWarningEvent,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log.DistributionWorkerForwardedWarning(
|
||||
m_loggingContext,
|
||||
new WorkerForwardedEvent()
|
||||
{
|
||||
Text = forwardedEvent.Text,
|
||||
WorkerName = worker.Name,
|
||||
EventId = forwardedEvent.EventId,
|
||||
EventName = forwardedEvent.EventName,
|
||||
EventKeywords = forwardedEvent.EventKeywords,
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -51,17 +51,17 @@ namespace BuildXL.Engine.Distribution
|
|||
}
|
||||
|
||||
if (((long)eventData.Keywords & (long)Keywords.NotForwardedToOrchestrator) > 0)
|
||||
{
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
PipProcessErrorEvent pipProcessErrorEvent = null;
|
||||
PipProcessEvent pipProcessEvent = null;
|
||||
if (eventData.EventId == (int)LogEventId.PipProcessError)
|
||||
{
|
||||
var pipProcessErrorEventFields = new PipProcessErrorEventFields(eventData.Payload, false);
|
||||
pipProcessErrorEvent = new PipProcessErrorEvent()
|
||||
var pipProcessErrorEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: false, isPipProcessError: true);
|
||||
pipProcessEvent = new PipProcessEvent()
|
||||
{
|
||||
PipSemiStableHash = pipProcessErrorEventFields.PipSemiStableHash,
|
||||
PipDescription = pipProcessErrorEventFields.PipDescription,
|
||||
|
@ -78,6 +78,21 @@ namespace BuildXL.Engine.Distribution
|
|||
};
|
||||
}
|
||||
|
||||
if (eventData.EventId == (int)LogEventId.PipProcessWarning)
|
||||
{
|
||||
var pipProcessWarningEventFields = new PipProcessEventFields(eventData.Payload, forwardedPayload: false, isPipProcessError: false);
|
||||
pipProcessEvent = new PipProcessEvent()
|
||||
{
|
||||
PipSemiStableHash = pipProcessWarningEventFields.PipSemiStableHash,
|
||||
PipDescription = pipProcessWarningEventFields.PipDescription,
|
||||
PipWorkingDirectory = pipProcessWarningEventFields.PipWorkingDirectory,
|
||||
PipExe = pipProcessWarningEventFields.PipExe,
|
||||
OutputToLog = pipProcessWarningEventFields.OutputToLog,
|
||||
MessageAboutPathsToLog = pipProcessWarningEventFields.MessageAboutPathsToLog,
|
||||
PathsToLog = pipProcessWarningEventFields.PathsToLog,
|
||||
};
|
||||
}
|
||||
|
||||
m_notificationManager.ReportEventMessage(new EventMessage()
|
||||
{
|
||||
Id = Interlocked.Increment(ref m_nextEventId),
|
||||
|
@ -86,7 +101,7 @@ namespace BuildXL.Engine.Distribution
|
|||
EventId = eventData.EventId,
|
||||
EventName = eventData.EventName,
|
||||
Text = text,
|
||||
PipProcessErrorEvent = pipProcessErrorEvent,
|
||||
PipProcessEvent = pipProcessEvent,
|
||||
});
|
||||
}
|
||||
catch (Exception ex) when (ExceptionUtilities.HandleUnexpectedException(ex))
|
||||
|
|
|
@ -24,7 +24,7 @@ using Grpc.Core;
|
|||
|
||||
namespace BuildXL.Engine.Distribution
|
||||
{
|
||||
internal interface IWorkerNotificationManager
|
||||
internal interface IWorkerNotificationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts the notification manager, which will start to listen
|
||||
|
@ -238,17 +238,17 @@ namespace BuildXL.Engine.Distribution
|
|||
// We keep message queues for every active pip step in this worker
|
||||
private readonly ConcurrentDictionary<long, PooledObjectWrapper<ConcurrentQueue<EventMessage>>> m_pendingMessages = new();
|
||||
|
||||
private readonly ObjectPool<ConcurrentQueue<EventMessage>> m_queuePool = new (
|
||||
() => new(),
|
||||
q =>
|
||||
{
|
||||
while (q.TryDequeue(out _))
|
||||
private readonly ObjectPool<ConcurrentQueue<EventMessage>> m_queuePool = new(
|
||||
() => new(),
|
||||
q =>
|
||||
{
|
||||
while (q.TryDequeue(out _))
|
||||
{
|
||||
// Queue has no .Clear(), dequeue everything.
|
||||
// Note that we will drain the queue anyways before
|
||||
// disposing the pooled object wrapper so this should be no-op
|
||||
}
|
||||
return q;
|
||||
return q;
|
||||
});
|
||||
|
||||
/// <nodoc/>
|
||||
|
@ -261,7 +261,7 @@ namespace BuildXL.Engine.Distribution
|
|||
return;
|
||||
}
|
||||
|
||||
if (TryExtractSemistableHashFromEvent(eventMessage, out var hash)
|
||||
if (TryExtractSemistableHashFromEvent(eventMessage, out var hash)
|
||||
&& m_pendingMessages.TryGetValue(hash, out var messageQueueForPip))
|
||||
{
|
||||
messageQueueForPip.Instance.Enqueue(eventMessage);
|
||||
|
@ -318,7 +318,7 @@ namespace BuildXL.Engine.Distribution
|
|||
// so extract it from there rather than using the regex
|
||||
if (eventMessage.EventId == (int)BuildXL.Processes.Tracing.LogEventId.PipProcessError)
|
||||
{
|
||||
hash = eventMessage.PipProcessErrorEvent.PipSemiStableHash;
|
||||
hash = eventMessage.PipProcessEvent.PipSemiStableHash;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -524,8 +524,8 @@ namespace BuildXL.Engine.Distribution
|
|||
public void MarkPipProcessingStarted(long semistableHash)
|
||||
{
|
||||
// Add a queue for pending messages for this pip step
|
||||
Contract.Assert(m_pendingMessages.TryAdd(semistableHash, m_queuePool.GetInstance()),
|
||||
"There shouldn't be a pending message queue for a pip we are about to process");
|
||||
Contract.Assert(m_pendingMessages.TryAdd(semistableHash, m_queuePool.GetInstance()),
|
||||
"There shouldn't be a pending message queue for a pip we are about to process");
|
||||
}
|
||||
|
||||
private static string GetPipResultsDescription(PipResultsInfo notificationArgs, IList<ExtendedPipCompletionData> pips)
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BuildXL.Utilities.Instrumentation.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// struct contain all fields of the original PipProcessError event
|
||||
/// </summary>
|
||||
public struct PipProcessErrorEventFields
|
||||
{
|
||||
/// <nodoc />
|
||||
public long PipSemiStableHash { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipDescription { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipSpecPath { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipWorkingDirectory { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipExe { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string OutputToLog { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string MessageAboutPathsToLog { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PathsToLog { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public int ExitCode { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string OptionalMessage { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string ShortPipDescription { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public long PipExecutionTimeMs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct PipProcessErrorEventFields from eventPayload
|
||||
/// </summary>
|
||||
public PipProcessErrorEventFields(ReadOnlyCollection<object> eventPayload, bool forwardedPayload)
|
||||
{
|
||||
// When the PipProcessErrorEvent is forwarded from worker it is encapsulated in a WorkerForwardedEvent, which has 4 other fields in front of the real pipProcessEvent.
|
||||
// So the actual event starts at index 4.
|
||||
|
||||
var startIndex = forwardedPayload ? 4 : 0;
|
||||
#pragma warning disable CS8600
|
||||
#pragma warning disable CS8601
|
||||
PipDescription = (string)eventPayload[1 + startIndex];
|
||||
PipSpecPath = (string)eventPayload[2 + startIndex];
|
||||
PipWorkingDirectory = (string)eventPayload[3 + startIndex];
|
||||
PipExe = (string)eventPayload[4 + startIndex];
|
||||
OutputToLog = (string)eventPayload[5 + startIndex];
|
||||
MessageAboutPathsToLog = (string)eventPayload[6 + startIndex];
|
||||
PathsToLog = (string)eventPayload[7 + startIndex];
|
||||
|
||||
OptionalMessage = (string)eventPayload[9 + startIndex];
|
||||
ShortPipDescription = (string)eventPayload[10 + startIndex];
|
||||
PipExecutionTimeMs = (long)eventPayload[11 + startIndex];
|
||||
#pragma warning restore CS8600
|
||||
#pragma warning restore CS8601
|
||||
|
||||
#pragma warning disable CS8605
|
||||
PipSemiStableHash = (long)eventPayload[0 + startIndex];
|
||||
ExitCode = (int)eventPayload[8 + startIndex];
|
||||
#pragma warning restore CS8605
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct PipProcessErrorEventFields
|
||||
/// </summary>
|
||||
public PipProcessErrorEventFields(
|
||||
long pipSemiStableHash,
|
||||
string pipDescription,
|
||||
string pipSpecPath,
|
||||
string pipWorkingDirectory,
|
||||
string pipExe,
|
||||
string outputToLog,
|
||||
string messageAboutPathsToLog,
|
||||
string pathsToLog,
|
||||
int exitCode,
|
||||
string optionalMessage,
|
||||
string shortPipDescription,
|
||||
long pipExecutionTimeMs
|
||||
)
|
||||
{
|
||||
PipSemiStableHash = pipSemiStableHash;
|
||||
PipDescription = pipDescription;
|
||||
PipSpecPath = pipSpecPath;
|
||||
PipWorkingDirectory = pipWorkingDirectory;
|
||||
PipExe = pipExe;
|
||||
OutputToLog = outputToLog;
|
||||
MessageAboutPathsToLog = messageAboutPathsToLog;
|
||||
PathsToLog = pathsToLog;
|
||||
ExitCode = exitCode;
|
||||
OptionalMessage = optionalMessage;
|
||||
ShortPipDescription = shortPipDescription;
|
||||
PipExecutionTimeMs = pipExecutionTimeMs;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BuildXL.Utilities.Instrumentation.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// struct contain all fields of the original PipProcessError/PipProcessWarning event
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Since both the events mostly have common fields a single struct is created for both the events.
|
||||
/// </remarks>
|
||||
public struct PipProcessEventFields
|
||||
{
|
||||
/// <nodoc />
|
||||
public long PipSemiStableHash { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipDescription { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipSpecPath { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipWorkingDirectory { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PipExe { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string OutputToLog { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string MessageAboutPathsToLog { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string PathsToLog { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public int ExitCode { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string OptionalMessage { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public string ShortPipDescription { get; }
|
||||
|
||||
/// <nodoc />
|
||||
public long PipExecutionTimeMs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct PipProcessEventFields from eventPayload
|
||||
/// </summary>
|
||||
public PipProcessEventFields(ReadOnlyCollection<object> eventPayload, bool forwardedPayload, bool isPipProcessError)
|
||||
{
|
||||
// When the PipProcessEvent is forwarded from worker it is encapsulated in a WorkerForwardedEvent, which has 4 other fields in front of the real pipProcessEvent.
|
||||
// So the actual event starts at index 4.
|
||||
// PipProcessWarningEvent does not contain the following fields - ExitCode, PipExecutionTimeMs, ShortPipDescription, OptionalMessage. These fields need to be empty when creating PipProcessWarningEvent.
|
||||
|
||||
var startIndex = forwardedPayload ? 4 : 0;
|
||||
#pragma warning disable CS8600
|
||||
#pragma warning disable CS8601
|
||||
PipDescription = (string)eventPayload[1 + startIndex];
|
||||
PipSpecPath = (string)eventPayload[2 + startIndex];
|
||||
PipWorkingDirectory = (string)eventPayload[3 + startIndex];
|
||||
PipExe = (string)eventPayload[4 + startIndex];
|
||||
OutputToLog = (string)eventPayload[5 + startIndex];
|
||||
MessageAboutPathsToLog = (string)eventPayload[6 + startIndex];
|
||||
PathsToLog = (string)eventPayload[7 + startIndex];
|
||||
if (isPipProcessError)
|
||||
{
|
||||
OptionalMessage = (string)eventPayload[9 + startIndex];
|
||||
ShortPipDescription = (string)eventPayload[10 + startIndex];
|
||||
PipExecutionTimeMs = (long)eventPayload[11 + startIndex];
|
||||
}
|
||||
#pragma warning restore CS8600
|
||||
#pragma warning restore CS8601
|
||||
|
||||
#pragma warning disable CS8605
|
||||
PipSemiStableHash = (long)eventPayload[0 + startIndex];
|
||||
if (isPipProcessError)
|
||||
{
|
||||
ExitCode = (int)eventPayload[8 + startIndex];
|
||||
}
|
||||
#pragma warning restore CS8605
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct PipProcessErrorEventFields
|
||||
/// This constructor is to be used for PipProcessError event since this event has a couple of fields extra.
|
||||
/// </summary>
|
||||
public PipProcessEventFields(
|
||||
long pipSemiStableHash,
|
||||
string pipDescription,
|
||||
string pipSpecPath,
|
||||
string pipWorkingDirectory,
|
||||
string pipExe,
|
||||
string outputToLog,
|
||||
string messageAboutPathsToLog,
|
||||
string pathsToLog,
|
||||
int exitCode,
|
||||
string optionalMessage,
|
||||
string shortPipDescription,
|
||||
long pipExecutionTimeMs
|
||||
)
|
||||
{
|
||||
PipSemiStableHash = pipSemiStableHash;
|
||||
PipDescription = pipDescription;
|
||||
PipSpecPath = pipSpecPath;
|
||||
PipWorkingDirectory = pipWorkingDirectory;
|
||||
PipExe = pipExe;
|
||||
OutputToLog = outputToLog;
|
||||
MessageAboutPathsToLog = messageAboutPathsToLog;
|
||||
PathsToLog = pathsToLog;
|
||||
ExitCode = exitCode;
|
||||
OptionalMessage = optionalMessage;
|
||||
ShortPipDescription = shortPipDescription;
|
||||
PipExecutionTimeMs = pipExecutionTimeMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for PipProcessWarning
|
||||
/// </summary>
|
||||
public PipProcessEventFields(
|
||||
long pipSemiStableHash,
|
||||
string pipDescription,
|
||||
string pipSpecPath,
|
||||
string pipWorkingDirectory,
|
||||
string pipExe,
|
||||
string outputToLog,
|
||||
string messageAboutPathsToLog,
|
||||
string pathsToLog
|
||||
)
|
||||
{
|
||||
PipSemiStableHash = pipSemiStableHash;
|
||||
PipDescription = pipDescription;
|
||||
PipSpecPath = pipSpecPath;
|
||||
PipWorkingDirectory = pipWorkingDirectory;
|
||||
PipExe = pipExe;
|
||||
OutputToLog = outputToLog;
|
||||
MessageAboutPathsToLog = messageAboutPathsToLog;
|
||||
PathsToLog = pathsToLog;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates PipProcessEvent object for PipProcessWarnings.
|
||||
/// </summary>
|
||||
public static PipProcessEventFields CreatePipProcessWarningEventFields(
|
||||
long pipSemiStableHash,
|
||||
string pipDescription,
|
||||
string pipSpecPath,
|
||||
string pipWorkingDirectory,
|
||||
string pipExe,
|
||||
string outputToLog,
|
||||
string messageAboutPathsToLog,
|
||||
string pathsToLog)
|
||||
{
|
||||
return new PipProcessEventFields(
|
||||
pipSemiStableHash,
|
||||
pipDescription,
|
||||
pipSpecPath,
|
||||
pipWorkingDirectory,
|
||||
pipExe,
|
||||
outputToLog,
|
||||
messageAboutPathsToLog,
|
||||
pathsToLog);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates PipProcessEvent object for PipProcessErrors.
|
||||
/// </summary>
|
||||
public static PipProcessEventFields CreatePipProcessErrorEventFields(
|
||||
long pipSemiStableHash,
|
||||
string pipDescription,
|
||||
string pipSpecPath,
|
||||
string pipWorkingDirectory,
|
||||
string pipExe,
|
||||
string outputToLog,
|
||||
string messageAboutPathsToLog,
|
||||
string pathsToLog,
|
||||
int exitCode,
|
||||
string optionalMessage,
|
||||
string shortPipDescription,
|
||||
long pipExecutionTimeMs)
|
||||
{
|
||||
return new PipProcessEventFields(
|
||||
pipSemiStableHash,
|
||||
pipDescription,
|
||||
pipSpecPath,
|
||||
pipWorkingDirectory,
|
||||
pipExe,
|
||||
outputToLog,
|
||||
messageAboutPathsToLog,
|
||||
pathsToLog,
|
||||
exitCode,
|
||||
optionalMessage,
|
||||
shortPipDescription,
|
||||
pipExecutionTimeMs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace BuildXL.Utilities.Instrumentation.Common
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an event forwarded from a worker
|
||||
/// </summary>
|
||||
|
@ -38,8 +38,8 @@ namespace BuildXL.Utilities.Instrumentation.Common
|
|||
public long EventKeywords { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The original PipProcessError event
|
||||
/// The original PipProcessError/PipProcessWarning event
|
||||
/// </summary>
|
||||
public PipProcessErrorEventFields PipProcessErrorEvent { get; set; }
|
||||
public PipProcessEventFields PipProcessEvent { get; set; }
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче