iOS网络数据指标收集
阅读原文时间:2023年08月13日阅读:1

在平时开发中有时候需要收集网络不同阶段性能数据来分析网络情况,下面总结了2种收集方式。

1.通过NSURLSession提供的代理方法收集

2.通过NSURLProtocol做统一网络请求拦截收集

通过NSURLSession提供的代理方法收集

当NSURLSessionTask完成并返回响应时,NSURLSession会收集一些关于任务运行的性能指标,如请求时间、响应时间、传输速度、重定向次数等等。这些指标会被包装成NSURLSessionTaskMetrics对象,并在任务完成时传递给代理对象。在这个方法中可以对这些指标进行处理和记录,以便对网络性能进行分析和优化。

@interface MySessionDelegate : NSObject

@end

@implementation MySessionDelegate

  • (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {
    // 打印出请求的各项指标
    for(NSURLSessionTaskTransactionMetrics *transaction in metrics.transactionMetrics) {
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)transaction.response;
    NSLog(@"Request URL: %@", transaction.request.URL);
    NSLog(@"HTTP Status Code: %ld", (long)response.statusCode);
    NSLog(@"Request Start Time: %@", transaction.startDate);
    NSLog(@"Request End Time: %@", transaction.endDate);
    NSLog(@"Request Duration: %f", [transaction.duration doubleValue]);
    NSLog(@"Bytes Sent: %lld", transaction.countOfRequestBodyBytesSent);
    NSLog(@"Bytes Received: %lld", transaction.countOfResponseBodyBytesReceived);
    NSLog(@"Redirection Count: %lu", (unsigned long)transaction.redirectCount);
    NSLog(@"Request Method: %@", transaction.request.HTTPMethod);
    }
    }

@end

通过NSURLProtocol做统一网络请求拦截收集

NSURLProtocol是自定义URL加载系统的一部分,允许开发者拦截URL请求并做自定义的逻辑处理。

NSURLProtocol的主要作用是在URL请求和URL响应之间添加拦截器,提供了对URL请求的拦截和处理的能力。

NSURLProtocol常用方法说明

canInitWithRequest::用于判断是否需要处理该请求,如果返回YES,则会继续调用其他方法处理该请求,如果返回NO,则会终止处理该请求。

canonicalRequestForRequest::用于获取规范化的请求对象,可以在这里修改请求头等信息。

startLoading::用于开始处理请求,可以在这里发起网络请求、读取本地缓存等操作。

stopLoading::用于停止处理请求,通常在此方法中取消网络请求、关闭文件等操作。

NSURLProtocol的使用非常灵活,可以用于实现自定义的网络拦截器、缓存策略、调试工具等。

代码举例

@interface MyURLProtocol : NSURLProtocol

@end

@interface MyURLProtocol()

@property(nonatomic, strong) NSURLConnection *connection;
@property(atomic, strong) NSMutableData *receivedData;

@end

@implementation MyURLProtocol

  • (BOOL)canInitWithRequest:(NSURLRequest *)request {
    if ([NSURLProtocol propertyForKey:kCustomURLProtocolKey inRequest:request]) {
    return NO;
    }

#if defined(Debug)
return YES;
#elif defined(Release)
return NO;
#endif
}

  • (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
    }

  • (void)startLoading {
    NSMutableURLRequest *mutableRequest = [[self request] mutableCopy];
    [NSURLProtocol setProperty:@YES forKey:kCustomURLProtocolKey inRequest:mutableRequest];
    self.connection = [NSURLConnection connectionWithRequest:mutableRequest delegate:self];
    }

  • (void)stopLoading {
    [self.connection cancel];
    self.connection = nil;
    }

#pragma mark - NSURLConnection Delegate

#pragma mark - NSURLConnection Delegate

  • (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
    [[self client] URLProtocol:self didReceiveResponse:response
    cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    }

  • (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
    [[self client] URLProtocol:self didLoadData:data];

    if (self.receivedData == nil) {
    self.receivedData = [[NSMutableData alloc] init];
    }

    [self.receivedData appendData:data];
    }

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSURLRequest *logRequest = [self.request copy];
NSData *data = [self.receivedData copy];
[[self client] URLProtocolDidFinishLoading:self];
self.connection = nil;
#if defined(Debug)
dispatch_async(dispatch_get_main_queue(), ^{
[[LogManager sharedInstance] addNetworkLog:logRequest response:data];
});
#else
dispatch_async(dispatch_get_main_queue(), ^{
[[LogManager sharedInstance] addNetworkLog:logRequest response:data];
});
#endif

}

  • (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
    [[self client] URLProtocol:self didFailWithError:error];
    self.connection = nil;
    }

@end