Files
youle_app_ios/Pods/Qiniu/QiniuSDK/Collect/QNUploadInfoReporter.m

243 lines
8.2 KiB
Objective-C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// QNUploadInfoReporter.m
// QiniuSDK
//
// Created by WorkSpace_Sun on 2019/6/24.
// Copyright © 2019 Qiniu. All rights reserved.
//
#import "QNDefine.h"
#import "QNZoneInfo.h"
#import "QNUploadInfoReporter.h"
#import "QNResponseInfo.h"
#import "QNUtils.h"
#import "QNFile.h"
#import "QNUpToken.h"
#import "QNUserAgent.h"
#import "QNAsyncRun.h"
#import "QNVersion.h"
#import "QNReportConfig.h"
#import "NSData+QNGZip.h"
#import "QNTransactionManager.h"
#import "QNRequestTransaction.h"
#define kQNUplogDelayReportTransactionName @"com.qiniu.uplog"
@interface QNUploadInfoReporter ()
@property (nonatomic, strong) QNReportConfig *config;
@property (nonatomic, assign) NSTimeInterval lastReportTime;
@property (nonatomic, strong) NSString *recorderFilePath;
@property (nonatomic, strong) NSString *recorderTempFilePath;
@property (nonatomic, copy) NSString *X_Log_Client_Id;
@property (nonatomic, strong) QNRequestTransaction *transaction;
@property (nonatomic, assign) BOOL isReporting;
@property (nonatomic, strong) dispatch_queue_t recordQueue;
@property (nonatomic, strong) dispatch_semaphore_t semaphore;
@end
@implementation QNUploadInfoReporter
+ (instancetype)sharedInstance {
static QNUploadInfoReporter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_config = [QNReportConfig sharedInstance];
_lastReportTime = 0;
_recorderFilePath = [NSString stringWithFormat:@"%@/%@", _config.recordDirectory, @"qiniu.log"];
_recorderTempFilePath = [NSString stringWithFormat:@"%@/%@", _config.recordDirectory, @"qiniuTemp.log"];
_recordQueue = dispatch_queue_create("com.qiniu.reporter", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)clean {
[self cleanRecorderFile];
[self cleanTempRecorderFile];
}
- (void)cleanRecorderFile {
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:_recorderFilePath]) {
NSError *error = nil;
[manager removeItemAtPath:_recorderFilePath error:&error];
if (error) {
NSLog(@"remove recorder file failed: %@", error);
return;
}
}
}
- (void)cleanTempRecorderFile {
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:_recorderTempFilePath]) {
NSError *error = nil;
[manager removeItemAtPath:_recorderTempFilePath error:&error];
if (error) {
NSLog(@"remove recorder temp file failed: %@", error);
return;
}
}
}
- (BOOL)checkReportAvailable {
if (!_config.isReportEnable) {
return NO;
}
if (_config.maxRecordFileSize <= _config.uploadThreshold) {
NSLog(@"maxRecordFileSize must be larger than uploadThreshold");
return NO;
}
return YES;
}
- (void)report:(NSString *)jsonString token:(NSString *)token {
if (![self checkReportAvailable] || !jsonString || !token || token.length == 0) {
return;
}
// 串行队列处理文件读写
dispatch_async(self.recordQueue, ^{
[kQNReporter saveReportJsonString:jsonString];
[kQNReporter reportToServerIfNeeded:token];
});
}
- (void)saveReportJsonString:(NSString *)jsonString {
NSString *finalRecordInfo = [jsonString stringByAppendingString:@"\n"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:self.recorderFilePath]) {
// 如果recordFile不存在创建文件并写入首行首次不上传
[finalRecordInfo writeToFile:_recorderFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
} else {
NSDictionary *recorderFileAttr = [fileManager attributesOfItemAtPath:self.recorderFilePath error:nil];
if ([recorderFileAttr fileSize] > self.config.maxRecordFileSize) {
return;
}
NSFileHandle *fileHandler = nil;
@try {
// 上传信息写入recorder文件
fileHandler = [NSFileHandle fileHandleForUpdatingAtPath:_recorderFilePath];
[fileHandler seekToEndOfFile];
[fileHandler writeData: [finalRecordInfo dataUsingEncoding:NSUTF8StringEncoding]];
} @catch (NSException *exception) {
NSLog(@"NSFileHandle cannot write data: %@", exception.description);
} @finally {
[fileHandler closeFile];
}
}
}
- (void)reportToServerIfNeeded:(NSString *)tokenString {
BOOL needToReport = NO;
long currentTime = [[NSDate date] timeIntervalSince1970];
long interval = self.config.interval * 10;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *recorderFileAttr = [fileManager attributesOfItemAtPath:self.recorderFilePath error:nil];
if ([fileManager fileExistsAtPath:self.recorderTempFilePath]) {
needToReport = YES;
} else if ((self.lastReportTime == 0 || (currentTime - self.lastReportTime) >= interval || [recorderFileAttr fileSize] > self.config.uploadThreshold) &&
([fileManager moveItemAtPath:self.recorderFilePath toPath:self.recorderTempFilePath error:nil])) {
needToReport = YES;
}
if (needToReport && !self.isReporting) {
[self reportToServer:tokenString];
} else {
// 有未上传日志存在,则 interval 时间后再次重试一次
if (![fileManager fileExistsAtPath:self.recorderFilePath] || [recorderFileAttr fileSize] == 0) {
return;
}
NSArray *transactionList = [kQNTransactionManager transactionsForName:kQNUplogDelayReportTransactionName];
if (transactionList != nil && transactionList.count > 1) {
return;
}
if (transactionList != nil && transactionList.count == 1) {
QNTransaction *transaction = transactionList.firstObject;
if (transaction != nil && !transaction.isExecuting) {
return;
}
}
QNTransaction *transaction = [QNTransaction transaction:kQNUplogDelayReportTransactionName after:interval action:^{
[kQNReporter reportToServerIfNeeded:tokenString];
}];
[kQNTransactionManager addTransaction:transaction];
}
}
- (void)reportToServer:(NSString *)tokenString {
if (tokenString == nil) {
return;
}
QNUpToken *token = [QNUpToken parse:tokenString];
if (!token.isValid) {
return;
}
NSData *logData = [self getLogData];
if (logData == nil) {
return;
}
self.isReporting = YES;
logData = [NSData qn_gZip:logData];
QNRequestTransaction *transaction = [self createUploadRequestTransaction:token];
[transaction reportLog:logData logClientId:self.X_Log_Client_Id complete:^(QNResponseInfo * _Nullable responseInfo, QNUploadRegionRequestMetrics * _Nullable metrics, NSDictionary * _Nullable response) {
if (responseInfo.isOK) {
self.lastReportTime = [[NSDate dateWithTimeIntervalSinceNow:0] timeIntervalSince1970];
if (!self.X_Log_Client_Id) {
self.X_Log_Client_Id = responseInfo.responseHeader[@"x-log-client-id"];
}
[self cleanTempRecorderFile];
} else {
NSLog(@"upload info report failed: %@", responseInfo);
}
self.isReporting = NO;
[self destroyUploadRequestTransaction:transaction];
}];
}
- (NSData *)getLogData {
return [NSData dataWithContentsOfFile:_recorderTempFilePath];
}
- (QNRequestTransaction *)createUploadRequestTransaction:(QNUpToken *)token{
if (self.config.serverURL) {
}
NSArray *hosts = nil;
if (self.config.serverHost) {
hosts = @[self.config.serverHost];
}
QNRequestTransaction *transaction = [[QNRequestTransaction alloc] initWithHosts:hosts
regionId:QNZoneInfoEmptyRegionId
token:token];
self.transaction = transaction;
return transaction;
}
- (void)destroyUploadRequestTransaction:(QNRequestTransaction *)transaction{
self.transaction = nil;
}
@end