Skip to content

Commit a531169

Browse files
committed
Add framework telemetry
1 parent de3b92c commit a531169

2 files changed

Lines changed: 79 additions & 12 deletions

File tree

src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#nullable disable
55

66
using System;
7+
using System.Collections.Concurrent;
78
using System.Collections.Generic;
89
using System.Diagnostics;
910
using System.Globalization;
@@ -30,6 +31,7 @@ namespace NuGet.Commands
3031
public class RestoreCommand
3132
{
3233
private readonly RestoreCollectorLogger _logger;
34+
private static readonly ConcurrentDictionary<NuGetFramework, string> _frameworkShortNameCache = new(NuGetFrameworkFullComparer.Instance);
3335

3436
private readonly RestoreRequest _request;
3537

@@ -58,6 +60,7 @@ private readonly Dictionary<RestoreTargetGraph, Dictionary<string, LibraryInclud
5860
private const string HttpSourcesCount = nameof(HttpSourcesCount);
5961
private const string LocalSourcesCount = nameof(LocalSourcesCount);
6062
private const string FallbackFoldersCount = nameof(FallbackFoldersCount);
63+
private const string TargetFrameworks = nameof(TargetFrameworks);
6164
private const string TargetFrameworksCount = nameof(TargetFrameworksCount);
6265
private const string RuntimeIdentifiersCount = nameof(RuntimeIdentifiersCount);
6366
private const string TreatWarningsAsErrors = nameof(TreatWarningsAsErrors);
@@ -381,7 +384,8 @@ private void InitializeTelemetry(TelemetryActivity telemetry, int httpSourcesCou
381384
telemetry.TelemetryEvent[IsLockFileEnabled] = _isLockFileEnabled;
382385
telemetry.TelemetryEvent[UseLegacyDependencyResolver] = _request.Project.RestoreMetadata.UseLegacyDependencyResolver;
383386
telemetry.TelemetryEvent[UsedLegacyDependencyResolver] = !_enableNewDependencyResolver;
384-
telemetry.TelemetryEvent[TargetFrameworksCount] = _request.Project.RestoreMetadata.TargetFrameworks.Count;
387+
telemetry.TelemetryEvent[TargetFrameworks] = GetTargetFrameworksAsString(_request.Project.TargetFrameworks);
388+
telemetry.TelemetryEvent[TargetFrameworksCount] = _request.Project.TargetFrameworks.Count;
385389
telemetry.TelemetryEvent[RuntimeIdentifiersCount] = _request.Project.RuntimeGraph.Runtimes.Count;
386390
telemetry.TelemetryEvent[TreatWarningsAsErrors] = _request.Project.RestoreMetadata.ProjectWideWarningProperties.AllWarningsAsErrors;
387391
telemetry.TelemetryEvent[SDKAnalysisLevel] = _request.Project.RestoreMetadata.SdkAnalysisLevel;
@@ -1256,23 +1260,39 @@ private bool EnsureNotDeprecatedProjectJsonProjectType()
12561260

12571261
return true;
12581262
}
1259-
private string ConcatAsString<T>(IEnumerable<T> enumerable)
1263+
1264+
private static string ConcatAsString<T>(HashSet<T> set)
12601265
{
1261-
string result = null;
1266+
if (set == null || set.Count == 0)
1267+
{
1268+
return null;
1269+
}
12621270

1263-
if (enumerable != null && enumerable.Any())
1271+
var builder = new StringBuilder();
1272+
foreach (T entry in set)
12641273
{
1265-
var builder = new StringBuilder();
1266-
foreach (var entry in enumerable)
1274+
builder.Append(entry);
1275+
builder.Append(';');
1276+
}
1277+
1278+
return builder.ToString(0, builder.Length - 1);
1279+
}
1280+
1281+
internal static string GetTargetFrameworksAsString(IList<TargetFrameworkInformation> targetFrameworks)
1282+
{
1283+
var builder = new StringBuilder();
1284+
1285+
foreach (TargetFrameworkInformation targetFramework in targetFrameworks)
1286+
{
1287+
if (builder.Length > 0)
12671288
{
1268-
builder.Append(entry.ToString());
1269-
builder.Append(";");
1289+
builder.Append(';');
12701290
}
12711291

1272-
result = builder.ToString(0, builder.Length - 1);
1292+
builder.Append(_frameworkShortNameCache.GetOrAdd(targetFramework.FrameworkName, static framework => framework.GetShortFolderName()));
12731293
}
12741294

1275-
return result;
1295+
return builder.ToString();
12761296
}
12771297

12781298
/// <summary>

test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests/RestoreCommandTests.cs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3082,6 +3082,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
30823082
["Audit.Duration.Total"] = value => value.Should().BeOfType<double>(),
30833083
["UseLegacyDependencyResolver"] = value => value.Should().BeOfType<bool>(),
30843084
["UsedLegacyDependencyResolver"] = value => value.Should().BeOfType<bool>(),
3085+
["TargetFrameworks"] = value => value.Should().Be("net472"),
30853086
["TargetFrameworksCount"] = value => value.Should().Be(1),
30863087
["RuntimeIdentifiersCount"] = value => value.Should().Be(0),
30873088
["TreatWarningsAsErrors"] = value => value.Should().Be(false),
@@ -3155,6 +3156,50 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
31553156
Assert.Null(projectInformationEvent["WarningCodes"]);
31563157
}
31573158

