Authored by 孟顺

移除http性能统计代码

review by 枪兵
//
// NSURLConnection+AutoTrack.h
// YHEventReport
//
// Created by 孙凯 on 2017/9/30.
// Copyright © 2017年 YOHO. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSURLConnection (AutoTrack)
+(void)startTrack;
@end
//
// NSURLConnection+AutoTrack.m
// YHEventReport
//
// Created by 孙凯 on 2017/9/30.
// Copyright © 2017年 YOHO. All rights reserved.
//
#import "NSURLConnection+AutoTrack.h"
#import "YHSwizzle.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import "YHEventReport.h"
#import "YHLog.h"
#import "YH_EventCollector.h"
@interface NSURLConnection()
@property(nullable,nonatomic,weak) id my_delegate;
@property (readonly, copy) NSURLResponse *my_response;
@end
@implementation NSURLConnection (AutoTrack)
#pragma mark - 属性
- (id)my_delegate
{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setMy_delegate:(id)my_delegate
{
objc_setAssociatedObject(self, @selector(my_delegate), my_delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)my_response
{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setMy_response:(id)my_response
{
objc_setAssociatedObject(self, @selector(my_response), my_response, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+(void)startTrack{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
@try {
SEL selectors[] = {
@selector(initWithRequest:delegate:),
@selector(initWithRequest:delegate:startImmediately:),
@selector(start),
};
for (NSUInteger index = 0; index < sizeof(selectors) / sizeof(SEL); ++index) {
SEL originalSelector = selectors[index];
SEL swizzledSelector = NSSelectorFromString([@"yher_" stringByAppendingString:NSStringFromSelector(originalSelector)]);
NSError *error = NULL;
[[self class] yh_swizzleMethod:originalSelector
withMethod:swizzledSelector
error:&error];
if (error) {
YHLog(@"Failed to swizzle: on UIControl. Details: %@", error);
error = NULL;
}
}
SEL class_selectors[] = {
@selector(sendSynchronousRequest:returningResponse:error:),
@selector(sendAsynchronousRequest:queue:completionHandler:),
};
for (NSUInteger index = 0; index < sizeof(class_selectors) / sizeof(SEL); ++index) {
Class selfClass = object_getClass([self class]);
SEL oriSEL = class_selectors[index];
Method oriMethod = class_getClassMethod(selfClass, oriSEL);
SEL cusSEL = NSSelectorFromString([@"yher_" stringByAppendingString:NSStringFromSelector(oriSEL)]);
Method cusMethod = class_getClassMethod(selfClass, cusSEL);
BOOL addSucc = class_addMethod(selfClass, oriSEL, method_getImplementation(cusMethod), method_getTypeEncoding(cusMethod));
if (addSucc) {
class_replaceMethod(selfClass, cusSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
}else {
method_exchangeImplementations(oriMethod, cusMethod);
}
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
});
}
- (nullable instancetype)yher_initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate startImmediately:(BOOL)startImmediately
{
[self setMy_delegate:delegate];
return [self yher_initWithRequest:request delegate:self startImmediately:startImmediately];
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
if ([super respondsToSelector:aSelector])
return YES;
if ([self.my_delegate respondsToSelector:aSelector])
return YES;
return NO;
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if ([self.my_delegate respondsToSelector:aSelector])
return self.my_delegate;
return [super forwardingTargetForSelector:aSelector];
}
- (nullable instancetype)yher_initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate
{
[self setMy_delegate:delegate];
return [self yher_initWithRequest:request delegate:self];
}
- (void)yher_start
{
@try {
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable) {
[[YH_EventCollector sharedInstance] timeEventStartWithRequestUrl:[self.currentRequest.URL absoluteString]];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
[self yher_start];
}
+ (nullable NSData *)yher_sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse * _Nullable * _Nullable)response error:(NSError **)error
{
NSString *hostInHTTPField = [request.allHTTPHeaderFields objectForKey:@"Host"];
@try {
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && ([[request.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
[[YH_EventCollector sharedInstance] timeEventStartWithRequestUrl:[request.URL absoluteString]];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
NSData *data = [self yher_sendSynchronousRequest:request returningResponse:response error:error];
@try {
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && !error && ([[request.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
NSURLResponse *res = *response;
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)res;
NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields];
NSString *contentLength = [NSString stringWithFormat:@"%lld",[[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue]];
NSString *statusCode = [NSString stringWithFormat:@"%ld",(long)httpResponse.statusCode];
NSString *HTTPBodyStr = [[NSString alloc]initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
[[YH_EventCollector sharedInstance] timeEventEndWithRequestUrl:[request.URL absoluteString] HTTPMethod:request.HTTPMethod statusCode:statusCode contentLength:contentLength HTTPBodyStr:HTTPBodyStr];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
return data;
}
+ (void)yher_sendAsynchronousRequest:(NSURLRequest*) request
queue:(NSOperationQueue*) queue
completionHandler:(void (^)(NSURLResponse* _Nullable response, NSData* _Nullable data, NSError* _Nullable connectionError)) handler
{
NSString *hostInHTTPField = [request.allHTTPHeaderFields objectForKey:@"Host"];
@try {
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && ([[request.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
[[YH_EventCollector sharedInstance] timeEventStartWithRequestUrl:[request.URL absoluteString]];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
[self yher_sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (handler) {
handler(response,data,connectionError);
}
@try {
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && !connectionError && ([[request.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields];
NSString *contentLength = [NSString stringWithFormat:@"%lld",[[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue]];
NSString *statusCode = [NSString stringWithFormat:@"%ld",(long)httpResponse.statusCode];
NSString *HTTPBodyStr = [[NSString alloc]initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
[[YH_EventCollector sharedInstance] timeEventEndWithRequestUrl:[request.URL absoluteString] HTTPMethod:request.HTTPMethod statusCode:statusCode contentLength:contentLength HTTPBodyStr:HTTPBodyStr];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
}];
}
#pragma mark - NSURLConnectionDelegate
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
connection.my_response = response;
if (self.my_delegate && [self.my_delegate respondsToSelector:@selector(connection:didReceiveResponse:)]) {
[self.my_delegate connection:connection didReceiveResponse:response];
}
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (self.my_delegate && [self.my_delegate respondsToSelector:@selector(connection:didReceiveData:)]) {
[self.my_delegate connection:connection didReceiveData:data];
}
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.my_delegate && [self.my_delegate respondsToSelector:@selector(connectionDidFinishLoading:)]) {
[self.my_delegate connectionDidFinishLoading:connection];
}
@try {
NSString *hostInHTTPField = [connection.currentRequest.allHTTPHeaderFields objectForKey:@"Host"];
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && ([[connection.currentRequest.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)connection.my_response;
NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields];
NSString *contentLength = [NSString stringWithFormat:@"%lld",[[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue]];
NSString *statusCode = [NSString stringWithFormat:@"%ld",(long)httpResponse.statusCode];
NSString *HTTPBodyStr = [[NSString alloc]initWithData:connection.currentRequest.HTTPBody encoding:NSUTF8StringEncoding];
[[YH_EventCollector sharedInstance] timeEventEndWithRequestUrl:[connection.currentRequest.URL absoluteString] HTTPMethod:connection.currentRequest.HTTPMethod statusCode:statusCode contentLength:contentLength HTTPBodyStr:HTTPBodyStr];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
if (self.my_delegate && [self.my_delegate respondsToSelector:@selector(connection:didFailWithError:)]) {
[self.my_delegate connection:connection didFailWithError:error];
}
}
@end
//
// NSURLSession+AutoTrack.h
// YHEventReport
//
// Created by 孙凯 on 2017/9/30.
// Copyright © 2017年 YOHO. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSURLSession (AutoTrack)
+(void)startTrack;
@end
@interface YherSessionDataTaskManager: NSObject
@end
//
// NSURLSession+AutoTrack.m
// YHEventReport
//
// Created by 孙凯 on 2017/9/30.
// Copyright © 2017年 YOHO. All rights reserved.
//
#import "NSURLSession+AutoTrack.h"
#import "YHSwizzle.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import "YHEventReport.h"
#import "YHLog.h"
#import "YH_EventCollector.h"
@interface NSURLSession()
@end
@implementation NSURLSession (AutoTrack)
#pragma mark - 属性
+(void)startTrack{
// static dispatch_once_t onceToken;
// dispatch_once(&onceToken, ^{
// @try {
// SEL selectors[] = {
// //@selector(dataTaskWithRequest:completionHandler:),
// //@selector(downloadTaskWithRequest:completionHandler:),
// };
//
// for (NSUInteger index = 0; index < sizeof(selectors) / sizeof(SEL); ++index) {
// SEL originalSelector = selectors[index];
// SEL swizzledSelector = NSSelectorFromString([@"yher_" stringByAppendingString:NSStringFromSelector(originalSelector)]);
// NSError *error = NULL;
// [[self class] yh_swizzleMethod:originalSelector
// withMethod:swizzledSelector
// error:&error];
// if (error) {
// YHLog(@"Failed to swizzle: on UIControl. Details: %@", error);
// error = NULL;
// }
// }
//
// } @catch (NSException *exception) {
// YHLog(@"%@ error: %@", self, exception);
// }
// });
}
- (NSURLSessionDataTask *)yher_dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler
{
if (completionHandler == nil) {
return [self yher_dataTaskWithRequest:request completionHandler:completionHandler];
}
return [self yher_dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (completionHandler) {
completionHandler(data,response,error);
}
@try {
NSString *hostInHTTPField = [request.allHTTPHeaderFields objectForKey:@"Host"];
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && !error && ([[request.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields];
NSString *contentLength = [NSString stringWithFormat:@"%lld",[[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue]];
NSString *statusCode = [NSString stringWithFormat:@"%ld",(long)httpResponse.statusCode];
NSString *HTTPBodyStr = [[NSString alloc]initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
[[YH_EventCollector sharedInstance] timeEventEndWithRequestUrl:[request.URL absoluteString] HTTPMethod:request.HTTPMethod statusCode:statusCode contentLength:contentLength HTTPBodyStr:HTTPBodyStr];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
}];
}
- (NSURLSessionDownloadTask *)yher_downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler
{
if (completionHandler == nil) {
return [self yher_downloadTaskWithRequest:request completionHandler:completionHandler];
}
return [self yher_downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (completionHandler) {
completionHandler(location,response,error);
}
@try {
NSString *hostInHTTPField = [request.allHTTPHeaderFields objectForKey:@"Host"];
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && !error && ([[request.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields];
NSString *contentLength = [NSString stringWithFormat:@"%lld",[[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue]];
NSString *statusCode = [NSString stringWithFormat:@"%ld",(long)httpResponse.statusCode];
NSString *HTTPBodyStr = [[NSString alloc]initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
[[YH_EventCollector sharedInstance] timeEventEndWithRequestUrl:[request.URL absoluteString] HTTPMethod:request.HTTPMethod statusCode:statusCode contentLength:contentLength HTTPBodyStr:HTTPBodyStr];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
}];
}
@end
@interface YherSessionDataTaskManager()
@end
@implementation YherSessionDataTaskManager
static inline void yher_swizzleSelector(Class class, SEL originalSelector, SEL swizzledSelector) {
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
static inline BOOL yher_addMethod(Class class, SEL selector, Method method) {
return class_addMethod(class, selector, method_getImplementation(method), method_getTypeEncoding(method));
}
+(void)load{
if (NSClassFromString(@"NSURLSessionTask")) {
NSURLSessionDataTask *localDataTask = [[NSURLSession sessionWithConfiguration:nil] dataTaskWithURL:nil];
IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([YherSessionDataTaskManager class], @selector(yher_resume)));
Class currentClass = [localDataTask class];
while (class_getInstanceMethod(currentClass, @selector(resume))) {
Class superClass = [currentClass superclass];
IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector(resume)));
IMP superclassResumeIMP = method_getImplementation(class_getInstanceMethod(superClass, @selector(resume)));
if (classResumeIMP != superclassResumeIMP &&
originalAFResumeIMP != classResumeIMP) {
[self yherswizzleResumeAndSuspendMethodForClass:currentClass];
}
currentClass = [currentClass superclass];
}
[localDataTask cancel];
}
}
+ (void)yherswizzleResumeAndSuspendMethodForClass:(Class)class {
Method yherResumeMethod = class_getInstanceMethod(self, @selector(yher_resume));
yher_addMethod(class, @selector(yher_resume), yherResumeMethod);
yher_swizzleSelector(class, @selector(resume), @selector(yher_resume));
}
- (void)yher_resume
{
@try {
NSURLSessionTask *task = (NSURLSessionTask*)self;
NSString *hostInHTTPField = [task.originalRequest.allHTTPHeaderFields objectForKey:@"Host"];
if ([YHEventReport sharedInstance].isPerformanceTrackEnabled && [YHEventReport sharedInstance].isHttpPerformanceTrackEnable && ([[task.originalRequest.URL host] isEqualToString:YHEventReportHttpHost] || [hostInHTTPField isEqualToString:YHEventReportHttpHost])) {
[[YH_EventCollector sharedInstance] timeEventStartWithRequestUrl:[task.originalRequest.URL absoluteString]];
}
} @catch (NSException *exception) {
YHLog(@"%@ error: %@", self, exception);
}
[self yher_resume];
}
@end
... ... @@ -101,19 +101,6 @@
* @property
*
* @abstract
* 是否开启Http加载性能上报
*
* @discussion
* 默认值为 关.
*/
@property (atomic,getter=isHttpPerformanceTrackEnable) BOOL httpPerformanceTrackEnable;
/**
* @property
*
* @abstract
* 是否开启app埋点数据上报
*
* @discussion
... ...
... ... @@ -21,12 +21,10 @@
#import "UITabBar+AutoTrack.h"
#import "UIButton+AutoTrack.h"
#import "UITapGestureRecognizer+AutoTrack.h"
#import "NSURLConnection+AutoTrack.h"
#import "YH_EventCacheManager.h"
#import "YH_CrashDataManager.h"
#import "YH_EventDataFactory.h"
#import "YH_CrashReporter.h"
#import "NSURLSession+AutoTrack.h"
#import "UIImageView+GestureAutoTrack.h"
#import "UILabel+GestureAutoTrack.h"
#import "YH_EventCollector.h"
... ... @@ -205,11 +203,6 @@ static NSArray *kYHEventReportIgnoredViewControllerArray;
[UICollectionView startTrack];
}
if ([YHEventReport sharedInstance].isHttpPerformanceTrackEnable) {
[NSURLConnection startTrack];
[NSURLSession startTrack];
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if ([YHEventReport sharedInstance].isControllerPerformanceTrackEnable) {
... ...
... ... @@ -19,8 +19,6 @@
#import "UITabBarItem+Yoho.h"
#import "UIButton+AutoTrack.h"
#import "UITapGestureRecognizer+AutoTrack.h"
#import "NSURLSession+AutoTrack.h"
#import "NSURLConnection+AutoTrack.h"
#import "UITableView+AutoTrack.h"
#import "UICollectionView+AutoTrack.h"
#import "YH_EventUtil.h"
... ...