66using System . Collections . Generic ;
77using System . Threading . Tasks ;
88using System . Linq ;
9+ using System . Diagnostics ;
910
1011namespace NuGetGallery
1112{
@@ -23,22 +24,25 @@ public class TyposquattingService : ITyposquattingService
2324 private readonly IContentObjectService _contentObjectService ;
2425 private readonly IPackageService _packageService ;
2526 private readonly IReservedNamespaceService _reservedNamespaceService ;
27+ private readonly ITelemetryService _telemetryService ;
2628
27- public TyposquattingService ( IContentObjectService contentObjectService , IPackageService packageService , IReservedNamespaceService reservedNamespaceService )
29+ public TyposquattingService ( IContentObjectService contentObjectService , IPackageService packageService , IReservedNamespaceService reservedNamespaceService , ITelemetryService telemetryService )
2830 {
2931 _contentObjectService = contentObjectService ?? throw new ArgumentNullException ( nameof ( contentObjectService ) ) ;
3032 _packageService = packageService ?? throw new ArgumentNullException ( nameof ( packageService ) ) ;
3133 _reservedNamespaceService = reservedNamespaceService ?? throw new ArgumentNullException ( nameof ( reservedNamespaceService ) ) ;
34+ _telemetryService = telemetryService ?? throw new ArgumentNullException ( nameof ( telemetryService ) ) ;
3235
3336 TyposquattingCheckListLength = _contentObjectService . TyposquattingConfiguration . PackageIdChecklistLength ;
3437 }
3538
3639 public bool IsUploadedPackageIdTyposquatting ( string uploadedPackageId , User uploadedPackageOwner , out List < string > typosquattingCheckCollisionIds )
3740 {
3841 typosquattingCheckCollisionIds = new List < string > ( ) ;
42+ var wasUploadBlocked = false ;
3943 if ( ! _contentObjectService . TyposquattingConfiguration . IsCheckEnabled || _reservedNamespaceService . GetReservedNamespacesForId ( uploadedPackageId ) . Any ( ) )
4044 {
41- return false ;
45+ return wasUploadBlocked ;
4246 }
4347
4448 if ( uploadedPackageId == null )
@@ -51,14 +55,17 @@ public bool IsUploadedPackageIdTyposquatting(string uploadedPackageId, User uplo
5155 throw new ArgumentNullException ( nameof ( uploadedPackageOwner ) ) ;
5256 }
5357
58+ var checklistRetrievalStopwatch = Stopwatch . StartNew ( ) ;
5459 var packageRegistrations = _packageService . GetAllPackageRegistrations ( ) ;
5560 var packagesCheckList = packageRegistrations
5661 . OrderByDescending ( pr => pr . IsVerified )
5762 . ThenByDescending ( pr => pr . DownloadCount )
5863 . Select ( pr => pr . Id )
5964 . Take ( TyposquattingCheckListLength )
6065 . ToList ( ) ;
66+ checklistRetrievalStopwatch . Stop ( ) ;
6167
68+ var algorithmProcessingStopwatch = Stopwatch . StartNew ( ) ;
6269 var threshold = GetThreshold ( uploadedPackageId ) ;
6370 uploadedPackageId = TyposquattingStringNormalization . NormalizeString ( uploadedPackageId ) ;
6471
@@ -72,11 +79,25 @@ public bool IsUploadedPackageIdTyposquatting(string uploadedPackageId, User uplo
7279 }
7380 } ) ;
7481
82+ algorithmProcessingStopwatch . Stop ( ) ;
83+
84+ var totalTime = checklistRetrievalStopwatch . Elapsed . Add ( algorithmProcessingStopwatch . Elapsed ) ;
85+ _telemetryService . TrackMetricForTyposquattingChecklistRetrievalTime ( uploadedPackageId , checklistRetrievalStopwatch . Elapsed ) ;
86+ _telemetryService . TrackMetricForTyposquattingAlgorithmProcessingTime ( uploadedPackageId , algorithmProcessingStopwatch . Elapsed ) ;
87+
7588 if ( collisionIds . Count == 0 )
7689 {
90+ _telemetryService . TrackMetricForTyposquattingCheckResultAndTotalTime (
91+ uploadedPackageId ,
92+ totalTime ,
93+ wasUploadBlocked ,
94+ typosquattingCheckCollisionIds ,
95+ TyposquattingCheckListLength ) ;
96+
7797 return false ;
7898 }
7999
100+ var ownersCheckStopwatch = Stopwatch . StartNew ( ) ;
80101 var collisionPackagesIdAndOwners = packageRegistrations
81102 . Where ( pr => collisionIds . Contains ( pr . Id ) )
82103 . Select ( pr => new { Id = pr . Id , Owners = pr . Owners . Select ( x => x . Key ) . ToList ( ) } )
@@ -99,7 +120,20 @@ public bool IsUploadedPackageIdTyposquatting(string uploadedPackageId, User uplo
99120 var isUserAllowedTyposquatting = collisionPackagesIdAndOwners
100121 . Any ( pio => pio . Owners . Any ( k => k == uploadedPackageOwner . Key ) ) ;
101122
102- return _contentObjectService . TyposquattingConfiguration . IsBlockUsersEnabled && ! isUserAllowedTyposquatting ;
123+ wasUploadBlocked = _contentObjectService . TyposquattingConfiguration . IsBlockUsersEnabled && ! isUserAllowedTyposquatting ;
124+
125+ ownersCheckStopwatch . Stop ( ) ;
126+
127+ totalTime = totalTime . Add ( ownersCheckStopwatch . Elapsed ) ;
128+ _telemetryService . TrackMetricForTyposquattingOwnersCheckTime ( uploadedPackageId , ownersCheckStopwatch . Elapsed ) ;
129+ _telemetryService . TrackMetricForTyposquattingCheckResultAndTotalTime (
130+ uploadedPackageId ,
131+ totalTime ,
132+ wasUploadBlocked ,
133+ typosquattingCheckCollisionIds ,
134+ TyposquattingCheckListLength ) ;
135+
136+ return wasUploadBlocked ;
103137 }
104138
105139 private static int GetThreshold ( string packageId )
@@ -112,7 +146,7 @@ private static int GetThreshold(string packageId)
112146 }
113147 }
114148
115- throw new ArgumentException ( "There is no predefined typo-squatting threshold for this package Id: " + packageId ) ;
149+ throw new ArgumentException ( String . Format ( "There is no predefined typo-squatting threshold for this package Id: {0}" , packageId ) ) ;
116150 }
117151 }
118152
0 commit comments