Skip to content

Commit 7e8d5f5

Browse files
authored
Integrate the initial node metrics (#11481)
2 parents 07caf62 + aa2d584 commit 7e8d5f5

12 files changed

+432
-17
lines changed

src/Build.UnitTests/TelemetryTests.cs

+28
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using System.Text.Json;
78
using Microsoft.Build.Execution;
89
using Microsoft.Build.Framework;
10+
using Microsoft.Build.Framework.Telemetry;
11+
using Microsoft.Build.TelemetryInfra;
912
using Microsoft.Build.UnitTests;
1013
using Shouldly;
1114
using Xunit;
@@ -165,5 +168,30 @@ public void WorkerNodeTelemetryCollection_CustomTargetsAndTasks()
165168

166169
workerNodeTelemetryData.TasksExecutionData.Keys.ShouldAllBe(k => !k.IsFromNugetCache);
167170
}
171+
172+
[Fact]
173+
public void Foo()
174+
{
175+
WorkerNodeTelemetryData wd = new WorkerNodeTelemetryData(
176+
new Dictionary<TaskOrTargetTelemetryKey, TaskExecutionStats>()
177+
{
178+
{
179+
new TaskOrTargetTelemetryKey("TaskA", false, true),
180+
new TaskExecutionStats(TimeSpan.FromSeconds(2.1554548), 5, 545)
181+
},
182+
{
183+
new TaskOrTargetTelemetryKey("TaskA", true, false),
184+
new TaskExecutionStats(TimeSpan.FromSeconds(254548), 6, 54545451)
185+
},
186+
},
187+
new Dictionary<TaskOrTargetTelemetryKey, bool>()
188+
{
189+
{ new TaskOrTargetTelemetryKey("TargetA", false, true, false), false },
190+
{ new TaskOrTargetTelemetryKey("TargetA", true, true, false), false },
191+
{ new TaskOrTargetTelemetryKey("TargetB", false, false, true), false }
192+
});
193+
194+
var holder = TelemetryDataUtils.AsActivityDataHolder(wd, true, true);
195+
}
168196
}
169197
}

src/Build/BackEnd/BuildManager/BuildManager.cs

+13-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
using Microsoft.Build.Logging;
3737
using Microsoft.Build.Shared;
3838
using Microsoft.Build.Shared.Debugging;
39+
using Microsoft.Build.TelemetryInfra;
3940
using Microsoft.NET.StringTools;
4041
using ExceptionHandling = Microsoft.Build.Shared.ExceptionHandling;
4142
using ForwardingLoggerRecord = Microsoft.Build.Logging.ForwardingLoggerRecord;
@@ -257,6 +258,11 @@ public class BuildManager : INodePacketHandler, IBuildComponentHost, IDisposable
257258
/// </summary>
258259
private BuildTelemetry? _buildTelemetry;
259260

261+
/// <summary>
262+
/// Logger, that if instantiated - will receive and expose telemetry data from worker nodes.
263+
/// </summary>
264+
private InternalTelemetryConsumingLogger? _telemetryConsumingLogger;
265+
260266
private ProjectCacheService? _projectCacheService;
261267

262268
private bool _hasProjectCacheServiceInitializedVsScenario;
@@ -563,6 +569,7 @@ public void BeginBuild(BuildParameters parameters)
563569
// Initialize components.
564570
_nodeManager = ((IBuildComponentHost)this).GetComponent(BuildComponentType.NodeManager) as INodeManager;
565571

572+
_buildParameters.IsTelemetryEnabled |= OpenTelemetryManager.Instance.IsActive();
566573
var loggingService = InitializeLoggingService();
567574

568575
// Log deferred messages and response files
@@ -1134,7 +1141,10 @@ private void EndBuildTelemetry()
11341141
{
11351142
OpenTelemetryManager.Instance.DefaultActivitySource?
11361143
.StartActivity("Build")?
1137-
.WithTags(_buildTelemetry!)
1144+
.WithTags(_buildTelemetry)
1145+
.WithTags(_telemetryConsumingLogger?.WorkerNodeTelemetryData.AsActivityDataHolder(
1146+
includeTasksDetails: !Traits.Instance.ExcludeTasksDetailsFromTelemetry,
1147+
includeTargetDetails: false))
11381148
.WithStartTime(_buildTelemetry!.InnerStartAt)
11391149
.Dispose();
11401150
OpenTelemetryManager.Instance.ForceFlush();
@@ -2986,10 +2996,10 @@ private ILoggingService CreateLoggingService(
29862996
loggerSwitchParameters: null,
29872997
verbosity: LoggerVerbosity.Quiet);
29882998

2989-
ILogger internalTelemetryLogger =
2999+
_telemetryConsumingLogger =
29903000
new InternalTelemetryConsumingLogger();
29913001

2992-
ForwardingLoggerRecord[] forwardingLogger = { new ForwardingLoggerRecord(internalTelemetryLogger, forwardingLoggerDescription) };
3002+
ForwardingLoggerRecord[] forwardingLogger = { new ForwardingLoggerRecord(_telemetryConsumingLogger, forwardingLoggerDescription) };
29933003

29943004
forwardingLoggers = forwardingLoggers?.Concat(forwardingLogger) ?? forwardingLogger;
29953005
}

