Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 5ece44e

Browse files
authored
Add metric to track package backup durations (#682)
Package backups exceeding the expected duration may be causing message duplication in the Orchestrator. This adds more telemetry around package backups for future investigations. Part of NuGet/NuGetGallery#6624
1 parent e261382 commit 5ece44e

5 files changed

Lines changed: 87 additions & 12 deletions

File tree

src/NuGet.Services.Validation.Orchestrator/Telemetry/ITelemetryService.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@ public interface ITelemetryService
1717
/// </summary>
1818
void TrackDurationToValidationSetCreation(TimeSpan duration);
1919

20+
/// <summary>
21+
/// Track how long a package's backup takes.
22+
/// </summary>
23+
/// <param name="validationSet">The validation set that requested the backup.</param>
24+
/// <returns>Reports the duration when disposed.</returns>
25+
IDisposable TrackDurationToBackupPackage(PackageValidationSet validationSet);
26+
2027
/// <summary>
2128
/// A counter metric emitted when a package changes package status. This metric is not emitted if package status
2229
/// does not change. This metric is emitted for revalidation if the terminal state changes.
2330
/// </summary>
2431
/// <param name="fromStatus">The status that the package moved from.</param>
25-
/// <param name="toStatus">The status that the package moved tp.</param>
32+
/// <param name="toStatus">The status that the package moved to.</param>
2633
void TrackPackageStatusChange(PackageStatus fromStatus, PackageStatus toStatus);
2734

2835
/// <summary>

src/NuGet.Services.Validation.Orchestrator/Telemetry/TelemetryService.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class TelemetryService : ITelemetryService, ISubscriptionProcessorTelemet
1616
private const string PackageCertificatesPrefix = "PackageCertificates.";
1717

1818
private const string DurationToValidationSetCreationSeconds = OrchestratorPrefix + "DurationToValidationSetCreationSeconds";
19+
private const string DurationToBackupPackageSeconds = OrchestratorPrefix + "DurationToBackupPackageSeconds";
1920
private const string PackageStatusChange = OrchestratorPrefix + "PackageStatusChange";
2021
private const string TotalValidationDurationSeconds = OrchestratorPrefix + "TotalValidationDurationSeconds";
2122
private const string SentValidationTakingTooLongMessage = OrchestratorPrefix + "SentValidationTakingTooLongMessage";
@@ -86,6 +87,18 @@ public void TrackDurationToValidationSetCreation(TimeSpan duration)
8687
duration.TotalSeconds);
8788
}
8889

90+
public IDisposable TrackDurationToBackupPackage(PackageValidationSet validationSet)
91+
{
92+
return _telemetryClient.TrackDuration(
93+
DurationToBackupPackageSeconds,
94+
new Dictionary<string, string>
95+
{
96+
{ ValidationTrackingId, validationSet.ValidationTrackingId.ToString() },
97+
{ PackageId, validationSet.PackageId },
98+
{ NormalizedVersion, validationSet.PackageNormalizedVersion }
99+
});
100+
}
101+
89102
public void TrackPackageStatusChange(PackageStatus fromStatus, PackageStatus toStatus)
90103
{
91104
_telemetryClient.TrackMetric(

src/NuGet.Services.Validation.Orchestrator/ValidationPackageFileService.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,22 @@ public Task CopyValidationPackageForValidationSetAsync(PackageValidationSet vali
118118

119119
public async Task BackupPackageFileFromValidationSetPackageAsync(PackageValidationSet validationSet)
120120
{
121-
_logger.LogInformation(
122-
"Backing up package for validation set {ValidationTrackingId} ({PackageId} {PackageVersion}).",
123-
validationSet.ValidationTrackingId,
124-
validationSet.PackageId,
125-
validationSet.PackageNormalizedVersion);
121+
using (_telemetryService.TrackDurationToBackupPackage(validationSet))
122+
{
123+
_logger.LogInformation(
124+
"Backing up package for validation set {ValidationTrackingId} ({PackageId} {PackageVersion}).",
125+
validationSet.ValidationTrackingId,
126+
validationSet.PackageId,
127+
validationSet.PackageNormalizedVersion);
126128

127-
var packageUri = await GetPackageForValidationSetReadUriAsync(
128-
validationSet,
129-
DateTimeOffset.UtcNow.Add(AccessDuration));
129+
var packageUri = await GetPackageForValidationSetReadUriAsync(
130+
validationSet,
131+
DateTimeOffset.UtcNow.Add(AccessDuration));
130132

131-
using (var packageStream = await _fileDownloader.DownloadAsync(packageUri, CancellationToken.None))
132-
{
133-
await StorePackageFileInBackupLocationAsync(validationSet, packageStream);
133+
using (var packageStream = await _fileDownloader.DownloadAsync(packageUri, CancellationToken.None))
134+
{
135+
await StorePackageFileInBackupLocationAsync(validationSet, packageStream);
136+
}
134137
}
135138
}
136139

tests/NuGet.Services.Validation.Orchestrator.Tests/TelemetryServiceFacts.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,48 @@ public void TrackDurationToHashPackage_TracksDuration()
7171

7272
_telemetryClient.VerifyAll();
7373
}
74+
75+
[Fact]
76+
public void TrackDurationToBackupPackage_TracksDuration()
77+
{
78+
// Arrange
79+
var validationTrackingId = Guid.NewGuid();
80+
var packageId = "a";
81+
var normalizedVersion = "b";
82+
var validationSet = new PackageValidationSet
83+
{
84+
ValidationTrackingId = validationTrackingId,
85+
PackageId = packageId,
86+
PackageNormalizedVersion = normalizedVersion
87+
};
88+
89+
var expectedReturnValue = Mock.Of<IDisposable>();
90+
91+
_telemetryClient.Setup(
92+
x => x.TrackMetric(
93+
It.IsNotNull<string>(),
94+
It.IsAny<double>(),
95+
It.IsNotNull<IDictionary<string, string>>()))
96+
.Callback((string metricName, double value, IDictionary<string, string> properties) =>
97+
{
98+
Assert.Equal("Orchestrator.DurationToBackupPackageSeconds", metricName);
99+
Assert.True(value > 0);
100+
Assert.NotEmpty(properties);
101+
Assert.Equal(new Dictionary<string, string>()
102+
{
103+
{ "ValidationTrackingId", validationTrackingId.ToString() },
104+
{ "PackageId", packageId },
105+
{ "NormalizedVersion", normalizedVersion },
106+
}, properties);
107+
});
108+
109+
// Act
110+
using (_telemetryService.TrackDurationToBackupPackage(validationSet))
111+
{
112+
}
113+
114+
// Assert
115+
_telemetryClient.VerifyAll();
116+
}
74117
}
75118
}

tests/NuGet.Services.Validation.Orchestrator.Tests/ValidationPackageFileServiceFacts.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ public async Task BackupPackageFileFromValidationSetPackageAsync()
112112
.Returns(Task.CompletedTask)
113113
.Verifiable();
114114

115+
var backupDurationMetric = new Mock<IDisposable>(MockBehavior.Strict);
116+
backupDurationMetric
117+
.Setup(m => m.Dispose())
118+
.Verifiable();
119+
120+
_telemetryService
121+
.Setup(t => t.TrackDurationToBackupPackage(_validationSet))
122+
.Returns(backupDurationMetric.Object);
123+
115124
var before = DateTimeOffset.UtcNow;
116125
await _target.BackupPackageFileFromValidationSetPackageAsync(_validationSet);
117126
var after = DateTimeOffset.UtcNow;

0 commit comments

Comments
 (0)