3159+
[Fact]
3160+
public async Task ExecuteAsync_WithMultiTargetedProject_PopulatesShortTargetFrameworkNamesTelemetry()
3161+
{
3162+
// Arrange
3163+
using var pathContext = new SimpleTestPathContext();
3164+
var projectName = "TestProject";
3165+
var projectPath = Path.Combine(pathContext.SolutionRoot, projectName);
3166+
PackageSpec packageSpec = ProjectTestHelpers.GetPackageSpec(projectName, pathContext.SolutionRoot, "net472", "a");
3167+
NuGetFramework secondFramework = NuGetFramework.Parse(".NETCoreApp,Version=v8.0");
3168+
packageSpec.TargetFrameworks.Add(new TargetFrameworkInformation() { FrameworkName = secondFramework });
3169+
packageSpec.RestoreMetadata.TargetFrameworks.Add(new ProjectRestoreMetadataFrameworkInfo(secondFramework) { TargetAlias = secondFramework.GetShortFolderName() });
3170+
packageSpec.RestoreMetadata.OriginalTargetFrameworks.Add(secondFramework.GetShortFolderName());
3171+
3172+
await SimpleTestPackageUtility.CreateFolderFeedV3Async(
3173+
pathContext.PackageSource,
3174+
PackageSaveMode.Defaultv3,
3175+
new SimpleTestPackageContext("a", "1.0.0"));
3176+
3177+
var logger = new TestLogger();
3178+
var request = new TestRestoreRequest(packageSpec, new PackageSource[] { new PackageSource(pathContext.PackageSource) }, pathContext.UserPackagesFolder, logger)
3179+
{
3180+
LockFilePath = Path.Combine(projectPath, "project.assets.json"),
3181+
ProjectStyle = ProjectStyle.PackageReference,
3182+
};
3183+
3184+
var telemetryEvents = new ConcurrentQueue<TelemetryEvent>();
3185+
var telemetryService = new Mock<INuGetTelemetryService>(MockBehavior.Loose);
3186+
telemetryService
3187+
.Setup(x => x.EmitTelemetryEvent(It.IsAny<TelemetryEvent>()))
3188+
.Callback<TelemetryEvent>(x => telemetryEvents.Enqueue(x));
3189+
3190+
TelemetryActivity.NuGetTelemetryService = telemetryService.Object;
3191+
3192+
// Act
3193+
var restoreCommand = new RestoreCommand(request);
3194+
RestoreResult result = await restoreCommand.ExecuteAsync();
3195+
3196+
// Assert
3197+
result.Success.Should().BeTrue(because: logger.ShowMessages());
3198+
var projectInformationEvent = telemetryEvents.Single(e => e.Name.Equals("ProjectRestoreInformation"));
3199+
projectInformationEvent["TargetFrameworks"].Should().Be("net472;net8.0");
3200+
projectInformationEvent["TargetFrameworksCount"].Should().Be(2);
3201+
}
3202+
31583203
[Fact]
31593204
public async Task ExecuteAsync_WithSinglePackage_WhenNoOping_PopulatesCorrectTelemetry()
31603205
{
@@ -3212,7 +3257,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
32123257

32133258
var projectInformationEvent = telemetryEvents.Single(e => e.Name.Equals("ProjectRestoreInformation"));
32143259

3215-
projectInformationEvent.Count.Should().Be(41);
3260+
projectInformationEvent.Count.Should().Be(42);
32163261

32173262
projectInformationEvent["RestoreSuccess"].Should().Be(true);
32183263
projectInformationEvent["NoOpResult"].Should().Be(true);
@@ -3239,6 +3284,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
32393284
projectInformationEvent["UseLegacyDependencyResolver"].Should().BeOfType<bool>();
32403285
projectInformationEvent["UsedLegacyDependencyResolver"].Should().BeOfType<bool>();
32413286
projectInformationEvent["Audit.Enabled"].Should().BeOfType<string>();
3287+
projectInformationEvent["TargetFrameworks"].Should().Be("net472");
32423288
projectInformationEvent["TargetFrameworksCount"].Should().Be(1);
32433289
projectInformationEvent["RuntimeIdentifiersCount"].Should().Be(0);
32443290
projectInformationEvent["TreatWarningsAsErrors"].Should().Be(true);
@@ -3312,11 +3358,12 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
33123358

33133359
var projectInformationEvent = telemetryEvents.Single(e => e.Name.Equals("ProjectRestoreInformation"));
33143360

3315-
projectInformationEvent.Count.Should().Be(49);
3361+
projectInformationEvent.Count.Should().Be(50);
33163362
projectInformationEvent["RestoreSuccess"].Should().Be(true);
33173363
projectInformationEvent["NoOpResult"].Should().Be(false);
33183364
projectInformationEvent["TotalUniquePackagesCount"].Should().Be(2);
33193365
projectInformationEvent["NewPackagesInstalledCount"].Should().Be(1);
3366+
projectInformationEvent["TargetFrameworks"].Should().Be("net472");
33203367
projectInformationEvent["PackageSourceMapping.IsMappingEnabled"].Should().Be(false);
33213368
projectInformationEvent["UpdatedAssetsFile"].Should().Be(true);
33223369
projectInformationEvent["UpdatedMSBuildFiles"].Should().Be(true);

0 commit comments

Comments
 (0)