豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 79664c2

Browse files
committed
Add telemetry to RestoreCommand as well
1 parent e1b0705 commit 79664c2

File tree

3 files changed

+162
-13
lines changed

3 files changed

+162
-13
lines changed

src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/PackageSourceTelemetry.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -204,24 +204,20 @@ internal static void AddNupkgCopiedData(ProtocolDiagnosticNupkgCopiedEvent ncEve
204204
{
205205
data.NupkgCount++;
206206
data.NupkgSize += ncEvent.FileSize;
207-
208-
if (!data.IdContainsNonAsciiCharacter && ncEvent.PackageId != null && HasNonstandardCharacters(ncEvent.PackageId))
209-
{
210-
data.IdContainsNonAsciiCharacter = true;
211-
}
207+
data.IdContainsNonAsciiCharacter = data.IdContainsNonAsciiCharacter || (ncEvent.PackageId != null && HasNonASCIICharacters(ncEvent.PackageId));
212208
}
213-
}
214209

215-
private static bool HasNonstandardCharacters(string packageId)
216-
{
217-
foreach (char c in packageId.AsSpan())
210+
bool HasNonASCIICharacters(string packageId)
218211
{
219-
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-'))
212+
foreach (char c in packageId.AsSpan())
220213
{
221-
return true;
214+
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-'))
215+
{
216+
return true;
217+
}
222218
}
219+
return false;
223220
}
224-
return false;
225221
}
226222

227223
public void Dispose()

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ private readonly Dictionary<RestoreTargetGraph, Dictionary<string, LibraryInclud
5454
private const string IsCentralVersionManagementEnabled = nameof(IsCentralVersionManagementEnabled);
5555
private const string TotalUniquePackagesCount = nameof(TotalUniquePackagesCount);
5656
private const string NewPackagesInstalledCount = nameof(NewPackagesInstalledCount);
57+
private const string AnyPackageIdContainsNonASCIICharacters = nameof(AnyPackageIdContainsNonASCIICharacters);
5758
private const string SourcesCount = nameof(SourcesCount);
5859
private const string HttpSourcesCount = nameof(HttpSourcesCount);
5960
private const string LocalSourcesCount = nameof(LocalSourcesCount);
@@ -741,6 +742,7 @@ private async Task<EvaluateLockFileResult>
741742
}
742743

743744
telemetry.TelemetryEvent[NewPackagesInstalledCount] = graphs.Where(g => !g.InConflict).SelectMany(g => g.Install).Distinct().Count();
745+
telemetry.TelemetryEvent[AnyPackageIdContainsNonASCIICharacters] = graphs.Where(g => !g.InConflict).SelectMany(g => g.Flattened).Any(i => HasNonASCIICharacters(i.Key.Name));
744746
telemetry.TelemetryEvent[RestoreSuccess] = success;
745747
}
746748

@@ -753,6 +755,23 @@ private async Task<EvaluateLockFileResult>
753755
packagesLockFile,
754756
packagesLockFilePath,
755757
cacheFile);
758+
759+
bool HasNonASCIICharacters(string packageId)
760+
{
761+
if (string.IsNullOrWhiteSpace(packageId))
762+
{
763+
return false;
764+
}
765+
766+
foreach (char c in packageId.AsSpan())
767+
{
768+
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-'))
769+
{
770+
return true;
771+
}
772+
}
773+
return false;
774+
}
756775
}
757776

758777
/// <summary>Run NuGetAudit on the project's resolved restore graphs, and log messages and telemetry with the results.</summary>

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

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2957,6 +2957,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
29572957
["NoOpDuration"] = value => value.Should().NotBeNull(),
29582958
["TotalUniquePackagesCount"] = value => value.Should().Be(1),
29592959
["NewPackagesInstalledCount"] = value => value.Should().Be(1),
2960+
["AnyPackageIdContainsNonASCIICharacters"] = value => value.Should().Be(false),
29602961
["EvaluateLockFileDuration"] = value => value.Should().NotBeNull(),
29612962
["CreateRestoreTargetGraphDuration"] = value => value.Should().NotBeNull(),
29622963
["GenerateRestoreGraphDuration"] = value => value.Should().NotBeNull(),
@@ -3235,7 +3236,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
32353236

32363237
var projectInformationEvent = telemetryEvents.Single(e => e.Name.Equals("ProjectRestoreInformation"));
32373238

