123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- //
- // QNUploadRequestMetrics.m
- // QiniuSDK
- //
- // Created by yangsen on 2020/4/29.
- // Copyright © 2020 Qiniu. All rights reserved.
- //
- #import "QNUtils.h"
- #import "QNUploadRequestMetrics.h"
- #import "NSURLRequest+QNRequest.h"
- #import "QNZoneInfo.h"
- @interface QNUploadMetrics()
- @property (nullable, strong) NSDate *startDate;
- @property (nullable, strong) NSDate *endDate;
- @end
- @implementation QNUploadMetrics
- //MARK:-- 构造
- + (instancetype)emptyMetrics {
- return [[self alloc] init];
- }
- - (NSNumber *)totalElapsedTime{
- return [QNUtils dateDuration:self.startDate endDate:self.endDate];
- }
- - (void)start {
- self.startDate = [NSDate date];
- }
- - (void)end {
- self.endDate = [NSDate date];
- }
- @end
- @interface QNUploadSingleRequestMetrics()
- @property (nonatomic, assign) int64_t countOfRequestHeaderBytes;
- @property (nonatomic, assign) int64_t countOfRequestBodyBytes;
- @end
- @implementation QNUploadSingleRequestMetrics
- + (instancetype)emptyMetrics{
- QNUploadSingleRequestMetrics *metrics = [[QNUploadSingleRequestMetrics alloc] init];
- return metrics;
- }
- - (instancetype)init{
- if (self = [super init]) {
- [self initData];
- }
- return self;
- }
- - (void)initData{
- _countOfRequestHeaderBytesSent = 0;
- _countOfRequestBodyBytesSent = 0;
- _countOfResponseHeaderBytesReceived = 0;
- _countOfResponseBodyBytesReceived = 0;
- }
- - (void)setRequest:(NSURLRequest *)request{
- NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:request.URL
- cachePolicy:request.cachePolicy
- timeoutInterval:request.timeoutInterval];
- newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
-
- self.countOfRequestHeaderBytes = [NSString stringWithFormat:@"%@", request.allHTTPHeaderFields].length;
- self.countOfRequestBodyBytes = [request.qn_getHttpBody length];
- _totalBytes = @(self.countOfRequestHeaderBytes + self.countOfRequestBodyBytes);
- _request = [newRequest copy];
- }
- - (void)setResponse:(NSURLResponse *)response {
- if ([response isKindOfClass:[NSHTTPURLResponse class]] &&
- [(NSHTTPURLResponse *)response statusCode] >= 200 &&
- [(NSHTTPURLResponse *)response statusCode] < 300) {
- _countOfRequestHeaderBytesSent = _countOfRequestHeaderBytes;
- _countOfRequestBodyBytesSent = _countOfRequestBodyBytes;
- }
- if (_countOfResponseBodyBytesReceived <= 0) {
- _countOfResponseBodyBytesReceived = response.expectedContentLength;
- }
- if (_countOfResponseHeaderBytesReceived <= 0 && [response isKindOfClass:[NSHTTPURLResponse class]]) {
- _countOfResponseHeaderBytesReceived = [NSString stringWithFormat:@"%@", [(NSHTTPURLResponse *)response allHeaderFields]].length;
- }
- _response = [response copy];
- }
- - (BOOL)isForsureHijacked {
- return [self.hijacked isEqualToString:kQNMetricsRequestHijacked];
- }
- - (BOOL)isMaybeHijacked {
- return [self.hijacked isEqualToString:kQNMetricsRequestMaybeHijacked];
- }
- - (NSNumber *)totalElapsedTime{
- return [self timeFromStartDate:self.startDate
- toEndDate:self.endDate];
- }
- - (NSNumber *)totalDnsTime{
- return [self timeFromStartDate:self.domainLookupStartDate
- toEndDate:self.domainLookupEndDate];
- }
- - (NSNumber *)totalConnectTime{
- return [self timeFromStartDate:self.connectStartDate
- toEndDate:self.connectEndDate];
- }
- - (NSNumber *)totalSecureConnectTime{
- return [self timeFromStartDate:self.secureConnectionStartDate
- toEndDate:self.secureConnectionEndDate];
- }
- - (NSNumber *)totalRequestTime{
- return [self timeFromStartDate:self.requestStartDate
- toEndDate:self.requestEndDate];
- }
- - (NSNumber *)totalWaitTime{
- return [self timeFromStartDate:self.requestEndDate
- toEndDate:self.responseStartDate];
- }
- - (NSNumber *)totalResponseTime{
- return [self timeFromStartDate:self.responseStartDate
- toEndDate:self.responseEndDate];
- }
- - (NSNumber *)bytesSend{
- int64_t totalBytes = [self totalBytes].integerValue;
- int64_t senderBytes = self.countOfRequestBodyBytesSent + self.countOfRequestHeaderBytesSent;
- int64_t bytes = MIN(totalBytes, senderBytes);
- return @(bytes);
- }
- - (NSNumber *)timeFromStartDate:(NSDate *)startDate toEndDate:(NSDate *)endDate{
- return [QNUtils dateDuration:startDate endDate:endDate];
- }
- - (NSNumber *)perceptiveSpeed {
- int64_t size = self.bytesSend.longLongValue + _countOfResponseHeaderBytesReceived + _countOfResponseBodyBytesReceived;
- if (size == 0 || self.totalElapsedTime == nil) {
- return nil;
- }
-
- return [QNUtils calculateSpeed:size totalTime:self.totalElapsedTime.longLongValue];
- }
- @end
- @interface QNUploadRegionRequestMetrics()
- @property (nonatomic, strong) id <QNUploadRegion> region;
- @property (nonatomic, copy) NSMutableArray<QNUploadSingleRequestMetrics *> *metricsListInter;
- @end
- @implementation QNUploadRegionRequestMetrics
- + (instancetype)emptyMetrics{
- QNUploadRegionRequestMetrics *metrics = [[QNUploadRegionRequestMetrics alloc] init];
- return metrics;
- }
- - (instancetype)initWithRegion:(id<QNUploadRegion>)region{
- if (self = [super init]) {
- _region = region;
- _metricsListInter = [NSMutableArray array];
- }
- return self;
- }
- - (QNUploadSingleRequestMetrics *)lastMetrics {
- @synchronized (self) {
- return self.metricsListInter.lastObject;
- }
- }
- - (NSNumber *)requestCount{
- if (self.metricsList) {
- return @(self.metricsList.count);
- } else {
- return @(0);
- }
- }
- - (NSNumber *)bytesSend{
- if (self.metricsList) {
- long long bytes = 0;
- for (QNUploadSingleRequestMetrics *metrics in self.metricsList) {
- bytes += metrics.bytesSend.longLongValue;
- }
- return @(bytes);
- } else {
- return @(0);
- }
- }
- - (void)addMetricsList:(NSArray<QNUploadSingleRequestMetrics *> *)metricsList{
- @synchronized (self) {
- [_metricsListInter addObjectsFromArray:metricsList];
- }
- }
- - (void)addMetrics:(QNUploadRegionRequestMetrics*)metrics{
- if ([metrics.region.zoneInfo.regionId isEqualToString:self.region.zoneInfo.regionId]) {
- @synchronized (self) {
- [_metricsListInter addObjectsFromArray:metrics.metricsListInter];
- }
- }
- }
- - (NSArray<QNUploadSingleRequestMetrics *> *)metricsList{
- @synchronized (self) {
- return [_metricsListInter copy];
- }
- }
- @end
- @interface QNUploadTaskMetrics()
- @property (nonatomic, copy) NSString *upType;
- @property (nonatomic, copy) NSMutableArray<NSString *> *metricsKeys;
- @property (nonatomic, strong) NSMutableDictionary<NSString *, QNUploadRegionRequestMetrics *> *metricsInfo;
- @end
- @implementation QNUploadTaskMetrics
- + (instancetype)emptyMetrics{
- QNUploadTaskMetrics *metrics = [[QNUploadTaskMetrics alloc] init];
- return metrics;
- }
- + (instancetype)taskMetrics:(NSString *)upType {
- QNUploadTaskMetrics *metrics = [self emptyMetrics];
- metrics.upType = upType;
- return metrics;
- }
- - (instancetype)init{
- if (self = [super init]) {
- _metricsKeys = [NSMutableArray array];
- _metricsInfo = [NSMutableDictionary dictionary];
- }
- return self;
- }
- - (QNUploadRegionRequestMetrics *)lastMetrics {
- if (self.metricsKeys.count < 1) {
- return nil;
- }
-
- @synchronized (self) {
- NSString *key = self.metricsKeys.lastObject;
- if (key == nil) {
- return nil;
- }
- return self.metricsInfo[key];
- }
- }
- - (NSNumber *)totalElapsedTime{
- NSDictionary *metricsInfo = [self syncCopyMetricsInfo];
- if (metricsInfo) {
- double time = 0;
- for (QNUploadRegionRequestMetrics *metrics in metricsInfo.allValues) {
- time += metrics.totalElapsedTime.doubleValue;
- }
- return time > 0 ? @(time) : nil;
- } else {
- return nil;
- }
- }
- - (NSNumber *)requestCount{
- NSDictionary *metricsInfo = [self syncCopyMetricsInfo];
- if (metricsInfo) {
- NSInteger count = 0;
- for (QNUploadRegionRequestMetrics *metrics in metricsInfo.allValues) {
- count += metrics.requestCount.integerValue;
- }
- return @(count);
- } else {
- return @(0);
- }
- }
- - (NSNumber *)bytesSend{
- NSDictionary *metricsInfo = [self syncCopyMetricsInfo];
- if (metricsInfo) {
- long long bytes = 0;
- for (QNUploadRegionRequestMetrics *metrics in metricsInfo.allValues) {
- bytes += metrics.bytesSend.longLongValue;
- }
- return @(bytes);
- } else {
- return @(0);
- }
- }
- - (NSNumber *)regionCount{
- NSDictionary *metricsInfo = [self syncCopyMetricsInfo];
- if (metricsInfo) {
- int count = 0;
- for (QNUploadRegionRequestMetrics *metrics in metricsInfo.allValues) {
- if (![metrics.region.zoneInfo.regionId isEqualToString:QNZoneInfoEmptyRegionId]) {
- count += 1;
- }
- }
- return @(count);
- } else {
- return @(0);
- }
- }
- - (void)setUcQueryMetrics:(QNUploadRegionRequestMetrics *)ucQueryMetrics {
- _ucQueryMetrics = ucQueryMetrics;
- [self addMetrics:ucQueryMetrics];
- }
- - (void)addMetrics:(QNUploadRegionRequestMetrics *)metrics{
- NSString *regionId = metrics.region.zoneInfo.regionId;
- if (!regionId) {
- return;
- }
- @synchronized (self) {
- QNUploadRegionRequestMetrics *metricsOld = self.metricsInfo[regionId];
- if (metricsOld) {
- [metricsOld addMetrics:metrics];
- } else {
- [self.metricsKeys addObject:regionId];
- self.metricsInfo[regionId] = metrics;
- }
- }
- }
- - (NSDictionary<NSString *, QNUploadRegionRequestMetrics *> *)syncCopyMetricsInfo {
- @synchronized (self) {
- return [_metricsInfo copy];
- }
- }
- @end
|