...
|
...
|
@@ -7,87 +7,112 @@ |
|
|
//
|
|
|
|
|
|
#import "SDWebImageManager+AutoTrack.h"
|
|
|
#import "YHSwizzle.h"
|
|
|
#import <objc/runtime.h>
|
|
|
#import <objc/message.h>
|
|
|
#import "YH_EventCollector.h"
|
|
|
#import "YHLog.h"
|
|
|
#import "YHEventReport.h"
|
|
|
|
|
|
@interface NSNumber (YH_UnitConvert)
|
|
|
|
|
|
@implementation SDWebImageManager (AutoTrack)
|
|
|
@property (nonatomic, copy, readonly) NSNumber *SToIntMS;//s -> ms 并取整
|
|
|
|
|
|
@end
|
|
|
|
|
|
@implementation NSNumber (YH_UnitConvert)
|
|
|
|
|
|
- (NSNumber *)SToIntMS {
|
|
|
const double s = self.doubleValue;
|
|
|
const double ms = s * 1000;
|
|
|
return @((NSUInteger)ceil(ms));
|
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
@interface NSURLSessionTaskTransactionMetrics (YH_TrackEvent)
|
|
|
|
|
|
@property (nonatomic, copy, readonly) NSNumber *totalTime;
|
|
|
@property (nonatomic, copy, readonly) NSNumber *dnsTime;
|
|
|
@property (nonatomic, copy, readonly) NSNumber *connectTime;
|
|
|
@property (nonatomic, copy, readonly) NSNumber *secureConnectTime;
|
|
|
@property (nonatomic, copy, readonly) NSNumber *requestTime;
|
|
|
@property (nonatomic, copy, readonly) NSNumber *responseTime;
|
|
|
|
|
|
@end
|
|
|
|
|
|
@implementation NSURLSessionTaskTransactionMetrics (YH_TrackEvent)
|
|
|
|
|
|
- (NSNumber *)timeIntervalFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
|
|
|
if (fromDate && toDate &&
|
|
|
[fromDate compare:toDate] == NSOrderedAscending) {
|
|
|
return @([toDate timeIntervalSinceDate:fromDate]);
|
|
|
}
|
|
|
return @(0.f);
|
|
|
}
|
|
|
|
|
|
- (NSNumber *)totalTime {
|
|
|
return [self timeIntervalFromDate:self.fetchStartDate toDate:self.responseEndDate];
|
|
|
}
|
|
|
|
|
|
- (NSNumber *)dnsTime {
|
|
|
return [self timeIntervalFromDate:self.domainLookupStartDate toDate:self.domainLookupEndDate];
|
|
|
}
|
|
|
|
|
|
- (void)setYh_webImageId:(NSString *)yh_webImageId{
|
|
|
objc_setAssociatedObject(self,@selector(yh_webImageId),yh_webImageId,OBJC_ASSOCIATION_RETAIN);
|
|
|
- (NSNumber *)connectTime {
|
|
|
return [self timeIntervalFromDate:self.connectStartDate toDate:self.connectEndDate];
|
|
|
}
|
|
|
|
|
|
- (NSString *)yh_webImageId{
|
|
|
return objc_getAssociatedObject(self, @selector(yh_webImageId));
|
|
|
- (NSNumber *)secureConnectTime {
|
|
|
return [self timeIntervalFromDate:self.secureConnectionStartDate toDate:self.secureConnectionEndDate];
|
|
|
}
|
|
|
|
|
|
- (NSNumber *)requestTime {
|
|
|
return [self timeIntervalFromDate:self.requestStartDate toDate:self.requestEndDate];
|
|
|
}
|
|
|
|
|
|
- (NSNumber *)responseTime {
|
|
|
return [self timeIntervalFromDate:self.responseStartDate toDate:self.responseEndDate];
|
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
@implementation SDWebImageManager (AutoTrack)
|
|
|
|
|
|
+(void)startTrack
|
|
|
{
|
|
|
static dispatch_once_t onceToken;
|
|
|
dispatch_once(&onceToken, ^{
|
|
|
@try {
|
|
|
|
|
|
NSError *downloadImageError = NULL;
|
|
|
[[self class] yh_swizzleMethod:@selector(downloadImageWithURL:options:progress:completed:)
|
|
|
withMethod:@selector(yher_downloadImageWithURL:options:progress:completed:)
|
|
|
error:&downloadImageError];
|
|
|
if (downloadImageError) {
|
|
|
downloadImageError = NULL;
|
|
|
}
|
|
|
|
|
|
} @catch (NSException *exception) {
|
|
|
YHLog(@"%@ error: %@", self, exception);
|
|
|
}
|
|
|
[[NSNotificationCenter defaultCenter] addObserverForName:@"yoho_image_download_network_metrics" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
|
[self reportImageViewPerformanceForNotification:note];
|
|
|
});
|
|
|
}];
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- (id <SDWebImageOperation>)yher_downloadImageWithURL:(NSURL *)url
|
|
|
options:(SDWebImageOptions)options
|
|
|
progress:(SDWebImageDownloaderProgressBlock)progressBlock
|
|
|
completed:(SDInternalCompletionBlock)completedBlock
|
|
|
{
|
|
|
@try {
|
|
|
if ([url isKindOfClass:NSString.class]) {
|
|
|
url = [NSURL URLWithString:(NSString *)url];
|
|
|
}
|
|
|
|
|
|
// Prevents app crashing on argument type error like sending NSNull instead of NSURL
|
|
|
if ([url isKindOfClass:NSURL.class]) {
|
|
|
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isImagePerformanceTrackEnable){
|
|
|
[[YH_EventCollector sharedInstance] timeEventStartWithWebImageDownloadURL:url.absoluteString];
|
|
|
}
|
|
|
}
|
|
|
} @catch (NSException *exception) {
|
|
|
YHLog(@"%@ error: %@", self, exception);
|
|
|
+ (void)reportImageViewPerformanceForNotification:(NSNotification *)note {
|
|
|
NSURLSessionTaskMetrics *metrics = note.userInfo[@"metrics"];
|
|
|
NSError *error = note.userInfo[@"error"];
|
|
|
NSParameterAssert([metrics isKindOfClass:[NSURLSessionTaskMetrics class]]);
|
|
|
if (error.code == NSURLErrorCancelled ) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
return [self yher_downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
|
|
|
|
|
@try {
|
|
|
if ([url isKindOfClass:NSURL.class]) {
|
|
|
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isImagePerformanceTrackEnable){
|
|
|
if (cacheType == SDImageCacheTypeNone) {//暂时只去下载的图片的时间,过滤掉读缓存的时间
|
|
|
if (error) {
|
|
|
[[YH_EventCollector sharedInstance] timeEventEndWithWebImageDownloadURL:url.absoluteString status:YHEventLoadStatusFailed];
|
|
|
}else{
|
|
|
[[YH_EventCollector sharedInstance] timeEventEndWithWebImageDownloadURL:url.absoluteString status:YHEventLoadStatusSuc];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} @catch (NSException *exception) {
|
|
|
YHLog(@"%@ error: %@", self, exception);
|
|
|
}
|
|
|
|
|
|
if (completedBlock) {
|
|
|
completedBlock(image,data,error,cacheType,finished,imageURL);
|
|
|
[metrics.transactionMetrics enumerateObjectsUsingBlock:^(NSURLSessionTaskTransactionMetrics * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
if (obj.resourceFetchType == NSURLSessionTaskMetricsResourceFetchTypeNetworkLoad) {
|
|
|
[self reportImageDownloadTransactionMetrics:obj];
|
|
|
}
|
|
|
}];
|
|
|
}
|
|
|
|
|
|
+ (void)reportImageDownloadTransactionMetrics:(NSURLSessionTaskTransactionMetrics *)transMetrics {
|
|
|
NSDictionary *performanceDict = @{ @"url" : transMetrics.request.URL.absoluteString ?: @"",
|
|
|
@"protocol": transMetrics.networkProtocolName ?:@"",
|
|
|
@"proxyConnection": transMetrics.proxyConnection ? @"1" : @"0",
|
|
|
@"reusedConnection": transMetrics.reusedConnection ? @"1" : @"0",
|
|
|
@"fetch": transMetrics.totalTime.SToIntMS,
|
|
|
@"dns": transMetrics.dnsTime.SToIntMS,
|
|
|
@"connect": transMetrics.connectTime.SToIntMS,
|
|
|
@"secureConnection": transMetrics.secureConnectTime.SToIntMS,
|
|
|
@"request": transMetrics.requestTime.SToIntMS,
|
|
|
@"response": transMetrics.responseTime.SToIntMS
|
|
|
};
|
|
|
[[YHEventReport sharedInstance] reportWithPointType:YHPT_PERFORMANCE pointName:YHPN_IMAGEVIEW parameters:performanceDict];
|
|
|
}
|
|
|
|
|
|
@end |
...
|
...
|
|