3238-
projectInformationEvent.Count.Should().Be(49);
3239+
projectInformationEvent.Count.Should().Be(50);
32393240
projectInformationEvent["RestoreSuccess"].Should().Be(true);
32403241
projectInformationEvent["NoOpResult"].Should().Be(false);
32413242
projectInformationEvent["TotalUniquePackagesCount"].Should().Be(2);
@@ -3644,6 +3645,139 @@ private static PackageSpec CreatePackageSpec(List<TargetFrameworkInformation> tf
36443645
return packageSpec;
36453646
}
36463647

3648+
[Fact]
3649+
public async Task ExecuteAsync_WithASCIIPackageId_AnyPackageIdContainsNonASCIICharactersIsFalse()
3650+
{
3651+
// Arrange
3652+
using var pathContext = new SimpleTestPathContext();
3653+
var projectName = "TestProject";
3654+
var projectPath = Path.Combine(pathContext.SolutionRoot, projectName);
3655+
PackageSpec packageSpec = ProjectTestHelpers.GetPackageSpec(projectName, pathContext.SolutionRoot, "net472", "My.Package1");
3656+
3657+
await SimpleTestPackageUtility.CreateFolderFeedV3Async(
3658+
pathContext.PackageSource,
3659+
PackageSaveMode.Defaultv3,
3660+
new SimpleTestPackageContext("My.Package1", "1.0.0"));
3661+
var logger = new TestLogger();
3662+
3663+
var request = new TestRestoreRequest(packageSpec, new PackageSource[] { new PackageSource(pathContext.PackageSource) }, pathContext.UserPackagesFolder, logger)
3664+
{
3665+
LockFilePath = Path.Combine(projectPath, "project.assets.json"),
3666+
ProjectStyle = ProjectStyle.PackageReference,
3667+
};
3668+
3669+
// Set-up telemetry service - Important to set-up the service *after* the package source creation call as that emits telemetry!
3670+
var telemetryEvents = new ConcurrentQueue<TelemetryEvent>();
3671+
var _telemetryService = new Mock<INuGetTelemetryService>(MockBehavior.Loose);
3672+
_telemetryService
3673+
.Setup(x => x.EmitTelemetryEvent(It.IsAny<TelemetryEvent>()))
3674+
.Callback<TelemetryEvent>(x => telemetryEvents.Enqueue(x));
3675+
3676+
TelemetryActivity.NuGetTelemetryService = _telemetryService.Object;
3677+
3678+
// Act
3679+
var restoreCommand = new RestoreCommand(request);
3680+
RestoreResult result = await restoreCommand.ExecuteAsync();
3681+
3682+
// Assert
3683+
result.Success.Should().BeTrue(because: logger.ShowMessages());
3684+
var projectInformationEvent = telemetryEvents.Single(e => e.Name.Equals("ProjectRestoreInformation"));
3685+
projectInformationEvent["AnyPackageIdContainsNonASCIICharacters"].Should().Be(false);
3686+
}
3687+
3688+
[Theory]
3689+
[InlineData("My_Package")] // underscore
3690+
[InlineData("Pac\u212Bage")] // Kelvin sign K (U+212A)
3691+
[InlineData("Package\u03B1")] // Greek lowercase alpha (U+03B1)
3692+
[InlineData("Package\u00E9")] // Latin small letter e with acute (U+00E9)
3693+
[InlineData("\u0410.Package")] // Cyrillic capital A (U+0410)
3694+
public async Task ExecuteAsync_WithNonASCIIPackageId_AnyPackageIdContainsNonASCIICharactersIsTrue(string packageId)
3695+
{
3696+
// Arrange
3697+
using var pathContext = new SimpleTestPathContext();
3698+
var projectName = "TestProject";
3699+
var projectPath = Path.Combine(pathContext.SolutionRoot, projectName);
3700+
PackageSpec packageSpec = ProjectTestHelpers.GetPackageSpec(projectName, pathContext.SolutionRoot, "net472", packageId);
3701+
3702+
await SimpleTestPackageUtility.CreateFolderFeedV3Async(
3703+
pathContext.PackageSource,
3704+
PackageSaveMode.Defaultv3,
3705+
new SimpleTestPackageContext(packageId, "1.0.0"));
3706+
var logger = new TestLogger();
3707+
3708+
var request = new TestRestoreRequest(packageSpec, new PackageSource[] { new PackageSource(pathContext.PackageSource) }, pathContext.UserPackagesFolder, logger)
3709+
{
3710+
LockFilePath = Path.Combine(projectPath, "project.assets.json"),
3711+
ProjectStyle = ProjectStyle.PackageReference,
3712+
};
3713+
3714+
// Set-up telemetry service - Important to set-up the service *after* the package source creation call as that emits telemetry!
3715+
var telemetryEvents = new ConcurrentQueue<TelemetryEvent>();
3716+
var _telemetryService = new Mock<INuGetTelemetryService>(MockBehavior.Loose);
3717+
_telemetryService
3718+
.Setup(x => x.EmitTelemetryEvent(It.IsAny<TelemetryEvent>()))
3719+
.Callback<TelemetryEvent>(x => telemetryEvents.Enqueue(x));
3720+
3721+
TelemetryActivity.NuGetTelemetryService = _telemetryService.Object;
3722+
3723+
// Act
3724+
var restoreCommand = new RestoreCommand(request);
3725+
RestoreResult result = await restoreCommand.ExecuteAsync();
3726+
3727+
// Assert
3728+
result.Success.Should().BeTrue(because: logger.ShowMessages());
3729+
var projectInformationEvent = telemetryEvents.Single(e => e.Name.Equals("ProjectRestoreInformation"));
3730+
projectInformationEvent["AnyPackageIdContainsNonASCIICharacters"].Should().Be(true);
3731+
}
3732+
3733+
[Theory]
3734+
[InlineData("My_Package")] // underscore
3735+
[InlineData("Pac\u212Bage")] // Kelvin sign K (U+212A)
3736+
[InlineData("Package\u03B1")] // Greek lowercase alpha (U+03B1)
3737+
public async Task ExecuteAsync_WithMixedPackageIds_AnyPackageIdContainsNonASCIICharactersIsTrue(string packageId)
3738+
{
3739+
// Arrange
3740+
using var pathContext = new SimpleTestPathContext();
3741+
var projectName = "TestProject";
3742+
var projectPath = Path.Combine(pathContext.SolutionRoot, projectName);
3743+
var asciiOnlyPkg = new SimpleTestPackageContext("Some.Package", "1.0.0");
3744+
var nonASCIIPkg = new SimpleTestPackageContext(packageId, "1.0.0");
3745+
asciiOnlyPkg.Dependencies.Add(nonASCIIPkg);
3746+
3747+
await SimpleTestPackageUtility.CreateFolderFeedV3Async(
3748+
pathContext.PackageSource,
3749+
PackageSaveMode.Defaultv3,
3750+
asciiOnlyPkg,
3751+
nonASCIIPkg);
3752+
3753+
PackageSpec packageSpec = ProjectTestHelpers.GetPackageSpec(projectName, pathContext.SolutionRoot, "net472", "Some.Package");
3754+
var logger = new TestLogger();
3755+
3756+
var request = new TestRestoreRequest(packageSpec, new PackageSource[] { new PackageSource(pathContext.PackageSource) }, pathContext.UserPackagesFolder, logger)
3757+
{
3758+
LockFilePath = Path.Combine(projectPath, "project.assets.json"),
3759+
ProjectStyle = ProjectStyle.PackageReference,
3760+
};
3761+
3762+
// Set-up telemetry service - Important to set-up the service *after* the package source creation call as that emits telemetry!
3763+
var telemetryEvents = new ConcurrentQueue<TelemetryEvent>();
3764+
var _telemetryService = new Mock<INuGetTelemetryService>(MockBehavior.Loose);
3765+
_telemetryService
3766+
.Setup(x => x.EmitTelemetryEvent(It.IsAny<TelemetryEvent>()))
3767+
.Callback<TelemetryEvent>(x => telemetryEvents.Enqueue(x));
3768+
3769+
TelemetryActivity.NuGetTelemetryService = _telemetryService.Object;
3770+
3771+
// Act
3772+
var restoreCommand = new RestoreCommand(request);
3773+
RestoreResult result = await restoreCommand.ExecuteAsync();
3774+
3775+
// Assert
3776+
result.Success.Should().BeTrue(because: logger.ShowMessages());
3777+
var projectInformationEvent = telemetryEvents.Single(e => e.Name.Equals("ProjectRestoreInformation"));
3778+
projectInformationEvent["AnyPackageIdContainsNonASCIICharacters"].Should().Be(true);
3779+
}
3780+
36473781
private Task<GraphNode<RemoteResolveResult>> DoWalkAsync(RemoteDependencyWalker walker, string name, NuGetFramework framework)
36483782
{
36493783
var range = new LibraryRange

0 commit comments

Comments
 (0)