Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
Merge pull request #4237 from Caelink/master
Browse files Browse the repository at this point in the history
Implement two ways to collect NSURLSessionTaskMetrics
  • Loading branch information
SlaunchaMan committed Jul 31, 2018
2 parents 7642bcf + 1d1c024 commit a101152
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
6 changes: 6 additions & 0 deletions AFNetworking/AFCompatibilityMacros.h
Expand Up @@ -34,4 +34,10 @@
#define AF_CAN_USE_AT_AVAILABLE 0
#endif

#if ((__IPHONE_OS_VERSION_MAX_ALLOWED && __IPHONE_OS_VERSION_MAX_ALLOWED < 100000) || (__MAC_OS_VERSION_MAX_ALLOWED && __MAC_OS_VERSION_MAX_ALLOWED < 101200) ||(__WATCH_OS_MAX_VERSION_ALLOWED && __WATCH_OS_MAX_VERSION_ALLOWED < 30000) ||(__TV_OS_MAX_VERSION_ALLOWED && __TV_OS_MAX_VERSION_ALLOWED < 100000))
#define AF_CAN_INCLUDE_SESSION_TASK_METRICS 0
#else
#define AF_CAN_INCLUDE_SESSION_TASK_METRICS 1
#endif

#endif /* AFCompatibilityMacros_h */
13 changes: 13 additions & 0 deletions AFNetworking/AFURLSessionManager.h
Expand Up @@ -378,6 +378,14 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * _Nullable error))block;

/**
Sets a block to be executed when metrics are finalized related to a specific task, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didFinishCollectingMetrics:`.
@param block A block object to be executed when a session task is completed. The block has no return value, and takes three arguments: the session, the task, and any metrics that were collected in the process of executing the task.
*/
#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
- (void)setTaskDidFinishCollectingMetricsBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSURLSessionTaskMetrics * _Nullable metrics))block;
#endif
///-------------------------------------------
/// @name Setting Data Task Delegate Callbacks
///-------------------------------------------
Expand Down Expand Up @@ -498,4 +506,9 @@ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey;
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey;