src/Build/Microsoft.Build.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,9 @@
174174
<Compile Include="Instance\IPropertyElementWithLocation.cs" />
175175
<Compile Include="Logging\BuildEventArgsExtensions.cs" />
176176
<Compile Include="Logging\TerminalLogger\**\*.cs" />
177+
<Compile Include="TelemetryInfra\InternalTelemetryConsumingLogger.cs" />
177178
<Compile Include="TelemetryInfra\ITelemetryForwarder.cs" />
179+
<Compile Include="TelemetryInfra\TelemetryDataUtils.cs" />
178180
<Compile Include="TelemetryInfra\TelemetryForwarderProvider.cs" />
179181
<Compile Include="Utilities\ReaderWriterLockSlimExtensions.cs" />
180182
<Compile Include="BackEnd\Node\ConsoleOutput.cs" />

src/Framework/Telemetry/InternalTelemetryConsumingLogger.cs src/Build/TelemetryInfra/InternalTelemetryConsumingLogger.cs

+25-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33

44
using System;
55
using System.Linq;
6+
using System.Text.Json;
7+
using Microsoft.Build.Framework;
8+
using Microsoft.Build.Framework.Telemetry;
9+
using System.IO;
610

7-
namespace Microsoft.Build.Framework;
11+
namespace Microsoft.Build.TelemetryInfra;
812

913
internal sealed class InternalTelemetryConsumingLogger : ILogger
1014
{
@@ -23,6 +27,8 @@ public void Initialize(IEventSource eventSource)
2327

2428
private readonly WorkerNodeTelemetryData _workerNodeTelemetryData = new();
2529

30+
public IWorkerNodeTelemetryData WorkerNodeTelemetryData => _workerNodeTelemetryData;
31+
2632
private void EventSource5_WorkerNodeTelemetryLogged(object? sender, WorkerNodeTelemetryEventArgs e)
2733
{
2834
_workerNodeTelemetryData.Add(e.WorkerNodeTelemetryData);
@@ -32,11 +38,12 @@ private void EventSourceOnBuildFinished(object sender, BuildFinishedEventArgs e)
3238
{
3339
TestOnly_InternalTelemetryAggregted?.Invoke(_workerNodeTelemetryData);
3440
FlushDataIntoConsoleIfRequested();
41+
FlushDataIntoJsonFileIfRequested();
3542
}
3643

3744
private void FlushDataIntoConsoleIfRequested()
3845
{
39-
if (Environment.GetEnvironmentVariable("MSBUILDOUTPUTNODESTELEMETRY") != "1")
46+
if (!Traits.IsEnvVarOneOrTrue("MSBUILDOUTPUTNODESTELEMETRY"))
4047
{
4148
return;
4249
}
@@ -75,6 +82,22 @@ private void FlushDataIntoConsoleIfRequested()
7582
Console.WriteLine("==========================================");
7683
}
7784

85+
private void FlushDataIntoJsonFileIfRequested()
86+
{
87+
const string jsonFileNameVariable = "MSBUILDNODETELEMETRYFILENAME";
88+
var jsonFilePath = Environment.GetEnvironmentVariable(jsonFileNameVariable);
89+
if (string.IsNullOrEmpty(jsonFilePath))
90+
{
91+
return;
92+
}
93+
94+
var telemetryTags = _workerNodeTelemetryData.AsActivityDataHolder(true, true)?.GetActivityProperties();
95+
96+
using var stream = File.OpenWrite(jsonFilePath);
97+
stream.SetLength(0);
98+
JsonSerializer.Serialize(stream, telemetryTags, new JsonSerializerOptions() { WriteIndented = true });
99+
}
100+
78101
public void Shutdown()
79102
{ }
80103
}

0 commit comments

Comments
 (0)