/**
The session task metrics taken from the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteSessionTaskMetrics`
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSessionTaskMetrics;

NS_ASSUME_NONNULL_END
49 changes: 49 additions & 0 deletions AFNetworking/AFURLSessionManager.m
Expand Up @@ -82,6 +82,7 @@ static dispatch_group_t url_session_manager_completion_group() {
NSString * const AFNetworkingTaskDidCompleteResponseDataKey = @"com.alamofire.networking.complete.finish.responsedata";
NSString * const AFNetworkingTaskDidCompleteErrorKey = @"com.alamofire.networking.task.complete.error";
NSString * const AFNetworkingTaskDidCompleteAssetPathKey = @"com.alamofire.networking.task.complete.assetpath";
NSString * const AFNetworkingTaskDidCompleteSessionTaskMetrics = @"com.alamofire.networking.complete.sessiontaskmetrics";

static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";

Expand All @@ -97,6 +98,9 @@ static dispatch_group_t url_session_manager_completion_group() {
typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task);
typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
typedef void (^AFURLSessionTaskDidCompleteBlock)(NSURLSession *session, NSURLSessionTask *task, NSError *error);
#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
typedef void (^AFURLSessionTaskDidFinishCollectingMetricsBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLSessionTaskMetrics * metrics);
#endif

typedef NSURLSessionResponseDisposition (^AFURLSessionDataTaskDidReceiveResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response);
typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask);
Expand All @@ -120,6 +124,9 @@ - (instancetype)initWithTask:(NSURLSessionTask *)task;
@property (nonatomic, strong) NSProgress *uploadProgress;
@property (nonatomic, strong) NSProgress *downloadProgress;
@property (nonatomic, copy) NSURL *downloadFileURL;
#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
@property (nonatomic, strong) NSURLSessionTaskMetrics *sessionTaskMetrics;
#endif
@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
Expand Down Expand Up @@ -210,6 +217,14 @@ - (void)URLSession:(__unused NSURLSession *)session
self.mutableData = nil;
}

#if AF_CAN_USE_AT_AVAILABLE && AF_CAN_INCLUDE_SESSION_TASK_METRICS
if (@available(iOS 10, macOS 10.12, watchOS 3, tvOS 10, *)) {
if (self.sessionTaskMetrics) {
userInfo[AFNetworkingTaskDidCompleteSessionTaskMetrics] = self.sessionTaskMetrics;
}
}
#endif

if (self.downloadFileURL) {
userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
} else if (data) {
Expand Down Expand Up @@ -258,6 +273,14 @@ - (void)URLSession:(__unused NSURLSession *)session
}
}

#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {
self.sessionTaskMetrics = metrics;
}
#endif

#pragma mark - NSURLSessionDataDelegate

- (void)URLSession:(__unused NSURLSession *)session
Expand Down Expand Up @@ -462,6 +485,9 @@ @interface AFURLSessionManager ()
@property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete;
#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidFinishCollectingMetricsBlock taskDidFinishCollectingMetrics;
#endif
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
Expand Down Expand Up @@ -871,6 +897,12 @@ - (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTas
self.taskDidComplete = block;
}

#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
- (void)setTaskDidFinishCollectingMetricsBlock:(void (^)(NSURLSession * _Nonnull, NSURLSessionTask * _Nonnull, NSURLSessionTaskMetrics * _Nullable))block {
self.taskDidFinishCollectingMetrics = block;
}
#endif

#pragma mark -

- (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block {
Expand Down Expand Up @@ -1077,6 +1109,23 @@ - (void)URLSession:(NSURLSession *)session
}
}

#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics
{
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
// Metrics may fire after URLSession:task:didCompleteWithError: is called, delegate may be nil
if (delegate) {
[delegate URLSession:session task:task didFinishCollectingMetrics:metrics];
}

if (self.taskDidFinishCollectingMetrics) {
self.taskDidFinishCollectingMetrics(session, task, metrics);
}
}
#endif

#pragma mark - NSURLSessionDataDelegate

- (void)URLSession:(NSURLSession *)session
Expand Down
25 changes: 25 additions & 0 deletions Tests/Tests/AFURLSessionManagerTests.m
Expand Up @@ -133,6 +133,31 @@ - (void)testDownloadTaskDoesReportProgress {
[self waitForExpectationsWithCommonTimeout];
}

- (void)testSessionTaskDoesReportMetrics {
[self expectationForNotification:AFNetworkingTaskDidCompleteNotification object:nil handler:^BOOL(NSNotification * _Nonnull notification) {
#if AF_CAN_USE_AT_AVAILABLE && AF_CAN_INCLUDE_SESSION_TASK_METRICS
if (@available(iOS 10, macOS 10.12, watchOS 3, tvOS 10, *)) {
return [notification userInfo][AFNetworkingTaskDidCompleteSessionTaskMetrics] != nil;
}
#endif
return YES;
}];

#if AF_CAN_INCLUDE_SESSION_TASK_METRICS
__weak XCTestExpectation *metricsBlock = [self expectationWithDescription:@"Metrics completion block is called"];
[self.localManager setTaskDidFinishCollectingMetricsBlock:^(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSURLSessionTaskMetrics * _Nullable metrics) {
[metricsBlock fulfill];
}];
#endif

NSURLSessionTask *task = [self.localManager downloadTaskWithRequest:[self bigImageURLRequest]
progress:nil
destination:nil
completionHandler:nil];
[task resume];
[self waitForExpectationsWithCommonTimeout];
}

// iOS 7 has a bug that may return nil for a session. To simulate that, nil out the
// session and it will return nil itself.
- (void)testFileUploadTaskReturnsNilWithBug {
Expand Down

0 comments on commit a101152

Please sign in to comment.